From 126ce64a241746c2ce27d2f6562ea42041424cb3 Mon Sep 17 00:00:00 2001 From: Sen Date: Sat, 31 May 2025 22:56:43 +0200 Subject: [PATCH] change svar implementation --- common/src/main/java/common/init/Config.java | 171 +----------------- common/src/main/java/common/util/Var.java | 16 ++ server/src/main/java/server/Server.java | 74 +++++--- .../server/command/commands/CommandSv.java | 24 +-- server/src/main/java/server/util/SVar.java | 84 +++++++++ .../src/main/java/server/util/ValueType.java | 5 + .../src/main/java/server/world/Converter.java | 11 +- 7 files changed, 171 insertions(+), 214 deletions(-) create mode 100644 common/src/main/java/common/util/Var.java create mode 100644 server/src/main/java/server/util/SVar.java create mode 100644 server/src/main/java/server/util/ValueType.java diff --git a/common/src/main/java/common/init/Config.java b/common/src/main/java/common/init/Config.java index 885a800..26fb982 100755 --- a/common/src/main/java/common/init/Config.java +++ b/common/src/main/java/common/init/Config.java @@ -1,130 +1,8 @@ package common.init; -import static java.lang.annotation.ElementType.FIELD; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Map; -import java.util.TreeMap; - -import common.util.ExtMath; +import common.util.Var; public abstract class Config { - public static enum ValueType { - STRING, BOOLEAN, INTEGER, FLOAT; - } - - @Target(FIELD) - @Retention(value = RetentionPolicy.RUNTIME) - private static @interface Var { - String name(); - float min() default (float)Integer.MIN_VALUE; - float max() default (float)Integer.MAX_VALUE; - boolean nonDefault() default false; - } - - public static class Value { - public final ValueType type; - public final String def; - public final boolean noDef; - private final Field field; - private final float min; - private final float max; - - private Runnable callback; - - private Value(Field field, Var value) { - this.type = field.getType() == int.class ? ValueType.INTEGER : (field.getType() == boolean.class ? ValueType.BOOLEAN : - (field.getType() == String.class ? ValueType.STRING : (field.getType() == float.class ? ValueType.FLOAT : null))); - if(this.type == null) - throw new IllegalArgumentException(value.name() + ": Unbekannter Variablen-Typ - " + field.getType()); - this.field = field; - this.def = this.getValue(); - this.noDef = value.nonDefault(); -// Clamped clamp = this.field.getAnnotation(Clamped.class); - this.min = (this.type == ValueType.INTEGER || this.type == ValueType.FLOAT) - ? value.min() : 0; - this.max = (this.type == ValueType.INTEGER || this.type == ValueType.FLOAT) - ? value.max() : (this.type == ValueType.BOOLEAN ? 1 : 0); -// Update update = this.field.getAnnotation(Update.class); -// if(value.callback() == Callback.class) { -// this.callback = null; -// } -// else { -// try { -// this.callback = value.callback().getConstructor().newInstance(); -// } -// catch(InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException -// | NoSuchMethodException e) { -// throw new RuntimeException(e); -// } -// } - this.setValue(this.def, this.noDef); - } - - public String getValue() { - try { - return "" + this.field.get(null); -// switch(this.type) { -// case STRING: -// default: -// return (String)this.field.get(null); -// case BOOLEAN: -// return "" + this.field.getBoolean(null); -// case INTEGER: -// return "" + this.field.getInt(null); -// case FLOAT: -// return "" + this.field.getFloat(null); -// } - } - catch(IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - private void setValue(String value, boolean noClamp) { - try { - switch(this.type) { - case STRING: - this.field.set(null, value); - break; - case BOOLEAN: - this.field.setBoolean(null, Boolean.parseBoolean(value)); - break; - case INTEGER: - int inum = 0; - try { - inum = Integer.parseInt(value); - } - catch(NumberFormatException e) { - } - this.field.setInt(null, noClamp ? inum : ExtMath.clampi(inum, (int)this.min, (int)this.max)); - break; - case FLOAT: - float fnum = 0.0f; - try { - fnum = Float.parseFloat(value); - } - catch(NumberFormatException e) { - } - if(!noClamp) - fnum = ExtMath.clampf(fnum, this.min, this.max); - int round = (int)(fnum * 1000.0f); - this.field.setFloat(null, (float)round / 1000.0f); - break; - } - } - catch(IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - } - - public static final Map VARS = new TreeMap(); - @Var(name = "fireTick") public static boolean fire = true; @Var(name = "mobGriefing") @@ -205,8 +83,6 @@ public abstract class Config { public static boolean mergeInfinite = true; @Var(name = "infighting") public static boolean infight = true; -// @Var(name = "infightSameType") -// public static boolean infightSame = true; @Var(name = "damageFall") public static boolean damageFall = true; @Var(name = "damageFire") @@ -450,15 +326,6 @@ public abstract class Config { @Var(name = "port", min = 1024, max = 32767, nonDefault = true) public static int port = -1; -// @Var(name = "spawnX", min = -World.MAX_SIZE + 1, max = World.MAX_SIZE - 1) -// public static int spawnX = 0; -// @Var(name = "spawnY", min = -1, max = 511) -// public static int spawnY = 64; -// @Var(name = "spawnZ", min = -World.MAX_SIZE + 1, max = World.MAX_SIZE - 1) -// public static int spawnZ = 0; -// @Var(name = "spawnDim") -// public static int spawnDim = 0; - @Var(name = "gravity") public static float gravity = 1.0f; @Var(name = "knockback") @@ -468,40 +335,4 @@ public abstract class Config { public static String password = ""; @Var(name = "baseSeed", nonDefault = true) public static String seed = ""; - - static { - for(Field field : Config.class.getDeclaredFields()) { - if(field.isAnnotationPresent(Var.class)) { - if(!Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) - throw new IllegalArgumentException("Feld für Variable " + field + " muss statisch und änderbar sein!"); - Var value = field.getAnnotation(Var.class); - if(value.name().isEmpty()) - throw new IllegalArgumentException("Variablenname von " + field + " kann nicht leer sein!"); - if(VARS.containsKey(value.name())) - throw new IllegalArgumentException("Variable " + value.name() + " existiert bereits!"); - VARS.put(value.name(), new Config.Value(field, value)); - } - } - } - - public static void clear() { - for(Config.Value value : VARS.values()) { - value.setValue(value.def, value.noDef); - } - } - - public static void setCallback(Runnable callback, String ... vars) { - for(String key : vars) { - VARS.get(key).callback = callback; - } - } - - public static void set(String key, String value, boolean update) { - Config.Value vl = VARS.get(key); - if(vl != null) { - vl.setValue(value, false); - if(update && vl.callback != null) - vl.callback.run(); - } - } } diff --git a/common/src/main/java/common/util/Var.java b/common/src/main/java/common/util/Var.java new file mode 100644 index 0000000..3951c15 --- /dev/null +++ b/common/src/main/java/common/util/Var.java @@ -0,0 +1,16 @@ +package common.util; + +import static java.lang.annotation.ElementType.FIELD; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(FIELD) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface Var { + String name(); + float min() default (float)Integer.MIN_VALUE; + float max() default (float)Integer.MAX_VALUE; + boolean nonDefault() default false; +} \ No newline at end of file diff --git a/server/src/main/java/server/Server.java b/server/src/main/java/server/Server.java index 5bd2ab4..db0800b 100755 --- a/server/src/main/java/server/Server.java +++ b/server/src/main/java/server/Server.java @@ -5,6 +5,8 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.net.InetAddress; import java.security.KeyPair; import java.security.PrivateKey; @@ -87,6 +89,7 @@ import common.util.LazyLoader; import common.util.PortalType; import common.util.Position; import common.util.Util; +import common.util.Var; import common.util.WorldPos; import common.world.World; import server.biome.GenBiome; @@ -97,6 +100,7 @@ import server.command.FixedExecutor; import server.network.HandshakeHandler; import server.network.Player; import server.network.User; +import server.util.SVar; import server.world.Converter; import server.world.Region; import server.world.WorldServer; @@ -109,6 +113,7 @@ public final class Server implements IThreadListener { }; private final Thread serverThread = Thread.currentThread(); + private final Map variables = Maps.newTreeMap(); private final List clients = Collections.synchronizedList(Lists.newArrayList()); private final List players = Lists.newArrayList(); private final Map online = Maps.newHashMap(); @@ -161,6 +166,7 @@ public final class Server implements IThreadListener { Registry.addShutdownHook(new Runnable() { public void run() { server.stopServer(); + Log.flushLog(); } }); Log.setSync(server); @@ -169,22 +175,22 @@ public final class Server implements IThreadListener { Log.flushLog(); } - public static void saveServerConfig(long time, Server server) { + private void saveServerConfig(long time) { TagObject data = new TagObject(); data.setLong("Time", time); data.setLong("LastAccess", System.currentTimeMillis()); data.setString("Version", Util.VERSION); TagObject cfg = new TagObject(); - for(String cvar : Config.VARS.keySet()) { - Config.Value value = Config.VARS.get(cvar); - if(!value.noDef || !value.def.equals(value.getValue())) - cfg.setString(cvar, value.getValue()); + for(String cvar : this.variables.keySet()) { + SVar value = this.variables.get(cvar); + if(!value.noDef || !value.def.equals(value.get())) + cfg.setString(cvar, value.get()); } data.setObject("Config", cfg); data.setObject("Universe", UniverseRegistry.toTags()); - if(server != null) { - data.setByteArray("PrivateKey", server.getPrivateKey().getEncoded()); - data.setByteArray("PublicKey", server.getPublicKey().getEncoded()); + if(this.keyPair != null) { + data.setByteArray("PrivateKey", this.keyPair.getPrivate().getEncoded()); + data.setByteArray("PublicKey", this.keyPair.getPublic().getEncoded()); } File nfile = new File("server.cdt.tmp"); File lfile = new File("server.cdt"); @@ -199,9 +205,7 @@ public final class Server implements IThreadListener { } } - public long loadServerConfig() { - Config.clear(); - UniverseRegistry.clear(); + private long loadServerConfig() { File file = new File("server.cdt"); if(!file.exists()) file = new File("server.cdt.tmp"); @@ -210,7 +214,9 @@ public final class Server implements IThreadListener { TagObject tag = TagObject.readGZip(file); TagObject cfg = tag.getObject("Config"); for(String key : cfg.keySet()) { - Config.set(key, cfg.getString(key), false); + SVar svar = this.variables.get(key); + if(svar != null) + svar.set(cfg.getString(key), false, false); } UniverseRegistry.fromTags(tag.getObject("Universe")); long lastPlayed = tag.getLong("LastAccess"); @@ -230,16 +236,40 @@ public final class Server implements IThreadListener { } catch(Exception e) { Log.IO.error(e, "Fehler beim Lesen von " + file); - Config.clear(); + for(SVar svar : this.variables.values()) { + svar.set(svar.def, svar.noDef, false); + } UniverseRegistry.clear(); } } Log.IO.info("Erstelle neue Welt und Konfiguration"); return World.START_TIME; } + + private void setCallback(Runnable callback, String ... vars) { + for(String key : vars) { + this.variables.get(key).setCallback(callback); + } + } + + public Map getVariables() { + return this.variables; + } private Server() { - Config.setCallback(new Runnable() { + for(Field field : Config.class.getDeclaredFields()) { + if(field.isAnnotationPresent(Var.class)) { + if(!Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) + throw new IllegalArgumentException("Feld für Variable " + field + " muss statisch und änderbar sein!"); + Var value = field.getAnnotation(Var.class); + if(value.name().isEmpty()) + throw new IllegalArgumentException("Variablenname von " + field + " kann nicht leer sein!"); + if(this.variables.containsKey(value.name())) + throw new IllegalArgumentException("Variable " + value.name() + " existiert bereits!"); + this.variables.put(value.name(), new SVar(field, value)); + } + } + this.setCallback(new Runnable() { public void run() { for(WorldServer world : Server.this.getWorlds()) { world.updatePhysics(); @@ -247,24 +277,22 @@ public final class Server implements IThreadListener { Server.this.sendPacket(new SPacketWorld(WorldServer.clampGravity(), Config.dayCycle, Config.timeFlow)); } }, "daylightCycle", "timeFlow", "gravity"); - Config.setCallback(new Runnable() { + this.setCallback(new Runnable() { public void run() { for(WorldServer world : Server.this.getWorlds()) { world.updateViewRadius(); } } }, "viewDistance"); - Config.setCallback(new Runnable() { + this.setCallback(new Runnable() { public void run() { Server.this.bind(Config.port); } }, "port"); - Config.setCallback(new Runnable() { + this.setCallback(new Runnable() { public void run() { - if((!Config.password.isEmpty() && Config.password.length() < 8) || Config.password.length() > IPlayer.MAX_PASS_LENGTH) { - Log.IO.error("Passwort muss aus 8-" + IPlayer.MAX_PASS_LENGTH + " Zeichen bestehen"); - Config.set("password", "", false); - } + if((!Config.password.isEmpty() && Config.password.length() < 8) || Config.password.length() > IPlayer.MAX_PASS_LENGTH) + Log.IO.warn("Passwort muss aus 8-" + IPlayer.MAX_PASS_LENGTH + " Zeichen bestehen, Login wird nicht möglich sein"); } }, "password"); } @@ -289,7 +317,7 @@ public final class Server implements IThreadListener { } public void saveWorldInfo() { - saveServerConfig(this.space.getDayTime(), this); + this.saveServerConfig(this.space.getDayTime()); WorldServer.saveWarps(this.warps); } @@ -365,7 +393,7 @@ public final class Server implements IThreadListener { } public void run(long time) { - Converter.convert(); + Converter.convert(this); long wtime = this.loadServerConfig(); if(this.keyPair == null) { Log.SYSTEM.info("Generiere neues Schlüsselpaar"); diff --git a/server/src/main/java/server/command/commands/CommandSv.java b/server/src/main/java/server/command/commands/CommandSv.java index 0d3c59e..9bbccf9 100644 --- a/server/src/main/java/server/command/commands/CommandSv.java +++ b/server/src/main/java/server/command/commands/CommandSv.java @@ -5,14 +5,14 @@ import java.util.Map.Entry; import common.collect.Lists; import common.color.TextColor; -import common.init.Config; -import common.init.Config.ValueType; import server.command.ArgumentSplitter; import server.command.Command; import server.command.CommandEnvironment; import server.command.Executor; import server.command.RunException; import server.command.StringCompleter; +import server.util.SVar; +import server.util.ValueType; public class CommandSv extends Command { public CommandSv() { @@ -21,7 +21,7 @@ public class CommandSv extends Command { this.setParamsOptional(); this.addString("variable", false, new StringCompleter() { public Collection complete(CommandEnvironment env) { - return Config.VARS.keySet(); + return env.getServer().getVariables().keySet(); } }); this.addString("value", true); @@ -29,17 +29,17 @@ public class CommandSv extends Command { public Iterable getCustomCompletions(CommandEnvironment env, Executor exec, ArgumentSplitter parsed, String param, String parser, String arg) { if(param.equals("value") && parsed.has("variable")) { - Config.Value sv = Config.VARS.get(parsed.get("variable")); + SVar sv = env.getServer().getVariables().get(parsed.get("variable")); if(sv != null && sv.type == ValueType.BOOLEAN) - return Boolean.parseBoolean(sv.getValue()) ? Lists.newArrayList("false", "true") : Lists.newArrayList("true", "false"); + return Boolean.parseBoolean(sv.get()) ? Lists.newArrayList("false", "true") : Lists.newArrayList("true", "false"); else if(sv != null && !sv.noDef && (sv.type == ValueType.INTEGER || sv.type == ValueType.FLOAT)) return Lists.newArrayList(sv.def); } return null; } - private String formatVariable(String name, Config.Value sv, String separator, boolean censor) { - String value = sv.getValue(); + private String formatVariable(String name, SVar sv, String separator, boolean censor) { + String value = sv.get(); StringBuilder sb = new StringBuilder(TextColor.YELLOW + name + TextColor.GRAY + " " + separator + " "); if(sv.noDef && sv.def.equals(value)) sb.append(TextColor.DGRAY + "[ - ]"); @@ -58,13 +58,13 @@ public class CommandSv extends Command { if(variable == null) { if(value != null) throw new RunException("Kann keinen Wert ohne eine Variable angeben"); - for(Entry entry : Config.VARS.entrySet()) { + for(Entry entry : env.getServer().getVariables().entrySet()) { exec.logConsole(this.formatVariable(entry.getKey(), entry.getValue(), "=", true)); } - exec.logConsole(TextColor.GREEN + "SVARs insgesamt registriert: %d", Config.VARS.size()); + exec.logConsole(TextColor.GREEN + "SVARs insgesamt registriert: %d", env.getServer().getVariables().size()); return null; } - Config.Value sv = Config.VARS.get(variable); + SVar sv = env.getServer().getVariables().get(variable); if(sv == null) throw new RunException("Variable '%s' existiert nicht", variable); if(value != null) { @@ -92,9 +92,9 @@ public class CommandSv extends Command { throw new RunException(TextColor.DRED + "'%s' ist keine gültige Zahl", value); } } - Config.set(variable, value, true); + sv.set(value, false, true); } exec.logConsole(this.formatVariable(variable, sv, value == null ? "=" : "->", false)); - return sv.noDef && sv.def.equals(sv.getValue()) ? null : sv.getValue(); + return sv.noDef && sv.def.equals(sv.get()) ? null : sv.get(); } } diff --git a/server/src/main/java/server/util/SVar.java b/server/src/main/java/server/util/SVar.java new file mode 100644 index 0000000..9c96405 --- /dev/null +++ b/server/src/main/java/server/util/SVar.java @@ -0,0 +1,84 @@ +package server.util; + +import java.lang.reflect.Field; + +import common.util.ExtMath; +import common.util.Var; + +public class SVar { + public final ValueType type; + public final String def; + public final boolean noDef; + private final Field field; + private final float min; + private final float max; + + private Runnable callback; + + public SVar(Field field, Var value) { + this.type = field.getType() == int.class ? ValueType.INTEGER : (field.getType() == boolean.class ? ValueType.BOOLEAN : + (field.getType() == String.class ? ValueType.STRING : (field.getType() == float.class ? ValueType.FLOAT : null))); + if(this.type == null) + throw new IllegalArgumentException(value.name() + ": Unbekannter Variablen-Typ - " + field.getType()); + this.field = field; + this.def = this.get(); + this.noDef = value.nonDefault(); + this.min = (this.type == ValueType.INTEGER || this.type == ValueType.FLOAT) + ? value.min() : 0; + this.max = (this.type == ValueType.INTEGER || this.type == ValueType.FLOAT) + ? value.max() : (this.type == ValueType.BOOLEAN ? 1 : 0); + this.set(this.def, this.noDef, false); + } + + public String get() { + try { + return "" + this.field.get(null); + } + catch(IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + public void setCallback(Runnable callback) { + this.callback = callback; + } + + public void set(String value, boolean noClamp, boolean update) { + try { + switch(this.type) { + case STRING: + this.field.set(null, value); + break; + case BOOLEAN: + this.field.setBoolean(null, Boolean.parseBoolean(value)); + break; + case INTEGER: + int inum = 0; + try { + inum = Integer.parseInt(value); + } + catch(NumberFormatException e) { + } + this.field.setInt(null, noClamp ? inum : ExtMath.clampi(inum, (int)this.min, (int)this.max)); + break; + case FLOAT: + float fnum = 0.0f; + try { + fnum = Float.parseFloat(value); + } + catch(NumberFormatException e) { + } + if(!noClamp) + fnum = ExtMath.clampf(fnum, this.min, this.max); + int round = (int)(fnum * 1000.0f); + this.field.setFloat(null, (float)round / 1000.0f); + break; + } + } + catch(IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + if(update && this.callback != null) + this.callback.run(); + } +} \ No newline at end of file diff --git a/server/src/main/java/server/util/ValueType.java b/server/src/main/java/server/util/ValueType.java new file mode 100644 index 0000000..f886f7c --- /dev/null +++ b/server/src/main/java/server/util/ValueType.java @@ -0,0 +1,5 @@ +package server.util; + +public enum ValueType { + STRING, BOOLEAN, INTEGER, FLOAT; +} \ No newline at end of file diff --git a/server/src/main/java/server/world/Converter.java b/server/src/main/java/server/world/Converter.java index a2eb75d..e0374eb 100644 --- a/server/src/main/java/server/world/Converter.java +++ b/server/src/main/java/server/world/Converter.java @@ -62,10 +62,8 @@ import common.entity.item.EntityBoat; import common.entity.item.EntityMinecart; import common.init.BlockRegistry; import common.init.Blocks; -import common.init.Config; import common.init.EntityRegistry; import common.init.TileRegistry; -import common.init.UniverseRegistry; import common.log.Log; import common.rng.Random; import common.tags.TagObject; @@ -87,7 +85,6 @@ import common.util.Facing; import common.util.NibbleArray; import common.world.State; import common.world.Weather; -import common.world.World; import server.Server; public abstract class Converter { @@ -1219,7 +1216,7 @@ public abstract class Converter { return start; } - public static boolean convert() { + public static boolean convert(Server server) { long cur = System.currentTimeMillis(); if(new File("server.cdt").exists()) return false; @@ -1295,15 +1292,11 @@ public abstract class Converter { Log.IO.warn("Konvertiere keine Chunk-Daten, da Version zu neu"); } Log.IO.info("Konvertiere Daten von level.dat"); - Config.clear(); - UniverseRegistry.clear(); NbtTag rules = tag.getTag("GameRules"); for(Entry rule : OLD_GAMERULES.entrySet()) { if(!rules.getString(rule.getKey()).isEmpty()) - Config.set(rule.getValue(), rules.getString(rule.getKey()), false); + server.getVariables().get(rule.getValue()).set(rules.getString(rule.getKey()), false, false); } - Log.IO.info("Speichere neue server.cdt ..."); - Server.saveServerConfig(World.START_TIME, null); Weather weather = tag.getByte("thundering") != 0 ? Weather.THUNDER : (tag.getByte("raining") != 0 ? Weather.RAIN : Weather.CLEAR); if(weather != Weather.CLEAR) { TagObject dataTag = new TagObject();