diff --git a/src/main/java/net/minestom/server/extras/bungee/BungeeCordProxy.java b/src/main/java/net/minestom/server/extras/bungee/BungeeCordProxy.java index a1c7d04a0..8c909ad35 100644 --- a/src/main/java/net/minestom/server/extras/bungee/BungeeCordProxy.java +++ b/src/main/java/net/minestom/server/extras/bungee/BungeeCordProxy.java @@ -1,5 +1,12 @@ package net.minestom.server.extras.bungee; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import net.minestom.server.entity.PlayerSkin; +import org.jetbrains.annotations.NotNull; + /** * BungeeCord forwarding support. This does not count as a security feature and you will still be required to manage your firewall. *
@@ -24,4 +31,29 @@ public final class BungeeCordProxy {
public static boolean isEnabled() {
return enabled;
}
+
+ public static PlayerSkin readSkin(@NotNull String json) {
+ JsonArray array = JsonParser.parseString(json).getAsJsonArray();
+ String skinTexture = null;
+ String skinSignature = null;
+
+ for (JsonElement element : array) {
+ JsonObject jsonObject = element.getAsJsonObject();
+ final String name = jsonObject.get("name").getAsString();
+ final String value = jsonObject.get("value").getAsString();
+ final String signature = jsonObject.get("signature").getAsString();
+
+ if (name.equals("textures")) {
+ skinTexture = value;
+ skinSignature = signature;
+ }
+
+ }
+
+ if (skinTexture != null && skinSignature != null) {
+ return new PlayerSkin(skinTexture, skinSignature);
+ } else {
+ return null;
+ }
+ }
}
diff --git a/src/main/java/net/minestom/server/network/PacketProcessor.java b/src/main/java/net/minestom/server/network/PacketProcessor.java
index 2b3f2b03d..01744d5a5 100644
--- a/src/main/java/net/minestom/server/network/PacketProcessor.java
+++ b/src/main/java/net/minestom/server/network/PacketProcessor.java
@@ -149,12 +149,20 @@ public final class PacketProcessor {
* @param reader the buffer containing the packet
*/
private void safeRead(@NotNull PlayerConnection connection, @NotNull Readable readable, @NotNull BinaryReader reader) {
+ final int readableBytes = reader.getBuffer().readableBytes();
+
+ // Check if there is anything to read
+ if (readableBytes == 0) {
+ return;
+ }
+
try {
readable.read(reader);
} catch (Exception e) {
final Player player = connection.getPlayer();
final String username = player != null ? player.getUsername() : "null";
LOGGER.warn("Connection " + connection.getRemoteAddress() + " (" + username + ") sent an unexpected packet.");
+ e.printStackTrace();
}
}
}
diff --git a/src/main/java/net/minestom/server/network/packet/client/handshake/HandshakePacket.java b/src/main/java/net/minestom/server/network/packet/client/handshake/HandshakePacket.java
index 75611ef9e..b64f08061 100644
--- a/src/main/java/net/minestom/server/network/packet/client/handshake/HandshakePacket.java
+++ b/src/main/java/net/minestom/server/network/packet/client/handshake/HandshakePacket.java
@@ -3,6 +3,7 @@ package net.minestom.server.network.packet.client.handshake;
import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
+import net.minestom.server.entity.PlayerSkin;
import net.minestom.server.extras.bungee.BungeeCordProxy;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
@@ -13,6 +14,7 @@ import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import java.net.SocketAddress;
+import java.util.UUID;
public class HandshakePacket implements ClientPreplayPacket {
@@ -31,7 +33,7 @@ public class HandshakePacket implements ClientPreplayPacket {
@Override
public void read(@NotNull BinaryReader reader) {
this.protocolVersion = reader.readVarInt();
- this.serverAddress = reader.readSizedString(256);
+ this.serverAddress = reader.readSizedString(BungeeCordProxy.isEnabled() ? Short.MAX_VALUE : 255);
this.serverPort = reader.readUnsignedShort();
this.nextState = reader.readVarInt();
}
@@ -49,8 +51,25 @@ public class HandshakePacket implements ClientPreplayPacket {
if (split.length == 3 || split.length == 4) {
this.serverAddress = split[0];
- final SocketAddress socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort());
+ final SocketAddress socketAddress = new java.net.InetSocketAddress(split[1],
+ ((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort());
nettyPlayerConnection.setRemoteAddress(socketAddress);
+
+ UUID playerUuid = UUID.fromString(
+ split[2]
+ .replaceFirst(
+ "(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)", "$1-$2-$3-$4-$5"
+ )
+ );
+ PlayerSkin playerSkin = null;
+
+ if (split.length == 4) {
+ playerSkin = BungeeCordProxy.readSkin(split[3]);
+ }
+
+ nettyPlayerConnection.UNSAFE_setBungeeUuid(playerUuid);
+ nettyPlayerConnection.UNSAFE_setBungeeSkin(playerSkin);
+
} else {
nettyPlayerConnection.sendPacket(new LoginDisconnectPacket(INVALID_BUNGEE_FORWARDING));
nettyPlayerConnection.disconnect();
diff --git a/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java b/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java
index 5a088174c..dd5e0a36c 100644
--- a/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java
+++ b/src/main/java/net/minestom/server/network/packet/client/login/LoginStartPacket.java
@@ -3,7 +3,9 @@ package net.minestom.server.network.packet.client.login;
import net.minestom.server.MinecraftServer;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
+import net.minestom.server.entity.Player;
import net.minestom.server.extras.MojangAuth;
+import net.minestom.server.extras.bungee.BungeeCordProxy;
import net.minestom.server.extras.velocity.VelocityProxy;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
@@ -27,8 +29,10 @@ public class LoginStartPacket implements ClientPreplayPacket {
@Override
public void process(@NotNull PlayerConnection connection) {
+ final boolean isNettyClient = connection instanceof NettyPlayerConnection;
+
// Cache the login username and start compression if enabled
- if (connection instanceof NettyPlayerConnection) {
+ if (isNettyClient) {
NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) connection;
nettyPlayerConnection.UNSAFE_setLoginUsername(username);
@@ -40,7 +44,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
}
// Proxy support (only for netty clients)
- if (connection instanceof NettyPlayerConnection) {
+ if (isNettyClient) {
final NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) connection;
{
@@ -65,7 +69,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
}
- if (MojangAuth.isUsingMojangAuth() && connection instanceof NettyPlayerConnection) {
+ if (MojangAuth.isUsingMojangAuth() && isNettyClient) {
// Mojang auth
if (CONNECTION_MANAGER.getPlayer(username) != null) {
connection.sendPacket(new LoginDisconnectPacket(ALREADY_CONNECTED_JSON));
@@ -79,10 +83,16 @@ public class LoginStartPacket implements ClientPreplayPacket {
EncryptionRequestPacket encryptionRequestPacket = new EncryptionRequestPacket(nettyPlayerConnection);
nettyPlayerConnection.sendPacket(encryptionRequestPacket);
} else {
+ final boolean bungee = BungeeCordProxy.isEnabled();
// Offline
- final UUID playerUuid = CONNECTION_MANAGER.getPlayerConnectionUuid(connection, username);
+ final UUID playerUuid = bungee && isNettyClient ?
+ ((NettyPlayerConnection) connection).getBungeeUuid() :
+ CONNECTION_MANAGER.getPlayerConnectionUuid(connection, username);
- CONNECTION_MANAGER.startPlayState(connection, playerUuid, username);
+ Player player = CONNECTION_MANAGER.startPlayState(connection, playerUuid, username);
+ if (bungee && isNettyClient) {
+ player.setSkin(((NettyPlayerConnection) connection).getBungeeSkin());
+ }
}
}
diff --git a/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java b/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java
index 3848b5c45..62fdc947f 100644
--- a/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java
+++ b/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java
@@ -4,6 +4,7 @@ import io.netty.channel.Channel;
import io.netty.channel.socket.SocketChannel;
import lombok.Getter;
import lombok.Setter;
+import net.minestom.server.entity.PlayerSkin;
import net.minestom.server.extras.mojangAuth.Decrypter;
import net.minestom.server.extras.mojangAuth.Encrypter;
import net.minestom.server.extras.mojangAuth.MojangCrypt;
@@ -18,6 +19,7 @@ import org.jetbrains.annotations.Nullable;
import javax.crypto.SecretKey;
import java.net.SocketAddress;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -40,6 +42,7 @@ public class NettyPlayerConnection extends PlayerConnection {
@Setter
private byte[] nonce = new byte[4];
+ // Data from client packets
private String loginUsername;
private String serverAddress;
private int serverPort;
@@ -48,6 +51,10 @@ public class NettyPlayerConnection extends PlayerConnection {
// cleared once the player enters the play state
private final Map
diff --git a/src/test/java/demo/Main.java b/src/test/java/demo/Main.java
index aa47ce449..d48d58588 100644
--- a/src/test/java/demo/Main.java
+++ b/src/test/java/demo/Main.java
@@ -6,8 +6,8 @@ import demo.blocks.UpdatableBlockDemo;
import demo.commands.*;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
+import net.minestom.server.extras.bungee.BungeeCordProxy;
import net.minestom.server.extras.optifine.OptifineSupport;
-import net.minestom.server.extras.velocity.VelocityProxy;
import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.rule.vanilla.RedstonePlacementRule;
import net.minestom.server.storage.StorageManager;
@@ -52,8 +52,8 @@ public class Main {
OptifineSupport.enable();
- VelocityProxy.enable("rBeJJ79W4MVU");
- //BungeeCordProxy.enable();
+ //VelocityProxy.enable("rBeJJ79W4MVU");
+ BungeeCordProxy.enable();
// MojangAuth.init();