add registration via command, password fields

This commit is contained in:
Sen 2025-05-15 21:25:28 +02:00
parent e4034898b9
commit 9077451c08
11 changed files with 232 additions and 15 deletions

View file

@ -0,0 +1,27 @@
package client.gui.element;
import client.gui.Font;
import client.renderer.Drawing;
import common.util.Util;
public class PasswordBox extends Textbox {
public PasswordBox(int x, int y, int w, int h, int cap, Callback callback, String text) {
super(x, y, w, h, cap, true, callback, text);
}
protected void drawForeground(int x1, int y1, int x2, int y2) {
Drawing.txt_draw(x1 + this.text_x, y1 + this.text_y,
x1 + this.text_x, y1 + this.text_y,
Integer.MAX_VALUE, Integer.MAX_VALUE, this.enabled ? this.gm.style.text_field : Util.mulColor(this.gm.style.text_field, 0.5f), this.text.isEmpty() ? "" : "****");
}
public void drawOverlay() {
if(Util.ftime() % 1.0f < 0.5f) {
int x1 = this.pos_x + this.margin_x1;
int y1 = this.pos_y + this.margin_y1;
int x2 = this.size_x - (this.margin_x1 + this.margin_x2);
int y2 = this.size_y - (this.margin_y1 + this.margin_y2);
Drawing.drawRect(x1, y1 + (y2 - Font.YGLYPH) / 2, 1, Font.YGLYPH, 0xff000000 | (~Util.mixColor(this.gm.style.field_top, this.gm.style.field_btm)));
}
}
}

View file

