login + network changes, add forms

This commit is contained in:
Sen 2025-05-14 14:58:06 +02:00
parent 111226fe28
commit eba8f6ea98
44 changed files with 894 additions and 224 deletions

View file

@ -15,6 +15,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
@ -36,6 +37,7 @@ import common.init.Config;
import common.init.EntityRegistry;
import common.init.Registry;
import common.init.UniverseRegistry;
import common.init.Config.ValueType;
import common.log.Log;
import common.nbt.NBTLoader;
import common.nbt.NBTTagCompound;
@ -69,7 +71,6 @@ import common.util.ExtMath;
import common.util.LazyLoadBase;
import common.util.PortalType;
import common.util.Position;
import common.util.Tuple;
import common.util.Util;
import common.util.WorldPos;
import common.world.World;
@ -90,6 +91,7 @@ import server.biome.Biome;
import server.clipboard.ReorderRegistry;
import server.clipboard.RotationRegistry;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.command.FixedExecutor;
import server.network.HandshakeHandler;
import server.network.Player;
@ -121,10 +123,11 @@ public final class Server implements IThreadListener {
private WorldServer space;
private ChannelFuture endpoint;
private boolean running = true;
private boolean stopped;
private boolean started;
private String endMessage = "Server beendet";
private long currentTime = System.nanoTime() / 1000L;
private long tpsTarget;
@ -333,6 +336,90 @@ public final class Server implements IThreadListener {
}
}
public boolean setVar(Executor exec, String line) {
if(line.length() < 1) {
for(Entry<String, Config.Value> entry : Config.VARS.entrySet()) {
Config.Value cvar = entry.getValue();
String v = cvar.getValue();
String comp = TextColor.YELLOW + entry.getKey() + TextColor.GRAY + " = ";
if(entry.getKey().equals("password") && !v.isEmpty())
comp += TextColor.NEON + "'****'";
else if(cvar.type == ValueType.STRING)
comp += TextColor.NEON + "'" + v + "'";
else
comp += ((cvar.type == ValueType.BOOLEAN ? (v.equals("true") ? TextColor.GREEN : TextColor.RED) : TextColor.BLUE)) + v;
if(!cvar.def.equals(v)) {
comp += TextColor.GRAY + " (" + TextColor.BROWN + cvar.def + TextColor.GRAY + ")";
}
exec.logConsole(comp);
}
exec.logConsole(TextColor.GREEN + "SVARs insgesamt registriert: %d", Config.VARS.size());
return true;
}
line = line.trim();
String[] args = /* line.isEmpty() ? new String[0] : */ line.split(" ", -1);
if(args.length == 1) {
// case 0:
// break;
// case 1:
Config.Value cfg = Config.VARS.get(args[0]);
if(cfg == null)
return false;
String v = cfg.getValue();
String comp = TextColor.YELLOW + args[0] + TextColor.GRAY + " = ";
if(cfg.type == ValueType.STRING)
comp += TextColor.NEON + "'" + v + "'";
else
comp += ((cfg.type == ValueType.BOOLEAN ? (v.equals("true") ? TextColor.GREEN : TextColor.RED) : TextColor.BLUE)) + v;
if(!cfg.def.equals(v))
comp += TextColor.GRAY + " (" + TextColor.BROWN + cfg.def + TextColor.GRAY + ")";
exec.logConsole(comp);
// break;
// default:
}
else {
Config.Value cv = Config.VARS.get(args[0]);
if(cv == null)
return false;
String value = args[1];
if(cv.type == ValueType.STRING && "\"\"".equals(value)) {
value = "";
}
// else if(cv.type == ValueType.BOOLEAN && "toggle".equalsIgnoreCase(value)) {
// value = "" + !Boolean.parseBoolean(cv.getValue());
// }
// else
if(cv.type == ValueType.BOOLEAN && !"true".equals(value) && !"false".equals(value)) {
if(!value.equalsIgnoreCase("true") && !value.equalsIgnoreCase("false")) {
exec.logConsole(TextColor.DRED + "'%s' ist nicht 'true' oder 'false'", value);
return true;
}
value = value.toLowerCase();
}
if(cv.type == ValueType.INTEGER) {
try {
Integer.parseInt(value);
}
catch(NumberFormatException e) {
exec.logConsole(TextColor.DRED + "'%s' ist keine gültige Zahl", value);
return true;
}
}
else if(cv.type == ValueType.FLOAT) {
try {
Float.parseFloat(value);
}
catch(NumberFormatException e) {
exec.logConsole(TextColor.DRED + "'%s' ist keine gültige Zahl", value);
return true;
}
}
Config.set(args[0], value, true);
exec.logConsole(TextColor.YELLOW + "%s" + TextColor.GRAY + " -> " + ((cv.type == ValueType.BOOLEAN ? (cv.getValue().equals("true") ? TextColor.GREEN : TextColor.RED) : (cv.type == ValueType.STRING ? TextColor.NEON : TextColor.BLUE))) + "%s", args[0], cv.type == ValueType.STRING ? ("'" + cv.getValue() + "'") : cv.getValue());
}
return true;
}
public void run(int port) {
long time = System.currentTimeMillis();
Log.JNI.info("Starte " + Config.NAME + " Server Version " + Config.VERSION);
@ -407,17 +494,12 @@ public final class Server implements IThreadListener {
}
if(line == null)
break;
if(line.startsWith("#")) {
line = line.substring(1);
Tuple<String, String> data = Util.getKeyValue(line);
if(data.first.equals("end"))
Server.this.shutdown();
continue;
}
final String cmd = line;
Server.this.schedule(new Runnable() {
public void run() {
Server.this.scriptEnv.execute(cmd, new FixedExecutor(Server.this, "#con", "KONSOLE", null));
FixedExecutor exec = new FixedExecutor(Server.this, "#con", "KONSOLE", null);
if(!Server.this.setVar(exec, cmd))
Server.this.scriptEnv.execute(cmd, exec);
}
});
}
@ -770,9 +852,9 @@ public final class Server implements IThreadListener {
if(!Config.register)
return "Anmeldung neuer Accounts ist auf diesem Server deaktiviert (Whitelisted)";
if(loginPass.length() == 0)
return "Ein neues Passwort ist erforderlich um diesen Server zu betreten (mindestens 8 Zeichen)";
if(loginPass.length() < 8)
return "Passwort ist zu kurz, mindestens 8 Zeichen";
return "Ein neues Passwort ist erforderlich um diesen Server zu betreten (mindestens " + Config.minPassLength + " Zeichen)";
if(loginPass.length() < Config.minPassLength)
return "Passwort ist zu kurz, mindestens " + Config.minPassLength + " Zeichen";
conn.setPassword(loginPass);
Log.JNI.info(loginUser + " registrierte sich mit Passwort");
}
@ -1135,42 +1217,12 @@ public final class Server implements IThreadListener {
player.connection.setPlayerHealthUpdated();
player.connection.sendPacket(new SPacketHeldItemChange(player.inventory.currentItem));
}
private void setLanEndpoint(int port) throws IOException {
synchronized(this.serverThread) {
if(this.endpoint != null)
this.unsetLanEndpoint();
// throw new IllegalStateException("Eingangspunkt bereits gesetzt");
Log.JNI.info("Öffne Port %d auf 0.0.0.0 (Timeout %ds)", port, Config.timeout);
this.endpoint = ((ServerBootstrap)((ServerBootstrap)(new ServerBootstrap()).channel(NioServerSocketChannel.class)).childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) throws Exception {
try {
channel.config().setOption(ChannelOption.TCP_NODELAY, Boolean.valueOf(true));
}
catch(ChannelException e) {
}
channel.pipeline().addLast((String)"timeout", (ChannelHandler)(new ReadTimeoutHandler(Config.timeout)))
.addLast((String)"splitter", (ChannelHandler)(new PacketSplitter()))
.addLast((String)"decoder", (ChannelHandler)(new PacketDecoder(true)))
.addLast((String)"prepender", (ChannelHandler)(new PacketPrepender()))
.addLast((String)"encoder", (ChannelHandler)(new PacketEncoder(false)));
NetConnection manager = new NetConnection();
Server.this.clients.add(manager);
channel.pipeline().addLast((String)"packet_handler", (ChannelHandler)manager);
manager.setNetHandler(new HandshakeHandler(Server.this, manager));
}
}).group(SERVER_NIO_EVENTLOOP.getValue()).localAddress((InetAddress)null, port)).bind().syncUninterruptibly();
}
}
private void unsetLanEndpoint() {
for(Player conn : Lists.newArrayList(this.players)) {
conn.disconnect();
}
this.terminateEndpoint();
}
private void terminateEndpoint() {
private void terminateEndpoint(String message) {
if(this.started)
for(Player conn : Lists.newArrayList(this.players)) {
conn.disconnect(message);
}
synchronized(this.serverThread) {
if(this.endpoint != null) {
Log.JNI.info("Schließe Port");
@ -1201,7 +1253,7 @@ public final class Server implements IThreadListener {
}
catch(Exception e) {
Log.JNI.error(e, "Konnte Paket von " + manager.getCutAddress() + " nicht verarbeiten");
manager.sendPacket(new SPacketDisconnect(), new GenericFutureListener<Future<? super Void>>() {
manager.sendPacket(new SPacketDisconnect(e.getMessage()), new GenericFutureListener<Future<? super Void>>() {
public void operationComplete(Future<? super Void> future) throws Exception {
manager.closeChannel("Fehlerhaftes Datenpaket");
}
@ -1227,11 +1279,7 @@ public final class Server implements IThreadListener {
this.setProgress(-1);
this.setMessage("Stoppe server");
Log.JNI.info("Beende Server");
if(this.started)
for(Player conn : Lists.newArrayList(this.players)) {
conn.disconnect();
}
this.terminateEndpoint();
this.terminateEndpoint(this.endMessage);
if(this.started) {
Log.JNI.info("Speichere Spieler");
this.saveAllPlayerData(true);
@ -1243,34 +1291,46 @@ public final class Server implements IThreadListener {
}
public void bind(int port) {
// this.schedule(new Runnable() {
// public void run() {
if(port >= 0) {
try {
Server.this.setLanEndpoint(port);
synchronized(this.serverThread) {
if(port >= 0) {
try {
if(this.endpoint != null)
this.terminateEndpoint("Wechsele auf Port " + port);
// throw new IllegalStateException("Eingangspunkt bereits gesetzt");
Log.JNI.info("Öffne Port %d auf 0.0.0.0 (Timeout %ds)", port, Config.timeout);
this.endpoint = ((ServerBootstrap)((ServerBootstrap)(new ServerBootstrap()).channel(NioServerSocketChannel.class)).childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel channel) throws Exception {
try {
channel.config().setOption(ChannelOption.TCP_NODELAY, Boolean.valueOf(true));
}
catch(ChannelException e) {
}
channel.pipeline().addLast((String)"timeout", (ChannelHandler)(new ReadTimeoutHandler(Config.timeout)))
.addLast((String)"splitter", (ChannelHandler)(new PacketSplitter()))
.addLast((String)"decoder", (ChannelHandler)(new PacketDecoder(true)))
.addLast((String)"prepender", (ChannelHandler)(new PacketPrepender()))
.addLast((String)"encoder", (ChannelHandler)(new PacketEncoder(false)));
NetConnection manager = new NetConnection();
Server.this.clients.add(manager);
channel.pipeline().addLast((String)"packet_handler", (ChannelHandler)manager);
manager.setNetHandler(new HandshakeHandler(Server.this, manager));
}
}).group(SERVER_NIO_EVENTLOOP.getValue()).localAddress((InetAddress)null, port)).bind().syncUninterruptibly();
}
catch(Throwable e) {
Log.JNI.error(e, "**** KONNTE NICHT AN PORT " + port + " ANBINDEN!");
}
}
catch(IOException e) {
Log.JNI.error(e, "**** KONNTE NICHT AN PORT " + port + " ANBINDEN!");
else {
if(this.endpoint != null)
this.terminateEndpoint("Trenne Verbindung");
}
}
else {
Server.this.unsetLanEndpoint();
}
// }
// });
}
public void shutdown() {
// Futures.getUnchecked(this.schedule(new Runnable() {
// public void run() {
// for(Player conn : Lists.newArrayList(Server.this.players)) { // = Server.this.getPlayer(Server.this.owner);
// // if(conn != null)
// if(conn.isLocal())
// Server.this.removePlayer(conn);
// }
// }
// }));
public void shutdown(String message) {
this.running = false;
this.endMessage = message;
}
public String getInfo() {

View file

@ -88,7 +88,7 @@ public abstract class ArgumentParser {
public abstract Object parse(CommandEnvironment env, String input);
public abstract Object getDefault(CommandEnvironment env);
public abstract Collection<String> getCompletions(CommandEnvironment env);
public abstract Class<?> getTypeClass();
public abstract Class<?> getTypeClass(boolean required);
public final String getName() {
return this.name;

View file

@ -5,7 +5,7 @@ public class BooleanParser extends EnumParser<Boolean> {
super(name, Boolean.class, def, true, false);
}
public Class<?> getTypeClass() {
return this.hasDefault() ? boolean.class : Boolean.class;
public Class<?> getTypeClass(boolean required) {
return this.hasDefault() || required ? boolean.class : Boolean.class;
}
}

View file

@ -54,7 +54,7 @@ public class CachedExecutable {
continue;
}
for(ArgumentParser parser : param.getParsers()) {
classes.add(parser.getTypeClass());
classes.add(parser.getTypeClass(param.isRequired()));
}
}
Method method;

View file

@ -192,6 +192,14 @@ public abstract class Command implements Executable {
protected Command addString(String name, boolean allowEmpty, StringCompleter completer) {
return this.addParameter(new StringParser(name, null, allowEmpty, null, null, null, completer));
}
protected Command addString(String name, String def, boolean allowEmpty, Object ... completions) {
return this.addParameter(new StringParser(name, def, allowEmpty, null, null, null, completions));
}
protected Command addString(String name, String def, boolean allowEmpty, StringCompleter completer) {
return this.addParameter(new StringParser(name, def, allowEmpty, null, null, null, completer));
}
public Map<String, Parameter> getParameters() {
return this.parameters;

View file

@ -19,9 +19,12 @@ import server.command.commands.CommandKick;
import server.command.commands.CommandMessage;
import server.command.commands.CommandMilk;
import server.command.commands.CommandOfflinetp;
import server.command.commands.CommandPasswd;
import server.command.commands.CommandPotion;
import server.command.commands.CommandRebind;
import server.command.commands.CommandRemove;
import server.command.commands.CommandRevoke;
import server.command.commands.CommandShutdown;
import server.command.commands.CommandSpawn;
import server.command.commands.CommandTele;
import server.command.commands.CommandTime;
@ -269,6 +272,9 @@ public class CommandEnvironment {
this.registerExecutable(new CommandWeather());
this.registerExecutable(new CommandKick());
this.registerExecutable(new CommandMessage());
this.registerExecutable(new CommandShutdown());
this.registerExecutable(new CommandRebind());
this.registerExecutable(new CommandPasswd());
this.registerExecutable(new CommandHelp(this));
}

View file

@ -43,7 +43,7 @@ public class DimensionParser extends CompletingParser {
return UniverseRegistry.getWorldNames();
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return Dimension.class;
}
}

View file

@ -75,8 +75,8 @@ public class DoubleParser extends DefaultingParser {
return (Double)super.getDefault(env);
}
public Class<?> getTypeClass() {
return this.hasDefault() ? double.class : Double.class;
public Class<?> getTypeClass(boolean required) {
return this.hasDefault() || required ? double.class : Double.class;
}
public Collection<String> getCompletions(CommandEnvironment env) {

View file

@ -129,7 +129,7 @@ public class EntityListParser extends EntityParser {
return comp;
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return List.class;
}
}

View file

@ -54,7 +54,7 @@ public class EntityParser extends PlayerEntityParser {
return comp;
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return this.livingOnly ? EntityLiving.class : Entity.class;
}
}

View file

@ -44,7 +44,7 @@ public class EnumParser<T> extends DefaultingParser {
return this.selections[id];
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return this.clazz;
}
}

View file

@ -3,6 +3,7 @@ package server.command;
import common.entity.Entity;
import common.util.BlockPos;
import common.util.Position;
import server.network.Player;
public interface Executor {
void logConsole(String msg);
@ -12,6 +13,14 @@ public interface Executor {
Entity getPointedEntity();
BlockPos getPointedPosition();
default boolean isConsole() {
return false;
}
default boolean isPlayer() {
return this instanceof Player;
}
default void logConsole(String fmt, Object ... args) {
this.logConsole(String.format(fmt, args));
}

View file

@ -50,4 +50,8 @@ public class FixedExecutor implements Executor {
public BlockPos getPointedPosition() {
return null;
}
public boolean isConsole() {
return true;
}
}

View file

@ -33,7 +33,7 @@ public class IntParser extends DefaultingParser {
return value;
}
public Class<?> getTypeClass() {
return this.hasDefault() ? int.class : Integer.class;
public Class<?> getTypeClass(boolean required) {
return this.hasDefault() || required ? int.class : Integer.class;
}
}

View file

@ -31,7 +31,7 @@ public class LongParser extends DefaultingParser {
return value;
}
public Class<?> getTypeClass() {
return this.hasDefault() ? long.class : Long.class;
public Class<?> getTypeClass(boolean required) {
return this.hasDefault() || required ? long.class : Long.class;
}
}

View file

@ -46,7 +46,7 @@ public class PlayerEntityListParser extends PlayerEntityParser {
return comp;
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return List.class;
}
}

View file

@ -21,7 +21,7 @@ public class PlayerEntityParser extends PlayerParser {
return net == null ? null : net.getPresentEntity();
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return EntityNPC.class;
}
}

View file

@ -39,7 +39,7 @@ public class PlayerListParser extends PlayerParser {
return comp;
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return List.class;
}
}

View file

@ -20,14 +20,14 @@ public class PlayerParser extends CompletingParser {
}
public Object getDefault(CommandEnvironment env) {
return this.useSender && env.getExecutor() instanceof Player ? (Player)env.getExecutor() : null;
return this.useSender && env.getExecutor().isPlayer() ? (Player)env.getExecutor() : null;
}
public Collection<String> getCompletions(CommandEnvironment env) {
return env.getServer().getAllUsernames();
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return Player.class;
}
}

View file

@ -53,7 +53,7 @@ public class StringParser extends DefaultingParser {
return input;
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return String.class;
}

View file

@ -20,7 +20,7 @@ public class TagParser extends DefaultingParser {
return value;
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return NBTTagCompound.class;
}
}

View file

@ -42,7 +42,7 @@ public class WorldParser extends DimensionParser {
return super.getCompletions(env);
}
public Class<?> getTypeClass() {
public Class<?> getTypeClass(boolean required) {
return WorldServer.class;
}
}

View file

@ -11,16 +11,16 @@ public class CommandKick extends Command {
super("kick");
this.addPlayer("player", false);
this.setParamsOptional();
this.addString("message", "Du wurdest vom Server geworfen", false);
}
public void exec(CommandEnvironment env, Executor exec, Player player) {
if(!(exec instanceof Player))
throw new RunException("Dieser Befehl kann nur von Spielern ausgeführt werden");
else if(player == exec)
public void exec(CommandEnvironment env, Executor exec, Player player, String message) {
if(player == exec)
throw new RunException("Du kannst nicht dich nicht selbst vom Server werfen");
else if(player.getAdmin())
throw new RunException("%s ist ein Admin", player.getUser());
player.disconnect();
player.disconnect(message);
exec.logConsole("%s wurde vom Server geworfen", player.getUser());
}
}

View file

@ -0,0 +1,64 @@
package server.command.commands;
import common.color.TextColor;
import common.init.Config;
import common.network.IPlayer;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.command.RunException;
import server.network.Player;
import server.util.Form;
public class CommandPasswd extends Command {
public CommandPasswd() {
super("passwd");
this.addPlayer("player", true);
this.setParamsOptional();
this.addString("password", false);
}
public void exec(CommandEnvironment env, Executor exec, Player player, String password) {
if(exec.isPlayer()) {
if(password != null)
throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden");
if(player.getAdmin() && player != exec)
throw new RunException("%s ist ein Admin", player.getUser());
((Player)exec).displayForm(new Form() {
private Field checkField;
private Field passwordField;
private Field confirmField;
protected void init() {
this.checkField = player != exec ? null : this.addField("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, "");
this.passwordField = this.addField("Neues Passwort", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
this.confirmField = this.addField("Passwort bestätigen", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
}
public String getTitle() {
return "Passwort für " + player.getUser() + " ändern";
}
protected void accept() {
if(this.checkField != null && !this.checkField.get().equals(player.getPassword())) {
exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben");
return;
}
if(!this.passwordField.get().equals(this.confirmField.get())) {
exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein");
return;
}
player.setPassword(this.passwordField.get());
exec.logConsole(TextColor.GREEN + "Passwort" + (player != exec ? " für %s" : "") + " gesetzt", player.getUser());
}
});
}
else if(exec.isConsole()) {
if(password == null)
throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden");
player.setPassword(password);
exec.logConsole(TextColor.GREEN + "Passwort für %s gesetzt", player.getUser());
}
}
}

View file

@ -0,0 +1,17 @@
package server.command.commands;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
public class CommandRebind extends Command {
public CommandRebind() {
super("rebind");
this.addInt("port", 1024, 65535);
}
public void exec(CommandEnvironment env, Executor exec, int port) {
env.getServer().bind(port);
}
}

View file

@ -14,7 +14,7 @@ public class CommandRevoke extends Command {
}
public void exec(CommandEnvironment env, Executor exec, Player player) {
if(exec instanceof Player)
if(!exec.isConsole())
throw new RunException("Dieser Befehl kann nur der Konsole ausgeführt werden");
// else if(player == exec)
// throw new RunException("Du kannst nicht deinen eigenen Admin-Status entfernen");

View file

@ -0,0 +1,18 @@
package server.command.commands;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
public class CommandShutdown extends Command {
public CommandShutdown() {
super("shutdown");
this.setParamsOptional();
this.addString("message", "Server beendet", false);
}
public void exec(CommandEnvironment env, Executor exec, String message) {
env.getServer().shutdown(message);
}
}

View file

@ -53,7 +53,7 @@ public class CommandSpawn extends Command {
}
world.strikeLightning(pos.xCoord, pos.yCoord, pos.zCoord, color,
tag != null && tag.hasKey("damage", 3) ? tag.getInteger("damage") : 0, tag != null && tag.hasKey("fire", 1) && tag.getBoolean("fire"),
exec instanceof Player && tag != null && tag.hasKey("summoned", 1) && tag.getBoolean("summoned") ? ((Player)exec).getPresentEntity() : null);
exec.isPlayer() && tag != null && tag.hasKey("summoned", 1) && tag.getBoolean("summoned") ? ((Player)exec).getPresentEntity() : null);
}
exec.logConsole("%sBlitz bei %d, %d, %d in %s erschaffen", count == 1 ? "" : (count + "x "), (int)pos.xCoord, (int)pos.yCoord, (int)pos.zCoord, world.dimension.getFormattedName(false));
return null;

View file

@ -4,7 +4,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;
@ -60,6 +59,7 @@ import common.packet.CPacketBreak;
import common.packet.CPacketCheat;
import common.packet.CPacketClick;
import common.packet.CPacketComplete;
import common.packet.CPacketForm;
import common.packet.CPacketInput;
import common.packet.CPacketKeepAlive;
import common.packet.CPacketMessage;
@ -88,6 +88,7 @@ import common.packet.SPacketCharacterList;
import common.packet.SPacketChunkData;
import common.packet.SPacketDestroyEntities;
import common.packet.SPacketDisconnect;
import common.packet.SPacketDisplayForm;
import common.packet.SPacketKeepAlive;
import common.packet.SPacketLoading;
import common.packet.SPacketMapChunkBulk;
@ -132,6 +133,7 @@ import server.clipboard.RotationRegistry;
import server.clipboard.RotationValue;
import server.clipboard.Vector;
import server.command.Executor;
import server.util.Form;
import server.world.Region;
import server.world.WorldServer;
@ -165,6 +167,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
private double lastPosZ;
private boolean hasMoved = true;
private boolean charEditor = true;
private Form form;
private boolean admin;
private int ping;
@ -200,6 +203,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
private float lastHealth = -1.0E8F;
private int lastExperience = -99999999;
private int currentWindowId;
private int currentFormId;
private int pointedEntity;
private BlockPos pointedPosition;
@ -410,6 +414,11 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
{
this.currentWindowId = this.currentWindowId % 100 + 1;
}
private void getNextFormId()
{
this.currentFormId = this.currentFormId % 100 + 1;
}
public void displayTradeGui(EntityNPC npc)
{
@ -1520,9 +1529,10 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
this.characters.set(this.selected, tag);
}
public void disconnect()
public void disconnect(String message)
{
this.connection.sendPacket(new SPacketDisconnect(), new GenericFutureListener < Future <? super Void >> ()
Log.JNI.info("Trenne %s: %s", this.user, message);
this.connection.sendPacket(new SPacketDisconnect(message), new GenericFutureListener < Future <? super Void >> ()
{
public void operationComplete(Future <? super Void > p_operationComplete_1_) throws Exception
{
@ -1676,87 +1686,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
private boolean setVar(String line) {
if(!this.isAdmin())
return false;
if(line.length() < 1) {
for(Entry<String, Config.Value> entry : Config.VARS.entrySet()) {
Config.Value cvar = entry.getValue();
String v = cvar.getValue();
String comp = TextColor.YELLOW + entry.getKey() + TextColor.GRAY + " = ";
if(entry.getKey().equals("password") && !v.isEmpty())
comp += TextColor.NEON + "'****'";
else if(cvar.type == ValueType.STRING)
comp += TextColor.NEON + "'" + v + "'";
else
comp += ((cvar.type == ValueType.BOOLEAN ? (v.equals("true") ? TextColor.GREEN : TextColor.RED) : TextColor.BLUE)) + v;
if(!cvar.def.equals(v)) {
comp += TextColor.GRAY + " (" + TextColor.BROWN + cvar.def + TextColor.GRAY + ")";
}
this.addConsole(comp);
}
this.addConsole(TextColor.GREEN + "SVARs insgesamt registriert: %d", Config.VARS.size());
return true;
}
line = line.trim();
String[] args = /* line.isEmpty() ? new String[0] : */ line.split(" ", -1);
if(args.length == 1) {
// case 0:
// break;
// case 1:
Config.Value cfg = Config.VARS.get(args[0]);
if(cfg == null)
return false;
String v = cfg.getValue();
String comp = TextColor.YELLOW + args[0] + TextColor.GRAY + " = ";
if(cfg.type == ValueType.STRING)
comp += TextColor.NEON + "'" + v + "'";
else
comp += ((cfg.type == ValueType.BOOLEAN ? (v.equals("true") ? TextColor.GREEN : TextColor.RED) : TextColor.BLUE)) + v;
if(!cfg.def.equals(v))
comp += TextColor.GRAY + " (" + TextColor.BROWN + cfg.def + TextColor.GRAY + ")";
this.addConsole(comp);
// break;
// default:
}
else {
Config.Value cv = Config.VARS.get(args[0]);
if(cv == null)
return false;
String value = args[1];
if(cv.type == ValueType.STRING && "\"\"".equals(value)) {
value = "";
}
// else if(cv.type == ValueType.BOOLEAN && "toggle".equalsIgnoreCase(value)) {
// value = "" + !Boolean.parseBoolean(cv.getValue());
// }
// else
if(cv.type == ValueType.BOOLEAN && !"true".equals(value) && !"false".equals(value)) {
if(!value.equalsIgnoreCase("true") && !value.equalsIgnoreCase("false")) {
this.addConsole(TextColor.DRED + "'%s' ist nicht 'true' oder 'false'", value);
return true;
}
value = value.toLowerCase();
}
if(cv.type == ValueType.INTEGER) {
try {
Integer.parseInt(value);
}
catch(NumberFormatException e) {
this.addConsole(TextColor.DRED + "'%s' ist keine gültige Zahl", value);
return true;
}
}
else if(cv.type == ValueType.FLOAT) {
try {
Float.parseFloat(value);
}
catch(NumberFormatException e) {
this.addConsole(TextColor.DRED + "'%s' ist keine gültige Zahl", value);
return true;
}
}
Config.set(args[0], value, true);
this.addConsole(TextColor.YELLOW + "%s" + TextColor.GRAY + " -> " + ((cv.type == ValueType.BOOLEAN ? (cv.getValue().equals("true") ? TextColor.GREEN : TextColor.RED) : (cv.type == ValueType.STRING ? TextColor.NEON : TextColor.BLUE))) + "%s", args[0], cv.type == ValueType.STRING ? ("'" + cv.getValue() + "'") : cv.getValue());
}
return true;
return this.server.setVar(this, line);
}
public void setAdmin(boolean admin) {
@ -3082,6 +3012,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
// this.signCommand = null;
// }
tileentitysign.setPlayer(null);
tileentitysign.markDirty();
worldserver.markBlockForUpdate(blockpos);
}
@ -3147,6 +3078,20 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
}
}
}
public void processForm(CPacketForm packet) {
NetHandler.checkThread(packet, this, this.server);
if(this.charEditor || this.form == null || packet.getId() != this.currentFormId)
return;
this.form.accept(packet.getData());
this.form = null;
}
public void displayForm(Form form) {
this.form = form;
this.getNextFormId();
this.sendPacket(new SPacketDisplayForm(this.currentFormId, form.getTitle(), form.getInputList()));
}
public Entity getPointedEntity() {
return this.pointedEntity != -1 && this.entity != null ? this.entity.worldObj.getEntityByID(this.pointedEntity) : null;

View file

@ -0,0 +1,179 @@
package server.util;
import java.util.List;
import common.collect.Lists;
import common.util.Displayable;
import common.util.Triplet;
public abstract class Form {
private abstract class FormElement {
protected final String name;
protected FormElement(String name) {
this.name = name;
}
protected abstract Object getInputData();
protected abstract int getInputParameter();
protected abstract boolean acceptValue(Object obj);
}
protected class Toggle extends FormElement {
private boolean value;
protected Toggle(String name, boolean value) {
super(name);
this.value = value;
}
protected Object getInputData() {
return this.value;
}
protected int getInputParameter() {
return 0;
}
protected boolean acceptValue(Object obj) {
if(obj instanceof Boolean)
this.value = (Boolean)obj;
return obj instanceof Boolean;
}
public boolean get() {
return this.value;
}
}
protected class Switch<T> extends FormElement {
private final T[] values;
private final int def;
private T value;
protected Switch(String name, T[] values, T value) {
super(name);
this.values = values;
this.value = value;
int def = 0;
for(int z = 0; z < values.length; z++) {
if(values[z] == value) {
def = z;
break;
}
}
this.def = def;
}
protected Object getInputData() {
String[] strs = new String[this.values.length];
for(int z = 0; z < strs.length; z++) {
strs[z] = this.values[z] instanceof Displayable ? ((Displayable)this.values[z]).getDisplay() : String.valueOf(this.values[z]);
}
return strs;
}
protected int getInputParameter() {
return this.def;
}
protected boolean acceptValue(Object obj) {
if(obj instanceof Integer && (Integer)obj >= 0 && (Integer)obj < this.values.length) {
this.value = this.values[(Integer)obj];
return true;
}
return false;
}
public T get() {
return this.value;
}
}
protected class Field extends FormElement {
private final int minLength;
private final int maxLength;
private String value;
protected Field(String name, String value, int min, int max) {
super(name);
this.value = value;
this.minLength = min;
this.maxLength = max;
}
protected Object getInputData() {
return this.value;
}
protected int getInputParameter() {
return (this.minLength << 16) | this.maxLength;
}
protected boolean acceptValue(Object obj) {
if(obj instanceof String && ((String)obj).length() >= this.minLength && ((String)obj).length() <= this.maxLength) {
this.value = (String)obj;
return true;
}
return false;
}
public String get() {
return this.value;
}
}
private final List<FormElement> inputs = Lists.newArrayList();
public Form() {
this.init();
}
private <T extends FormElement> T add(T elem) {
this.inputs.add(elem);
return elem;
}
protected Toggle addToggle(String name, boolean def) {
return this.add(new Toggle(name, def));
}
protected <T> Switch<T> addSwitch(String name, T def, T ... values) {
return this.add(new Switch<T>(name, values, def));
}
protected Field addField(String name, int minLength, int maxLength, String def) {
return this.add(new Field(name, def, minLength, maxLength));
}
public abstract String getTitle();
protected abstract void init();
protected abstract void accept();
protected void cancel() {
}
public final Triplet<String, Object, Integer>[] getInputList() {
Triplet<String, Object, Integer>[] data = new Triplet[this.inputs.size()];
for(int z = 0; z < data.length; z++) {
data[z] = new Triplet<String, Object, Integer>(this.inputs.get(z).name, this.inputs.get(z).getInputData(), this.inputs.get(z).getInputParameter());
}
return data;
}
public final void accept(Object[] data) {
if(data == null || data.length != this.inputs.size()) {
this.cancel();
return;
}
for(int z = 0; z < data.length; z++) {
if(!this.inputs.get(z).acceptValue(data[z])) {
this.cancel();
return;
}
}
this.accept();
}
}