add /tick, /freeze and variable overrides

This commit is contained in:
Sen 2025-08-03 14:33:45 +02:00
parent 50fec6dd56
commit 83082f4f3c
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
5 changed files with 153 additions and 9 deletions

View file

@ -116,6 +116,7 @@ public final class Server implements IThreadListener, Executor {
private final Thread thread = Thread.currentThread();
private final NioEventLoopGroup eventGroup = new NioEventLoopGroup(0, Util.getThreadFactory("Netty Server IO"));
private final Map<String, SVar> variables = Maps.newTreeMap();
private final Map<String, Map<String, Object>> overrides = Maps.newTreeMap();
private final List<NetConnection> clients = Collections.<NetConnection>synchronizedList(Lists.<NetConnection>newArrayList());
private final List<Player> players = Lists.<Player>newArrayList();
private final Map<String, Player> online = Maps.<String, Player>newHashMap();
@ -350,9 +351,10 @@ public final class Server implements IThreadListener, Executor {
tag.setString("Version", Util.VERSION);
TagObject cfg = new TagObject();
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());
SVar sv = this.variables.get(cvar);
String value = this.getVariableOverrideValue(cvar);
if(!sv.noDef || !sv.def.equals(value))
cfg.setString(cvar, value);
}
tag.setObject("Config", cfg);
writeDimensions(tag);
@ -456,6 +458,91 @@ public final class Server implements IThreadListener, Executor {
return this.variables;
}
public boolean setVariableOverride(String id, Runnable func) {
Map<String, Object> map = Maps.newHashMap();
for(Entry<String, SVar> entry : this.variables.entrySet()) {
map.put(entry.getKey(), entry.getValue().getRaw());
}
func.run();
for(Iterator<Entry<String, Object>> iter = map.entrySet().iterator(); iter.hasNext();) {
Entry<String, Object> entry = iter.next();
SVar sv = this.variables.get(entry.getKey());
if(!sv.getRaw().equals(entry.getValue())) {
for(Iterator<Entry<String, Map<String, Object>>> oiter = this.overrides.entrySet().iterator(); oiter.hasNext();) {
Entry<String, Map<String, Object>> oentry = oiter.next();
Object value = oentry.getValue().remove(entry.getKey());
if(value == null)
continue;
if(oentry.getValue().isEmpty())
oiter.remove();
if(sv.getRaw().equals(value))
iter.remove();
break;
}
sv.set(sv.get(), false, true);
if(sv.sync)
this.sendPacket(new SPacketServerConfig(entry.getKey(), sv.getRaw()));
}
else {
iter.remove();
}
}
if(!map.isEmpty())
this.overrides.put(id, map);
return !map.isEmpty();
}
public boolean unsetVariableOverride(String id) {
Map<String, Object> map = this.overrides.remove(id);
if(map == null)
return false;
for(Entry<String, Object> entry : map.entrySet()) {
SVar sv = this.variables.get(entry.getKey());
if(!sv.getRaw().equals(entry.getValue())) {
sv.set("" + entry.getValue(), false, true);
if(sv.sync)
this.sendPacket(new SPacketServerConfig(entry.getKey(), sv.getRaw()));
}
}
return true;
}
public String removeVariableOverride(String var) {
for(Iterator<Entry<String, Map<String, Object>>> iter = this.overrides.entrySet().iterator(); iter.hasNext();) {
Entry<String, Map<String, Object>> entry = iter.next();
Object value = entry.getValue().remove(var);
if(value == null)
continue;
String id = entry.getKey();
if(entry.getValue().isEmpty())
iter.remove();
SVar sv = this.variables.get(var);
if(!sv.getRaw().equals(value)) {
sv.set("" + value, false, true);
if(sv.sync)
this.sendPacket(new SPacketServerConfig(var, sv.getRaw()));
}
return id;
}
return null;
}
public String getVariableOverride(String var) {
for(Entry<String, Map<String, Object>> entry : this.overrides.entrySet()) {
if(entry.getValue().containsKey(var))
return entry.getKey();
}
return null;
}
public String getVariableOverrideValue(String var) {
for(Entry<String, Map<String, Object>> entry : this.overrides.entrySet()) {
if(entry.getValue().containsKey(var))
return "" + entry.getValue().get(var);
}
return this.variables.get(var).get();
}
private Server() {
for(Class<?> clazz : new Class[] {Vars.class, SVars.class}) {
for(Field field : clazz.getDeclaredFields()) {

View file

@ -279,6 +279,8 @@ public class CommandEnvironment {
this.registerExecutable(new CommandEffect());
this.registerExecutable(new CommandExterminatus());
this.registerExecutable(new CommandReset());
this.registerExecutable(new CommandTick());
this.registerExecutable(new CommandFreeze());
this.registerExecutable(new CommandSet());
}

View file

@ -0,0 +1,22 @@
package server.command.commands;
import common.vars.Vars;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.vars.SVars;
public class CommandFreeze extends Command {
public CommandFreeze() {
super("freeze");
}
public void exec(CommandEnvironment env, Executor exec) {
if(env.getServer().unsetVariableOverride("freeze")) {
exec.log("Die Welt ist jetzt nicht mehr eingefroren");
return;
}
env.getServer().setVariableOverride("freeze", () -> {SVars.randomTick = 0; SVars.boltChance = 0; SVars.weatherTick = 0; SVars.weatherChance = 0; SVars.tickSpawn = false; Vars.dayCycle = false; Vars.mobTick = false; Vars.liquidPhysics = false; Vars.blockGravity = false; Vars.fire = false;});
exec.log("Welt wurde eingefroren");
}
}

View file

@ -39,7 +39,7 @@ public class CommandSv extends Command {
return null;
}
private String formatVariable(String name, SVar sv, String separator, boolean censor) {
private String formatVariable(String name, SVar sv, String override, String separator, boolean censor) {
String value = sv.get();
StringBuilder sb = new StringBuilder(Color.YELLOW + name + Color.GRAY + " " + separator + " ");
if(sv.noDef && sv.def.equals(value))
@ -52,6 +52,8 @@ public class CommandSv extends Command {
sb.append(((sv.type == ValueType.BOOLEAN ? (value.equals("true") ? Color.GREEN : Color.RED) : Color.BLUE)) + value);
if(!sv.def.equals(value))
sb.append(Color.GRAY + " (" + (sv.noDef ? Color.DARK_GRAY + "[ - ]" : Color.BROWN + sv.def) + Color.GRAY + ")");
if(override != null)
sb.append(Color.GRAY + " [" + Color.RED + override + Color.GRAY + "]");
return sb.toString();
}
@ -60,7 +62,7 @@ public class CommandSv extends Command {
if(value != null)
throw new RunException("Kann keinen Wert ohne eine Variable angeben");
for(Entry<String, SVar> entry : env.getServer().getVariables().entrySet()) {
exec.log(this.formatVariable(entry.getKey(), entry.getValue(), "=", true));
exec.log(this.formatVariable(entry.getKey(), entry.getValue(), env.getServer().getVariableOverride(entry.getKey()), "=", true));
}
exec.log(Color.GREEN + "SVARs insgesamt registriert: %d", env.getServer().getVariables().size());
return null;
@ -93,11 +95,16 @@ public class CommandSv extends Command {
throw new RunException(Color.DARK_RED + "'%s' ist keine gültige Zahl", value);
}
}
String override = env.getServer().removeVariableOverride(variable);
if(override != null)
exec.log(Color.YELLOW + "Überschreibung %s für %s entfernt", override, variable);
if(override == null || !value.equals(sv.get())) {
sv.set(value, false, true);
if(sv.sync)
env.getServer().sendPacket(new SPacketServerConfig(variable, sv.getRaw()));
}
exec.log(this.formatVariable(variable, sv, value == null ? "=" : "->", false));
}
exec.log(this.formatVariable(variable, sv, env.getServer().getVariableOverride(variable), value == null ? "=" : "->", false));
return sv.noDef && sv.def.equals(sv.get()) ? null : sv.get();
}
}

View file

@ -0,0 +1,26 @@
package server.command.commands;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
public class CommandTick extends Command {
public CommandTick() {
super("tick");
this.setParamsOptional();
this.addDouble("target", 2.0, 10000.0);
}
public void exec(CommandEnvironment env, Executor exec, Double target) {
if(target != null) {
float last = env.getServer().getTpsTarget();
env.getServer().setTpsTarget(target.floatValue());
exec.log("Soll-Tick-Geschwindigkeit von %.1f T/s auf %.1f T/s gesetzt", last, env.getServer().getTpsTarget());
}
else {
float avg = env.getServer().getAverageTps();
exec.log("Aktuelle Soll-Tick-Geschwindigkeit beträgt %.1f T/s, es werden %.2f T/s bei durchschnittlich %.2f ms erreicht (potenziell %.2f T/s)", env.getServer().getTpsTarget(), env.getServer().getTpsRate(), avg, avg > 0.0f ? 1000.0f / avg : Float.POSITIVE_INFINITY);
}
}
}