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 {
}
}
}