From b01cbad932e2172e3fd86bf9ed75a1f4a3f8591d Mon Sep 17 00:00:00 2001 From: LOOHP Date: Tue, 4 Aug 2020 19:07:19 +0800 Subject: [PATCH] Support Bungeecord IP forwarding --- src/com/loohp/limbo/Console.java | 71 ++++++++++++++++- .../loohp/limbo/File/ServerProperties.java | 6 ++ src/com/loohp/limbo/Limbo.java | 2 +- .../loohp/limbo/Server/ClientConnection.java | 77 ++++++++++++++++--- .../Packets/PacketLoginInPluginMessaging.java | 43 +++++++++++ .../PacketLoginOutPluginMessaging.java | 48 ++++++++++++ .../Packets/PacketPlayInPluginMessaging.java | 36 +++++++++ .../Packets/PacketPlayOutPluginMessaging.java | 41 ++++++++++ .../limbo/Utils/BungeeLoginMessageUtils.java | 58 ++++++++++++++ src/com/loohp/limbo/Utils/DataTypeIO.java | 5 ++ .../{SkinUtils.java => MojangAPIUtils.java} | 20 ++++- src/mapping.json | 12 ++- src/server.properties | 3 + 13 files changed, 401 insertions(+), 21 deletions(-) create mode 100644 src/com/loohp/limbo/Server/Packets/PacketLoginInPluginMessaging.java create mode 100644 src/com/loohp/limbo/Server/Packets/PacketLoginOutPluginMessaging.java create mode 100644 src/com/loohp/limbo/Server/Packets/PacketPlayInPluginMessaging.java create mode 100644 src/com/loohp/limbo/Server/Packets/PacketPlayOutPluginMessaging.java create mode 100644 src/com/loohp/limbo/Utils/BungeeLoginMessageUtils.java rename src/com/loohp/limbo/Utils/{SkinUtils.java => MojangAPIUtils.java} (83%) diff --git a/src/com/loohp/limbo/Console.java b/src/com/loohp/limbo/Console.java index ca912d9..4436eb1 100644 --- a/src/com/loohp/limbo/Console.java +++ b/src/com/loohp/limbo/Console.java @@ -9,6 +9,7 @@ import java.io.PrintStream; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; +import java.util.Locale; import com.loohp.limbo.Player.Player; import com.loohp.limbo.Utils.CustomStringUtils; @@ -66,11 +67,77 @@ public class Console { } public class ConsoleOutputStream extends PrintStream { - - public ConsoleOutputStream(OutputStream out) { + + public ConsoleOutputStream(OutputStream out) { super(out); } + @Override + public PrintStream printf(Locale l, String format, Object... args) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + return super.printf(l, "[" + date + "] " + format, args); + } + + @Override + public PrintStream printf(String format, Object... args) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + return super.printf("[" + date + "] " + format, args); + } + + @Override + public void println() { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] "); + } + + @Override + public void println(boolean x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + x); + } + + @Override + public void println(char x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + x); + } + + @Override + public void println(char[] x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + String.valueOf(x)); + } + + @Override + public void println(double x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + x); + } + + @Override + public void println(float x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + x); + } + + @Override + public void println(int x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + x); + } + + @Override + public void println(long x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + x); + } + + @Override + public void println(Object x) { + String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); + super.println("[" + date + "] " + x); + } + @Override public void println(String string) { String date = new SimpleDateFormat("HH':'mm':'ss").format(new Date()); diff --git a/src/com/loohp/limbo/File/ServerProperties.java b/src/com/loohp/limbo/File/ServerProperties.java index 1b9420a..cc4262a 100644 --- a/src/com/loohp/limbo/File/ServerProperties.java +++ b/src/com/loohp/limbo/File/ServerProperties.java @@ -33,6 +33,7 @@ public class ServerProperties { String motdJson; String versionString; int protocol; + boolean bungeecord; Optional favicon; @@ -63,6 +64,7 @@ public class ServerProperties { allowFlight = Boolean.parseBoolean(prop.getProperty("allow-flight")); motdJson = prop.getProperty("motd"); versionString = prop.getProperty("version"); + bungeecord = Boolean.parseBoolean(prop.getProperty("bungeecord")); File png = new File("server-icon.png"); if (png.exists()) { @@ -84,6 +86,10 @@ public class ServerProperties { System.out.println("Loaded server.properties"); } + public boolean isBungeecord() { + return bungeecord; + } + public Optional getFavicon() { return favicon; } diff --git a/src/com/loohp/limbo/Limbo.java b/src/com/loohp/limbo/Limbo.java index f41cadf..5e68755 100644 --- a/src/com/loohp/limbo/Limbo.java +++ b/src/com/loohp/limbo/Limbo.java @@ -215,7 +215,7 @@ public class Limbo { base = base.replace("%PROTOCOL%", String.valueOf(properties.getProtocol())); base = base.replace("%MOTD%", properties.getMotdJson()); base = base.replace("%MAXPLAYERS%", String.valueOf(properties.getMaxPlayers())); - base = base.replace("%ONLINECLIENTS%", String.valueOf(server.getClients().size())); + base = base.replace("%ONLINECLIENTS%", String.valueOf(getPlayers().size())); if (properties.getFavicon().isPresent()) { String icon = "\"favicon\":\"data:image/png;base64," + ImageUtils.imgToBase64String(properties.getFavicon().get(), "png") + "\","; diff --git a/src/com/loohp/limbo/Server/ClientConnection.java b/src/com/loohp/limbo/Server/ClientConnection.java index 80925a8..e4e4e5a 100644 --- a/src/com/loohp/limbo/Server/ClientConnection.java +++ b/src/com/loohp/limbo/Server/ClientConnection.java @@ -3,6 +3,7 @@ package com.loohp.limbo.Server; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.net.InetAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Optional; @@ -16,6 +17,7 @@ import com.loohp.limbo.Player.Player; import com.loohp.limbo.Server.Packets.Packet; import com.loohp.limbo.Server.Packets.PacketHandshakingIn; import com.loohp.limbo.Server.Packets.PacketLoginInLoginStart; +import com.loohp.limbo.Server.Packets.PacketLoginOutDisconnect; import com.loohp.limbo.Server.Packets.PacketLoginOutLoginSuccess; import com.loohp.limbo.Server.Packets.PacketOut; import com.loohp.limbo.Server.Packets.PacketPlayInChat; @@ -42,8 +44,8 @@ import com.loohp.limbo.Server.Packets.PacketStatusOutPong; import com.loohp.limbo.Server.Packets.PacketStatusOutResponse; import com.loohp.limbo.Utils.CustomStringUtils; import com.loohp.limbo.Utils.DataTypeIO; -import com.loohp.limbo.Utils.SkinUtils; -import com.loohp.limbo.Utils.SkinUtils.SkinResponse; +import com.loohp.limbo.Utils.MojangAPIUtils; +import com.loohp.limbo.Utils.MojangAPIUtils.SkinResponse; import com.loohp.limbo.World.BlockPosition; import com.loohp.limbo.World.DimensionRegistry; import com.loohp.limbo.World.World; @@ -73,10 +75,17 @@ public class ClientConnection extends Thread { private DataOutputStream output; + private InetAddress iNetAddress; + public ClientConnection(Socket client_socket) { this.client_socket = client_socket; + this.iNetAddress = client_socket.getInetAddress(); } + public InetAddress getiNetAddress() { + return iNetAddress; + } + public long getLastKeepAlivePayLoad() { return lastKeepAlivePayLoad; } @@ -123,6 +132,23 @@ public class ClientConnection extends Thread { e.printStackTrace(); } } + + public void disconnectDuringLogin(BaseComponent[] reason) { + try { + PacketLoginOutDisconnect packet = new PacketLoginOutDisconnect(ComponentSerializer.toString(reason)); + byte[] packetByte = packet.serializePacket(); + DataTypeIO.writeVarInt(output, packetByte.length); + output.write(packetByte); + output.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + client_socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } @Override public void run() { @@ -133,8 +159,17 @@ public class ClientConnection extends Thread { DataInputStream input = new DataInputStream(client_socket.getInputStream()); output = new DataOutputStream(client_socket.getOutputStream()); DataTypeIO.readVarInt(input); - int handShakeId = DataTypeIO.readVarInt(input); - PacketHandshakingIn handshake = (PacketHandshakingIn) Packet.getHandshakeIn().get(handShakeId).getConstructor(DataInputStream.class).newInstance(input); + + //int handShakeId = DataTypeIO.readVarInt(input); + DataTypeIO.readVarInt(input); + + PacketHandshakingIn handshake = new PacketHandshakingIn(input); + + boolean isBungeecord = Limbo.getInstance().getServerProperties().isBungeecord(); + String bungeeForwarding = handshake.getServerAddress(); + UUID bungeeUUID = null; + SkinResponse bungeeSkin = null; + switch (handshake.getHandshakeType()) { case STATUS: state = ClientState.STATUS; @@ -146,7 +181,7 @@ public class ClientConnection extends Thread { //do nothing } else if (packetType.equals(PacketStatusInRequest.class)) { String str = client_socket.getInetAddress().getHostName() + ":" + client_socket.getPort(); - System.out.println("[/" + str + "] <-> InitialHandler has pinged"); + Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Handshake Status has pinged"); PacketStatusOutResponse packet = new PacketStatusOutResponse(Limbo.getInstance().getServerListResponseJson()); sendPacket(packet); } else if (packetType.equals(PacketStatusInPing.class)) { @@ -159,6 +194,27 @@ public class ClientConnection extends Thread { break; case LOGIN: state = ClientState.LOGIN; + + if (isBungeecord) { + try { + String[] data = bungeeForwarding.split("\\x00"); + //String host = data[0]; + String ip = data[1]; + + bungeeUUID = UUID.fromString(data[2].replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5")); + iNetAddress = InetAddress.getByName(ip); + + String skinJson = data[3]; + + String skin = skinJson.split("\"value\":\"")[1].split("\"")[0]; + String signature = skinJson.split("\"signature\":\"")[1].split("\"")[0]; + bungeeSkin = new SkinResponse(skin, signature); + } catch (Exception e) { + Limbo.getInstance().getConsole().sendMessage("If you wish to use bungeecord's IP forwarding, please enable that in your bungeecord config.yml as well!"); + disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")}); + } + } + while (client_socket.isConnected()) { int size = DataTypeIO.readVarInt(input); int packetId = DataTypeIO.readVarInt(input); @@ -169,7 +225,8 @@ public class ClientConnection extends Thread { } else if (packetType.equals(PacketLoginInLoginStart.class)) { PacketLoginInLoginStart start = new PacketLoginInLoginStart(input); String username = start.getUsername(); - UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8)); + UUID uuid = isBungeecord ? bungeeUUID : UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8)); + PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(uuid, username); sendPacket(success); @@ -216,7 +273,7 @@ public class ClientConnection extends Thread { player.setLocation(new Location(world, s.getX(), s.getY(), s.getZ(), s.getYaw(), s.getPitch())); sendPacket(positionLook); - SkinResponse skinresponce = SkinUtils.getSkinFromMojangServer(player.getName()); + SkinResponse skinresponce = isBungeecord ? bungeeSkin : MojangAPIUtils.getSkinFromMojangServer(player.getName()); PlayerSkinProperty skin = skinresponce != null ? new PlayerSkinProperty(skinresponce.getSkin(), skinresponce.getSignature()) : null; PacketPlayOutPlayerInfo info = new PacketPlayOutPlayerInfo(PlayerInfoAction.ADD_PLAYER, player.getUUID(), new PlayerInfoData.PlayerInfoDataAddPlayer(player.getName(), Optional.ofNullable(skin), p.getDefaultGamemode(), 0, false, Optional.empty())); sendPacket(info); @@ -240,7 +297,7 @@ public class ClientConnection extends Thread { sendPacket(abilities); String str = client_socket.getInetAddress().getHostName() + ":" + client_socket.getPort() + "|" + player.getName(); - System.out.println("[/" + str + "] <-> Player had connected to the Limbo server!"); + Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!"); while (client_socket.isConnected()) { try { @@ -272,7 +329,7 @@ public class ClientConnection extends Thread { } else if (packetType.equals(PacketPlayInKeepAlive.class)) { PacketPlayInKeepAlive alive = new PacketPlayInKeepAlive(input); if (alive.getPayload() != lastKeepAlivePayLoad) { - System.out.println("Incorrect Payload recieved in KeepAlive packet for player " + player.getName()); + Limbo.getInstance().getConsole().sendMessage("Incorrect Payload recieved in KeepAlive packet for player " + player.getName()); break; } } else if (packetType.equals(PacketPlayInChat.class)) { @@ -299,7 +356,7 @@ public class ClientConnection extends Thread { } } str = client_socket.getInetAddress().getHostName() + ":" + client_socket.getPort() + "|" + player.getName(); - System.out.println("[/" + str + "] <-> Player had disconnected!"); + Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had disconnected!"); } } catch (Exception e) {} diff --git a/src/com/loohp/limbo/Server/Packets/PacketLoginInPluginMessaging.java b/src/com/loohp/limbo/Server/Packets/PacketLoginInPluginMessaging.java new file mode 100644 index 0000000..18d1600 --- /dev/null +++ b/src/com/loohp/limbo/Server/Packets/PacketLoginInPluginMessaging.java @@ -0,0 +1,43 @@ +package com.loohp.limbo.Server.Packets; + +import java.io.DataInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import com.loohp.limbo.Utils.DataTypeIO; +import com.loohp.limbo.Utils.NamespacedKey; + +public class PacketLoginInPluginMessaging extends PacketIn { + + private int messageId; + private NamespacedKey channel; + private byte[] data; + + public PacketLoginInPluginMessaging(int messageId, NamespacedKey channel, byte[] data) { + this.messageId = messageId; + this.channel = channel; + this.data = data; + } + + public PacketLoginInPluginMessaging(DataInputStream in, int packetLength, int packetId) throws IOException { + messageId = DataTypeIO.readVarInt(in); + String rawChannel = DataTypeIO.readString(in); + channel = new NamespacedKey(rawChannel); + int dataLength = packetLength - DataTypeIO.getVarIntLength(packetId) - DataTypeIO.getVarIntLength(messageId) - DataTypeIO.getStringLength(rawChannel, StandardCharsets.UTF_8); + data = new byte[dataLength]; + in.read(data); + } + + public int getMessageId() { + return messageId; + } + + public NamespacedKey getChannel() { + return channel; + } + + public byte[] getData() { + return data; + } + +} diff --git a/src/com/loohp/limbo/Server/Packets/PacketLoginOutPluginMessaging.java b/src/com/loohp/limbo/Server/Packets/PacketLoginOutPluginMessaging.java new file mode 100644 index 0000000..08a0335 --- /dev/null +++ b/src/com/loohp/limbo/Server/Packets/PacketLoginOutPluginMessaging.java @@ -0,0 +1,48 @@ +package com.loohp.limbo.Server.Packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import com.loohp.limbo.Utils.DataTypeIO; +import com.loohp.limbo.Utils.NamespacedKey; + +public class PacketLoginOutPluginMessaging extends PacketOut { + + private int messageId; + private NamespacedKey channel; + private byte[] data; + + public PacketLoginOutPluginMessaging(int messageId, NamespacedKey channel, byte[] data) { + this.messageId = messageId; + this.channel = channel; + this.data = data; + } + + public int getMessageId() { + return messageId; + } + + public NamespacedKey getChannel() { + return channel; + } + + public byte[] getData() { + return data; + } + + @Override + public byte[] serializePacket() throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + DataOutputStream output = new DataOutputStream(buffer); + output.writeByte(Packet.getLoginOut().get(getClass())); + DataTypeIO.writeVarInt(output, messageId); + DataTypeIO.writeString(output, channel.toString(), StandardCharsets.UTF_8); + output.write(data); + + return buffer.toByteArray(); + } + +} diff --git a/src/com/loohp/limbo/Server/Packets/PacketPlayInPluginMessaging.java b/src/com/loohp/limbo/Server/Packets/PacketPlayInPluginMessaging.java new file mode 100644 index 0000000..2281920 --- /dev/null +++ b/src/com/loohp/limbo/Server/Packets/PacketPlayInPluginMessaging.java @@ -0,0 +1,36 @@ +package com.loohp.limbo.Server.Packets; + +import java.io.DataInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import com.loohp.limbo.Utils.DataTypeIO; +import com.loohp.limbo.Utils.NamespacedKey; + +public class PacketPlayInPluginMessaging extends PacketIn { + + private NamespacedKey channel; + private byte[] data; + + public PacketPlayInPluginMessaging(NamespacedKey channel, byte[] data) { + this.channel = channel; + this.data = data; + } + + public PacketPlayInPluginMessaging(DataInputStream in, int packetLength, int packetId) throws IOException { + String rawChannel = DataTypeIO.readString(in); + channel = new NamespacedKey(rawChannel); + int dataLength = packetLength - DataTypeIO.getVarIntLength(packetId) - DataTypeIO.getStringLength(rawChannel, StandardCharsets.UTF_8); + data = new byte[dataLength]; + in.read(data); + } + + public NamespacedKey getChannel() { + return channel; + } + + public byte[] getData() { + return data; + } + +} diff --git a/src/com/loohp/limbo/Server/Packets/PacketPlayOutPluginMessaging.java b/src/com/loohp/limbo/Server/Packets/PacketPlayOutPluginMessaging.java new file mode 100644 index 0000000..038de63 --- /dev/null +++ b/src/com/loohp/limbo/Server/Packets/PacketPlayOutPluginMessaging.java @@ -0,0 +1,41 @@ +package com.loohp.limbo.Server.Packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import com.loohp.limbo.Utils.DataTypeIO; +import com.loohp.limbo.Utils.NamespacedKey; + +public class PacketPlayOutPluginMessaging extends PacketOut { + + private NamespacedKey channel; + private byte[] data; + + public PacketPlayOutPluginMessaging(NamespacedKey channel, byte[] data) { + this.channel = channel; + this.data = data; + } + + public NamespacedKey getChannel() { + return channel; + } + + public byte[] getData() { + return data; + } + + @Override + public byte[] serializePacket() throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + DataOutputStream output = new DataOutputStream(buffer); + output.writeByte(Packet.getPlayOut().get(getClass())); + DataTypeIO.writeString(output, channel.toString(), StandardCharsets.UTF_8); + output.write(data); + + return buffer.toByteArray(); + } + +} diff --git a/src/com/loohp/limbo/Utils/BungeeLoginMessageUtils.java b/src/com/loohp/limbo/Utils/BungeeLoginMessageUtils.java new file mode 100644 index 0000000..267a5ba --- /dev/null +++ b/src/com/loohp/limbo/Utils/BungeeLoginMessageUtils.java @@ -0,0 +1,58 @@ +package com.loohp.limbo.Utils; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.UUID; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import com.loohp.limbo.Server.Packets.PacketPlayOutPluginMessaging; + +public class BungeeLoginMessageUtils { + + public static void sendUUIDRequest(DataOutputStream output) throws IOException { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("UUID"); + + PacketPlayOutPluginMessaging packet = new PacketPlayOutPluginMessaging(new NamespacedKey("bungeecord", "main"), out.toByteArray()); + byte[] packetByte = packet.serializePacket(); + DataTypeIO.writeVarInt(output, packetByte.length); + output.write(packetByte); + } + + public static UUID readUUIDResponse(byte[] data) { + ByteArrayDataInput in = ByteStreams.newDataInput(data); + String subchannel = in.readUTF(); + if (subchannel.equals("UUID")) { + return UUID.fromString(in.readUTF()); + } else { + throw new RuntimeException("Bungeecord Message receieved is not an IP"); + } + } + + public static void sendIPRequest(DataOutputStream output) throws IOException { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("IP"); + + PacketPlayOutPluginMessaging packet = new PacketPlayOutPluginMessaging(new NamespacedKey("bungeecord", "main"), out.toByteArray()); + byte[] packetByte = packet.serializePacket(); + DataTypeIO.writeVarInt(output, packetByte.length); + output.write(packetByte); + } + + public static InetAddress readIPResponse(byte[] data) throws UnknownHostException { + ByteArrayDataInput in = ByteStreams.newDataInput(data); + String subchannel = in.readUTF(); + if (subchannel.equals("IP")) { + String ip = in.readUTF(); + in.readInt(); + return InetAddress.getByName(ip); + } else { + throw new RuntimeException("Bungeecord Message receieved is not an IP"); + } + } + +} diff --git a/src/com/loohp/limbo/Utils/DataTypeIO.java b/src/com/loohp/limbo/Utils/DataTypeIO.java index 0b682ff..d4d5b4e 100644 --- a/src/com/loohp/limbo/Utils/DataTypeIO.java +++ b/src/com/loohp/limbo/Utils/DataTypeIO.java @@ -40,6 +40,11 @@ public class DataTypeIO { return new String(b); } + public static int getStringLength(String string, Charset charset) throws IOException { + byte[] bytes = string.getBytes(charset); + return bytes.length; + } + public static void writeString(DataOutputStream out, String string, Charset charset) throws IOException { byte[] bytes = string.getBytes(charset); writeVarInt(out, bytes.length); diff --git a/src/com/loohp/limbo/Utils/SkinUtils.java b/src/com/loohp/limbo/Utils/MojangAPIUtils.java similarity index 83% rename from src/com/loohp/limbo/Utils/SkinUtils.java rename to src/com/loohp/limbo/Utils/MojangAPIUtils.java index adc53bf..7227705 100644 --- a/src/com/loohp/limbo/Utils/SkinUtils.java +++ b/src/com/loohp/limbo/Utils/MojangAPIUtils.java @@ -9,7 +9,7 @@ import java.util.stream.Collectors; import javax.net.ssl.HttpsURLConnection; -public class SkinUtils { +public class MojangAPIUtils { public static class SkinResponse { @@ -31,7 +31,7 @@ public class SkinUtils { } - public static SkinResponse getSkinFromMojangServer(String username) { + public static UUID getOnlineUUIDOfPlayerFromMojang(String username) { try { URL url = new URL("https://api.mojang.com/users/profiles/minecraft/" + username); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); @@ -42,8 +42,12 @@ public class SkinUtils { connection.addRequestProperty("Pragma", "no-cache"); if (connection.getResponseCode() == HttpsURLConnection.HTTP_OK) { String reply = new BufferedReader(new InputStreamReader(connection.getInputStream())).readLine(); - String uuid = reply.split("\"id\":\"")[1].split("\"")[0]; - return getSkinFromMojangServer(UUID.fromString(uuid.replaceFirst( "([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5" ))); + if (!reply.contains("\"error\":\"BadRequestException\"")) { + String uuid = reply.split("\"id\":\"")[1].split("\"")[0]; + return UUID.fromString(uuid.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5")); + } else { + return null; + } } else { System.out.println("Connection could not be opened (Response code " + connection.getResponseCode() + ", " + connection.getResponseMessage() + ")"); return null; @@ -54,6 +58,14 @@ public class SkinUtils { } } + public static SkinResponse getSkinFromMojangServer(String username) { + UUID uuid = getOnlineUUIDOfPlayerFromMojang(username); + if (uuid == null) { + return null; + } + return getSkinFromMojangServer(uuid); + } + public static SkinResponse getSkinFromMojangServer(UUID uuid) { try { URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid.toString() + "?unsigned=false"); diff --git a/src/mapping.json b/src/mapping.json index b4657b6..7f01fe4 100644 --- a/src/mapping.json +++ b/src/mapping.json @@ -3,18 +3,21 @@ "0x00": "PacketHandshakingIn" }, "LoginIn": { - "0x00": "PacketLoginInLoginStart" + "0x00": "PacketLoginInLoginStart", + "0x02": "PacketLoginInPluginMessaging" }, "LoginOut": { "PacketLoginOutLoginSuccess": "0x02", - "PacketLoginOutDisconnect": "0x00" + "PacketLoginOutDisconnect": "0x00", + "PacketLoginOutPluginMessaging": "0x04", }, "PlayIn": { "0x10": "PacketPlayInKeepAlive", "0x03": "PacketPlayInChat", "0x13": "PacketPlayInPositionAndLook", "0x12": "PacketPlayInPosition", - "0x14": "PacketPlayInRotation" + "0x14": "PacketPlayInRotation", + "0x0B": "PacketPlayInPluginMessaging" }, "PlayOut": { "PacketPlayOutLogin": "0x25", @@ -27,7 +30,8 @@ "PacketPlayOutPlayerInfo": "0x33", "PacketPlayOutUpdateViewPosition": "0x40", "PacketPlayOutShowPlayerSkins": "0x44", - "PacketPlayOutDisconnect": "0x1A" + "PacketPlayOutDisconnect": "0x1A", + "PacketPlayOutPluginMessaging": "0x17" }, "StatusIn": { "0x01": "PacketStatusInPing", diff --git a/src/server.properties b/src/server.properties index e94dcc9..9a0358f 100644 --- a/src/server.properties +++ b/src/server.properties @@ -7,6 +7,9 @@ server-port=30000 #Server ip, localhost for local access only server-ip=localhost +#Whether this is server is behind a bungeecord proxy +bungeecord=true + #World Name and the Schematic file containing map level-name=world;spawn.schem