@ -6,6 +6,7 @@ import client.gui.element.ActButton.Mode;
import client.gui.element.Element; import client.gui.element.Element;
import client.gui.element.Label; import client.gui.element.Label;
import client.gui.element.NavButton; import client.gui.element.NavButton;
import client.gui.element.PasswordBox;
import client.gui.element.Switch; import client.gui.element.Switch;
import client.gui.element.Textbox; import client.gui.element.Textbox;
import client.gui.element.Textbox.Action; import client.gui.element.Textbox.Action;
@ -56,12 +57,14 @@ public class GuiForm extends Gui implements ActButton.Callback {
} }
else { else {
this.labels[z] = this.add(new Label(0, 50 * z - 20, 300, 20, name, true)); this.labels[z] = this.add(new Label(0, 50 * z - 20, 300, 20, name, true));
this.inputs[z] = this.add(new Textbox(0, 50 * z, 300, 24, Math.min(param & 0xffff, 256), true, new Textbox.Callback() { Textbox.Callback callback = new Textbox.Callback() {
public void use(Textbox elem, Action value) { public void use(Textbox elem, Action value) {
if(value == Action.FOCUS) if(value == Action.FOCUS)
GuiForm.this.labels[index].setText(name); GuiForm.this.labels[index].setText(name);
} }
}, (String)obj)); };
this.inputs[z] = this.add((param & 0x80000000) != 0 ? new PasswordBox(0, 50 * z, 300, 24, Math.min(param & 0xffff, 256), callback, (String)obj) :
new Textbox(0, 50 * z, 300, 24, Math.min(param & 0xffff, 256), true, callback, (String)obj));
} }
} }
this.add(new NavButton(0, 50 * (this.inputs.length + 1), 148, 24, null, "Abbrechen")); this.add(new NavButton(0, 50 * (this.inputs.length + 1), 148, 24, null, "Abbrechen"));
@ -98,7 +101,7 @@ public class GuiForm extends Gui implements ActButton.Callback {
public void use(ActButton elem, Mode action) { public void use(ActButton elem, Mode action) {
for(int z = 0; z < this.inputs.length; z++) { for(int z = 0; z < this.inputs.length; z++) {
if(this.inputs[z] instanceof Textbox) { if(this.inputs[z] instanceof Textbox) {
int min = this.inputData[z].third >> 16; int min = (this.inputData[z].third & 0x7fffffff) >> 16;
String text = this.inputs[z].getText(); String text = this.inputs[z].getText();
if(text.length() < min) { if(text.length() < min) {
if(!GuiForm.this.labels[z].getText().startsWith("" + TextColor.RED)) if(!GuiForm.this.labels[z].getText().startsWith("" + TextColor.RED))

View file

@ -267,7 +267,7 @@ public final class Server implements IThreadListener {
} }
} }
public Position getOfflinePosition(String user) { public NBTTagCompound loadPlayerData(String user) {
if(this.debug || !IPlayer.isValidUser(user)) if(this.debug || !IPlayer.isValidUser(user))
return null; return null;
NBTTagCompound tag = null; NBTTagCompound tag = null;
@ -281,6 +281,28 @@ public final class Server implements IThreadListener {
catch(Exception e) { catch(Exception e) {
Log.JNI.error(e, "Konnte Spielerdaten für " + user + " (offline) nicht laden"); Log.JNI.error(e, "Konnte Spielerdaten für " + user + " (offline) nicht laden");
} }
return tag;
}
public void writePlayerData(String user, NBTTagCompound tag) {
if(this.debug || !IPlayer.isValidUser(user))
return;
try {
File tmp = new File(new File("players"), user + ".nbt.tmp");
File dat = new File(new File("players"), user + ".nbt");
NBTLoader.writeGZip(tag, tmp);
if(dat.exists()) {
dat.delete();
}
tmp.renameTo(dat);
}
catch(Exception e) {
Log.JNI.error(e, "Konnte Spielerdaten für " + user + " (offline) nicht speichern");
}
}
public Position getOfflinePosition(String user) {
NBTTagCompound tag = this.loadPlayerData(user);
if(tag == null) if(tag == null)
return null; return null;
NBTTagList pos = tag.getTagList("Pos", 6); NBTTagList pos = tag.getTagList("Pos", 6);
@ -294,7 +316,7 @@ public final class Server implements IThreadListener {
return new Position(posX, posY, posZ, rotYaw, rotPitch, dimension); return new Position(posX, posY, posZ, rotYaw, rotPitch, dimension);
} }
private void saveAllWorlds(boolean message) { public void saveAllWorlds(boolean message) {
if(this.debug) if(this.debug)
return; return;
if(message) if(message)
@ -672,6 +694,10 @@ public final class Server implements IThreadListener {
return this.worlds; return this.worlds;
} }
public void resetSaveTimer() {
this.saveTimer = 0;
}
public long[] getTickTimes() { public long[] getTickTimes() {
return this.tickTimes; return this.tickTimes;
} }

View file

@ -7,6 +7,7 @@ import java.util.Map;
import common.collect.Lists; import common.collect.Lists;
import common.collect.Maps; import common.collect.Maps;
import common.util.CharValidator;
import common.util.Vec3; import common.util.Vec3;
import common.world.World; import common.world.World;
import server.command.DoubleParser.DefType; import server.command.DoubleParser.DefType;
@ -200,6 +201,10 @@ public abstract class Command implements Executable {
protected Command addString(String name, String def, boolean allowEmpty, StringCompleter completer) { protected Command addString(String name, String def, boolean allowEmpty, StringCompleter completer) {
return this.addParameter(new StringParser(name, def, allowEmpty, null, null, null, completer)); return this.addParameter(new StringParser(name, def, allowEmpty, null, null, null, completer));
} }
protected Command addString(String name, boolean allowEmpty, Integer min, Integer max, CharValidator validator) {
return this.addParameter(new StringParser(name, null, allowEmpty, min, max, validator));
}
public Map<String, Parameter> getParameters() { public Map<String, Parameter> getParameters() {
return this.parameters; return this.parameters;

View file

@ -20,10 +20,13 @@ import server.command.commands.CommandMessage;
import server.command.commands.CommandMilk; import server.command.commands.CommandMilk;
import server.command.commands.CommandOfflinetp; import server.command.commands.CommandOfflinetp;
import server.command.commands.CommandPasswd; import server.command.commands.CommandPasswd;
import server.command.commands.CommandPlayers;
import server.command.commands.CommandPotion; import server.command.commands.CommandPotion;
import server.command.commands.CommandRebind; import server.command.commands.CommandRebind;
import server.command.commands.CommandRegister;
import server.command.commands.CommandRemove; import server.command.commands.CommandRemove;
import server.command.commands.CommandRevoke; import server.command.commands.CommandRevoke;
import server.command.commands.CommandSave;
import server.command.commands.CommandShutdown; import server.command.commands.CommandShutdown;
import server.command.commands.CommandSpawn; import server.command.commands.CommandSpawn;
import server.command.commands.CommandTele; import server.command.commands.CommandTele;
@ -275,6 +278,9 @@ public class CommandEnvironment {
this.registerExecutable(new CommandShutdown()); this.registerExecutable(new CommandShutdown());
this.registerExecutable(new CommandRebind()); this.registerExecutable(new CommandRebind());
this.registerExecutable(new CommandPasswd()); this.registerExecutable(new CommandPasswd());
this.registerExecutable(new CommandPlayers());
this.registerExecutable(new CommandSave());
this.registerExecutable(new CommandRegister());
this.registerExecutable(new CommandHelp(this)); this.registerExecutable(new CommandHelp(this));
} }

View file

@ -31,9 +31,9 @@ public class CommandPasswd extends Command {
private Field confirmField; private Field confirmField;
protected void init() { protected void init() {
this.checkField = player != exec ? null : this.addField("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, ""); this.checkField = player != exec ? null : this.addPassword("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, "");
this.passwordField = this.addField("Neues Passwort", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, ""); this.passwordField = this.addPassword("Neues Passwort", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
this.confirmField = this.addField("Passwort bestätigen", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, ""); this.confirmField = this.addPassword("Passwort bestätigen", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
} }
public String getTitle() { public String getTitle() {
@ -41,7 +41,12 @@ public class CommandPasswd extends Command {
} }
protected void accept() { protected void accept() {
if(this.checkField != null && !this.checkField.get().equals(player.getPassword())) { Player plr = env.getServer().getPlayer(player.getUser());
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec)) {
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
return;
}
if(this.checkField != null && !this.checkField.get().equals(plr.getPassword())) {
exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben"); exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben");
return; return;
} }
@ -49,8 +54,8 @@ public class CommandPasswd extends Command {
exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein"); exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein");
return; return;
} }
player.setPassword(this.passwordField.get()); plr.setPassword(this.passwordField.get());
exec.logConsole(TextColor.GREEN + "Passwort" + (player != exec ? " für %s" : "") + " gesetzt", player.getUser()); exec.logConsole(TextColor.GREEN + "Passwort" + (plr != exec ? " für %s" : "") + " gesetzt", plr.getUser());
} }
}); });
} }

View file

@ -0,0 +1,32 @@
package server.command.commands;
import java.util.List;
import common.color.TextColor;
import common.entity.npc.EntityNPC;
import common.util.ExtMath;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.network.Player;
public class CommandPlayers extends Command {
public CommandPlayers() {
super("players");
this.addFlag("coords", 'c');
}
public void exec(CommandEnvironment env, Executor exec, boolean coords) {
List<Player> players = env.getServer().getPlayers();
if(players.isEmpty()) {
exec.logConsole(TextColor.DGRAY + "Es sind keine Spieler online");
return;
}
exec.logConsole(TextColor.GREEN + "Es " + (players.size() == 1 ? "ist" : "sind") + " " + TextColor.YELLOW + "%d" + TextColor.GREEN + " Spieler online", players.size());
for(Player player : players) {
EntityNPC entity = player.getPresentEntity();
exec.logConsole("%s%s" + TextColor.GRAY + ": '%s" + TextColor.GRAY + "'" + (coords ? " [" + TextColor.ORANGE + "%s @ %d, %d, %d" + TextColor.GRAY + "]" : ""), player.isAdmin() ? TextColor.RED : TextColor.NEON, player.getUser(), entity == null ? TextColor.DGRAY + "<->" : TextColor.ACID + entity.getCommandName(), entity == null ? null : entity.worldObj.dimension.getFormattedName(false), entity == null ? null : ExtMath.floord(entity.posX), entity == null ? null : ExtMath.floord(entity.posY), entity == null ? null : ExtMath.floord(entity.posZ));
}
}
}

View file

@ -0,0 +1,72 @@
package server.command.commands;
import common.color.TextColor;
import common.init.Config;
import common.nbt.NBTTagCompound;
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 CommandRegister extends Command {
public CommandRegister() {
super("register");
this.addString("username", false, null, IPlayer.MAX_USER_LENGTH, IPlayer.VALID_USER);
this.setParamsOptional();
this.addString("password", false);
this.addFlag("admin", 'a');
}
public void exec(CommandEnvironment env, Executor exec, String username, String password, boolean admin) {
Player player = env.getServer().getPlayer(username);
if(player != null)
throw new RunException("Ein Spieler mit diesem Nutzernamen ist bereits online");
NBTTagCompound tag = env.getServer().loadPlayerData(username);
if(tag != null)
throw new RunException("Ein Spieler mit diesem Nutzernamen ist bereits registriert");
if(exec.isPlayer()) {
if(password != null)
throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden");
((Player)exec).displayForm(new Form() {
private Field passwordField;
private Field confirmField;
protected void init() {
this.passwordField = this.addPassword("Passwort", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
this.confirmField = this.addPassword("Passwort bestätigen", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
}
public String getTitle() {
return "Spieler " + username + " registrieren";
}
protected void accept() {
if(!((Player)exec).isAdmin() || env.getServer().getPlayer(username) != null || env.getServer().loadPlayerData(username) != null) {
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
return;
}
if(!this.passwordField.get().equals(this.confirmField.get())) {
exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein");
return;
}
NBTTagCompound user = new NBTTagCompound();
user.setString("password", this.passwordField.get());
env.getServer().writePlayerData(username, user);
exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username);
}
});
}
else if(exec.isConsole()) {
if(password == null)
throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden");
NBTTagCompound user = new NBTTagCompound();
user.setString("password", password);
env.getServer().writePlayerData(username, user);
exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username);
}
}
}

View file

@ -0,0 +1,35 @@
package server.command.commands;
import common.color.TextColor;
import common.packet.SPacketMessage;
import common.packet.SPacketMessage.Type;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.world.Region;
public class CommandSave extends Command {
public CommandSave() {
super("save");
this.addFlag("message", 'm');
this.addFlag("flush", 'f');
}
public void exec(CommandEnvironment env, Executor exec, boolean message, boolean flush) {
if(message)
env.getServer().sendPacket(new SPacketMessage(TextColor.RED + "Speichere Serverdaten, der Server könnte kurz einfrieren", Type.FEED));
exec.logConsole(TextColor.ORANGE + "Speichere Spielerdaten ...");
env.getServer().saveAllPlayerData(true);
exec.logConsole(TextColor.ORANGE + "Speichere Weltdaten ...");
env.getServer().saveAllWorlds(true);
env.getServer().resetSaveTimer();
if(flush) {
exec.logConsole(TextColor.ORANGE + "Beende E/A ...");
Region.finishWrite();
}
exec.logConsole(TextColor.DGREEN + "Alle Serverdaten wurden gespeichert");
if(message)
env.getServer().sendPacket(new SPacketMessage(TextColor.GREEN + "Die Serverdaten wurden gespeichert", Type.FEED));
}
}

View file

@ -339,7 +339,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
} }
public boolean getAdmin() { public boolean getAdmin() {
return this.admin; return this.isAdmin();
} }
public void setPassword(String pass) { public void setPassword(String pass) {

View file

@ -94,14 +94,16 @@ public abstract class Form {
protected class Field extends FormElement { protected class Field extends FormElement {
private final int minLength; private final int minLength;
private final int maxLength; private final int maxLength;
private final boolean password;
private String value; private String value;
protected Field(String name, String value, int min, int max) { protected Field(String name, String value, int min, int max, boolean password) {
super(name); super(name);
this.value = value; this.value = value;
this.minLength = min; this.minLength = min;
this.maxLength = max; this.maxLength = max;
this.password = password;
} }
protected Object getInputData() { protected Object getInputData() {
@ -109,7 +111,7 @@ public abstract class Form {
} }
protected int getInputParameter() { protected int getInputParameter() {
return (this.minLength << 16) | this.maxLength; return (this.password ? 0x80000000 : 0) | (this.minLength << 16) | this.maxLength;
} }
protected boolean acceptValue(Object obj) { protected boolean acceptValue(Object obj) {
@ -145,7 +147,11 @@ public abstract class Form {
} }
protected Field addField(String name, int minLength, int maxLength, String def) { protected Field addField(String name, int minLength, int maxLength, String def) {
return this.add(new Field(name, def, minLength, maxLength)); return this.add(new Field(name, def, minLength, maxLength, false));
}
protected Field addPassword(String name, int minLength, int maxLength, String def) {
return this.add(new Field(name, def, minLength, maxLength, true));
} }
public abstract String getTitle(); public abstract String getTitle();