diff --git a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java index f497395e..ee7b65a6 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java @@ -2,7 +2,9 @@ package net.md_5.bungee.api.connection; import java.net.InetSocketAddress; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import net.md_5.bungee.api.config.ListenerInfo; +import org.jetbrains.annotations.ApiStatus; /** * Represents a user attempting to log into the proxy. @@ -89,4 +91,18 @@ public interface PendingConnection extends Connection * @return Whether the client is using a legacy client. */ boolean isLegacy(); + + /** + * Retrieves a cookie from this pending connection. + * + * @param cookie the resource location of the cookie, for example + * "bungeecord:my_cookie" + * @return a {@link CompletableFuture} that will be completed when the + * Cookie response is received. If the cookie is not set in the client, the + * {@link CompletableFuture} will complete with a null value + * @throws IllegalStateException if the player's version is not at least + * 1.20.5 + */ + @ApiStatus.Experimental + CompletableFuture retrieveCookie(String cookie); } diff --git a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java index ab879248..0fe647b8 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java @@ -3,6 +3,7 @@ package net.md_5.bungee.api.connection; import java.util.Locale; import java.util.Map; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.CommandSender; @@ -13,6 +14,7 @@ import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.score.Scoreboard; +import org.jetbrains.annotations.ApiStatus; /** * Represents a player whose connection is being connected to somewhere else, @@ -339,4 +341,45 @@ public interface ProxiedPlayer extends Connection, CommandSender */ @Deprecated Scoreboard getScoreboard(); + + /** + * Retrieves a cookie from this player. + * + * @param cookie the resource location of the cookie, for example + * "bungeecord:my_cookie" + * @return a {@link CompletableFuture} that will be completed when the + * Cookie response is received. If the cookie is not set in the client, the + * {@link CompletableFuture} will complete with a null value + * @throws IllegalStateException if the player's version is not at least + * 1.20.5 + */ + @ApiStatus.Experimental + CompletableFuture retrieveCookie(String cookie); + + /** + * Stores a cookie in this player's client. + * + * @param cookie the resource location of the cookie, for example + * "bungeecord:my_cookie" + * @param data the data to store in the cookie + * @throws IllegalStateException if the player's version is not at least + * 1.20.5 + */ + @ApiStatus.Experimental + void storeCookie(String cookie, byte[] data); + + /** + * Requests this player to connect to a different server specified by host + * and port. + * + * This is a client-side transfer - host and port should not specify a + * BungeeCord backend server. + * + * @param host the host of the server to transfer to + * @param port the port of the server to transfer to + * @throws IllegalStateException if the players version is not at least + * 1.20.5 + */ + @ApiStatus.Experimental + void transfer(String host, int port); } 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 4383dbb5..4b52c8b1 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 @@ -8,6 +8,8 @@ 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; +import net.md_5.bungee.protocol.packet.CookieRequest; +import net.md_5.bungee.protocol.packet.CookieResponse; import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionResponse; import net.md_5.bungee.protocol.packet.EntityStatus; @@ -40,6 +42,7 @@ import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.StartConfiguration; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; +import net.md_5.bungee.protocol.packet.StoreCookie; import net.md_5.bungee.protocol.packet.Subtitle; import net.md_5.bungee.protocol.packet.SystemChat; import net.md_5.bungee.protocol.packet.TabCompleteRequest; @@ -47,6 +50,7 @@ import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.Team; import net.md_5.bungee.protocol.packet.Title; import net.md_5.bungee.protocol.packet.TitleTimes; +import net.md_5.bungee.protocol.packet.Transfer; import net.md_5.bungee.protocol.packet.ViewDistance; public abstract class AbstractPacketHandler @@ -243,4 +247,20 @@ public abstract class AbstractPacketHandler public void handle(FinishConfiguration finishConfiguration) throws Exception { } + + public void handle(Transfer transfer) throws Exception + { + } + + public void handle(StoreCookie storeCookie) throws Exception + { + } + + public void handle(CookieRequest cookieRequest) throws Exception + { + } + + public void handle(CookieResponse cookieResponse) throws Exception + { + } } 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 cc08447c..05522d8e 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 @@ -16,6 +16,8 @@ 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.CookieRequest; +import net.md_5.bungee.protocol.packet.CookieResponse; import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionResponse; import net.md_5.bungee.protocol.packet.EntityStatus; @@ -46,6 +48,7 @@ import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.StartConfiguration; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; +import net.md_5.bungee.protocol.packet.StoreCookie; import net.md_5.bungee.protocol.packet.Subtitle; import net.md_5.bungee.protocol.packet.SystemChat; import net.md_5.bungee.protocol.packet.TabCompleteRequest; @@ -53,6 +56,7 @@ import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.Team; import net.md_5.bungee.protocol.packet.Title; import net.md_5.bungee.protocol.packet.TitleTimes; +import net.md_5.bungee.protocol.packet.Transfer; import net.md_5.bungee.protocol.packet.ViewDistance; public enum Protocol @@ -90,7 +94,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_1, 0x20 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x1F ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x23 ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x24 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x24 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x25 ) ); TO_CLIENT.registerPacket( Login.class, @@ -106,7 +111,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_1, 0x25 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x24 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x28 ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x29 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x29 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x2A ) ); TO_CLIENT.registerPacket( Chat.class, Chat::new, @@ -136,7 +142,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x3D ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x41 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x43 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x45 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x45 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x46 ) ); TO_CLIENT.registerPacket( BossBar.class, @@ -195,7 +202,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x54 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x58 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x5A ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x5C ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x5C ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x5D ) ); TO_CLIENT.registerPacket( ScoreboardScore.class, @@ -212,12 +220,14 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x57 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5B ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x5D ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x5F ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x5F ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x60 ) ); TO_CLIENT.registerPacket( ScoreboardScoreReset.class, ScoreboardScoreReset::new, - map( ProtocolConstants.MINECRAFT_1_20_3, 0x42 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x42 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x43 ) ); TO_CLIENT.registerPacket( ScoreboardDisplay.class, @@ -234,7 +244,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x4D ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x51 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x53 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x55 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x55 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x56 ) ); TO_CLIENT.registerPacket( Team.class, @@ -251,7 +262,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x56 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5A ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x5C ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x5E ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x5E ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x5F ) ); TO_CLIENT.registerPacket( PluginMessage.class, @@ -268,7 +280,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_1, 0x16 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x15 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x17 ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x18 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x18 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x19 ) ); TO_CLIENT.registerPacket( Kick.class, @@ -285,7 +298,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_1, 0x19 ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x17 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x1A ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x1B ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x1B ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x1C ) ); TO_CLIENT.registerPacket( Title.class, @@ -303,7 +317,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x5B ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5F ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x61 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x63 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x63 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x64 ) ); TO_CLIENT.registerPacket( ClearTitles.class, @@ -323,7 +338,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x59 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x5D ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x5F ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x61 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x61 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x62 ) ); TO_CLIENT.registerPacket( TitleTimes.class, @@ -334,7 +350,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x5C ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x60 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x62 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x64 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x64 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x65 ) ); TO_CLIENT.registerPacket( SystemChat.class, @@ -344,7 +361,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x60 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x64 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x67 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x69 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x69 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x6B ) ); TO_CLIENT.registerPacket( PlayerListHeaderFooter.class, @@ -365,7 +383,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x61 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x65 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x68 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x6A ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x6A ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x6C ) ); TO_CLIENT.registerPacket( EntityStatus.class, @@ -382,7 +401,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_1, 0x1A ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x19 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x1C ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x1D ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x1D ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x1E ) ); TO_CLIENT.registerPacket( Commands.class, @@ -408,7 +428,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_1, 0x1D ), map( ProtocolConstants.MINECRAFT_1_19_3, 0x1C ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x1F ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x20 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x20 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x21 ) ); TO_CLIENT.registerPacket( ViewDistance.class, @@ -422,7 +443,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x4B ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x4F ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x51 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x53 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x53 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x61 ) ); TO_CLIENT.registerPacket( ServerData.class, @@ -432,27 +454,46 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x41 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x45 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x47 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x49 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x49 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x4A ) ); TO_CLIENT.registerPacket( PlayerListItemRemove.class, PlayerListItemRemove::new, map( ProtocolConstants.MINECRAFT_1_19_3, 0x35 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x39 ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x3B ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x3B ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x3C ) ); TO_CLIENT.registerPacket( PlayerListItemUpdate.class, PlayerListItemUpdate::new, map( ProtocolConstants.MINECRAFT_1_19_3, 0x36 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x3A ), - map( ProtocolConstants.MINECRAFT_1_20_2, 0x3C ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x3C ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x3D ) ); TO_CLIENT.registerPacket( StartConfiguration.class, StartConfiguration::new, map( ProtocolConstants.MINECRAFT_1_20_2, 0x65 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x67 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x67 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x68 ) + ); + TO_CLIENT.registerPacket( + CookieRequest.class, + CookieRequest::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x16 ) + ); + TO_CLIENT.registerPacket( + StoreCookie.class, + StoreCookie::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x6A ) + ); + TO_CLIENT.registerPacket( + Transfer.class, + Transfer::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x72 ) ); TO_SERVER.registerPacket( @@ -471,7 +512,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x11 ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x12 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x14 ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x15 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x15 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x16 ) ); TO_SERVER.registerPacket( Chat.class, Chat::new, @@ -538,13 +580,19 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_3, 0x0C ), map( ProtocolConstants.MINECRAFT_1_19_4, 0x0D ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_20_3, 0x10 ) + map( ProtocolConstants.MINECRAFT_1_20_3, 0x10 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x11 ) ); TO_SERVER.registerPacket( StartConfiguration.class, StartConfiguration::new, map( ProtocolConstants.MINECRAFT_1_20_2, 0x0B ) ); + TO_SERVER.registerPacket( + CookieResponse.class, + CookieResponse::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x10 ) + ); } }, // 1 @@ -605,6 +653,11 @@ public enum Protocol LoginPayloadRequest::new, map( ProtocolConstants.MINECRAFT_1_13, 0x04 ) ); + TO_CLIENT.registerPacket( + CookieRequest.class, + CookieRequest::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x05 ) + ); TO_SERVER.registerPacket( LoginRequest.class, @@ -626,6 +679,11 @@ public enum Protocol LoginAcknowledged::new, map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 ) ); + TO_SERVER.registerPacket( + CookieResponse.class, + CookieResponse::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 ) + ); } }, // 3 @@ -633,25 +691,45 @@ public enum Protocol { { + + TO_CLIENT.registerPacket( + CookieRequest.class, + CookieRequest::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x00 ) + ); TO_CLIENT.registerPacket( PluginMessage.class, PluginMessage::new, - map( ProtocolConstants.MINECRAFT_1_20_2, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x00 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x01 ) ); TO_CLIENT.registerPacket( Kick.class, Kick::new, - map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x02 ) ); TO_CLIENT.registerPacket( FinishConfiguration.class, FinishConfiguration::new, - map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x03 ) ); TO_CLIENT.registerPacket( KeepAlive.class, KeepAlive::new, - map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 ) + ); + TO_CLIENT.registerPacket( + StoreCookie.class, + StoreCookie::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x09 ) + ); + TO_CLIENT.registerPacket( + Transfer.class, + Transfer::new, + map( ProtocolConstants.MINECRAFT_1_20_5, 0x0A ) ); TO_SERVER.registerPacket( @@ -662,17 +740,20 @@ public enum Protocol TO_SERVER.registerPacket( PluginMessage.class, PluginMessage::new, - map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x02 ) ); TO_SERVER.registerPacket( FinishConfiguration.class, FinishConfiguration::new, - map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x03 ) ); TO_SERVER.registerPacket( KeepAlive.class, KeepAlive::new, - map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 ) + map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 ), + map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 ) ); } }; 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 6cb4c798..80e06337 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 @@ -45,6 +45,7 @@ public class ProtocolConstants public static final int MINECRAFT_1_20 = 763; public static final int MINECRAFT_1_20_2 = 764; public static final int MINECRAFT_1_20_3 = 765; + public static final int MINECRAFT_1_20_5 = 1073741997; public static final List SUPPORTED_VERSIONS; public static final List SUPPORTED_VERSION_IDS; @@ -109,7 +110,7 @@ public class ProtocolConstants if ( SNAPSHOT_SUPPORT ) { // supportedVersions.add( "1.20.x" ); - // supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20_3 ); + supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20_5 ); } SUPPORTED_VERSIONS = supportedVersions.build(); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/CookieRequest.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/CookieRequest.java new file mode 100644 index 00000000..cb29519a --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/CookieRequest.java @@ -0,0 +1,38 @@ +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 CookieRequest extends DefinedPacket +{ + + private String cookie; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + cookie = readString( buf ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( cookie, 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/CookieResponse.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/CookieResponse.java new file mode 100644 index 00000000..77a541b6 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/CookieResponse.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 CookieResponse extends DefinedPacket +{ + + private String cookie; + private byte[] data; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + cookie = readString( buf ); + data = readNullable( DefinedPacket::readArray, buf ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( cookie, buf ); + writeNullable( data, DefinedPacket::writeArray, 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/EncryptionRequest.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionRequest.java index a29524ca..2c167475 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionRequest.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionRequest.java @@ -19,6 +19,7 @@ public class EncryptionRequest extends DefinedPacket private String serverId; private byte[] publicKey; private byte[] verifyToken; + private boolean shouldAuthenticate; @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) @@ -26,6 +27,10 @@ public class EncryptionRequest extends DefinedPacket serverId = readString( buf ); publicKey = readArray( buf ); verifyToken = readArray( buf ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 ) + { + shouldAuthenticate = buf.readBoolean(); + } } @Override @@ -34,6 +39,10 @@ public class EncryptionRequest extends DefinedPacket writeString( serverId, buf ); writeArray( publicKey, buf ); writeArray( verifyToken, buf ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 ) + { + buf.writeBoolean( shouldAuthenticate ); + } } @Override 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 f110c655..c3ca42d7 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 @@ -41,6 +41,7 @@ public class Login extends DefinedPacket private boolean flat; private Location deathLocation; private int portalCooldown; + private boolean secureProfile; @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) @@ -154,6 +155,11 @@ public class Login extends DefinedPacket { portalCooldown = readVarInt( buf ); } + + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 ) + { + secureProfile = buf.readBoolean(); + } } @Override @@ -275,6 +281,11 @@ public class Login extends DefinedPacket { writeVarInt( portalCooldown, buf ); } + + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 ) + { + buf.writeBoolean( secureProfile ); + } } @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ServerData.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ServerData.java index d3427f38..f9f485e4 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ServerData.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ServerData.java @@ -33,7 +33,7 @@ public class ServerData extends DefinedPacket { if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 ) { - icon = DefinedPacket.readArray( buf ); + icon = readArray( buf ); } else { icon = readString( buf ); @@ -45,7 +45,7 @@ public class ServerData extends DefinedPacket preview = buf.readBoolean(); } - if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 && protocolVersion < ProtocolConstants.MINECRAFT_1_20_5 ) { enforceSecure = buf.readBoolean(); } @@ -76,7 +76,7 @@ public class ServerData extends DefinedPacket buf.writeBoolean( true ); if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 ) { - DefinedPacket.writeArray( (byte[]) icon, buf ); + writeArray( (byte[]) icon, buf ); } else { writeString( (String) icon, buf ); @@ -91,7 +91,7 @@ public class ServerData extends DefinedPacket buf.writeBoolean( preview ); } - if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 && protocolVersion < ProtocolConstants.MINECRAFT_1_20_5 ) { buf.writeBoolean( enforceSecure ); } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/StoreCookie.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/StoreCookie.java new file mode 100644 index 00000000..7a728a04 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/StoreCookie.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 StoreCookie extends DefinedPacket +{ + + private String key; + private byte[] data; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + key = readString( buf ); + data = readArray( buf, 5120 ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( key, buf ); + writeArray( data, 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/Transfer.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Transfer.java new file mode 100644 index 00000000..6f7d0440 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Transfer.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 Transfer extends DefinedPacket +{ + + private String host; + private int port; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + host = readString( buf ); + port = readVarInt( buf ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( host, buf ); + writeVarInt( port, buf ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} 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 de12a565..fb497ca0 100644 --- a/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java +++ b/proxy/src/main/java/net/md_5/bungee/EncryptionUtil.java @@ -73,7 +73,8 @@ public class EncryptionUtil byte[] pubKey = keys.getPublic().getEncoded(); byte[] verify = new byte[ 4 ]; random.nextBytes( verify ); - return new EncryptionRequest( hash, pubKey, verify ); + // always auth for now + return new EncryptionRequest( hash, pubKey, verify, true ); } public static boolean check(PlayerPublicKey publicKey, UUID uuid) 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 dc6a5a8f..193a2057 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -243,7 +243,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.isLimitedCrafting(), login.isDebug(), login.isFlat(), login.getDeathLocation(), - login.getPortalCooldown() ); + login.getPortalCooldown(), login.isSecureProfile() ); user.unsafe().sendPacket( modLogin ); 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 04143a46..9edec410 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Objects; import java.util.Queue; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.logging.Level; import lombok.Getter; @@ -60,7 +61,9 @@ 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.StoreCookie; import net.md_5.bungee.protocol.packet.SystemChat; +import net.md_5.bungee.protocol.packet.Transfer; import net.md_5.bungee.tab.ServerUnique; import net.md_5.bungee.tab.TabList; import net.md_5.bungee.util.CaseInsensitiveSet; @@ -771,4 +774,26 @@ public final class UserConnection implements ProxiedPlayer { return serverSentScoreboard; } + + @Override + public CompletableFuture retrieveCookie(String cookie) + { + return pendingConnection.retrieveCookie( cookie ); + } + + @Override + public void storeCookie(String cookie, byte[] data) + { + Preconditions.checkState( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_5, "Cookies are only supported in 1.20.5 and above" ); + + unsafe().sendPacket( new StoreCookie( cookie, data ) ); + } + + @Override + public void transfer(String host, int port) + { + Preconditions.checkState( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_5, "Transfers are only supported in 1.20.5 and above" ); + + unsafe().sendPacket( new Transfer( host, port ) ); + } } 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 54c3223c..6967d4fc 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 @@ -68,6 +68,7 @@ public class Configuration implements ProxyConfig private int compressionThreshold = 256; private boolean preventProxyConnections; private boolean forgeSupport; + private boolean rejectTransfers; public void load() { @@ -103,6 +104,7 @@ public class Configuration implements ProxyConfig compressionThreshold = adapter.getInt( "network_compression_threshold", compressionThreshold ); preventProxyConnections = adapter.getBoolean( "prevent_proxy_connections", preventProxyConnections ); forgeSupport = adapter.getBoolean( "forge_support", forgeSupport ); + rejectTransfers = adapter.getBoolean( "reject_transfers", rejectTransfers ); disabledCommands = new CaseInsensitiveSet( (Collection) adapter.getList( "disabled_commands", Arrays.asList( "disabledcommandhere" ) ) ); 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 b1b087aa..b51500be 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 @@ -11,12 +11,19 @@ import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.time.Instant; import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import javax.crypto.SecretKey; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.ToString; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeServerInfo; import net.md_5.bungee.EncryptionUtil; @@ -51,6 +58,8 @@ 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.CookieRequest; +import net.md_5.bungee.protocol.packet.CookieResponse; import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionResponse; import net.md_5.bungee.protocol.packet.Handshake; @@ -86,6 +95,19 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Getter private final Set registeredChannels = new HashSet<>(); private State thisState = State.HANDSHAKE; + private final Queue requestedCookies = new LinkedList<>(); + + @Data + @ToString + @EqualsAndHashCode + @AllArgsConstructor + public static class CookieFuture + { + + private String cookie; + private CompletableFuture future; + } + private final Unsafe unsafe = new Unsafe() { @Override @@ -109,6 +131,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection private boolean legacy; @Getter private String extraDataInHandshake = ""; + @Getter + private boolean transferred; private UserConnection userCon; @Override @@ -349,6 +373,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection ch.setProtocol( Protocol.STATUS ); break; case 2: + case 3: + transferred = handshake.getRequestedProtocol() == 3; // Login bungee.getLogger().log( Level.INFO, "{0} has connected", this ); thisState = State.USERNAME; @@ -365,6 +391,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection } return; } + + if ( transferred && bungee.config.isRejectTransfers() ) + { + disconnect( bungee.getTranslation( "reject_transfer" ) ); + return; + } break; default: throw new QuietException( "Cannot request protocol " + handshake.getRequestedProtocol() ); @@ -643,6 +675,34 @@ public class InitialHandler extends PacketHandler implements PendingConnection disconnect( "Unexpected custom LoginPayloadResponse" ); } + @Override + public void handle(CookieResponse cookieResponse) + { + // be careful, backend server could also make the client send a cookie response + CookieFuture future; + synchronized ( requestedCookies ) + { + future = requestedCookies.peek(); + if ( future != null ) + { + if ( future.cookie.equals( cookieResponse.getCookie() ) ) + { + Preconditions.checkState( future == requestedCookies.poll(), "requestedCookies queue mismatch" ); + } else + { + future = null; // leave for handling by backend + } + } + } + + if ( future != null ) + { + future.getFuture().complete( cookieResponse.getData() ); + + throw CancelSendSignal.INSTANCE; + } + } + @Override public void disconnect(String reason) { @@ -775,4 +835,26 @@ public class InitialHandler extends PacketHandler implements PendingConnection brandMessage = input; } } + + @Override + public CompletableFuture retrieveCookie(String cookie) + { + Preconditions.checkState( getVersion() >= ProtocolConstants.MINECRAFT_1_20_5, "Cookies are only supported in 1.20.5 and above" ); + Preconditions.checkState( loginRequest != null, "Cannot retrieve cookies for status or legacy connections" ); + + if ( cookie.indexOf( ':' ) == -1 ) + { + // if we request an invalid resource location (no prefix) the client will respond with "minecraft:" prefix + cookie = "minecraft:" + cookie; + } + + CompletableFuture future = new CompletableFuture<>(); + synchronized ( requestedCookies ) + { + requestedCookies.add( new CookieFuture( cookie, future ) ); + } + unsafe.sendPacket( new CookieRequest( cookie ) ); + + return future; + } } 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 460aa491..95c7f3c4 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 @@ -32,6 +32,7 @@ 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.CookieResponse; import net.md_5.bungee.protocol.packet.FinishConfiguration; import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.LoginAcknowledged; @@ -363,6 +364,12 @@ public class UpstreamBridge extends PacketHandler con.sendQueuedPackets(); } + @Override + public void handle(CookieResponse cookieResponse) throws Exception + { + con.getPendingConnection().handle( cookieResponse ); + } + @Override public String toString() { 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 9a47f2ec..2bf92a03 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 @@ -86,6 +86,8 @@ public abstract class EntityMap return EntityMap_1_16_2.INSTANCE_1_20_2; case ProtocolConstants.MINECRAFT_1_20_3: return EntityMap_1_16_2.INSTANCE_1_20_3; + case ProtocolConstants.MINECRAFT_1_20_5: + return EntityMap_1_16_2.INSTANCE_1_20_5; } 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 007957a8..b92f3f1f 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 @@ -22,6 +22,7 @@ class EntityMap_1_16_2 extends EntityMap static final EntityMap_1_16_2 INSTANCE_1_19_4 = new EntityMap_1_16_2( 0x03, 0x30 ); static final EntityMap_1_16_2 INSTANCE_1_20_2 = new EntityMap_1_16_2( -1, 0x33 ); static final EntityMap_1_16_2 INSTANCE_1_20_3 = new EntityMap_1_16_2( -1, 0x34 ); + static final EntityMap_1_16_2 INSTANCE_1_20_5 = new EntityMap_1_16_2( -1, 0x6F ); // private final int spawnPlayerId; private final int spectateId; diff --git a/proxy/src/main/resources/messages.properties b/proxy/src/main/resources/messages.properties index e42b798b..149c742f 100644 --- a/proxy/src/main/resources/messages.properties +++ b/proxy/src/main/resources/messages.properties @@ -40,3 +40,4 @@ command_perms_permission=\u00a79- {0} command_ip=\u00a79IP of {0} is {1} illegal_chat_characters=\u00a7cIllegal characters in chat ({0}) kick_message=\u00a7cYou have been kicked off the proxy. +reject_transfer=\u00a7cYour transfer was rejected.