From 8bd1b4dedb088f98d86ce409cce3db691174511a Mon Sep 17 00:00:00 2001 From: Sen Date: Wed, 4 Jun 2025 12:40:28 +0200 Subject: [PATCH] add commands --- proxy/src/main/java/proxy/Proxy.java | 99 +++++++- .../src/main/java/proxy/command/Command.java | 29 +++ .../main/java/proxy/command/CommandExit.java | 29 +++ .../main/java/proxy/command/CommandHelp.java | 42 ++++ .../main/java/proxy/command/RunException.java | 28 +++ .../main/java/proxy/network/ProxyHandler.java | 218 +++++++++++++----- .../proxy/packet/R00PacketDisconnect.java | 6 +- .../main/java/proxy/packet/S02PacketChat.java | 4 +- .../proxy/packet/S33PacketUpdateSign.java | 4 +- .../proxy/packet/S3APacketTabComplete.java | 2 +- .../proxy/packet/S40PacketDisconnect.java | 6 +- .../util/{ChatColor.java => Formatter.java} | 35 ++- proxy/src/main/java/proxy/util/User.java | 10 + 13 files changed, 435 insertions(+), 77 deletions(-) create mode 100644 proxy/src/main/java/proxy/command/Command.java create mode 100644 proxy/src/main/java/proxy/command/CommandExit.java create mode 100644 proxy/src/main/java/proxy/command/CommandHelp.java create mode 100644 proxy/src/main/java/proxy/command/RunException.java rename proxy/src/main/java/proxy/util/{ChatColor.java => Formatter.java} (65%) diff --git a/proxy/src/main/java/proxy/Proxy.java b/proxy/src/main/java/proxy/Proxy.java index 4c4bc80..8391210 100755 --- a/proxy/src/main/java/proxy/Proxy.java +++ b/proxy/src/main/java/proxy/Proxy.java @@ -23,10 +23,14 @@ import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; import java.net.IDN; import java.net.InetAddress; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -58,9 +62,10 @@ import proxy.network.PacketPrepender; import proxy.network.Handler.ThreadQuickExitException; import proxy.network.HandshakeHandler; import proxy.network.ProxyHandler; +import proxy.command.*; import proxy.network.Connection; import proxy.packet.S40PacketDisconnect; -import proxy.util.ChatColor; +import proxy.util.Formatter; import proxy.util.ServerInfo; import proxy.util.User; import proxy.util.LazyLoader; @@ -84,21 +89,22 @@ public class Proxy { private final List endpoints = Collections.synchronizedList(Lists.newArrayList()); private final List networkManagers = Collections.synchronizedList(Lists.newArrayList()); private final Queue> futureTaskQueue = Queues.>newArrayDeque(); - private final Map users = Maps.newHashMap(); - private final Map players = Maps.newHashMap(); + private final Map users = Maps.newTreeMap(); + private final Map players = Maps.newTreeMap(); + private final Map commands = Maps.newTreeMap(); private final Thread serverThread; private int compression = -1; private boolean epoll = false; private boolean register = true; private boolean checkCase = true; - private String forwardHost = "lian.dd"; + private String forwardHost = "127.0.0.1"; private int forwardPort = 25565; private String proxyHost = ""; private int proxyPort = 25566; private int minPassLength = 8; private int maxAttempts = 5; - private ServerInfo status = getStatus(new File("icon.png"), ChatColor.AQUA + "Server\n" + ChatColor.GREEN + "Test!!", 90, 10, "Test1", + private ServerInfo status = getStatus(new File("icon.png"), Formatter.AQUA + "Server\n" + Formatter.GREEN + "Test!!", 90, 10, "Test1", "Test2 ...", "Test #3 !!"); private static String getIcon(File file) { @@ -144,6 +150,7 @@ public class Proxy { public Proxy() { this.serverThread = Thread.currentThread(); this.isAlive = true; + this.registerCommands(); } public void run() { @@ -160,6 +167,31 @@ public class Proxy { Proxy.this.terminateEndpoints(); } }, "Proxy shutdown thread")); + Thread con = new Thread(new Runnable() { + private final BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(System.in))); + + public void run() { + while(true) { + String line; + try { + line = this.reader.readLine(); + } + catch(IOException e) { + line = null; + } + if(line == null) + break; + final String cmd = line; + Proxy.this.schedule(new Runnable() { + public void run() { + Proxy.this.runCommand(null, Formatter.filterSpaces(cmd).split(" ", -1), cmd); + } + }); + } + } + }, "Proxy console handler"); + con.setDaemon(true); + con.start(); while(this.running) { synchronized (this.futureTaskQueue) { @@ -357,4 +389,61 @@ public class Proxy { public boolean isLoggedIn(String user) { return this.players.containsKey(user.toLowerCase(Locale.US)); } + + public ProxyHandler getPlayer(String user) { + return this.players.get(user.toLowerCase(Locale.US)); + } + + private void register(Command cmd) { + if(this.commands.containsKey(cmd.getName())) + throw new IllegalArgumentException("Command '" + cmd.getName() + "' ist already registered"); + this.commands.put(cmd.getName(), cmd); + } + + private void registerCommands() { + this.register(new CommandHelp()); + this.register(new CommandExit()); + } + + public Map getCommands() { + return this.commands; + } + + public Collection getPlayers() { + return this.players.values(); + } + + public void shutdown() { + this.running = false; + } + + public void runCommand(ProxyHandler player, String[] args, String line) { + if(args.length == 0) + args = new String[] {"help"}; + Command cmd = this.commands.get(args[0].toLowerCase()); + if(cmd == null) { + if(player != null) + player.sendMessage(Formatter.DARK_RED + "Proxy command '%s' not found", args[0]); + else + Log.error("Command '%s' not found", args[0]); + return; + } + String[] argv = new String[args.length - 1]; + System.arraycopy(args, 1, argv, 0, argv.length); + try { + cmd.run(this, player, argv); + } + catch(RunException e) { + if(player != null) + player.sendMessage(Formatter.DARK_RED + e.getMessage()); + else + Log.error(e.getMessage()); + } + catch(Throwable t) { + if(player != null) + player.sendMessage(Formatter.DARK_RED + "Internal error trying to execute command"); + Log.error(t, "Could not execute '%s'" + (player != null ? " as %s" : ""), line, player != null ? player.getUsername() : null); + } + Log.info((player != null ? "%s executed" : "Executed") + ": %s", player != null ? player.getUsername() : line, line); + } } diff --git a/proxy/src/main/java/proxy/command/Command.java b/proxy/src/main/java/proxy/command/Command.java new file mode 100644 index 0000000..e3ed5c7 --- /dev/null +++ b/proxy/src/main/java/proxy/command/Command.java @@ -0,0 +1,29 @@ +package proxy.command; + +import proxy.Proxy; +import proxy.network.ProxyHandler; +import proxy.util.Formatter; +import proxy.util.Log; + +public abstract class Command { + public abstract String getName(); + public abstract String getHelp(); + public String getArgs() { + return null; + } + public abstract void run(Proxy proxy, ProxyHandler player, String[] args); + public Iterable complete(Proxy proxy, ProxyHandler player, String[] args) { + return null; + } + + protected static void sendMessage(ProxyHandler player, String msg) { + if(player != null) + player.sendMessage(Formatter.DARK_PURPLE + msg); + else + Log.info(msg); + } + + protected static void sendMessage(ProxyHandler player, String fmt, Object ... args) { + sendMessage(player, String.format(fmt, args)); + } +} diff --git a/proxy/src/main/java/proxy/command/CommandExit.java b/proxy/src/main/java/proxy/command/CommandExit.java new file mode 100644 index 0000000..ffc1860 --- /dev/null +++ b/proxy/src/main/java/proxy/command/CommandExit.java @@ -0,0 +1,29 @@ +package proxy.command; + +import com.google.common.collect.Lists; + +import proxy.Proxy; +import proxy.network.ProxyHandler; +import proxy.util.Formatter; + +public class CommandExit extends Command { + public String getName() { + return "exit"; + } + + public String getHelp() { + return "Stops the proxy with an optional exit message"; + } + + public String getArgs() { + return "[message ...]"; + } + + public void run(Proxy proxy, ProxyHandler player, String[] args) { + String msg = args.length == 0 ? "Proxy stopped" : Formatter.joinSpace(args); + for(ProxyHandler plr : Lists.newArrayList(proxy.getPlayers())) { + plr.disconnect(msg); + } + proxy.shutdown(); + } +} diff --git a/proxy/src/main/java/proxy/command/CommandHelp.java b/proxy/src/main/java/proxy/command/CommandHelp.java new file mode 100644 index 0000000..b754835 --- /dev/null +++ b/proxy/src/main/java/proxy/command/CommandHelp.java @@ -0,0 +1,42 @@ +package proxy.command; + +import java.util.Locale; + +import proxy.Proxy; +import proxy.network.ProxyHandler; + +public class CommandHelp extends Command { + public String getName() { + return "help"; + } + + public String getHelp() { + return "Displays proxy command help"; + } + + public String getArgs() { + return "[command]"; + } + + private static String formatCommand(Command cmd, boolean prefix) { + String args = cmd.getArgs(); + return (prefix ? "/vproxy " : "") + cmd.getName() + (args == null || args.isEmpty() ? "" : " " + args); + } + + public void run(Proxy proxy, ProxyHandler player, String[] args) { + if(args.length == 0) { + for(Command cmd : proxy.getCommands().values()) { + sendMessage(player, formatCommand(cmd, player != null)); + } + return; + } + Command cmd = proxy.getCommands().get(args[0].toLowerCase(Locale.US)); + if(cmd == null) + throw new RunException("Command '%s' not found", args[0]); + sendMessage(player, formatCommand(cmd, player != null)); + } + + public Iterable complete(Proxy proxy, ProxyHandler player, String[] args) { + return args.length == 1 ? proxy.getCommands().keySet() : null; + } +} diff --git a/proxy/src/main/java/proxy/command/RunException.java b/proxy/src/main/java/proxy/command/RunException.java new file mode 100644 index 0000000..2cb117d --- /dev/null +++ b/proxy/src/main/java/proxy/command/RunException.java @@ -0,0 +1,28 @@ +package proxy.command; + +public class RunException extends RuntimeException { + public RunException(String desc) { + super(desc); + this.setStackTrace(new StackTraceElement[0]); + } + + public RunException(String fmt, Object ... args) { + super(String.format(fmt, args)); + this.setStackTrace(new StackTraceElement[0]); + } + + public RunException(Throwable cause, String desc) { + super(desc, cause); + this.setStackTrace(new StackTraceElement[0]); + } + + public RunException(Throwable cause, String fmt, Object ... args) { + super(String.format(fmt, args), cause); + this.setStackTrace(new StackTraceElement[0]); + } + + public synchronized Throwable fillInStackTrace() { + this.setStackTrace(new StackTraceElement[0]); + return this; + } +} diff --git a/proxy/src/main/java/proxy/network/ProxyHandler.java b/proxy/src/main/java/proxy/network/ProxyHandler.java index 02a1975..c2608ae 100755 --- a/proxy/src/main/java/proxy/network/ProxyHandler.java +++ b/proxy/src/main/java/proxy/network/ProxyHandler.java @@ -6,10 +6,17 @@ import io.netty.util.concurrent.GenericFutureListener; import java.net.IDN; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicInteger; + +import com.google.common.collect.Lists; import proxy.Proxy; +import proxy.command.Command; import proxy.packet.*; -import proxy.util.ChatColor; +import proxy.util.Formatter; import proxy.util.User; import proxy.util.Stack; import proxy.util.Log; @@ -47,6 +54,8 @@ public class ProxyHandler implements Handler { } } + private static final AtomicInteger CONN_COUNTER = new AtomicInteger(); + private final Proxy proxy; private final Connection client; private final String username; @@ -62,6 +71,8 @@ public class ProxyHandler implements Handler { private int passwordAttempts; private boolean wasClosed; private volatile int signPreloaded; + private String completion; + private boolean admin; private static boolean isAllowedChar(char ch) { return ch != 167 && ch >= 32 && ch != 127; @@ -92,19 +103,23 @@ public class ProxyHandler implements Handler { this.username = username; } + public String getUsername() { + return this.username; + } + public void setupPlayer() { this.sendToClient(new S01PacketJoinGame(0, true)); this.sendToClient(new S03PacketTimeUpdate(3000L, false)); this.sendToClient(new S26PacketMapChunkBulk(0, 64, 0)); this.sendToClient(new S08PacketPlayerPosLook(0.5, 65.0, 0.5, 0.0f, 0.0f)); - this.sendMessage(ChatColor.DARK_PURPLE + "Welcome %s, please log in using the sign gui ...", this.username); + this.sendMessage(Formatter.DARK_PURPLE + "Welcome %s, please log in using the sign gui ...", this.username); } - + public void sendMessage(String message) { this.sendToClient(new S02PacketChat(message)); } - - public void sendMessage(String fmt, Object ... args) { + + public void sendMessage(String fmt, Object... args) { this.sendToClient(new S02PacketChat(String.format(fmt, args))); } @@ -156,33 +171,41 @@ public class ProxyHandler implements Handler { } }); } - + private void connectToServer() { this.proxy.setLoggedIn(this.username, this); - Log.info("Connecting %s to %s:%d", this.username, this.proxy.getForwardHost(), this.proxy.getForwardPort()); - final Connection conn; - try { - conn = Connection.createNetworkManagerAndConnect(InetAddress.getByName(IDN.toASCII(this.proxy.getForwardHost())), this.proxy.getForwardPort(), this.proxy.isUsingEPoll()); - } - catch(UnknownHostException e) { - this.disconnect("Could not connect to server: unknown host, check if the hostname is correct"); - Log.error(e, "Could not connect to server"); - return; - } - catch(Exception e) { - this.disconnect("Could not connect to server: connection failed, check if the server is running and reachable on this port"); - Log.error(e, "Could not connect to server"); - return; - } - conn.setNetHandler(new ProxyLoginHandler()); - conn.sendPacket(new H00PacketHandshake(47, this.proxy.getForwardHost(), this.proxy.getForwardPort(), Protocol.LOGIN), new GenericFutureListener>() { - public void operationComplete(Future future) throws Exception { - conn.sendPacket(new L00PacketLoginStart(ProxyHandler.this.username)); + final String host = this.proxy.getForwardHost(); + final int port = this.proxy.getForwardPort(); + Log.info("Connecting %s to %s:%d", this.username, host, port); + new Thread(new Runnable() { + public void run() { + final Connection conn; + try { + conn = Connection.createNetworkManagerAndConnect(InetAddress.getByName(IDN.toASCII(host)), + port, ProxyHandler.this.proxy.isUsingEPoll()); + } + catch(UnknownHostException e) { + ProxyHandler.this.disconnect("Could not connect to server: unknown host, check if the hostname is correct"); + Log.error(e, "Could not connect to server"); + return; + } + catch(Exception e) { + ProxyHandler.this.disconnect("Could not connect to server: connection failed, check if the server is running and reachable on this port"); + Log.error(e, "Could not connect to server"); + return; + } + conn.setNetHandler(new ProxyLoginHandler()); + conn.sendPacket(new H00PacketHandshake(47, host, port, Protocol.LOGIN), + new GenericFutureListener>() { + public void operationComplete(Future future) throws Exception { + conn.sendPacket(new L00PacketLoginStart(ProxyHandler.this.username)); + } + }); + ProxyHandler.this.server = conn; + ProxyHandler.this.connecting = true; + Log.info("Connected %s to login phase", ProxyHandler.this.username); } - }); - this.server = conn; - this.connecting = true; - Log.info("Connected %s to login phase", this.username); + }, "Forward connector #" + CONN_COUNTER.incrementAndGet()).start(); } public void processInput(C0CPacketInput packetIn) { @@ -198,7 +221,7 @@ public class ProxyHandler implements Handler { this.sendToClient(new S08PacketPlayerPosLook(0.5, 65.0, 0.5, 0.0f, 0.0f)); if(this.signPreloaded == 1) { this.signPreloaded = 2; - this.setSign(ChatColor.DARK_BLUE + "" + ChatColor.UNDERLINE + "Enter password", ChatColor.DARK_GRAY + "Use 1 or 2 lines"); + this.setSign(Formatter.DARK_BLUE + "" + Formatter.UNDERLINE + "Enter password", Formatter.DARK_GRAY + "Use 1 or 2 lines"); } else if(this.signPreloaded == 0) { this.signPreloaded = 1; @@ -219,12 +242,12 @@ public class ProxyHandler implements Handler { this.proxy.setLoggedOut(this.username); Log.info("%s lost connection: " + reason, this.username); } - + private void setSign(String message, String desc) { this.sendToClient(new S33PacketUpdateSign(0, 66, 1, "", "", message, desc)); this.sendToClient(new S36PacketSignEditorOpen(0, 66, 1)); } - + private void handlePassword(String password) { if(password.isEmpty()) { if(this.wasClosed) { @@ -232,7 +255,7 @@ public class ProxyHandler implements Handler { } else { this.wasClosed = true; - this.setSign(ChatColor.GOLD + "Press esc again", ChatColor.GOLD + "to disconnect ..."); + this.setSign(Formatter.GOLD + "Press esc again", Formatter.GOLD + "to disconnect ..."); } return; } @@ -243,14 +266,17 @@ public class ProxyHandler implements Handler { this.disconnect("You are not whitelisted on this server"); } else if(password.isEmpty() || password.length() < this.proxy.getMinimumPasswordLength()) { - this.setSign(ChatColor.DARK_RED + "" + ChatColor.UNDERLINE + "Too short" + ChatColor.DARK_RED + ", use", ChatColor.DARK_RED + "" + this.proxy.getMinimumPasswordLength() + "-32 characters"); + this.setSign(Formatter.DARK_RED + "" + Formatter.UNDERLINE + "Too short" + Formatter.DARK_RED + ", use", + Formatter.DARK_RED + "" + this.proxy.getMinimumPasswordLength() + "-32 characters"); } else if(password.length() > 32) { - this.setSign(ChatColor.DARK_RED + "" + ChatColor.UNDERLINE + "Too long" + ChatColor.DARK_RED + ", use", ChatColor.DARK_RED + "" + this.proxy.getMinimumPasswordLength() + "-32 characters"); + this.setSign(Formatter.DARK_RED + "" + Formatter.UNDERLINE + "Too long" + Formatter.DARK_RED + ", use", + Formatter.DARK_RED + "" + this.proxy.getMinimumPasswordLength() + "-32 characters"); } else { this.proxy.setUser(this.username, User.createUser(this.username, password)); Log.info("%s registered with password", this.username); + this.admin = true; //false; this.connectToServer(); } } @@ -259,7 +285,7 @@ public class ProxyHandler implements Handler { if(++this.passwordAttempts >= this.proxy.getMaximumPasswordAttempts()) this.disconnect("Too many password attempts"); else - this.setSign(ChatColor.DARK_RED + "" + ChatColor.UNDERLINE + "Wrong password", ChatColor.DARK_RED + "Please try again"); + this.setSign(Formatter.DARK_RED + "" + Formatter.UNDERLINE + "Wrong password", Formatter.DARK_RED + "Please try again"); Log.info("%s failed password attempt %d/%d", this.username, this.passwordAttempts, this.proxy.getMaximumPasswordAttempts()); } else if(this.proxy.isCheckingCase() && !stored.getName().equals(this.username)) { @@ -268,6 +294,7 @@ public class ProxyHandler implements Handler { } else { Log.info("%s logged in with password", this.username); + this.admin = true; //stored.isAdmin(); this.connectToServer(); } } @@ -276,8 +303,8 @@ public class ProxyHandler implements Handler { public void processUpdateSign(C12PacketUpdateSign packetIn) { if(!this.connected) { Handler.syncToMain(packetIn, this, this.proxy); - String line1 = ChatColor.fromJsonString(packetIn.getLines()[0]); - String line2 = ChatColor.fromJsonString(packetIn.getLines()[1]); + String line1 = Formatter.fromJsonString(packetIn.getLines()[0]); + String line2 = Formatter.fromJsonString(packetIn.getLines()[1]); if(line1 == null || line2 == null || line1.length() > 50 || line2.length() > 50 || !isValidString(line1) || !isValidString(line2)) return; String password = line1 + line2; @@ -286,29 +313,111 @@ public class ProxyHandler implements Handler { } String[] lines = packetIn.getLines(); for(String line : lines) { - String value = ChatColor.fromJsonString(line); + String value = Formatter.fromJsonString(line); if(value == null || value.length() > 50 || !isValidString(value)) return; } this.sendToServer(packetIn); } + public List getCompletions(String[] args) { + if(args.length == 0) + args = new String[] {""}; + String param = args[0]; + List list = Lists.newArrayList(); + if(args.length == 1) { + for(String cmd : this.proxy.getCommands().keySet()) { + if(cmd.regionMatches(true, 0, param, 0, param.length())) + list.add(cmd); + } + return list; + } + else if(args.length > 1) { + Command cmd = this.proxy.getCommands().get(param.toLowerCase(Locale.US)); + if(cmd == null) + return list; + String[] argv = new String[args.length - 1]; + System.arraycopy(args, 1, argv, 0, argv.length); + Iterable comps = cmd.complete(this.proxy, this, argv); + if(comps == null) + return list; + param = args[args.length - 1]; + for(String comp : comps) { + if(comp.regionMatches(true, 0, param, 0, param.length())) + list.add(comp); + } + } + return list; + } + public void processChatMessage(C01PacketChatMessage packetIn) { - if(this.connected) + if(this.connected) { + Handler.syncToMain(packetIn, this, this.proxy); + String msg = packetIn.getMessage(); + if(msg.startsWith("/")) { + if(msg.indexOf(' ') == -1) { + if(msg.equals("/vproxy")) { + if(!this.admin) { + this.sendMessage(Formatter.DARK_RED + "You are not allowed to execute this command"); + return; + } + this.proxy.runCommand(this, new String[0], msg); + return; + } + } + else { + if(msg.startsWith("/vproxy ")) { + if(!this.admin) { + this.sendMessage(Formatter.DARK_RED + "You are not allowed to execute this command"); + return; + } + String[] args = Formatter.filterSpaces(msg).split(" ", -1); + String[] argv = new String[args.length - 1]; + System.arraycopy(args, 1, argv, 0, argv.length); + this.proxy.runCommand(this, argv, msg); + return; + } + } + } this.sendToServer(packetIn); + } } public void processTabComplete(C14PacketTabComplete packetIn) { -// PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.proxy); - if(this.connected) // { -// this.completion = packetIn.getMessage(); + if(this.connected) { + Handler.syncToMain(packetIn, this, this.proxy); + this.completion = packetIn.getMessage(); this.sendToServer(packetIn); -// } -// else { -// List list = Lists.newArrayList(); -// // TODO: completions -// this.sendToClient(new S3APacketTabComplete(list.toArray(new String[list.size()]))); -// } + } + } + + public void handleTabComplete(S3APacketTabComplete packetIn) { + Handler.syncToMain(packetIn, this, this.proxy); + String[] comps = packetIn.getMatches(); + if(this.completion != null) { + if(this.admin && this.completion.startsWith("/")) { + if(this.completion.indexOf(' ') == -1) { + List list = Lists.newArrayList(comps); + if("/vproxy".regionMatches(true, 0, this.completion, 0, this.completion.length())) + list.add("/vproxy"); + Collections.sort(list); + this.sendToClient(new S3APacketTabComplete(list.toArray(new String[list.size()]))); + this.completion = null; + return; + } + else if(this.completion.startsWith("/vproxy ")) { + String[] args = this.completion.split(" ", -1); + String[] argv = new String[args.length - 1]; + System.arraycopy(args, 1, argv, 0, argv.length); + List list = this.getCompletions(argv); + this.sendToClient(new S3APacketTabComplete(list.toArray(new String[list.size()]))); + this.completion = null; + return; + } + } + this.completion = null; + } + this.sendToClient(packetIn); } public void processPlayerDigging(C07PacketPlayerDigging packetIn) { @@ -405,7 +514,7 @@ public class ProxyHandler implements Handler { PacketBuffer packetbuffer = packetIn.getBufferData(); String brand = packetbuffer.readStringFromBuffer(32767); Log.info("Client brand of %s: %s", this.username, - filterString(ChatColor.strip(brand.length() > 128 ? brand.substring(0, 128) + " ..." : brand))); + filterString(Formatter.strip(brand.length() > 128 ? brand.substring(0, 128) + " ..." : brand))); packetbuffer.release(); } return; @@ -527,15 +636,6 @@ public class ProxyHandler implements Handler { this.server.setCompressionTreshold(packetIn.getThreshold()); } - public void handleTabComplete(S3APacketTabComplete packetIn) { -// PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.proxy); -// String[] comps = packetIn.func_149630_c(); -// if(this.completion != null) { -// // TODO: completion -// } - this.sendToClient(packetIn); - } - public void handleKeepAlive(S00PacketKeepAlive packetIn) { this.sendToClient(packetIn); } diff --git a/proxy/src/main/java/proxy/packet/R00PacketDisconnect.java b/proxy/src/main/java/proxy/packet/R00PacketDisconnect.java index 2d893d6..7192317 100755 --- a/proxy/src/main/java/proxy/packet/R00PacketDisconnect.java +++ b/proxy/src/main/java/proxy/packet/R00PacketDisconnect.java @@ -5,7 +5,7 @@ import java.io.IOException; import proxy.network.ProxyHandler.ProxyLoginHandler; import proxy.network.Packet; import proxy.network.PacketBuffer; -import proxy.util.ChatColor; +import proxy.util.Formatter; public class R00PacketDisconnect implements Packet { @@ -17,7 +17,7 @@ public class R00PacketDisconnect implements Packet public R00PacketDisconnect(String reasonIn) { - this.reason = ChatColor.toJsonString(reasonIn); + this.reason = Formatter.toJsonString(reasonIn); } /** @@ -46,6 +46,6 @@ public class R00PacketDisconnect implements Packet public String getReason() { - return ChatColor.getStringOrJson(this.reason); + return Formatter.getStringOrJson(this.reason); } } diff --git a/proxy/src/main/java/proxy/packet/S02PacketChat.java b/proxy/src/main/java/proxy/packet/S02PacketChat.java index a2c9f09..7ea87e5 100755 --- a/proxy/src/main/java/proxy/packet/S02PacketChat.java +++ b/proxy/src/main/java/proxy/packet/S02PacketChat.java @@ -5,7 +5,7 @@ import java.io.IOException; import proxy.network.ProxyHandler; import proxy.network.Packet; import proxy.network.PacketBuffer; -import proxy.util.ChatColor; +import proxy.util.Formatter; public class S02PacketChat implements Packet { @@ -18,7 +18,7 @@ public class S02PacketChat implements Packet public S02PacketChat(String message) { - this.chatComponent = ChatColor.toJsonString(message); + this.chatComponent = Formatter.toJsonString(message); this.type = 0; } diff --git a/proxy/src/main/java/proxy/packet/S33PacketUpdateSign.java b/proxy/src/main/java/proxy/packet/S33PacketUpdateSign.java index 4cef649..97939b2 100755 --- a/proxy/src/main/java/proxy/packet/S33PacketUpdateSign.java +++ b/proxy/src/main/java/proxy/packet/S33PacketUpdateSign.java @@ -6,7 +6,7 @@ import proxy.network.ProxyHandler; import proxy.network.Packet; import proxy.network.PacketBuffer; import proxy.util.Vec3; -import proxy.util.ChatColor; +import proxy.util.Formatter; public class S33PacketUpdateSign implements Packet { @@ -19,7 +19,7 @@ public class S33PacketUpdateSign implements Packet public S33PacketUpdateSign(int x, int y, int z, String line1, String line2, String line3, String line4) { this.blockPos = new Vec3(x, y, z); - this.lines = new String[] {ChatColor.toJsonString(line1), ChatColor.toJsonString(line2), ChatColor.toJsonString(line3), ChatColor.toJsonString(line4)}; + this.lines = new String[] {Formatter.toJsonString(line1), Formatter.toJsonString(line2), Formatter.toJsonString(line3), Formatter.toJsonString(line4)}; } /** diff --git a/proxy/src/main/java/proxy/packet/S3APacketTabComplete.java b/proxy/src/main/java/proxy/packet/S3APacketTabComplete.java index 08c827f..d98a8c0 100755 --- a/proxy/src/main/java/proxy/packet/S3APacketTabComplete.java +++ b/proxy/src/main/java/proxy/packet/S3APacketTabComplete.java @@ -53,7 +53,7 @@ public class S3APacketTabComplete implements Packet handler.handleTabComplete(this); } - public String[] func_149630_c() + public String[] getMatches() { return this.matches; } diff --git a/proxy/src/main/java/proxy/packet/S40PacketDisconnect.java b/proxy/src/main/java/proxy/packet/S40PacketDisconnect.java index 927b461..61a31a3 100755 --- a/proxy/src/main/java/proxy/packet/S40PacketDisconnect.java +++ b/proxy/src/main/java/proxy/packet/S40PacketDisconnect.java @@ -5,7 +5,7 @@ import java.io.IOException; import proxy.network.ProxyHandler; import proxy.network.Packet; import proxy.network.PacketBuffer; -import proxy.util.ChatColor; +import proxy.util.Formatter; public class S40PacketDisconnect implements Packet { @@ -17,7 +17,7 @@ public class S40PacketDisconnect implements Packet public S40PacketDisconnect(String reasonIn) { - this.reason = ChatColor.toJsonString(reasonIn); + this.reason = Formatter.toJsonString(reasonIn); } /** @@ -46,6 +46,6 @@ public class S40PacketDisconnect implements Packet public String getReason() { - return ChatColor.getStringOrJson(this.reason); + return Formatter.getStringOrJson(this.reason); } } diff --git a/proxy/src/main/java/proxy/util/ChatColor.java b/proxy/src/main/java/proxy/util/Formatter.java similarity index 65% rename from proxy/src/main/java/proxy/util/ChatColor.java rename to proxy/src/main/java/proxy/util/Formatter.java index 19e84ec..c3b0ecd 100755 --- a/proxy/src/main/java/proxy/util/ChatColor.java +++ b/proxy/src/main/java/proxy/util/Formatter.java @@ -6,7 +6,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; -public enum ChatColor { +public enum Formatter { BLACK('0'), DARK_BLUE('1'), DARK_GREEN('2'), @@ -58,8 +58,39 @@ public enum ChatColor { String str = fromJsonString(json); return str == null ? "JSON:" + json : str; } + + public static String filterSpaces(String str) { + StringBuilder sb = new StringBuilder(); + boolean space = true; + for(int z = 0; z < str.length(); z++) { + char ch = str.charAt(z); + if(ch != ' ') { + sb.append(ch); + space = false; + } + else if(!space) { + sb.append(' '); + space = true; + } + } + return sb.toString().trim(); + } + + public static String joinSpace(String ... objs) { + return joinSpace(objs); + } + + public static String joinSpace(Object ... objs) { + StringBuilder sb = new StringBuilder(); + for(Object obj : objs) { + if(sb.length() != 0) + sb.append(' '); + sb.append(obj); + } + return sb.toString(); + } - private ChatColor(char code) { + private Formatter(char code) { this.value = "\u00a7" + code; } diff --git a/proxy/src/main/java/proxy/util/User.java b/proxy/src/main/java/proxy/util/User.java index 2348fdc..dd6fd03 100644 --- a/proxy/src/main/java/proxy/util/User.java +++ b/proxy/src/main/java/proxy/util/User.java @@ -12,6 +12,8 @@ public class User { private final byte[] hash; private final byte[] salt; + private boolean admin; + public User(String username, byte[] hash, byte[] salt) { this.username = username; this.hash = hash; @@ -26,6 +28,14 @@ public class User { return MessageDigest.isEqual(hashPassword(password, this.salt), this.hash); } + public boolean isAdmin() { + return this.admin; + } + + public void setAdmin(boolean admin) { + this.admin = admin; + } + private static byte[] hashPassword(String pass, byte[] salt) { try { MessageDigest digest = MessageDigest.getInstance("SHA-512");