HytaleBanProvider class

Пакет: com.hypixel.hytale.server.core.modules.accesscontrol.provider

Файл: com/hypixel/hytale/server/core/modules/accesscontrol/provider/HytaleBanProvider.java

extends: BlockingDiskFile

implements: BanProvider

Поля (31)

МодификаторыТипИмя
continue
BsonValue var1
BsonDocument var1
List var1
int var15
BsonArray var2
RawJsonReader var2
BsonValue var2
ExtraInfo var2
Ban var2
Ban var2
Ban var2
Ban var2
Map var2
Map var3
BsonValue var3
BsonArray var3
Ban var3
boolean var3
List var3
List var4
BsonDocument var4
Boolean var4
BsonValue var5
long var6
BsonDocument var6
BsonDocument var7
Ban var7
Ban var8
var8
BsonValue var8

Методы (21)

МодификаторыВозвратСигнатура
abstract throw new IllegalArgumentExceptionthrow new IllegalArgumentException("Ban has no \"" + var1 + "\"")
abstract throw new IllegalStateExceptionthrow new IllegalStateException("Version " + var6 + " of " + this.path + " is newer than the 1 this server writes. Bans it holds would not be enforced")
abstract throw new IllegalStateExceptionthrow new IllegalStateException(this.path + " has no Bans array, so the bans it holds cannot be read")
private record UnreadableEntryrecord UnreadableEntry(@Nullable UUID target, @Nonnull BsonValue entry)
private boolean dropUnreadableEntriesboolean dropUnreadableEntries(@Nonnull UUID var1)
for for(BsonValue var6 : var2)
for for(HytaleBanProvider.UnreadableEntry var17 : var4)
abstract for for(int var2 = 0; var2 < this.unreadableEntries.size()
if if(var5 != null)
if if(var6 > 1L)
if if(var1 == null)
if if(var2 == null)
if if(var2 == null)
if if(var2 == null)
if if(var7 != null)
if if(var4 == null || !var4)
private boolean isDeniedByUnreadableEntryboolean isDeniedByUnreadableEntry(@Nonnull UUID var1)
public boolean modifyboolean modify(@Nonnull Function<Map<UUID, Ban>, Boolean> var1)
private boolean namedByUnreadableEntryboolean namedByUnreadableEntry(@Nonnull UUID var1)
private void restorevoid restore(@Nonnull Map<UUID, Ban> var1, @Nonnull List<HytaleBanProvider.UnreadableEntry> var2)
abstract super super(var1)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.modules.accesscontrol.provider;

class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.codec.ExtraInfo;
class="kw">import com.hypixel.hytale.codec.util.RawJsonReader;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.modules.accesscontrol.ban.Ban;
class="kw">import com.hypixel.hytale.server.core.util.BsonUtil;
class="kw">import com.hypixel.hytale.server.core.util.io.BlockingDiskFile;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
class="kw">import java.io.BufferedReader;
class="kw">import java.io.BufferedWriter;
class="kw">import java.io.IOException;
class="kw">import java.nio.file.Path;
class="kw">import java.time.Instant;
class="kw">import java.util.ArrayList;
class="kw">import java.util.Collection;
class="kw">import java.util.List;
class="kw">import java.util.Map;
class="kw">import java.util.Objects;
class="kw">import java.util.Optional;
class="kw">import java.util.UUID;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.function.Function;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.bson.BsonArray;
class="kw">import org.bson.BsonDocument;
class="kw">import org.bson.BsonInt32;
class="kw">import org.bson.BsonValue;

class="kw">public class HytaleBanProvider class="kw">extends BlockingDiskFile class="kw">implements BanProvider {
   @Nonnull
   class="kw">public class="kw">static class="kw">final String BAN_FILE_PATH = "bans.json";
   class="kw">private class="kw">static class="kw">final int VERSION = 1;
   @Nonnull
   class="kw">private class="kw">static class="kw">final String VERSION_KEY = "Version";
   @Nonnull
   class="kw">private class="kw">static class="kw">final String BANS_KEY = "Bans";
   class="kw">private class="kw">static class="kw">final int READ_BUFFER_SIZE = 8192;
   @Nonnull
   class="kw">private class="kw">static class="kw">final CompletableFuture<Optional<Message>> NO_REASON_ANSWER = CompletableFuture.completedFuture(NO_REASON);
   @Nonnull
   class="kw">private class="kw">static class="kw">final CompletableFuture<Optional<Message>> UNDESCRIBED_BAN_ANSWER = CompletableFuture.completedFuture(UNDESCRIBED_BAN);
   class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
   class="kw">private class="kw">final Map<UUID, Ban> bans = new Object2ObjectOpenHashMap();
   class="kw">private class="kw">final List<HytaleBanProvider.UnreadableEntry> unreadableEntries = new ArrayList<>();

   class="kw">public HytaleBanProvider(@Nonnull Path var1) {
      super(var1);
   }

   @Override
   class="kw">protected void read(@Nonnull BufferedReader var1) class="kw">throws IOException {
      BsonArray var2 = this.readEntries(var1);
      Map var3 = new Object2ObjectOpenHashMap();
      List var4 = new ArrayList<>();

      for (BsonValue var6 : var2) {
         if (!var6.isDocument()) {
            var4.add(new HytaleBanProvider.UnreadableEntry(null, var6));
            LOGGER.at(Level.WARNING).log("An entry in %s is not a ban, keeping it as it is: %s", this.path, var6);
         } else {
            BsonDocument var7 = var6.asDocument();

            Ban var8;
            try {
               var8 = Ban.CODEC.decode(migrateEntry(var7));
               Objects.requireNonNull(var8.getTarget(), "Ban has no Target");
               Objects.requireNonNull(var8.getBy(), "Ban has no By");
               Objects.requireNonNull(var8.getTimestamp(), "Ban has no Timestamp");
            } catch (Exception var14) {
               var4.add(new HytaleBanProvider.UnreadableEntry(readTarget(var7), var7));
               ((HytaleLogger.Api)LOGGER.at(Level.WARNING).withCause(var14)).log("Could not read a ban in %s, keeping it as it is: %s", this.path, var7);
               class="kw">continue;
            }

            if (var8.isInEffect()) {
               var3.put(var8.getTarget(), var8);
            }
         }
      }

      this.fileLock.writeLock().lock();

      try {
         this.bans.clear();
         this.bans.putAll(var3);
         this.unreadableEntries.clear();
         this.unreadableEntries.addAll(var4);
      } class="kw">finally {
         this.fileLock.writeLock().unlock();
      }

      if (!var4.isEmpty()) {
         int var15 = 0;

         for (HytaleBanProvider.UnreadableEntry var17 : var4) {
            if (var17.target() != null) {
               var15++;
            }
         }

         LOGGER.at(Level.WARNING)
            .log("%d of %d entries in %s could not be read. %d of them still deny their target", var4.size(), var4.size() + var3.size(), this.path, var15);
      }
   }

   @Nonnull
   class="kw">private BsonArray readEntries(@Nonnull BufferedReader var1) class="kw">throws IOException {
      RawJsonReader var2 = new RawJsonReader(var1, new char[8192]);
      var2.consumeWhiteSpace();
      BsonValue var3 = RawJsonReader.readBsonValue(var2);
      if (var3.isArray()) {
         LOGGER.at(Level.INFO).log("Reading %s in the form the server wrote before the bans carried a version", this.path);
         class="kw">return var3.asArray();
      }

      if (!var3.isDocument()) {
         throw new IllegalStateException(this.path + " holds a " + var3.getBsonType() + " rather than a ban list");
      }

      BsonDocument var4 = var3.asDocument();
      BsonValue var5 = var4.get("Version");
      if (var5 != null) {
         if (!var5.isInt32() && !var5.isInt64()) {
            throw new IllegalStateException(
               "The Version of " + this.path + " is a " + var5.getBsonType() + " rather than a whole number, so the bans it holds cannot be read"
            );
         }

         long var6 = var5.asNumber().longValue();
         if (var6 > 1L) {
            throw new IllegalStateException(
               "Version " + var6 + " of " + this.path + " is newer than the 1 this server writes. Bans it holds would not be enforced"
            );
         }
      }

      BsonValue var8 = var4.get("Bans");
      if (var8 != null && var8.isArray()) {
         class="kw">return var8.asArray();
      } else {
         throw new IllegalStateException(this.path + " has no Bans array, so the bans it holds cannot be read");
      }
   }

   @Nullable
   class="kw">private class="kw">static UUID readTarget(@Nonnull BsonDocument var0) {
      BsonValue var1 = var0.get(var0.containsKey("Target") ? "Target" : "target");
      if (var1 == null) {
         class="kw">return null;
      }

      try {
         class="kw">return UUID.fromString(var1.asString().getValue());
      } catch (RuntimeException var3) {
         class="kw">return null;
      }
   }

   @Nonnull
   class="kw">private class="kw">static BsonDocument migrateEntry(@Nonnull BsonDocument var0) {
      if (!var0.containsKey("type")) {
         class="kw">return var0;
      }

      BsonDocument var1 = new BsonDocument()
         .append("Target", require(var0, "target"))
         .append("By", require(var0, "by"))
         .append("Timestamp", toTimestamp(require(var0, "timestamp")));
      if (var0.containsKey("reason")) {
         var1.append("Reason", var0.get("reason"));
      }

      if (var0.containsKey("expiresOn")) {
         var1.append("ExpiresOn", toTimestamp(var0.get("expiresOn")));
      }

      class="kw">return var1;
   }

   @Nonnull
   class="kw">private class="kw">static BsonValue require(@Nonnull BsonDocument var0, @Nonnull String var1) {
      BsonValue var2 = var0.get(var1);
      if (var2 == null) {
         throw new IllegalArgumentException("Ban has no \"" + var1 + "\"");
      } else {
         class="kw">return var2;
      }
   }

   @Nonnull
   class="kw">private class="kw">static BsonValue toTimestamp(@Nonnull BsonValue var0) {
      class="kw">return Codec.INSTANT.encode(Instant.ofEpochMilli(var0.asNumber().longValue()), ExtraInfo.THREAD_LOCAL.get());
   }

   @Override
   class="kw">protected void write(@Nonnull BufferedWriter var1) class="kw">throws IOException {
      ExtraInfo var2 = ExtraInfo.THREAD_LOCAL.get();
      BsonArray var3 = new BsonArray();
      this.unreadableEntries.forEach(var1x -> var3.add(var1x.entry()));

      for (Ban var5 : this.bans.values()) {
         if (var5.isInEffect()) {
            var3.add(Ban.CODEC.encode(var5, var2));
         }
      }

      BsonDocument var6 = new BsonDocument().append("Version", new BsonInt32(1)).append("Bans", var3);
      var1.write(BsonUtil.toJson(var6));
   }

   @Override
   class="kw">protected void create(@Nonnull BufferedWriter var1) class="kw">throws IOException {
      var1.write(BsonUtil.toJson(new BsonDocument().append("Version", new BsonInt32(1)).append("Bans", new BsonArray())));
   }

   @Override
   class="kw">public boolean hasBan(@Nonnull UUID var1) {
      this.fileLock.readLock().lock();

      try {
         Ban var2 = this.bans.get(var1);
         if (var2 == null) {
            class="kw">return this.namedByUnreadableEntry(var1);
         }

         if (var2.isInEffect()) {
            class="kw">return true;
         }
      } class="kw">finally {
         this.fileLock.readLock().unlock();
      }

      class="kw">return this.dropExpiredBan(var1) != null || this.isDeniedByUnreadableEntry(var1);
   }

   @Nonnull
   @Override
   class="kw">public CompletableFuture<Optional<Message>> getDisconnectReason(@Nonnull UUID var1) {
      this.fileLock.readLock().lock();

      try {
         Ban var2 = this.bans.get(var1);
         if (var2 == null) {
            class="kw">return this.namedByUnreadableEntry(var1) ? UNDESCRIBED_BAN_ANSWER : NO_REASON_ANSWER;
         }

         if (var2.isInEffect()) {
            class="kw">return CompletableFuture.completedFuture(Optional.of(var2.getDisconnectReason()));
         }
      } class="kw">finally {
         this.fileLock.readLock().unlock();
      }

      Ban var7 = this.dropExpiredBan(var1);
      if (var7 != null) {
         class="kw">return CompletableFuture.completedFuture(Optional.of(var7.getDisconnectReason()));
      } else {
         class="kw">return this.isDeniedByUnreadableEntry(var1) ? UNDESCRIBED_BAN_ANSWER : NO_REASON_ANSWER;
      }
   }

   class="kw">private boolean isDeniedByUnreadableEntry(@Nonnull UUID var1) {
      this.fileLock.readLock().lock();

      try {
         class="kw">return this.namedByUnreadableEntry(var1);
      } class="kw">finally {
         this.fileLock.readLock().unlock();
      }
   }

   class="kw">private boolean namedByUnreadableEntry(@Nonnull UUID var1) {
      for (int var2 = 0; var2 < this.unreadableEntries.size(); var2++) {
         if (var1.equals(this.unreadableEntries.get(var2).target())) {
            class="kw">return true;
         }
      }

      class="kw">return false;
   }

   @Nullable
   @Override
   class="kw">public Ban getBan(@Nonnull UUID var1) {
      this.fileLock.readLock().lock();

      try {
         Ban var2 = this.bans.get(var1);
         if (var2 == null || var2.isInEffect()) {
            class="kw">return var2;
         }
      } class="kw">finally {
         this.fileLock.readLock().unlock();
      }

      class="kw">return this.dropExpiredBan(var1);
   }

   @Override
   class="kw">public boolean addBan(@Nonnull Ban var1) {
      class="kw">return this.modify(var2 -> {
         Ban var3 = var2.get(var1.getTarget());
         if (var3 != null && var3.isInEffect()) {
            class="kw">return Boolean.FALSE;
         }

         this.dropUnreadableEntries(var1.getTarget());
         var2.put(var1.getTarget(), var1);
         class="kw">return Boolean.TRUE;
      });
   }

   @Override
   class="kw">public boolean removeBan(@Nonnull UUID var1) {
      class="kw">return this.modify(var2 -> {
         boolean var3 = this.dropUnreadableEntries(var1);
         class="kw">return var2.remove(var1) != null || var3;
      });
   }

   class="kw">private boolean dropUnreadableEntries(@Nonnull UUID var1) {
      class="kw">return this.unreadableEntries.removeIf(var1x -> var1.equals(var1x.target()));
   }

   @Nonnull
   @Override
   class="kw">public Collection<Ban> getBans() {
      List var1 = new ArrayList<>();
      this.fileLock.readLock().lock();

      try {
         for (Ban var3 : this.bans.values()) {
            if (var3.isInEffect()) {
               var1.add(var3);
            }
         }
      } class="kw">finally {
         this.fileLock.readLock().unlock();
      }

      class="kw">return List.copyOf(var1);
   }

   @Nullable
   class="kw">private Ban dropExpiredBan(@Nonnull UUID var1) {
      this.fileLock.writeLock().lock();

      try {
         Ban var2 = this.bans.get(var1);
         if (var2 != null && !var2.isInEffect()) {
            this.bans.remove(var1);
            class="kw">return null;
         } else {
            class="kw">return var2;
         }
      } class="kw">finally {
         this.fileLock.writeLock().unlock();
      }
   }

   @Override
   class="kw">public void load() {
      this.syncLoad();
   }

   @Override
   class="kw">public void save() {
      this.syncSave();
   }

   class="kw">public boolean modify(@Nonnull Function<Map<UUID, Ban>, Boolean> var1) {
      this.fileLock.writeLock().lock();

      try {
         Map var2 = new Object2ObjectOpenHashMap(this.bans);
         List var3 = new ArrayList<>(this.unreadableEntries);

         try {
            Boolean var4 = var1.apply(this.bans);
            if (var4 == null || !var4) {
               this.restore(var2, var3);
               class="kw">return false;
            }

            this.syncSave();
         } catch (RuntimeException | Error var9) {
            this.restore(var2, var3);
            throw var9;
         }

         class="kw">return true;
      } class="kw">finally {
         this.fileLock.writeLock().unlock();
      }
   }

   class="kw">private void restore(@Nonnull Map<UUID, Ban> var1, @Nonnull List<HytaleBanProvider.UnreadableEntry> var2) {
      this.bans.clear();
      this.bans.putAll(var1);
      this.unreadableEntries.clear();
      this.unreadableEntries.addAll(var2);
   }

   class="kw">private record UnreadableEntry(@Nullable UUID target, @Nonnull BsonValue entry) {
      class="kw">private UnreadableEntry {
      }
   }
}