diff --git a/src/main/java/me/vlod/pinto/PintoServer.java b/src/main/java/me/vlod/pinto/PintoServer.java index c0836a6..1440c22 100644 --- a/src/main/java/me/vlod/pinto/PintoServer.java +++ b/src/main/java/me/vlod/pinto/PintoServer.java @@ -420,7 +420,7 @@ public void sendHeartbeat() { int onlineClients = 0; for (NetworkHandler client : this.clients) { - if (client.loggedIn && NetHandlerUtils + if (client.userName != null && NetHandlerUtils .getToOthersStatus(client.databaseEntry.status) != UserStatus.OFFLINE) { onlineClients++; } diff --git a/src/main/java/me/vlod/pinto/Utils.java b/src/main/java/me/vlod/pinto/Utils.java index b5884e7..e5dccc0 100644 --- a/src/main/java/me/vlod/pinto/Utils.java +++ b/src/main/java/me/vlod/pinto/Utils.java @@ -160,7 +160,7 @@ public static String[] splitBySpace(String str) { /** * Gets a salted MD5 hash from the specified string * - * @param salt the salt to use + * @param salt the salt to use (can be empty) * @param content the string to hash * @return the MD5 hash or empty on error */ @@ -174,6 +174,24 @@ public static String getMD5HashFromStr(String salt, String content) { } } + + /** + * Gets a salted SHA256 hash from the specified string + * + * @param salt the salt to use (can be empty) + * @param content the string to hash + * @return the SHA256 hash or empty on error + */ + public static String getSHA256HashFromStr(String salt, String content) { + try { + MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); + messageDigest.update((salt + content).getBytes()); + return (new BigInteger(1, messageDigest.digest())).toString(16); + } catch (Exception ex) { + return ""; + } + } + /** * Splits the specified string into chunks
* From https://stackoverflow.com/a/3760193 diff --git a/src/main/java/me/vlod/pinto/consolehandler/ConsoleHandler.java b/src/main/java/me/vlod/pinto/consolehandler/ConsoleHandler.java index d745f42..314eade 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/ConsoleHandler.java +++ b/src/main/java/me/vlod/pinto/consolehandler/ConsoleHandler.java @@ -8,16 +8,18 @@ import me.vlod.pinto.PintoServer; import me.vlod.pinto.Tuple; import me.vlod.pinto.Utils; -import me.vlod.pinto.consolehandler.commands.BanCMD; -import me.vlod.pinto.consolehandler.commands.BanIPCMD; -import me.vlod.pinto.consolehandler.commands.GetIPCMD; -import me.vlod.pinto.consolehandler.commands.KickCMD; -import me.vlod.pinto.consolehandler.commands.KickIPCMD; -import me.vlod.pinto.consolehandler.commands.NotificationCMD; -import me.vlod.pinto.consolehandler.commands.ReloadCMD; -import me.vlod.pinto.consolehandler.commands.StopCMD; -import me.vlod.pinto.consolehandler.commands.UnbanCMD; -import me.vlod.pinto.consolehandler.commands.UnbanIPCMD; +import me.vlod.pinto.consolehandler.commands.Ban; +import me.vlod.pinto.consolehandler.commands.BanIP; +import me.vlod.pinto.consolehandler.commands.ChangePassword; +import me.vlod.pinto.consolehandler.commands.GetIP; +import me.vlod.pinto.consolehandler.commands.Kick; +import me.vlod.pinto.consolehandler.commands.KickIP; +import me.vlod.pinto.consolehandler.commands.ListUsers; +import me.vlod.pinto.consolehandler.commands.Notification; +import me.vlod.pinto.consolehandler.commands.Reload; +import me.vlod.pinto.consolehandler.commands.Stop; +import me.vlod.pinto.consolehandler.commands.Unban; +import me.vlod.pinto.consolehandler.commands.UnbanIP; public class ConsoleHandler { protected PintoServer server; @@ -28,16 +30,18 @@ public class ConsoleHandler { public ConsoleHandler(PintoServer server, ConsoleCaller caller) { this.server = server; this.caller = caller; - this.commands.add(new BanCMD()); - this.commands.add(new BanIPCMD()); - this.commands.add(new GetIPCMD()); - this.commands.add(new KickCMD()); - this.commands.add(new KickIPCMD()); - this.commands.add(new ReloadCMD()); - this.commands.add(new UnbanCMD()); - this.commands.add(new UnbanIPCMD()); - this.commands.add(new StopCMD()); - this.commands.add(new NotificationCMD()); + this.commands.add(new Ban()); + this.commands.add(new BanIP()); + this.commands.add(new GetIP()); + this.commands.add(new Kick()); + this.commands.add(new KickIP()); + this.commands.add(new Reload()); + this.commands.add(new Unban()); + this.commands.add(new UnbanIP()); + this.commands.add(new Stop()); + this.commands.add(new ListUsers()); + this.commands.add(new Notification()); + this.commands.add(new ChangePassword()); } public void handleInput(String input) { diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/BanCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/Ban.java similarity index 94% rename from src/main/java/me/vlod/pinto/consolehandler/commands/BanCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/Ban.java index 7a8639c..09b7962 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/BanCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/Ban.java @@ -4,7 +4,7 @@ import me.vlod.pinto.consolehandler.ConsoleCaller; import me.vlod.pinto.consolehandler.ConsoleCommand; -public class BanCMD implements ConsoleCommand { +public class Ban implements ConsoleCommand { @Override public String getName() { return "ban"; diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/BanIPCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/BanIP.java similarity index 88% rename from src/main/java/me/vlod/pinto/consolehandler/commands/BanIPCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/BanIP.java index 55ec5e1..bd2b59e 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/BanIPCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/BanIP.java @@ -4,10 +4,10 @@ import me.vlod.pinto.consolehandler.ConsoleCaller; import me.vlod.pinto.consolehandler.ConsoleCommand; -public class BanIPCMD implements ConsoleCommand { +public class BanIP implements ConsoleCommand { @Override public String getName() { - return "banip"; + return "ban-ip"; } @Override @@ -17,7 +17,7 @@ public String getDescription() { @Override public String getUsage() { - return "banip "; + return "ban-ip "; } @Override diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/ChangePassword.java b/src/main/java/me/vlod/pinto/consolehandler/commands/ChangePassword.java new file mode 100644 index 0000000..5a2ff10 --- /dev/null +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/ChangePassword.java @@ -0,0 +1,57 @@ +package me.vlod.pinto.consolehandler.commands; + +import me.vlod.pinto.PintoServer; +import me.vlod.pinto.UserDatabaseEntry; +import me.vlod.pinto.Utils; +import me.vlod.pinto.consolehandler.ConsoleCaller; +import me.vlod.pinto.consolehandler.ConsoleCommand; +import me.vlod.pinto.networking.NetworkHandler; + +public class ChangePassword implements ConsoleCommand { + @Override + public String getName() { + return "change-password"; + } + + @Override + public String getDescription() { + return "Changes a user's password, they will be kicked"; + } + + @Override + public String getUsage() { + return "change-password "; + } + + @Override + public int getMinArgsCount() { + return 2; + } + + @Override + public int getMaxArgsCount() { + return 2; + } + + @Override + public void execute(PintoServer server, ConsoleCaller caller, String[] args) throws Exception { + String user = args[0]; + String password = args[1]; + + if (!UserDatabaseEntry.isRegistered(server, user)) { + PintoServer.logger.error("The account %s is not registered", user); + return; + } + + UserDatabaseEntry userDatabaseEntry = new UserDatabaseEntry(server, user); + userDatabaseEntry.load(); + userDatabaseEntry.passwordHash = Utils.getSHA256HashFromStr("", password); + userDatabaseEntry.save(); + PintoServer.logger.info("Successfully changed %s's password", user); + + NetworkHandler netHandler = server.getHandlerByName(user); + if (netHandler != null) { + netHandler.kick("Your password has been modified!"); + } + } +} diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/GetIPCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/GetIP.java similarity index 90% rename from src/main/java/me/vlod/pinto/consolehandler/commands/GetIPCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/GetIP.java index cf23c60..8bc5358 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/GetIPCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/GetIP.java @@ -5,10 +5,10 @@ import me.vlod.pinto.consolehandler.ConsoleCommand; import me.vlod.pinto.networking.NetworkHandler; -public class GetIPCMD implements ConsoleCommand { +public class GetIP implements ConsoleCommand { @Override public String getName() { - return "getip"; + return "get-ip"; } @Override @@ -18,7 +18,7 @@ public String getDescription() { @Override public String getUsage() { - return "getip "; + return "get-ip "; } @Override diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/KickCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/Kick.java similarity index 95% rename from src/main/java/me/vlod/pinto/consolehandler/commands/KickCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/Kick.java index b9f8cfd..b059053 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/KickCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/Kick.java @@ -5,7 +5,7 @@ import me.vlod.pinto.consolehandler.ConsoleCommand; import me.vlod.pinto.networking.NetworkHandler; -public class KickCMD implements ConsoleCommand { +public class Kick implements ConsoleCommand { @Override public String getName() { return "kick"; diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/KickIPCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/KickIP.java similarity index 90% rename from src/main/java/me/vlod/pinto/consolehandler/commands/KickIPCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/KickIP.java index 1b11be7..0d6f913 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/KickIPCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/KickIP.java @@ -5,10 +5,10 @@ import me.vlod.pinto.consolehandler.ConsoleCommand; import me.vlod.pinto.networking.NetworkHandler; -public class KickIPCMD implements ConsoleCommand { +public class KickIP implements ConsoleCommand { @Override public String getName() { - return "kickip"; + return "kick-ip"; } @Override @@ -18,7 +18,7 @@ public String getDescription() { @Override public String getUsage() { - return "kickip "; + return "kick-ip "; } @Override diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/ListUsers.java b/src/main/java/me/vlod/pinto/consolehandler/commands/ListUsers.java new file mode 100644 index 0000000..49c2865 --- /dev/null +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/ListUsers.java @@ -0,0 +1,45 @@ +package me.vlod.pinto.consolehandler.commands; + +import me.vlod.pinto.PintoServer; +import me.vlod.pinto.configuration.MainConfig; +import me.vlod.pinto.consolehandler.ConsoleCaller; +import me.vlod.pinto.consolehandler.ConsoleCommand; +import me.vlod.pinto.networking.NetworkHandler; + +public class ListUsers implements ConsoleCommand { + @Override + public String getName() { + return "list-users"; + } + + @Override + public String getDescription() { + return "Lists all connected users"; + } + + @Override + public String getUsage() { + return "list-users"; + } + + @Override + public int getMinArgsCount() { + return 0; + } + + @Override + public int getMaxArgsCount() { + return 0; + } + + @Override + public void execute(PintoServer server, ConsoleCaller caller, String[] args) throws Exception { + PintoServer.logger.info("There are %d clients out of the max of %d connected%s", + server.clients.size(), MainConfig.instance.maxUsers, server.clients.size() > 0 ? ":" : ""); + + for (NetworkHandler client : server.clients.toArray(new NetworkHandler[0])) { + PintoServer.logger.info("- %s (%s)", client.networkAddress, + client.userName != null ? client.userName : "** UNAUTHENTICATED **"); + } + } +} diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/NotificationCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/Notification.java similarity index 93% rename from src/main/java/me/vlod/pinto/consolehandler/commands/NotificationCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/Notification.java index a5eb425..7a04901 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/NotificationCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/Notification.java @@ -5,7 +5,7 @@ import me.vlod.pinto.consolehandler.ConsoleCommand; import me.vlod.pinto.networking.packet.PacketPopup; -public class NotificationCMD implements ConsoleCommand { +public class Notification implements ConsoleCommand { @Override public String getName() { return "notification"; diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/ReloadCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/Reload.java similarity index 93% rename from src/main/java/me/vlod/pinto/consolehandler/commands/ReloadCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/Reload.java index 3fd8529..111eacb 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/ReloadCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/Reload.java @@ -4,7 +4,7 @@ import me.vlod.pinto.consolehandler.ConsoleCaller; import me.vlod.pinto.consolehandler.ConsoleCommand; -public class ReloadCMD implements ConsoleCommand { +public class Reload implements ConsoleCommand { @Override public String getName() { return "reload"; diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/StopCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/Stop.java similarity index 94% rename from src/main/java/me/vlod/pinto/consolehandler/commands/StopCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/Stop.java index 5ef5d66..3e1581a 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/StopCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/Stop.java @@ -4,7 +4,7 @@ import me.vlod.pinto.consolehandler.ConsoleCaller; import me.vlod.pinto.consolehandler.ConsoleCommand; -public class StopCMD implements ConsoleCommand { +public class Stop implements ConsoleCommand { @Override public String getName() { return "stop"; diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/UnbanCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/Unban.java similarity index 93% rename from src/main/java/me/vlod/pinto/consolehandler/commands/UnbanCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/Unban.java index 1d62e15..c423789 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/UnbanCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/Unban.java @@ -4,7 +4,7 @@ import me.vlod.pinto.consolehandler.ConsoleCaller; import me.vlod.pinto.consolehandler.ConsoleCommand; -public class UnbanCMD implements ConsoleCommand { +public class Unban implements ConsoleCommand { @Override public String getName() { return "unban"; diff --git a/src/main/java/me/vlod/pinto/consolehandler/commands/UnbanIPCMD.java b/src/main/java/me/vlod/pinto/consolehandler/commands/UnbanIP.java similarity index 88% rename from src/main/java/me/vlod/pinto/consolehandler/commands/UnbanIPCMD.java rename to src/main/java/me/vlod/pinto/consolehandler/commands/UnbanIP.java index 7bbee54..76cefaa 100644 --- a/src/main/java/me/vlod/pinto/consolehandler/commands/UnbanIPCMD.java +++ b/src/main/java/me/vlod/pinto/consolehandler/commands/UnbanIP.java @@ -4,10 +4,10 @@ import me.vlod.pinto.consolehandler.ConsoleCaller; import me.vlod.pinto.consolehandler.ConsoleCommand; -public class UnbanIPCMD implements ConsoleCommand { +public class UnbanIP implements ConsoleCommand { @Override public String getName() { - return "unbanip"; + return "unban-ip"; } @Override @@ -17,7 +17,7 @@ public String getDescription() { @Override public String getUsage() { - return "unbanip "; + return "unban-ip "; } @Override diff --git a/src/main/java/me/vlod/pinto/networking/NetworkClient.java b/src/main/java/me/vlod/pinto/networking/NetworkClient.java index 69befdd..a0ec833 100644 --- a/src/main/java/me/vlod/pinto/networking/NetworkClient.java +++ b/src/main/java/me/vlod/pinto/networking/NetworkClient.java @@ -1,5 +1,6 @@ package me.vlod.pinto.networking; +import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -48,7 +49,7 @@ public NetworkClient(RSAPublicKey rsaPublicKey, RSAPrivateKey rsaPrivateKey, Soc this.networkAddress = new NetworkAddress(this.socket); this.isConnected = true; - this.socket.setSoTimeout(10000); + this.socket.setSoTimeout(20000); this.inputStream = this.socket.getInputStream(); this.outputStream = this.socket.getOutputStream(); @@ -136,10 +137,10 @@ public void sendPacket(Packet packet) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); + BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(this.outputStream, 4096); try { synchronized (this.sendLock) { - dataOutputStream.write("PMSG".getBytes(StandardCharsets.US_ASCII)); // Header dataOutputStream.writeInt(packet.getID()); // ID packet.write(dataOutputStream); // Data dataOutputStream.flush(); @@ -151,21 +152,59 @@ public void sendPacket(Packet packet) { byte[] encryptedPacketData = this.cipherEncryptor.doFinal(packetData); byteArrayOutputStream.close(); - this.outputStream.write(iv.getIV()); - this.outputStream.write(Utils.intToBytes(encryptedPacketData.length)); - this.outputStream.write(encryptedPacketData); - this.outputStream.flush(); + bufferedOutputStream.write("PMSG".getBytes(StandardCharsets.US_ASCII)); + bufferedOutputStream.write(iv.getIV()); + bufferedOutputStream.write(Utils.intToBytes(encryptedPacketData.length)); + bufferedOutputStream.write(encryptedPacketData); + bufferedOutputStream.flush(); } catch (Exception ex) { this.disconnect(String.format("Internal error (%s)", ex.getMessage())); PintoServer.logger.throwable(ex); } } + private void processReceivedEncryptedData(byte[] encryptedData, byte[] iv) throws Exception { + this.cipherDecryptor.init(Cipher.DECRYPT_MODE, this.secretKey, new IvParameterSpec(iv)); + byte[] decryptedData = this.cipherDecryptor.doFinal(encryptedData); + DataInputStream dataInputStream = + new DataInputStream(new ByteArrayInputStream(decryptedData)); + + int id = dataInputStream.readInt(); + Packet packet = Packets.getPacketByID(id); + + if (packet == null) { + throw new SocketException(String.format("Bad packet ID: %d", id)); + } + + packet.read(dataInputStream); + receivedPacket.call(packet); + } + private void readThread_Func() { while (this.isConnected) { try { + int headerPart0 = this.inputStream.read(); + int headerPart1 = this.inputStream.read(); + int headerPart2 = this.inputStream.read(); + int headerPart3 = this.inputStream.read(); + + if (headerPart0 == -1 || + headerPart1 == -1 || + headerPart2 == -1 || + headerPart3 == -1) { + throw new SocketException("Client disconnect"); + } + + if (headerPart0 != 'P' || + headerPart1 != 'M' || + headerPart2 != 'S' || + headerPart3 != 'G') { + throw new SocketException("Bad packet header!"); + } + byte[] iv = new byte[16]; this.inputStream.read(iv); + byte[] encryptedDataSize = new byte[4]; this.inputStream.read(encryptedDataSize); @@ -173,33 +212,7 @@ private void readThread_Func() { int readAmount = this.inputStream.read(encryptedData); if (readAmount == -1) throw new SocketException("Client disconnect"); - this.cipherDecryptor.init(Cipher.DECRYPT_MODE, this.secretKey, new IvParameterSpec(iv)); - byte[] decryptedData = this.cipherDecryptor.doFinal(encryptedData); - DataInputStream dataInputStream = - new DataInputStream(new ByteArrayInputStream(decryptedData)); - - int headerPart0 = dataInputStream.read(); - int headerPart1 = dataInputStream.read(); - int headerPart2 = dataInputStream.read(); - int headerPart3 = dataInputStream.read(); - - // PMSG - if (headerPart0 != 'P' || - headerPart1 != 'M' || - headerPart2 != 'S' || - headerPart3 != 'G') { - throw new SocketException("Bad packet header!"); - } - - int id = dataInputStream.readInt(); - Packet packet = Packets.getPacketByID(id); - - if (packet == null) { - throw new SocketException(String.format("Bad packet ID: %d", id)); - } - - packet.read(dataInputStream); - receivedPacket.call(packet); + this.processReceivedEncryptedData(encryptedData, iv); Thread.sleep(1); } catch (Exception ex) { diff --git a/src/main/java/me/vlod/pinto/networking/NetworkHandler.java b/src/main/java/me/vlod/pinto/networking/NetworkHandler.java index dbae44f..0e79d57 100644 --- a/src/main/java/me/vlod/pinto/networking/NetworkHandler.java +++ b/src/main/java/me/vlod/pinto/networking/NetworkHandler.java @@ -40,11 +40,11 @@ public class NetworkHandler { public NetworkAddress networkAddress; public ConsoleHandler consoleHandler; public int noLoginKickTicks; + public int ticksTillNextKeepAlive; public int noKeepAlivePacketTicks; public int messageRateLimitTicks; public byte protocolVersion; public boolean hasDisconnected; - public boolean loggedIn; public UserDatabaseEntry databaseEntry; public String userName; public String motd = ""; @@ -107,7 +107,7 @@ private void onDisconnect(String reason) { this.hasDisconnected = true; this.changeStatus(UserStatus.OFFLINE, "", true); this.server.clients.remove(this); - PintoServer.logger.info("%s has disconnected: %s", this.networkAddress, reason); + PintoServer.logger.info("%s has disconnected: %s", this.networkAddress, reason.replace("\n", "\\n")); this.server.eventSender.send(new ClientDisconnectedEvent(this, reason)); this.server.sendHeartbeat(); } @@ -125,6 +125,7 @@ public void sendPacket(Packet packet) { packet.getID(), this.networkAddress, (this.userName != null ? this.userName : "** UNAUTHENTICATED **")); } + this.networkClient.sendPacket(packet); this.server.eventSender.send(new SentPacketEvent(this, packet)); } @@ -135,21 +136,28 @@ public void onTick() { this.server.clients.remove(this); return; } - this.noLoginKickTicks++; + this.noLoginKickTicks++; if (this.noLoginKickTicks > 6 && this.userName == null) { this.kick("No login packet received in an acceptable time frame!"); return; } - if (this.noKeepAlivePacketTicks > 5) { + if (this.noKeepAlivePacketTicks > 2) { this.kick("Timed out"); return; } - this.sendPacket(new PacketKeepAlive()); - this.noKeepAlivePacketTicks++; - if (this.messageRateLimitTicks > 0) this.messageRateLimitTicks--; + this.ticksTillNextKeepAlive++; + if (this.ticksTillNextKeepAlive >= 5) { + this.sendPacket(new PacketKeepAlive()); + this.noKeepAlivePacketTicks++; + this.ticksTillNextKeepAlive = 0; + } + + if (this.messageRateLimitTicks > 0) { + this.messageRateLimitTicks--; + } } private void performSync() { @@ -176,7 +184,8 @@ private void performSync() { public void kick(String reason) { PintoServer.logger.info("Kicking %s (%s): %s", this.networkAddress, - (this.userName != null ? this.userName : "** UNAUTHENTICATED **"), reason); + (this.userName != null ? this.userName : "** UNAUTHENTICATED **"), + reason.replace("\n", "\\n")); this.sendPacket(new PacketLogout(reason)); this.networkClient.disconnect(null, true); this.onDisconnect(String.format("Kicked (%s)", reason)); @@ -203,9 +212,6 @@ public void changeStatus(UserStatus status, String motd, boolean noSelfUpdate) { } private void finishLogin() { - // Mark the client as logged in - this.loggedIn = true; - // Send the login packet to let the client know they have logged in this.sendPacket(new PacketLogin(this.protocolVersion, "", "")); PintoServer.logger.info("%s has logged in (Client version %s)",