From eccdf87f2217ae3a0f6943134d8c61df3f9d0097 Mon Sep 17 00:00:00 2001 From: md_5 Date: Wed, 8 Jun 2022 02:00:00 +1000 Subject: [PATCH] Minecraft 1.19 support --- api/pom.xml | 10 +- bootstrap/pom.xml | 4 +- chat/pom.xml | 4 +- config/pom.xml | 4 +- event/pom.xml | 4 +- log/pom.xml | 4 +- module/cmd-alert/pom.xml | 4 +- module/cmd-find/pom.xml | 4 +- module/cmd-list/pom.xml | 4 +- module/cmd-send/pom.xml | 4 +- module/cmd-server/pom.xml | 4 +- module/pom.xml | 4 +- module/reconnect-yaml/pom.xml | 4 +- native/pom.xml | 4 +- pom.xml | 4 +- protocol/pom.xml | 4 +- .../protocol/AbstractPacketHandler.java | 20 +++ .../md_5/bungee/protocol/DefinedPacket.java | 61 +++++++ .../net/md_5/bungee/protocol/Location.java | 11 ++ .../md_5/bungee/protocol/PlayerPublicKey.java | 12 ++ .../net/md_5/bungee/protocol/Property.java | 19 ++ .../net/md_5/bungee/protocol/Protocol.java | 95 +++++++--- .../bungee/protocol/ProtocolConstants.java | 11 +- .../bungee/protocol/packet/ClientChat.java | 50 ++++++ .../bungee/protocol/packet/ClientCommand.java | 68 ++++++++ .../md_5/bungee/protocol/packet/Commands.java | 163 +++++++++++------- .../protocol/packet/EncryptionResponse.java | 31 +++- .../md_5/bungee/protocol/packet/Login.java | 25 ++- .../bungee/protocol/packet/LoginRequest.java | 15 +- .../bungee/protocol/packet/LoginSuccess.java | 10 ++ .../bungee/protocol/packet/PlayerChat.java | 84 +++++++++ .../protocol/packet/PlayerListItem.java | 48 ++---- .../md_5/bungee/protocol/packet/Respawn.java | 25 ++- .../bungee/protocol/packet/SystemChat.java | 41 +++++ proxy/pom.xml | 21 +-- .../java/net/md_5/bungee/EncryptionUtil.java | 64 ++++++- .../java/net/md_5/bungee/ServerConnector.java | 10 +- .../java/net/md_5/bungee/UserConnection.java | 13 +- .../net/md_5/bungee/conf/Configuration.java | 5 + .../bungee/connection/InitialHandler.java | 28 ++- .../md_5/bungee/connection/LoginResult.java | 11 +- .../bungee/connection/UpstreamBridge.java | 40 ++++- .../net/md_5/bungee/entitymap/EntityMap.java | 2 + .../bungee/entitymap/EntityMap_1_16_2.java | 2 + .../java/net/md_5/bungee/tab/TabList.java | 12 +- proxy/src/main/resources/messages.properties | 3 + .../resources/yggdrasil_session_pubkey.der | Bin 0 -> 550 bytes query/pom.xml | 4 +- slf4j/pom.xml | 4 +- 49 files changed, 851 insertions(+), 227 deletions(-) create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/Location.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/PlayerPublicKey.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/Property.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientChat.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientCommand.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerChat.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/SystemChat.java create mode 100644 proxy/src/main/resources/yggdrasil_session_pubkey.der diff --git a/api/pom.xml b/api/pom.xml index 79cab35b..22735ae6 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-api - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-API @@ -52,21 +52,21 @@ org.apache.maven maven-resolver-provider - 3.8.4 + 3.8.5 provided org.apache.maven.resolver maven-resolver-connector-basic - 1.7.2 + 1.8.0 provided org.apache.maven.resolver maven-resolver-transport-http - 1.7.2 + 1.8.0 provided diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index c7eabe73..6e5c197d 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-bootstrap - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Bootstrap diff --git a/chat/pom.xml b/chat/pom.xml index 0c244852..a8a94a9c 100644 --- a/chat/pom.xml +++ b/chat/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-chat - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Chat diff --git a/config/pom.xml b/config/pom.xml index 87208ac2..6557b88d 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-config - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Config diff --git a/event/pom.xml b/event/pom.xml index 37320a3b..46c38144 100644 --- a/event/pom.xml +++ b/event/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-event - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Event diff --git a/log/pom.xml b/log/pom.xml index 28545b92..8bba9f62 100644 --- a/log/pom.xml +++ b/log/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-log - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Log diff --git a/module/cmd-alert/pom.xml b/module/cmd-alert/pom.xml index dcf93888..88b4aa99 100644 --- a/module/cmd-alert/pom.xml +++ b/module/cmd-alert/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-alert - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar cmd_alert diff --git a/module/cmd-find/pom.xml b/module/cmd-find/pom.xml index 59163873..cb15b266 100644 --- a/module/cmd-find/pom.xml +++ b/module/cmd-find/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-find - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar cmd_find diff --git a/module/cmd-list/pom.xml b/module/cmd-list/pom.xml index 23f69747..81a660bf 100644 --- a/module/cmd-list/pom.xml +++ b/module/cmd-list/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-list - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar cmd_list diff --git a/module/cmd-send/pom.xml b/module/cmd-send/pom.xml index db9e4762..574b6af3 100644 --- a/module/cmd-send/pom.xml +++ b/module/cmd-send/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-send - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar cmd_send diff --git a/module/cmd-server/pom.xml b/module/cmd-server/pom.xml index 06f55aa8..f9de38c4 100644 --- a/module/cmd-server/pom.xml +++ b/module/cmd-server/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-server - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar cmd_server diff --git a/module/pom.xml b/module/pom.xml index 32d966a0..cbc26049 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT pom BungeeCord Modules diff --git a/module/reconnect-yaml/pom.xml b/module/reconnect-yaml/pom.xml index 4bb408fe..4f3332dd 100644 --- a/module/reconnect-yaml/pom.xml +++ b/module/reconnect-yaml/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-reconnect-yaml - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar reconnect_yaml diff --git a/native/pom.xml b/native/pom.xml index aa62ce2a..f7773d80 100644 --- a/native/pom.xml +++ b/native/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-native - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Native diff --git a/pom.xml b/pom.xml index 1b1e8e9d..27f16b27 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT pom BungeeCord-Parent @@ -73,7 +73,7 @@ unknown 1.18.22 - 4.1.72.Final + 4.1.77.Final 1.8 1.8 UTF-8 diff --git a/protocol/pom.xml b/protocol/pom.xml index e7a492f6..de6bd2e0 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-protocol - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Protocol diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java index 15a61b7e..35236382 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java @@ -3,6 +3,8 @@ package net.md_5.bungee.protocol; import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.ClearTitles; +import net.md_5.bungee.protocol.packet.ClientChat; +import net.md_5.bungee.protocol.packet.ClientCommand; import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.ClientStatus; import net.md_5.bungee.protocol.packet.Commands; @@ -21,6 +23,7 @@ import net.md_5.bungee.protocol.packet.LoginPayloadResponse; import net.md_5.bungee.protocol.packet.LoginRequest; import net.md_5.bungee.protocol.packet.LoginSuccess; import net.md_5.bungee.protocol.packet.PingPacket; +import net.md_5.bungee.protocol.packet.PlayerChat; import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter; import net.md_5.bungee.protocol.packet.PlayerListItem; import net.md_5.bungee.protocol.packet.PluginMessage; @@ -32,6 +35,7 @@ import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; import net.md_5.bungee.protocol.packet.Subtitle; +import net.md_5.bungee.protocol.packet.SystemChat; import net.md_5.bungee.protocol.packet.TabCompleteRequest; import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.Team; @@ -78,6 +82,22 @@ public abstract class AbstractPacketHandler { } + public void handle(ClientChat chat) throws Exception + { + } + + public void handle(PlayerChat chat) throws Exception + { + } + + public void handle(SystemChat chat) throws Exception + { + } + + public void handle(ClientCommand command) throws Exception + { + } + public void handle(Respawn respawn) throws Exception { } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java index 8b2a2822..3af9c94b 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java @@ -214,6 +214,67 @@ public abstract class DefinedPacket return new UUID( input.readLong(), input.readLong() ); } + public static void writeProperties(Property[] properties, ByteBuf buf) + { + writeVarInt( properties.length, buf ); + for ( Property prop : properties ) + { + writeString( prop.getName(), buf ); + writeString( prop.getValue(), buf ); + if ( prop.getSignature() != null ) + { + buf.writeBoolean( true ); + writeString( prop.getSignature(), buf ); + } else + { + buf.writeBoolean( false ); + } + } + } + + public static Property[] readProperties(ByteBuf buf) + { + Property[] properties = new Property[ DefinedPacket.readVarInt( buf ) ]; + for ( int j = 0; j < properties.length; j++ ) + { + String name = readString( buf ); + String value = readString( buf ); + if ( buf.readBoolean() ) + { + properties[j] = new Property( name, value, DefinedPacket.readString( buf ) ); + } else + { + properties[j] = new Property( name, value ); + } + } + + return properties; + } + + public static void writePublicKey(PlayerPublicKey publicKey, ByteBuf buf) + { + if ( publicKey != null ) + { + buf.writeBoolean( true ); + buf.writeLong( publicKey.getExpiry() ); + writeArray( publicKey.getKey(), buf ); + writeArray( publicKey.getSignature(), buf ); + } else + { + buf.writeBoolean( false ); + } + } + + public static PlayerPublicKey readPublicKey(ByteBuf buf) + { + if ( buf.readBoolean() ) + { + return new PlayerPublicKey( buf.readLong(), readArray( buf ), readArray( buf ) ); + } + + return null; + } + public static Tag readTag(ByteBuf input) { Tag tag = NamedTag.read( new DataInputStream( new ByteBufInputStream( input ) ) ); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Location.java b/protocol/src/main/java/net/md_5/bungee/protocol/Location.java new file mode 100644 index 00000000..e6a9f894 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Location.java @@ -0,0 +1,11 @@ +package net.md_5.bungee.protocol; + +import lombok.Data; + +@Data +public class Location +{ + + private final String dimension; + private final long pos; +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/PlayerPublicKey.java b/protocol/src/main/java/net/md_5/bungee/protocol/PlayerPublicKey.java new file mode 100644 index 00000000..7f2cc798 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/PlayerPublicKey.java @@ -0,0 +1,12 @@ +package net.md_5.bungee.protocol; + +import lombok.Data; + +@Data +public class PlayerPublicKey +{ + + private final long expiry; + private final byte[] key; + private final byte[] signature; +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Property.java b/protocol/src/main/java/net/md_5/bungee/protocol/Property.java new file mode 100644 index 00000000..2e0b1d73 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Property.java @@ -0,0 +1,19 @@ +package net.md_5.bungee.protocol; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Property +{ + + private String name; + private String value; + private String signature; + + public Property(String name, String value) + { + this( name, value, null ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java index 21f4a5d5..38394808 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java @@ -12,6 +12,8 @@ import lombok.Getter; import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.ClearTitles; +import net.md_5.bungee.protocol.packet.ClientChat; +import net.md_5.bungee.protocol.packet.ClientCommand; import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.Commands; import net.md_5.bungee.protocol.packet.EncryptionRequest; @@ -27,6 +29,7 @@ import net.md_5.bungee.protocol.packet.LoginPayloadResponse; import net.md_5.bungee.protocol.packet.LoginRequest; import net.md_5.bungee.protocol.packet.LoginSuccess; import net.md_5.bungee.protocol.packet.PingPacket; +import net.md_5.bungee.protocol.packet.PlayerChat; import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter; import net.md_5.bungee.protocol.packet.PlayerListItem; import net.md_5.bungee.protocol.packet.PluginMessage; @@ -38,6 +41,7 @@ import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; import net.md_5.bungee.protocol.packet.Subtitle; +import net.md_5.bungee.protocol.packet.SystemChat; import net.md_5.bungee.protocol.packet.TabCompleteRequest; import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.Team; @@ -75,7 +79,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x21 ), map( ProtocolConstants.MINECRAFT_1_16, 0x20 ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x1F ), - map( ProtocolConstants.MINECRAFT_1_17, 0x21 ) + map( ProtocolConstants.MINECRAFT_1_17, 0x21 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x1E ) ); TO_CLIENT.registerPacket( Login.class, @@ -86,17 +91,18 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x26 ), map( ProtocolConstants.MINECRAFT_1_16, 0x25 ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x24 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x26 ) + map( ProtocolConstants.MINECRAFT_1_17, 0x26 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x23 ) ); - TO_CLIENT.registerPacket( - Chat.class, + TO_CLIENT.registerPacket( Chat.class, Chat::new, map( ProtocolConstants.MINECRAFT_1_8, 0x02 ), map( ProtocolConstants.MINECRAFT_1_9, 0x0F ), map( ProtocolConstants.MINECRAFT_1_13, 0x0E ), map( ProtocolConstants.MINECRAFT_1_15, 0x0F ), map( ProtocolConstants.MINECRAFT_1_16, 0x0E ), - map( ProtocolConstants.MINECRAFT_1_17, 0x0F ) + map( ProtocolConstants.MINECRAFT_1_17, 0x0F ), + map( ProtocolConstants.MINECRAFT_1_19, -1 ) ); TO_CLIENT.registerPacket( Respawn.class, @@ -110,7 +116,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x3B ), map( ProtocolConstants.MINECRAFT_1_16, 0x3A ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x39 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x3D ) + map( ProtocolConstants.MINECRAFT_1_17, 0x3D ), + map( ProtocolConstants.MINECRAFT_1_19, 0x3B ) ); TO_CLIENT.registerPacket( BossBar.class, @@ -118,7 +125,13 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_9, 0x0C ), map( ProtocolConstants.MINECRAFT_1_15, 0x0D ), map( ProtocolConstants.MINECRAFT_1_16, 0x0C ), - map( ProtocolConstants.MINECRAFT_1_17, 0x0D ) + map( ProtocolConstants.MINECRAFT_1_17, 0x0D ), + map( ProtocolConstants.MINECRAFT_1_19, 0x0A ) + ); + TO_CLIENT.registerPacket( + PlayerChat.class, + PlayerChat::new, + map( ProtocolConstants.MINECRAFT_1_19, 0x30 ) ); TO_CLIENT.registerPacket( PlayerListItem.class, // PlayerInfo @@ -131,7 +144,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x34 ), map( ProtocolConstants.MINECRAFT_1_16, 0x33 ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x32 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x36 ) + map( ProtocolConstants.MINECRAFT_1_17, 0x36 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x34 ) ); TO_CLIENT.registerPacket( TabCompleteResponse.class, @@ -142,7 +156,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x11 ), map( ProtocolConstants.MINECRAFT_1_16, 0x10 ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_17, 0x11 ) + map( ProtocolConstants.MINECRAFT_1_17, 0x11 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x0E ) ); TO_CLIENT.registerPacket( ScoreboardObjective.class, @@ -202,7 +217,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x19 ), map( ProtocolConstants.MINECRAFT_1_16, 0x18 ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x17 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x18 ) + map( ProtocolConstants.MINECRAFT_1_17, 0x18 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x15 ) ); TO_CLIENT.registerPacket( Kick.class, @@ -214,7 +230,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x1B ), map( ProtocolConstants.MINECRAFT_1_16, 0x1A ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x19 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x1A ) + map( ProtocolConstants.MINECRAFT_1_17, 0x1A ), + map( ProtocolConstants.MINECRAFT_1_19, 0x17 ) ); TO_CLIENT.registerPacket( Title.class, @@ -232,7 +249,8 @@ public enum Protocol TO_CLIENT.registerPacket( ClearTitles.class, ClearTitles::new, - map( ProtocolConstants.MINECRAFT_1_17, 0x10 ) + map( ProtocolConstants.MINECRAFT_1_17, 0x10 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x0D ) ); TO_CLIENT.registerPacket( Subtitle.class, @@ -246,6 +264,11 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_17, 0x5A ), map( ProtocolConstants.MINECRAFT_1_18, 0x5B ) ); + TO_CLIENT.registerPacket( + SystemChat.class, + SystemChat::new, + map( ProtocolConstants.MINECRAFT_1_19, 0x5F ) + ); TO_CLIENT.registerPacket( PlayerListHeaderFooter.class, PlayerListHeaderFooter::new, @@ -259,7 +282,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x54 ), map( ProtocolConstants.MINECRAFT_1_16, 0x53 ), map( ProtocolConstants.MINECRAFT_1_17, 0x5E ), - map( ProtocolConstants.MINECRAFT_1_18, 0x5F ) + map( ProtocolConstants.MINECRAFT_1_18, 0x5F ), + map( ProtocolConstants.MINECRAFT_1_19, 0x60 ) ); TO_CLIENT.registerPacket( EntityStatus.class, @@ -271,7 +295,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x1C ), map( ProtocolConstants.MINECRAFT_1_16, 0x1B ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x1A ), - map( ProtocolConstants.MINECRAFT_1_17, 0x1B ) + map( ProtocolConstants.MINECRAFT_1_17, 0x1B ), + map( ProtocolConstants.MINECRAFT_1_19, 0x18 ) ); TO_CLIENT.registerPacket( Commands.class, @@ -280,7 +305,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x12 ), map( ProtocolConstants.MINECRAFT_1_16, 0x11 ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x10 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x12 ) + map( ProtocolConstants.MINECRAFT_1_17, 0x12 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x0F ) ); TO_CLIENT.registerPacket( GameState.class, @@ -288,7 +314,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_15, 0x1F ), map( ProtocolConstants.MINECRAFT_1_16, 0x1E ), map( ProtocolConstants.MINECRAFT_1_16_2, 0x1D ), - map( ProtocolConstants.MINECRAFT_1_17, 0x1E ) + map( ProtocolConstants.MINECRAFT_1_17, 0x1E ), + map( ProtocolConstants.MINECRAFT_1_19, 0x1B ) ); TO_CLIENT.registerPacket( ViewDistance.class, @@ -296,7 +323,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_14, 0x41 ), map( ProtocolConstants.MINECRAFT_1_15, 0x42 ), map( ProtocolConstants.MINECRAFT_1_16, 0x41 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x4A ) + map( ProtocolConstants.MINECRAFT_1_17, 0x4A ), + map( ProtocolConstants.MINECRAFT_1_19, 0x49 ) ); TO_SERVER.registerPacket( @@ -309,16 +337,27 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_13, 0x0E ), map( ProtocolConstants.MINECRAFT_1_14, 0x0F ), map( ProtocolConstants.MINECRAFT_1_16, 0x10 ), - map( ProtocolConstants.MINECRAFT_1_17, 0x0F ) + map( ProtocolConstants.MINECRAFT_1_17, 0x0F ), + map( ProtocolConstants.MINECRAFT_1_19, 0x11 ) ); - TO_SERVER.registerPacket( - Chat.class, + TO_SERVER.registerPacket( Chat.class, Chat::new, map( ProtocolConstants.MINECRAFT_1_8, 0x01 ), map( ProtocolConstants.MINECRAFT_1_9, 0x02 ), map( ProtocolConstants.MINECRAFT_1_12, 0x03 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x02 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x03 ) + map( ProtocolConstants.MINECRAFT_1_14, 0x03 ), + map( ProtocolConstants.MINECRAFT_1_19, -1 ) + ); + TO_SERVER.registerPacket( + ClientCommand.class, + ClientCommand::new, + map( ProtocolConstants.MINECRAFT_1_19, 0x03 ) + ); + TO_SERVER.registerPacket( + ClientChat.class, + ClientChat::new, + map( ProtocolConstants.MINECRAFT_1_19, 0x04 ) ); TO_SERVER.registerPacket( TabCompleteRequest.class, @@ -328,7 +367,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_12, 0x02 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x01 ), map( ProtocolConstants.MINECRAFT_1_13, 0x05 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x06 ) + map( ProtocolConstants.MINECRAFT_1_14, 0x06 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x08 ) ); TO_SERVER.registerPacket( ClientSettings.class, @@ -337,7 +377,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_9, 0x04 ), map( ProtocolConstants.MINECRAFT_1_12, 0x05 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x04 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x05 ) + map( ProtocolConstants.MINECRAFT_1_14, 0x05 ), + map( ProtocolConstants.MINECRAFT_1_19, 0x07 ) ); TO_SERVER.registerPacket( PluginMessage.class, @@ -348,7 +389,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_12_1, 0x09 ), map( ProtocolConstants.MINECRAFT_1_13, 0x0A ), map( ProtocolConstants.MINECRAFT_1_14, 0x0B ), - map( ProtocolConstants.MINECRAFT_1_17, 0x0A ) + map( ProtocolConstants.MINECRAFT_1_17, 0x0A ), + map( ProtocolConstants.MINECRAFT_1_19, 0x0C ) ); } }, @@ -554,6 +596,11 @@ public enum Protocol { // Mapping is non current, but the next one may be ok ProtocolMapping nextMapping = mappings[mappingIndex + 1]; + if ( nextMapping.packetID < 0 ) + { + break; + } + if ( nextMapping.protocolVersion == protocol ) { Preconditions.checkState( nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion ); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java b/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java index 7da127fb..180a5759 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java @@ -38,6 +38,7 @@ public class ProtocolConstants public static final int MINECRAFT_1_17_1 = 756; public static final int MINECRAFT_1_18 = 757; public static final int MINECRAFT_1_18_2 = 758; + public static final int MINECRAFT_1_19 = 759; public static final List SUPPORTED_VERSIONS; public static final List SUPPORTED_VERSION_IDS; @@ -54,7 +55,8 @@ public class ProtocolConstants "1.15.x", "1.16.x", "1.17.x", - "1.18.x" + "1.18.x", + "1.19.x" ); ImmutableList.Builder supportedVersionIds = ImmutableList.builder().add( ProtocolConstants.MINECRAFT_1_8, @@ -87,13 +89,14 @@ public class ProtocolConstants ProtocolConstants.MINECRAFT_1_17, ProtocolConstants.MINECRAFT_1_17_1, ProtocolConstants.MINECRAFT_1_18, - ProtocolConstants.MINECRAFT_1_18_2 + ProtocolConstants.MINECRAFT_1_18_2, + ProtocolConstants.MINECRAFT_1_19 ); if ( SNAPSHOT_SUPPORT ) { - // supportedVersions.add( "1.18.x" ); - // supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_18 ); + // supportedVersions.add( "1.19.x" ); + // supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_19 ); } SUPPORTED_VERSIONS = supportedVersions.build(); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientChat.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientChat.java new file mode 100644 index 00000000..0569170f --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientChat.java @@ -0,0 +1,50 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ClientChat extends DefinedPacket +{ + + private String message; + private long timestamp; + private long salt; + private byte[] signature; + private boolean signedPreview; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + message = readString( buf, 256 ); + timestamp = buf.readLong(); + salt = buf.readLong(); + signature = readArray( buf ); + signedPreview = buf.readBoolean(); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( message, buf ); + buf.writeLong( timestamp ); + buf.writeLong( salt ); + writeArray( signature, buf ); + buf.writeBoolean( signedPreview ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientCommand.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientCommand.java new file mode 100644 index 00000000..53c4144f --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientCommand.java @@ -0,0 +1,68 @@ +package net.md_5.bungee.protocol.packet; + +import com.google.common.base.Preconditions; +import io.netty.buffer.ByteBuf; +import java.util.HashMap; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ClientCommand extends DefinedPacket +{ + + private String command; + private long timestamp; + private long salt; + private Map signatures; + private boolean signedPreview; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + command = readString( buf ); + timestamp = buf.readLong(); + salt = buf.readLong(); + + int cnt = readVarInt( buf ); + Preconditions.checkArgument( cnt <= 8, "Too many signatures" ); + signatures = new HashMap<>( cnt ); + for ( int i = 0; i < cnt; i++ ) + { + signatures.put( readString( buf, 16 ), readArray( buf ) ); + } + + signedPreview = buf.readBoolean(); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( command, buf ); + buf.writeLong( timestamp ); + buf.writeLong( salt ); + + writeVarInt( signatures.size(), buf ); + for ( Map.Entry entry : signatures.entrySet() ) + { + writeString( entry.getKey(), buf ); + writeArray( entry.getValue(), buf ); + } + + buf.writeBoolean( signedPreview ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java index 633e557c..0eb3661b 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java @@ -23,11 +23,13 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.RootCommandNode; import io.netty.buffer.ByteBuf; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collection; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import lombok.AllArgsConstructor; @@ -36,6 +38,7 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; @Data @NoArgsConstructor @@ -56,7 +59,7 @@ public class Commands extends DefinedPacket private RootCommandNode root; @Override - public void read(ByteBuf buf) + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { int nodeCount = readVarInt( buf ); NetworkNode[] nodes = new NetworkNode[ nodeCount ]; @@ -79,9 +82,7 @@ public class Commands extends DefinedPacket break; case NODE_ARGUMENT: String name = readString( buf ); - String parser = readString( buf ); - - argumentBuilder = RequiredArgumentBuilder.argument( name, ArgumentRegistry.read( parser, buf ) ); + argumentBuilder = RequiredArgumentBuilder.argument( name, ArgumentRegistry.read( buf, protocolVersion ) ); if ( ( flags & FLAG_SUGGESTIONS ) != 0 ) { @@ -126,7 +127,7 @@ public class Commands extends DefinedPacket } @Override - public void write(ByteBuf buf) + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { Map indexMap = new LinkedHashMap<>(); Deque nodeQueue = new ArrayDeque<>(); @@ -210,7 +211,7 @@ public class Commands extends DefinedPacket ArgumentCommandNode argumentNode = (ArgumentCommandNode) node; writeString( argumentNode.getName(), buf ); - ArgumentRegistry.write( argumentNode.getType(), buf ); + ArgumentRegistry.write( argumentNode.getType(), buf, protocolVersion ); if ( argumentNode.getCustomSuggestions() != null ) { @@ -308,6 +309,7 @@ public class Commands extends DefinedPacket { private static final Map PROVIDERS = new HashMap<>(); + private static final List PROVIDER_LIST = new ArrayList<>(); private static final Map, ProperArgumentSerializer> PROPER_PROVIDERS = new HashMap<>(); // private static final ArgumentSerializer VOID = new ArgumentSerializer() @@ -492,6 +494,12 @@ public class Commands extends DefinedPacket writeVarInt( t.getType().ordinal(), buf ); } + @Override + protected int getIntKey() + { + return 5; + } + @Override protected String getKey() { @@ -515,82 +523,113 @@ public class Commands extends DefinedPacket static { - PROVIDERS.put( "brigadier:bool", VOID ); - PROVIDERS.put( "brigadier:float", FLOAT ); - PROVIDERS.put( "brigadier:double", DOUBLE ); - PROVIDERS.put( "brigadier:integer", INTEGER ); - PROVIDERS.put( "brigadier:long", LONG ); + register( "brigadier:bool", VOID ); + register( "brigadier:float", FLOAT ); + register( "brigadier:double", DOUBLE ); + register( "brigadier:integer", INTEGER ); + register( "brigadier:long", LONG ); - PROVIDERS.put( "brigadier:string", STRING ); + register( "brigadier:string", STRING ); PROPER_PROVIDERS.put( StringArgumentType.class, STRING ); - PROVIDERS.put( "minecraft:entity", BYTE ); - PROVIDERS.put( "minecraft:game_profile", VOID ); - PROVIDERS.put( "minecraft:block_pos", VOID ); - PROVIDERS.put( "minecraft:column_pos", VOID ); - PROVIDERS.put( "minecraft:vec3", VOID ); - PROVIDERS.put( "minecraft:vec2", VOID ); - PROVIDERS.put( "minecraft:block_state", VOID ); - PROVIDERS.put( "minecraft:block_predicate", VOID ); - PROVIDERS.put( "minecraft:item_stack", VOID ); - PROVIDERS.put( "minecraft:item_predicate", VOID ); - PROVIDERS.put( "minecraft:color", VOID ); - PROVIDERS.put( "minecraft:component", VOID ); - PROVIDERS.put( "minecraft:message", VOID ); - PROVIDERS.put( "minecraft:nbt_compound_tag", VOID ); // 1.14 - PROVIDERS.put( "minecraft:nbt_tag", VOID ); // 1.14 - PROVIDERS.put( "minecraft:nbt", VOID ); // 1.13 - PROVIDERS.put( "minecraft:nbt_path", VOID ); - PROVIDERS.put( "minecraft:objective", VOID ); - PROVIDERS.put( "minecraft:objective_criteria", VOID ); - PROVIDERS.put( "minecraft:operation", VOID ); - PROVIDERS.put( "minecraft:particle", VOID ); - PROVIDERS.put( "minecraft:rotation", VOID ); - PROVIDERS.put( "minecraft:scoreboard_slot", VOID ); - PROVIDERS.put( "minecraft:score_holder", BYTE ); - PROVIDERS.put( "minecraft:swizzle", VOID ); - PROVIDERS.put( "minecraft:team", VOID ); - PROVIDERS.put( "minecraft:item_slot", VOID ); - PROVIDERS.put( "minecraft:resource_location", VOID ); - PROVIDERS.put( "minecraft:mob_effect", VOID ); - PROVIDERS.put( "minecraft:function", VOID ); - PROVIDERS.put( "minecraft:entity_anchor", VOID ); - PROVIDERS.put( "minecraft:int_range", VOID ); - PROVIDERS.put( "minecraft:float_range", VOID ); - PROVIDERS.put( "minecraft:item_enchantment", VOID ); - PROVIDERS.put( "minecraft:entity_summon", VOID ); - PROVIDERS.put( "minecraft:dimension", VOID ); - PROVIDERS.put( "minecraft:time", VOID ); // 1.14 - PROVIDERS.put( "minecraft:uuid", VOID ); // 1.16 - PROVIDERS.put( "minecraft:test_argument", VOID ); // 1.16, debug - PROVIDERS.put( "minecraft:test_class", VOID ); // 1.16, debug - PROVIDERS.put( "minecraft:angle", VOID ); // 1.16.2 - PROVIDERS.put( "minecraft:resource", RAW_STRING ); // 1.18.2 - PROVIDERS.put( "minecraft:resource_or_tag", RAW_STRING ); // 1.18.2 + register( "minecraft:entity", BYTE ); + register( "minecraft:game_profile", VOID ); + register( "minecraft:block_pos", VOID ); + register( "minecraft:column_pos", VOID ); + register( "minecraft:vec3", VOID ); + register( "minecraft:vec2", VOID ); + register( "minecraft:block_state", VOID ); + register( "minecraft:block_predicate", VOID ); + register( "minecraft:item_stack", VOID ); + register( "minecraft:item_predicate", VOID ); + register( "minecraft:color", VOID ); + register( "minecraft:component", VOID ); + register( "minecraft:message", VOID ); + register( "minecraft:nbt_compound_tag", VOID ); // 1.14 + register( "minecraft:nbt_tag", VOID ); // 1.14 + register( "minecraft:nbt_path", VOID ); + register( "minecraft:objective", VOID ); + register( "minecraft:objective_criteria", VOID ); + register( "minecraft:operation", VOID ); + register( "minecraft:particle", VOID ); + register( "minecraft:angle", VOID ); // 1.16.2 + register( "minecraft:rotation", VOID ); + register( "minecraft:scoreboard_slot", VOID ); + register( "minecraft:score_holder", BYTE ); + register( "minecraft:swizzle", VOID ); + register( "minecraft:team", VOID ); + register( "minecraft:item_slot", VOID ); + register( "minecraft:resource_location", VOID ); + register( "minecraft:mob_effect", VOID ); + register( "minecraft:function", VOID ); + register( "minecraft:entity_anchor", VOID ); + register( "minecraft:int_range", VOID ); + register( "minecraft:float_range", VOID ); + register( "minecraft:item_enchantment", VOID ); + register( "minecraft:entity_summon", VOID ); + register( "minecraft:dimension", VOID ); + register( "minecraft:time", VOID ); // 1.14 + register( "minecraft:resource_or_tag", RAW_STRING ); // 1.18.2 + register( "minecraft:resource", RAW_STRING ); // 1.18.2 + register( "minecraft:template_mirror", VOID ); // 1.19 + register( "minecraft:template_rotation", VOID ); // 1.19 + register( "minecraft:uuid", VOID ); // 1.16 + + register( "minecraft:nbt", VOID ); // 1.13 // removed } - private static ArgumentType read(String key, ByteBuf buf) + private static void register(String name, ArgumentSerializer serializer) { - ArgumentSerializer reader = PROVIDERS.get( key ); + PROVIDERS.put( name, serializer ); + PROVIDER_LIST.add( serializer ); + } + + private static ArgumentType read(ByteBuf buf, int protocolVersion) + { + Object key; + ArgumentSerializer reader; + + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + key = readVarInt( buf ); + reader = PROVIDER_LIST.get( (Integer) key ); + } else + { + key = readString( buf ); + reader = PROVIDERS.get( (String) key ); + } + Preconditions.checkArgument( reader != null, "No provider for argument " + key ); Object val = reader.read( buf ); return val != null && PROPER_PROVIDERS.containsKey( val.getClass() ) ? (ArgumentType) val : new DummyType( key, reader, val ); } - private static void write(ArgumentType arg, ByteBuf buf) + private static void write(ArgumentType arg, ByteBuf buf, int protocolVersion) { ProperArgumentSerializer proper = PROPER_PROVIDERS.get( arg.getClass() ); if ( proper != null ) { - writeString( proper.getKey(), buf ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + writeVarInt( proper.getIntKey(), buf ); + } else + { + writeString( proper.getKey(), buf ); + } proper.write( buf, arg ); } else { Preconditions.checkArgument( arg instanceof DummyType, "Non dummy arg " + arg.getClass() ); DummyType dummy = (DummyType) arg; - writeString( dummy.key, buf ); + if ( dummy.key instanceof Integer ) + { + writeVarInt( (Integer) dummy.key, buf ); + } else + { + writeString( (String) dummy.key, buf ); + } dummy.serializer.write( buf, dummy.value ); } } @@ -599,7 +638,7 @@ public class Commands extends DefinedPacket private static class DummyType implements ArgumentType { - private final String key; + private final Object key; private final ArgumentSerializer serializer; private final T value; @@ -621,6 +660,8 @@ public class Commands extends DefinedPacket private abstract static class ProperArgumentSerializer extends ArgumentSerializer { + protected abstract int getIntKey(); + protected abstract String getKey(); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java index 388f6cdb..8a60be9f 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java @@ -18,19 +18,36 @@ public class EncryptionResponse extends DefinedPacket private byte[] sharedSecret; private byte[] verifyToken; + private EncryptionData encryptionData; - @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { sharedSecret = readArray( buf, 128 ); - verifyToken = readArray( buf, 128 ); + if ( protocolVersion < ProtocolConstants.MINECRAFT_1_19 || buf.readBoolean() ) + { + verifyToken = readArray( buf, 128 ); + } else + { + encryptionData = new EncryptionData( buf.readLong(), readArray( buf ) ); + } } @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { writeArray( sharedSecret, buf ); - writeArray( verifyToken, buf ); + if ( verifyToken != null ) + { + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + buf.writeBoolean( true ); + } + writeArray( verifyToken, buf ); + } else + { + buf.writeLong( encryptionData.getSalt() ); + writeArray( encryptionData.getSignature(), buf ); + } } @Override @@ -38,4 +55,12 @@ public class EncryptionResponse extends DefinedPacket { handler.handle( this ); } + + @Data + public static class EncryptionData + { + + private final long salt; + private final byte[] signature; + } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java index 3cab0d3d..bc7baee3 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java @@ -9,6 +9,7 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.Location; import net.md_5.bungee.protocol.ProtocolConstants; import se.llbit.nbt.Tag; @@ -37,6 +38,7 @@ public class Login extends DefinedPacket private boolean normalRespawn; private boolean debug; private boolean flat; + private Location deathLocation; @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) @@ -63,7 +65,7 @@ public class Login extends DefinedPacket if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 ) { - if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 ) + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 ) { dimension = readTag( buf ); } else @@ -118,6 +120,13 @@ public class Login extends DefinedPacket debug = buf.readBoolean(); flat = buf.readBoolean(); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + if ( buf.readBoolean() ) + { + deathLocation = new Location( readString( buf ), buf.readLong() ); + } + } } @Override @@ -144,7 +153,7 @@ public class Login extends DefinedPacket if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 ) { - if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 ) + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 ) { writeTag( (Tag) dimension, buf ); } else @@ -199,6 +208,18 @@ public class Login extends DefinedPacket buf.writeBoolean( debug ); buf.writeBoolean( flat ); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + if ( deathLocation != null ) + { + buf.writeBoolean( true ); + writeString( deathLocation.getDimension(), buf ); + buf.writeLong( deathLocation.getPos() ); + } else + { + buf.writeBoolean( false ); + } + } } @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java index 08ee376e..8b148625 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java @@ -7,6 +7,8 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.PlayerPublicKey; +import net.md_5.bungee.protocol.ProtocolConstants; @Data @NoArgsConstructor @@ -16,17 +18,26 @@ public class LoginRequest extends DefinedPacket { private String data; + private PlayerPublicKey publicKey; @Override - public void read(ByteBuf buf) + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { data = readString( buf, 16 ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + publicKey = readPublicKey( buf ); + } } @Override - public void write(ByteBuf buf) + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { writeString( data, buf ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + writePublicKey( publicKey, buf ); + } } @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java index 551bd104..07fb3d79 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java @@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.Property; import net.md_5.bungee.protocol.ProtocolConstants; @Data @@ -19,6 +20,7 @@ public class LoginSuccess extends DefinedPacket private UUID uuid; private String username; + private Property[] properties; @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) @@ -31,6 +33,10 @@ public class LoginSuccess extends DefinedPacket uuid = UUID.fromString( readString( buf ) ); } username = readString( buf ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + properties = readProperties( buf ); + } } @Override @@ -44,6 +50,10 @@ public class LoginSuccess extends DefinedPacket writeString( uuid.toString(), buf ); } writeString( username, buf ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + writeProperties( properties, buf ); + } } @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerChat.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerChat.java new file mode 100644 index 00000000..ca0e5964 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerChat.java @@ -0,0 +1,84 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class PlayerChat extends DefinedPacket +{ + + private static final UUID EMPTY_UUID = new UUID( 0L, 0L ); + private String signedContent; + private String unsignedContent; // nullable + private UUID sender; + private int typeId; + private String displayName; + private String teamName; // nullable + private long timestamp; + private long salt; + private byte[] signature; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + signedContent = readString( buf, 262144 ); + if ( buf.readBoolean() ) + { + unsignedContent = readString( buf, 262144 ); + } + typeId = readVarInt( buf ); + sender = readUUID( buf ); + displayName = readString( buf, 262144 ); + if ( buf.readBoolean() ) + { + teamName = readString( buf, 262144 ); + } + timestamp = buf.readLong(); + salt = buf.readLong(); + signature = readArray( buf ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( signedContent, buf ); + if ( unsignedContent != null ) + { + buf.writeBoolean( true ); + writeString( unsignedContent, buf ); + } else + { + buf.writeBoolean( false ); + } + writeVarInt( typeId, buf ); + writeUUID( sender, buf ); + writeString( displayName, buf ); + if ( teamName != null ) + { + buf.writeBoolean( true ); + writeString( teamName, buf ); + } else + { + buf.writeBoolean( false ); + } + buf.writeLong( timestamp ); + buf.writeLong( salt ); + writeArray( signature, buf ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java index 92bacc7c..7dfdb58d 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java @@ -7,6 +7,8 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.PlayerPublicKey; +import net.md_5.bungee.protocol.Property; import net.md_5.bungee.protocol.ProtocolConstants; @Data @@ -31,31 +33,17 @@ public class PlayerListItem extends DefinedPacket { case ADD_PLAYER: item.username = DefinedPacket.readString( buf ); - item.properties = new String[ DefinedPacket.readVarInt( buf ) ][]; - for ( int j = 0; j < item.properties.length; j++ ) - { - String name = DefinedPacket.readString( buf ); - String value = DefinedPacket.readString( buf ); - if ( buf.readBoolean() ) - { - item.properties[j] = new String[] - { - name, value, DefinedPacket.readString( buf ) - }; - } else - { - item.properties[j] = new String[] - { - name, value - }; - } - } + item.properties = DefinedPacket.readProperties( buf ); item.gamemode = DefinedPacket.readVarInt( buf ); item.ping = DefinedPacket.readVarInt( buf ); if ( buf.readBoolean() ) { item.displayName = DefinedPacket.readString( buf ); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + item.publicKey = readPublicKey( buf ); + } break; case UPDATE_GAMEMODE: item.gamemode = DefinedPacket.readVarInt( buf ); @@ -84,20 +72,7 @@ public class PlayerListItem extends DefinedPacket { case ADD_PLAYER: DefinedPacket.writeString( item.username, buf ); - DefinedPacket.writeVarInt( item.properties.length, buf ); - for ( String[] prop : item.properties ) - { - DefinedPacket.writeString( prop[0], buf ); - DefinedPacket.writeString( prop[1], buf ); - if ( prop.length >= 3 ) - { - buf.writeBoolean( true ); - DefinedPacket.writeString( prop[2], buf ); - } else - { - buf.writeBoolean( false ); - } - } + DefinedPacket.writeProperties( item.properties, buf ); DefinedPacket.writeVarInt( item.gamemode, buf ); DefinedPacket.writeVarInt( item.ping, buf ); buf.writeBoolean( item.displayName != null ); @@ -105,6 +80,10 @@ public class PlayerListItem extends DefinedPacket { DefinedPacket.writeString( item.displayName, buf ); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + writePublicKey( item.publicKey, buf ); + } break; case UPDATE_GAMEMODE: DefinedPacket.writeVarInt( item.gamemode, buf ); @@ -148,7 +127,8 @@ public class PlayerListItem extends DefinedPacket // ADD_PLAYER private String username; - private String[][] properties; + private Property[] properties; + private PlayerPublicKey publicKey; // ADD_PLAYER & UPDATE_GAMEMODE private int gamemode; diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Respawn.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Respawn.java index 36db3d49..65cddbec 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Respawn.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Respawn.java @@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.Location; import net.md_5.bungee.protocol.ProtocolConstants; import se.llbit.nbt.Tag; @@ -27,13 +28,14 @@ public class Respawn extends DefinedPacket private boolean debug; private boolean flat; private boolean copyMeta; + private Location deathLocation; @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 ) { - if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 ) + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 ) { dimension = readTag( buf ); } else @@ -64,6 +66,13 @@ public class Respawn extends DefinedPacket { levelType = readString( buf ); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + if ( buf.readBoolean() ) + { + deathLocation = new Location( readString( buf ), buf.readLong() ); + } + } } @Override @@ -71,7 +80,7 @@ public class Respawn extends DefinedPacket { if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 ) { - if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 ) + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16_2 && protocolVersion < ProtocolConstants.MINECRAFT_1_19 ) { writeTag( (Tag) dimension, buf ); } else @@ -102,6 +111,18 @@ public class Respawn extends DefinedPacket { writeString( levelType, buf ); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19 ) + { + if ( deathLocation != null ) + { + buf.writeBoolean( true ); + writeString( deathLocation.getDimension(), buf ); + buf.writeLong( deathLocation.getPos() ); + } else + { + buf.writeBoolean( false ); + } + } } @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/SystemChat.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/SystemChat.java new file mode 100644 index 00000000..f353e61f --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/SystemChat.java @@ -0,0 +1,41 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class SystemChat extends DefinedPacket +{ + + private String message; + private int position; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + message = readString( buf, 262144 ); + position = readVarInt( buf ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( message, buf ); + writeVarInt( position, buf ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/proxy/pom.xml b/proxy/pom.xml index b49b4c5c..af8f76b2 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-proxy - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Proxy @@ -94,36 +94,27 @@ mysql mysql-connector-java - 8.0.27 + 8.0.29 runtime org.apache.maven maven-resolver-provider - 3.8.4 + 3.8.5 runtime org.apache.maven.resolver maven-resolver-connector-basic - 1.7.2 + 1.8.0 runtime org.apache.maven.resolver maven-resolver-transport-http - 1.7.2 + 1.8.0 runtime - - - - - src/main/resources - true - - - diff --git a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java index f76c395a..ad7ea6a2 100644 --- a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java +++ b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java @@ -1,5 +1,9 @@ package net.md_5.bungee; +import com.google.common.io.ByteStreams; +import com.google.common.primitives.Longs; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.Key; import java.security.KeyFactory; @@ -7,8 +11,11 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; +import java.security.Signature; +import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; +import java.util.Base64; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.SecretKey; @@ -18,6 +25,7 @@ import net.md_5.bungee.jni.NativeCode; import net.md_5.bungee.jni.cipher.BungeeCipher; import net.md_5.bungee.jni.cipher.JavaCipher; import net.md_5.bungee.jni.cipher.NativeCipher; +import net.md_5.bungee.protocol.PlayerPublicKey; import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionResponse; @@ -28,10 +36,12 @@ public class EncryptionUtil { private static final Random random = new Random(); + private static final Base64.Encoder MIME_ENCODER = Base64.getMimeEncoder( 76, "\n".getBytes( StandardCharsets.UTF_8 ) ); public static final KeyPair keys; @Getter private static final SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" ); public static final NativeCode nativeFactory = new NativeCode<>( "native-cipher", JavaCipher::new, NativeCipher::new ); + private static final PublicKey MOJANG_KEY; static { @@ -44,6 +54,14 @@ public class EncryptionUtil { throw new ExceptionInInitializerError( ex ); } + + try + { + MOJANG_KEY = KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( ByteStreams.toByteArray( EncryptionUtil.class.getResourceAsStream( "/yggdrasil_session_pubkey.der" ) ) ) ); + } catch ( IOException | NoSuchAlgorithmException | InvalidKeySpecException ex ) + { + throw new ExceptionInInitializerError( ex ); + } } public static EncryptionRequest encryptRequest() @@ -55,17 +73,40 @@ public class EncryptionUtil return new EncryptionRequest( hash, pubKey, verify ); } + public static boolean check(PlayerPublicKey publicKey) throws GeneralSecurityException + { + Signature signature = Signature.getInstance( "SHA1withRSA" ); + signature.initVerify( MOJANG_KEY ); + + signature.update( ( publicKey.getExpiry() + "-----BEGIN RSA PUBLIC KEY-----\n" + MIME_ENCODER.encodeToString( getPubkey( publicKey.getKey() ).getEncoded() ) + "\n-----END RSA PUBLIC KEY-----\n" ).getBytes( StandardCharsets.US_ASCII ) ); + + return signature.verify( publicKey.getSignature() ); + } + + public static boolean check(PlayerPublicKey publicKey, EncryptionResponse resp, EncryptionRequest request) throws GeneralSecurityException + { + if ( publicKey != null ) + { + Signature signature = Signature.getInstance( "SHA256withRSA" ); + signature.initVerify( getPubkey( publicKey.getKey() ) ); + + signature.update( request.getVerifyToken() ); + signature.update( Longs.toByteArray( resp.getEncryptionData().getSalt() ) ); + + return signature.verify( resp.getEncryptionData().getSignature() ); + } else + { + Cipher cipher = Cipher.getInstance( "RSA" ); + cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() ); + byte[] decrypted = cipher.doFinal( resp.getVerifyToken() ); + + return Arrays.equals( request.getVerifyToken(), decrypted ); + } + } + public static SecretKey getSecret(EncryptionResponse resp, EncryptionRequest request) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance( "RSA" ); - cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() ); - byte[] decrypted = cipher.doFinal( resp.getVerifyToken() ); - - if ( !Arrays.equals( request.getVerifyToken(), decrypted ) ) - { - throw new IllegalStateException( "Key pairs do not match!" ); - } - cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() ); return new SecretKeySpec( cipher.doFinal( resp.getSharedSecret() ), "AES" ); } @@ -80,7 +121,12 @@ public class EncryptionUtil public static PublicKey getPubkey(EncryptionRequest request) throws GeneralSecurityException { - return KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( request.getPublicKey() ) ); + return getPubkey( request.getPublicKey() ); + } + + private static PublicKey getPubkey(byte[] b) throws GeneralSecurityException + { + return KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( b ) ); } public static byte[] encrypt(Key key, byte[] b) throws GeneralSecurityException diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java index 7c082d46..380d0aea 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -123,7 +123,7 @@ public class ServerConnector extends PacketHandler channel.write( copiedHandshake ); channel.setProtocol( Protocol.LOGIN ); - channel.write( new LoginRequest( user.getName() ) ); + channel.write( new LoginRequest( user.getName(), null ) ); } @Override @@ -225,7 +225,7 @@ public class ServerConnector extends PacketHandler // Set tab list size, TODO: what shall we do about packet mutability Login modLogin = new Login( login.getEntityId(), login.isHardcore(), login.getGameMode(), login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), - (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.getSimulationDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), login.isFlat() ); + (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.getSimulationDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), login.isFlat(), login.getDeathLocation() ); user.unsafe().sendPacket( modLogin ); @@ -243,7 +243,7 @@ public class ServerConnector extends PacketHandler } user.getSentBossBars().clear(); - user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); + user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false, login.getDeathLocation() ) ); user.getServer().disconnect( "Quitting" ); } else { @@ -292,11 +292,11 @@ public class ServerConnector extends PacketHandler user.setDimensionChange( true ); if ( login.getDimension() == user.getDimension() ) { - user.unsafe().sendPacket( new Respawn( (Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); + user.unsafe().sendPacket( new Respawn( (Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false, login.getDeathLocation() ) ); } user.setServerEntityId( login.getEntityId() ); - user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); + user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false, login.getDeathLocation() ) ); if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_14 ) { user.unsafe().sendPacket( new ViewDistance( login.getViewDistance() ) ); diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index c64a3e65..e1b084ea 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -59,6 +59,7 @@ import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter; import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.SetCompression; +import net.md_5.bungee.protocol.packet.SystemChat; import net.md_5.bungee.tab.ServerUnique; import net.md_5.bungee.tab.TabList; import net.md_5.bungee.util.CaseInsensitiveSet; @@ -416,6 +417,10 @@ public final class UserConnection implements ProxiedPlayer public void chat(String message) { Preconditions.checkState( server != null, "Not connected to server" ); + if ( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_19 ) + { + throw new UnsupportedOperationException( "Cannot spoof chat on this client version!" ); + } server.getCh().write( new Chat( message ) ); } @@ -472,7 +477,13 @@ public final class UserConnection implements ProxiedPlayer private void sendMessage(ChatMessageType position, UUID sender, String message) { - unsafe().sendPacket( new Chat( message, (byte) position.ordinal(), sender ) ); + if ( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_19 ) + { + unsafe().sendPacket( new SystemChat( message, position.ordinal() ) ); + } else + { + unsafe().sendPacket( new Chat( message, (byte) position.ordinal(), sender ) ); + } } private void sendMessage(ChatMessageType position, UUID sender, BaseComponent... message) diff --git a/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java b/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java index e1a6b2b3..54c3223c 100644 --- a/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java +++ b/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java @@ -47,6 +47,10 @@ public class Configuration implements ProxyConfig * Should we check minecraft.net auth. */ private boolean onlineMode = true; + /** + * Whether to check the authentication server public key. + */ + private boolean enforceSecureProfile; /** * Whether we log proxy commands to the proxy log */ @@ -86,6 +90,7 @@ public class Configuration implements ProxyConfig timeout = adapter.getInt( "timeout", timeout ); uuid = adapter.getString( "stats", uuid ); onlineMode = adapter.getBoolean( "online_mode", onlineMode ); + enforceSecureProfile = adapter.getBoolean( "enforce_secure_profile", enforceSecureProfile ); logCommands = adapter.getBoolean( "log_commands", logCommands ); logPings = adapter.getBoolean( "log_pings", logPings ); remotePingCache = adapter.getInt( "remote_ping_cache", remotePingCache ); diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 89f2d9fe..62408738 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -9,6 +9,7 @@ import java.net.SocketAddress; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; +import java.time.Instant; import java.util.HashSet; import java.util.Set; import java.util.UUID; @@ -49,6 +50,7 @@ import net.md_5.bungee.netty.cipher.CipherDecoder; import net.md_5.bungee.netty.cipher.CipherEncoder; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.PacketWrapper; +import net.md_5.bungee.protocol.PlayerPublicKey; import net.md_5.bungee.protocol.Protocol; import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.EncryptionRequest; @@ -358,6 +360,29 @@ public class InitialHandler extends PacketHandler implements PendingConnection disconnect( bungee.getTranslation( "name_invalid" ) ); return; } + + if ( BungeeCord.getInstance().config.isEnforceSecureProfile() ) + { + PlayerPublicKey publicKey = loginRequest.getPublicKey(); + if ( publicKey == null ) + { + disconnect( bungee.getTranslation( "secure_profile_required" ) ); + return; + } + + if ( Instant.ofEpochMilli( publicKey.getExpiry() ).isBefore( Instant.now() ) ) + { + disconnect( bungee.getTranslation( "secure_profile_expired" ) ); + return; + } + + if ( !EncryptionUtil.check( publicKey ) ) + { + disconnect( bungee.getTranslation( "secure_profile_invalid" ) ); + return; + } + } + this.loginRequest = loginRequest; int limit = BungeeCord.getInstance().config.getPlayerLimit(); @@ -410,6 +435,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection public void handle(final EncryptionResponse encryptResponse) throws Exception { Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" ); + Preconditions.checkState( EncryptionUtil.check( loginRequest.getPublicKey(), encryptResponse, request ), "Invalid verification" ); SecretKey sharedKey = EncryptionUtil.getSecret( encryptResponse, request ); BungeeCipher decrypt = EncryptionUtil.getCipher( false, sharedKey ); @@ -524,7 +550,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() ); userCon.init(); - unsafe.sendPacket( new LoginSuccess( getUniqueId(), getName() ) ); + unsafe.sendPacket( new LoginSuccess( getUniqueId(), getName(), loginProfile.getProperties() ) ); ch.setProtocol( Protocol.GAME ); ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) ); diff --git a/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java b/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java index d2ba8a4f..5dc8a220 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java @@ -2,6 +2,7 @@ package net.md_5.bungee.connection; import lombok.AllArgsConstructor; import lombok.Data; +import net.md_5.bungee.protocol.Property; @Data @AllArgsConstructor @@ -11,14 +12,4 @@ public class LoginResult private String id; private String name; private Property[] properties; - - @Data - @AllArgsConstructor - public static class Property - { - - private String name; - private String value; - private String signature; - } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 5d112a7c..bb3faf5d 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -26,6 +26,8 @@ import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.Chat; +import net.md_5.bungee.protocol.packet.ClientChat; +import net.md_5.bungee.protocol.packet.ClientCommand; import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.PlayerListItem; @@ -145,9 +147,33 @@ public class UpstreamBridge extends PacketHandler @Override public void handle(Chat chat) throws Exception { - for ( int index = 0, length = chat.getMessage().length(); index < length; index++ ) + String message = handleChat( chat.getMessage() ); + if ( message != null ) { - char c = chat.getMessage().charAt( index ); + chat.setMessage( message ); + con.getServer().unsafe().sendPacket( chat ); + } + + throw CancelSendSignal.INSTANCE; + } + + @Override + public void handle(ClientChat chat) throws Exception + { + handleChat( chat.getMessage() ); + } + + @Override + public void handle(ClientCommand command) throws Exception + { + handleChat( "/" + command.getCommand() ); + } + + private String handleChat(String message) + { + for ( int index = 0, length = message.length(); index < length; index++ ) + { + char c = message.charAt( index ); if ( !AllowedCharacters.isChatAllowedCharacter( c ) ) { con.disconnect( bungee.getTranslation( "illegal_chat_characters", Util.unicode( c ) ) ); @@ -155,16 +181,16 @@ public class UpstreamBridge extends PacketHandler } } - ChatEvent chatEvent = new ChatEvent( con, con.getServer(), chat.getMessage() ); + ChatEvent chatEvent = new ChatEvent( con, con.getServer(), message ); if ( !bungee.getPluginManager().callEvent( chatEvent ).isCancelled() ) { - chat.setMessage( chatEvent.getMessage() ); - if ( !chatEvent.isCommand() || !bungee.getPluginManager().dispatchCommand( con, chat.getMessage().substring( 1 ) ) ) + message = chatEvent.getMessage(); + if ( !chatEvent.isCommand() || !bungee.getPluginManager().dispatchCommand( con, message.substring( 1 ) ) ) { - con.getServer().unsafe().sendPacket( chat ); + return message; } } - throw CancelSendSignal.INSTANCE; + return null; } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java index 75164c67..81a1cfc3 100644 --- a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java @@ -74,6 +74,8 @@ public abstract class EntityMap case ProtocolConstants.MINECRAFT_1_18: case ProtocolConstants.MINECRAFT_1_18_2: return EntityMap_1_16_2.INSTANCE_1_18; + case ProtocolConstants.MINECRAFT_1_19: + return EntityMap_1_16_2.INSTANCE_1_19; } throw new RuntimeException( "Version " + version + " has no entity map" ); } diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java index 2f0e303d..b9d0b651 100644 --- a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java @@ -17,6 +17,8 @@ class EntityMap_1_16_2 extends EntityMap static final EntityMap_1_16_2 INSTANCE_1_16_2 = new EntityMap_1_16_2( 0x04, 0x2D ); static final EntityMap_1_16_2 INSTANCE_1_17 = new EntityMap_1_16_2( 0x04, 0x2D ); static final EntityMap_1_16_2 INSTANCE_1_18 = new EntityMap_1_16_2( 0x04, 0x2D ); + static final EntityMap_1_16_2 INSTANCE_1_19 = new EntityMap_1_16_2( 0x02, 0x2F ); + // private final int spawnPlayerId; private final int spectateId; diff --git a/proxy/src/main/java/net/md_5/bungee/tab/TabList.java b/proxy/src/main/java/net/md_5/bungee/tab/TabList.java index 7d79ef7b..6fea5221 100644 --- a/proxy/src/main/java/net/md_5/bungee/tab/TabList.java +++ b/proxy/src/main/java/net/md_5/bungee/tab/TabList.java @@ -5,6 +5,7 @@ import net.md_5.bungee.BungeeCord; import net.md_5.bungee.UserConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.connection.LoginResult; +import net.md_5.bungee.protocol.Property; import net.md_5.bungee.protocol.packet.PlayerListItem; @RequiredArgsConstructor @@ -38,20 +39,15 @@ public abstract class TabList LoginResult loginResult = player.getPendingConnection().getLoginProfile(); if ( loginResult != null && loginResult.getProperties() != null ) { - String[][] props = new String[ loginResult.getProperties().length ][]; + Property[] props = new Property[ loginResult.getProperties().length ]; for ( int i = 0; i < props.length; i++ ) { - props[i] = new String[] - { - loginResult.getProperties()[i].getName(), - loginResult.getProperties()[i].getValue(), - loginResult.getProperties()[i].getSignature() - }; + props[i] = new Property( loginResult.getProperties()[i].getName(), loginResult.getProperties()[i].getValue(), loginResult.getProperties()[i].getSignature() ); } item.setProperties( props ); } else { - item.setProperties( new String[ 0 ][ 0 ] ); + item.setProperties( new Property[ 0 ] ); } if ( playerListItem.getAction() == PlayerListItem.Action.ADD_PLAYER || playerListItem.getAction() == PlayerListItem.Action.UPDATE_GAMEMODE ) { diff --git a/proxy/src/main/resources/messages.properties b/proxy/src/main/resources/messages.properties index e16cf0a8..2b05a2dd 100644 --- a/proxy/src/main/resources/messages.properties +++ b/proxy/src/main/resources/messages.properties @@ -22,6 +22,9 @@ total_players=Total players online: {0} name_invalid=Username contains invalid characters. ping_cannot_connect=\u00a7c[Bungee] Can''t connect to server. offline_mode_player=Not authenticated with Minecraft.net +secure_profile_required=A secure profile is required to join this server. +secure_profile_expired=Secure profile expired. +secure_profile_invalid=Secure profile invalid. message_needed=\u00a7cYou must supply a message. error_occurred_player=\u00a7cAn error occurred while parsing your message. (Hover for details) error_occurred_console=\u00a7cAn error occurred while parsing your message: {0} diff --git a/proxy/src/main/resources/yggdrasil_session_pubkey.der b/proxy/src/main/resources/yggdrasil_session_pubkey.der new file mode 100644 index 0000000000000000000000000000000000000000..9c79a3aa4771da1f15af37a2af0898f878ad816f GIT binary patch literal 550 zcmV+>0@?jAf&wBi4F(A+hDe6@4FLfG1potr0uKN%f&vNxf&u{m%20R*skxUv>`)yD7%qARQ>bP36CtP}x@~Z9*VkPYUS6pWrZtT#q)8GCbf0*5+4Pyw;#Tq!Aq{bDO|Iw<43LnG*#4;?Z&LM71zXE@J`@_dMl`?qQ1 z@3qR;mm=XG_-{G#4vhRxmZiQslrTtB_&7&0ECnD9)gZ}j`e&Je+s net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-query - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-Query diff --git a/slf4j/pom.xml b/slf4j/pom.xml index 293597b6..b995ba85 100644 --- a/slf4j/pom.xml +++ b/slf4j/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-slf4j - 1.18-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT jar BungeeCord-SLF4J