From be01c28a164204aebe233b95536ca92fe69d394a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 20:58:10 +0000 Subject: [PATCH 01/45] Bump snakeyaml from 1.31 to 1.32 --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0383f5d..4710657 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ org.yaml snakeyaml - 1.31 + 1.32 compile From d10dd40dcb71d8198e55694cab3d157dc2e12191 Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:24:14 +0200 Subject: [PATCH 02/45] Update ProtocolCodecs.java --- .../waterdog/waterdogpe/network/protocol/ProtocolCodecs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java index b6fda9f..6121783 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java @@ -117,7 +117,7 @@ public class ProtocolCodecs { HANDLED_PACKETS.add(ModalFormRequestPacket.class); HANDLED_PACKETS.add(ModalFormResponsePacket.class); HANDLED_PACKETS.add(BlockEntityDataPacket.class); - + HANDLED_PACKETS.add(ClientboundCloseFormPacket.class); } private static final List UPDATERS = new ObjectArrayList<>(); From 06b6fa08d7c80afcf2862e8a7c1396cf5f62a40d Mon Sep 17 00:00:00 2001 From: Alemiz Date: Tue, 22 Oct 2024 17:48:29 +0200 Subject: [PATCH 03/45] Add support for 1.20.40 --- .../waterdog/waterdogpe/network/protocol/ProtocolCodecs.java | 1 + .../waterdogpe/network/protocol/ProtocolVersion.java | 4 +++- .../waterdogpe/network/protocol/rewrite/EntityMap.java | 5 +++++ src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java index 1d7e2e6..f8c8f01 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java @@ -112,6 +112,7 @@ public class ProtocolCodecs { HANDLED_PACKETS.add(LevelChunkPacket.class); HANDLED_PACKETS.add(ClientCheatAbilityPacket.class); HANDLED_PACKETS.add(ToastRequestPacket.class); + HANDLED_PACKETS.add(MovementEffectPacket.class); } private static final List UPDATERS = new ObjectArrayList<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 19428ae..2783985 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -63,6 +63,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v686.Bedrock_v686; import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712; import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729; +import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -111,7 +112,8 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_0(685, Bedrock_v685.CODEC), MINECRAFT_PE_1_21_2(686, Bedrock_v686.CODEC), MINECRAFT_PE_1_21_20(712, Bedrock_v712.CODEC), - MINECRAFT_PE_1_21_30(729, Bedrock_v729.CODEC); + MINECRAFT_PE_1_21_30(729, Bedrock_v729.CODEC), + MINECRAFT_PE_1_21_40(748, Bedrock_v748.CODEC); private static final ProtocolVersion[] VALUES = values(); private static final Int2ObjectMap VERSIONS = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index 15a1df4..7b00731 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -332,6 +332,11 @@ public PacketSignal handle(AnimateEntityPacket packet) { return signal; } + @Override + public PacketSignal handle(MovementEffectPacket packet) { + return rewriteId(packet.getEntityRuntimeId(), packet::setEntityRuntimeId); + } + private PacketSignal rewriteMetadata(EntityDataMap metadata) { PacketSignal signal = PacketSignal.UNHANDLED; for (EntityDataType data : ENTITY_DATA_FIELDS) { diff --git a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java index 6e2ab02..ea8e63f 100644 --- a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java +++ b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java @@ -161,7 +161,7 @@ public void rebuildPackets() { for (ResourcePack pack : this.packs.values()) { ResourcePacksInfoPacket.Entry infoEntry = new ResourcePacksInfoPacket.Entry(pack.getPackId().toString(), pack.getVersion().toString(), - pack.getPackSize(), pack.getContentKey(), "", pack.getContentKey().equals("") ? "" : pack.getPackId().toString(), false, false, false); + pack.getPackSize(), pack.getContentKey(), "", pack.getContentKey().equals("") ? "" : pack.getPackId().toString(), false, false, false, null); ResourcePackStackPacket.Entry stackEntry = new ResourcePackStackPacket.Entry(pack.getPackId().toString(), pack.getVersion().toString(), ""); if (pack.getType().equals(ResourcePack.TYPE_RESOURCES)) { this.packsInfoPacket.getResourcePackInfos().add(infoEntry); From cfc4f11e4c6cc495a924313c58ee860e91b04acc Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Wed, 23 Oct 2024 21:52:55 +0200 Subject: [PATCH 04/45] Add support for 1.20.40 --- .../waterdog/waterdogpe/network/protocol/ProtocolCodecs.java | 1 + .../waterdogpe/network/protocol/ProtocolVersion.java | 4 +++- .../waterdogpe/network/protocol/rewrite/EntityMap.java | 5 +++++ src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java index 6121783..1fbc864 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java @@ -112,6 +112,7 @@ public class ProtocolCodecs { HANDLED_PACKETS.add(LevelChunkPacket.class); HANDLED_PACKETS.add(ClientCheatAbilityPacket.class); HANDLED_PACKETS.add(ToastRequestPacket.class); + HANDLED_PACKETS.add(MovementEffectPacket.class); HANDLED_PACKETS.add(PlaySoundPacket.class); HANDLED_PACKETS.add(PlayerAuthInputPacket.class); HANDLED_PACKETS.add(ModalFormRequestPacket.class); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 50e4846..278681c 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -64,6 +64,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v686.Bedrock_v686; import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712; import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729; +import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -112,7 +113,8 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_0(685, Bedrock_v685.CODEC), MINECRAFT_PE_1_21_2(686, Bedrock_v686.CODEC), MINECRAFT_PE_1_21_20(712, Bedrock_v712.CODEC), - MINECRAFT_PE_1_21_30(729, Bedrock_v729.CODEC); + MINECRAFT_PE_1_21_30(729, Bedrock_v729.CODEC), + MINECRAFT_PE_1_21_40(748, Bedrock_v748.CODEC); private static final ProtocolVersion[] VALUES = values(); private static final Int2ObjectMap VERSIONS = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index 15a1df4..7b00731 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -332,6 +332,11 @@ public PacketSignal handle(AnimateEntityPacket packet) { return signal; } + @Override + public PacketSignal handle(MovementEffectPacket packet) { + return rewriteId(packet.getEntityRuntimeId(), packet::setEntityRuntimeId); + } + private PacketSignal rewriteMetadata(EntityDataMap metadata) { PacketSignal signal = PacketSignal.UNHANDLED; for (EntityDataType data : ENTITY_DATA_FIELDS) { diff --git a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java index 6e2ab02..ea8e63f 100644 --- a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java +++ b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java @@ -161,7 +161,7 @@ public void rebuildPackets() { for (ResourcePack pack : this.packs.values()) { ResourcePacksInfoPacket.Entry infoEntry = new ResourcePacksInfoPacket.Entry(pack.getPackId().toString(), pack.getVersion().toString(), - pack.getPackSize(), pack.getContentKey(), "", pack.getContentKey().equals("") ? "" : pack.getPackId().toString(), false, false, false); + pack.getPackSize(), pack.getContentKey(), "", pack.getContentKey().equals("") ? "" : pack.getPackId().toString(), false, false, false, null); ResourcePackStackPacket.Entry stackEntry = new ResourcePackStackPacket.Entry(pack.getPackId().toString(), pack.getVersion().toString(), ""); if (pack.getType().equals(ResourcePack.TYPE_RESOURCES)) { this.packsInfoPacket.getResourcePackInfos().add(infoEntry); From 4e645e787b6f53b8584bc2944234f9e699a5551b Mon Sep 17 00:00:00 2001 From: Alemiz Date: Wed, 4 Dec 2024 17:59:34 +0100 Subject: [PATCH 05/45] Add support for MCBE 1.21.50 --- .../waterdogpe/network/protocol/ProtocolVersion.java | 5 ++++- src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 2783985..eb076ee 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -64,6 +64,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712; import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729; import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; +import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -113,7 +114,9 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_2(686, Bedrock_v686.CODEC), MINECRAFT_PE_1_21_20(712, Bedrock_v712.CODEC), MINECRAFT_PE_1_21_30(729, Bedrock_v729.CODEC), - MINECRAFT_PE_1_21_40(748, Bedrock_v748.CODEC); + MINECRAFT_PE_1_21_40(748, Bedrock_v748.CODEC), + MINECRAFT_PE_1_21_50_29(765, 766, Bedrock_v766.CODEC), + MINECRAFT_PE_1_21_50(766, Bedrock_v766.CODEC); private static final ProtocolVersion[] VALUES = values(); private static final Int2ObjectMap VERSIONS = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java index ea8e63f..d0e7538 100644 --- a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java +++ b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java @@ -160,7 +160,7 @@ public void rebuildPackets() { this.stackPacket.setGameVersion(""); for (ResourcePack pack : this.packs.values()) { - ResourcePacksInfoPacket.Entry infoEntry = new ResourcePacksInfoPacket.Entry(pack.getPackId().toString(), pack.getVersion().toString(), + ResourcePacksInfoPacket.Entry infoEntry = new ResourcePacksInfoPacket.Entry(pack.getPackId(), pack.getVersion().toString(), pack.getPackSize(), pack.getContentKey(), "", pack.getContentKey().equals("") ? "" : pack.getPackId().toString(), false, false, false, null); ResourcePackStackPacket.Entry stackEntry = new ResourcePackStackPacket.Entry(pack.getPackId().toString(), pack.getVersion().toString(), ""); if (pack.getType().equals(ResourcePack.TYPE_RESOURCES)) { From 15fce290beb7dcc456db8f16929993d3653c0112 Mon Sep 17 00:00:00 2001 From: Alemiz Date: Wed, 4 Dec 2024 18:00:51 +0100 Subject: [PATCH 06/45] Missed version here --- src/main/java/dev/waterdog/waterdogpe/VersionInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java b/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java index 90751a0..adb9219 100644 --- a/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java +++ b/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java @@ -22,7 +22,7 @@ public class VersionInfo { public static final boolean DEFAULT_DEBUG = true; - private final String baseVersion = "2.0.2"; + private final String baseVersion = "2.0.3"; private final String buildVersion = "#build"; private final String author = "WaterdogTEAM"; private final int metricsId = 15678; From e37a3226dff5d80efd13704a779fb280cf2cd2e0 Mon Sep 17 00:00:00 2001 From: Alemiz Date: Wed, 4 Dec 2024 18:04:30 +0100 Subject: [PATCH 07/45] Set world template fields --- src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java index d0e7538..53a9881 100644 --- a/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java +++ b/src/main/java/dev/waterdog/waterdogpe/packs/PackManager.java @@ -149,6 +149,8 @@ public boolean unregisterPack(UUID packId) { public void rebuildPackets() { this.packsInfoPacket.setForcedToAccept(this.proxy.getConfiguration().isForceServerPacks()); + this.packsInfoPacket.setWorldTemplateId(UUID.randomUUID()); + this.packsInfoPacket.setWorldTemplateVersion(""); this.stackPacket.setForcedToAccept(this.proxy.getConfiguration().isOverwriteClientPacks()); this.packsInfoPacket.getBehaviorPackInfos().clear(); From 94476df2d4799f8be21c4bef6870f4b7ce03ddd8 Mon Sep 17 00:00:00 2001 From: Alemiz Date: Wed, 4 Dec 2024 18:06:11 +0100 Subject: [PATCH 08/45] Next is v2.0.4 --- pom.xml | 2 +- src/main/java/dev/waterdog/waterdogpe/VersionInfo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 858d925..d78a10c 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ dev.waterdog.waterdogpe waterdog - 2.0.3-SNAPSHOT + 2.0.4-SNAPSHOT jar diff --git a/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java b/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java index adb9219..c163dd9 100644 --- a/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java +++ b/src/main/java/dev/waterdog/waterdogpe/VersionInfo.java @@ -22,7 +22,7 @@ public class VersionInfo { public static final boolean DEFAULT_DEBUG = true; - private final String baseVersion = "2.0.3"; + private final String baseVersion = "2.0.4"; private final String buildVersion = "#build"; private final String author = "WaterdogTEAM"; private final int metricsId = 15678; From 9ecb8cf94fd91d440d049c709245ae4303440016 Mon Sep 17 00:00:00 2001 From: Encritary Date: Sat, 21 Dec 2024 12:08:35 +0300 Subject: [PATCH 09/45] fix: fix NPE on early packet send for versions before 1.20.60 java.lang.NullPointerException: Cannot invoke "org.cloudburstmc.protocol.bedrock.netty.codec.compression.CompressionStrategy.getDefaultCompression()" because "this.compressionStrategy" is null at dev.waterdog.waterdogpe.network.connection.peer.ProxiedBedrockPeer.sendPacket0(ProxiedBedrockPeer.java:122) ~[waterdog.jar:?] at dev.waterdog.waterdogpe.network.connection.peer.ProxiedBedrockPeer.lambda$sendPacket$0(ProxiedBedrockPeer.java:114) ~[waterdog.jar:?] at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173) ~[waterdog.jar:?] at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166) ~[waterdog.jar:?] at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) ~[waterdog.jar:?] at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:413) ~[waterdog.jar:?] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[waterdog.jar:?] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[waterdog.jar:?] --- .../network/connection/peer/ProxiedBedrockPeer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/ProxiedBedrockPeer.java b/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/ProxiedBedrockPeer.java index cbbb452..57d4e0a 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/ProxiedBedrockPeer.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/ProxiedBedrockPeer.java @@ -118,8 +118,8 @@ public void sendPacket(BedrockBatchWrapper wrapper) { private void sendPacket0(BedrockBatchWrapper wrapper) { if (!(wrapper.getAlgorithm() instanceof PacketCompressionAlgorithm)) { wrapper.setCompressed(null); // Do not allow using unsupported algorithms when sending to client - } else if (this.version.isBefore(ProtocolVersion.MINECRAFT_PE_1_20_60) && - !Objects.equals(wrapper.getAlgorithm(), this.compressionStrategy.getDefaultCompression().getAlgorithm())) { + } else if (this.version.isBefore(ProtocolVersion.MINECRAFT_PE_1_20_60) && (this.compressionStrategy == null || + !Objects.equals(wrapper.getAlgorithm(), this.compressionStrategy.getDefaultCompression().getAlgorithm()))) { wrapper.setCompressed(null); // Before 1.20.60 dynamic compression is not supported } From df1b45df7c9ce4be152b98d5860375f810b81cfa Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:56:51 +0100 Subject: [PATCH 10/45] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index a333c35..a57e586 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,7 @@ If you haven't used WaterdogPE before, we recommend you to take a look at our [s *Please note that the config from the old Waterdog (Bungee) is not compatible with WaterdogPE* ### Supported Software -Our focus lies on PowerNukkitX 2.0 since its the only server software that's worth using. (Besides Nukkit Mot maybe?) - -You can find list of currently supported/unsupported software [here](https://docs.waterdog.dev/books/waterdogpe-setup/page/software-compatibility). +Our focus lies on PowerNukkitX since its the only server software that's worth using. ## Compiling From 4184b92b8ad936171275c1dfda7f3a0ddad1099d Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:25:00 +0100 Subject: [PATCH 11/45] ? --- .../waterdogpe/network/protocol/ProtocolCodecs.java | 1 + .../network/protocol/handler/ProxyBatchBridge.java | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java index 1fbc864..01f56a0 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java @@ -118,6 +118,7 @@ public class ProtocolCodecs { HANDLED_PACKETS.add(ModalFormRequestPacket.class); HANDLED_PACKETS.add(ModalFormResponsePacket.class); HANDLED_PACKETS.add(BlockEntityDataPacket.class); + HANDLED_PACKETS.add(InventoryTransactionPacket.class); HANDLED_PACKETS.add(ClientboundCloseFormPacket.class); } diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/ProxyBatchBridge.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/ProxyBatchBridge.java index e30b210..cf48ac1 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/ProxyBatchBridge.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/ProxyBatchBridge.java @@ -28,6 +28,7 @@ import org.cloudburstmc.protocol.bedrock.netty.BedrockPacketWrapper; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacketHandler; +import org.cloudburstmc.protocol.bedrock.packet.DisconnectPacket; import org.cloudburstmc.protocol.common.PacketSignal; import org.cloudburstmc.protocol.common.util.Preconditions; @@ -53,7 +54,11 @@ public void onBedrockBatch(ProxiedConnection source, BedrockBatchWrapper batch) while (iterator.hasNext()) { BedrockPacketWrapper wrapper = iterator.next(); if (wrapper.getPacket() == null) { - this.decodePacket(wrapper, source.getPacketDirection()); + try { + this.decodePacket(wrapper, source.getPacketDirection()); + } catch (Exception e) { + source.sendPacket(new DisconnectPacket()); + } } PacketSignal signal = this.handlePacket(wrapper.getPacket()); From 143727b894a20cdcf5d83489e2b3cd8db4fb369e Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 12 Feb 2025 18:15:22 +0300 Subject: [PATCH 12/45] Add support for 1.21.60 --- pom.xml | 2 +- .../waterdog/waterdogpe/network/protocol/ProtocolVersion.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d78a10c..2c9e302 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ UTF-8 17 1.0.0.CR3-SNAPSHOT - 3.0.0.Beta5-SNAPSHOT + 3.0.0.Beta6-SNAPSHOT 2.17.1 3.23.0 4.1.101.Final diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index eb076ee..c9156db 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -116,7 +116,8 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_30(729, Bedrock_v729.CODEC), MINECRAFT_PE_1_21_40(748, Bedrock_v748.CODEC), MINECRAFT_PE_1_21_50_29(765, 766, Bedrock_v766.CODEC), - MINECRAFT_PE_1_21_50(766, Bedrock_v766.CODEC); + MINECRAFT_PE_1_21_50(766, Bedrock_v766.CODEC), + MINECRAFT_PE_1_21_60(776, Bedrock_v766.CODEC); private static final ProtocolVersion[] VALUES = values(); private static final Int2ObjectMap VERSIONS = new Int2ObjectOpenHashMap<>(); From b6b93d2014e67491f5eebafe82ce2c5b104863fb Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 12 Feb 2025 18:49:52 +0300 Subject: [PATCH 13/45] Handle ItemComponentPacket to load item definitions after 1.21.60 --- .../downstream/AbstractDownstreamHandler.java | 21 +++++++++++++++++++ .../ConnectedDownstreamHandler.java | 13 ++++++++++++ .../handler/downstream/InitialHandler.java | 13 +++--------- .../waterdogpe/player/ProxiedPlayer.java | 13 ++++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java index 28cbcc3..9b2f430 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java @@ -22,12 +22,17 @@ import dev.waterdog.waterdogpe.network.protocol.rewrite.RewriteMaps; import dev.waterdog.waterdogpe.player.ProxiedPlayer; import dev.waterdog.waterdogpe.network.protocol.Signals; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper; import org.cloudburstmc.protocol.bedrock.data.command.CommandData; import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumConstraint; import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.netty.BedrockBatchWrapper; import org.cloudburstmc.protocol.bedrock.packet.*; import org.cloudburstmc.protocol.common.PacketSignal; +import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry; import java.util.*; import java.util.function.Consumer; @@ -149,4 +154,20 @@ public RewriteMaps getRewriteMaps() { public ClientConnection getConnection() { return connection; } + + protected void setItemDefinitions(Collection definitions) { + BedrockCodecHelper codecHelper = this.player.getConnection() + .getPeer() + .getCodecHelper(); + SimpleDefinitionRegistry.Builder itemRegistry = SimpleDefinitionRegistry.builder(); + IntSet runtimeIds = new IntOpenHashSet(); + for (ItemDefinition definition : definitions) { + if (runtimeIds.add(definition.getRuntimeId())) { + itemRegistry.add(definition); + } else { + player.getLogger().warning("[{}|{}] has duplicate item definition: {}", this.player.getName(), this.connection.getServerInfo().getServerName(), definition); + } + } + codecHelper.setItemDefinitions(itemRegistry.build()); + } } diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java index c28004b..97379cc 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java @@ -17,6 +17,7 @@ import dev.waterdog.waterdogpe.network.connection.client.ClientConnection; import dev.waterdog.waterdogpe.network.connection.handler.ReconnectReason; +import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import dev.waterdog.waterdogpe.network.protocol.handler.PluginPacketHandler; import org.cloudburstmc.protocol.bedrock.PacketDirection; import org.cloudburstmc.protocol.bedrock.packet.*; @@ -38,6 +39,18 @@ public ConnectedDownstreamHandler(ProxiedPlayer player, ClientConnection connect super(player, connection); } + @Override + public PacketSignal handle(ItemComponentPacket packet) { + if (!this.player.acceptItemComponentPacket()) { + return Signals.CANCEL; + } + player.setAcceptItemComponentPacket(false); + if (this.player.getProtocol().isAfterOrEqual(ProtocolVersion.MINECRAFT_PE_1_21_60)) { + setItemDefinitions(packet.getItems()); + } + return super.handle(packet); + } + @Override public PacketSignal handlePacket(BedrockPacket packet) { PacketSignal signal = super.handlePacket(packet); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java index 3796c6a..d65e60a 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java @@ -130,17 +130,10 @@ public final PacketSignal handle(StartGamePacket packet) { BedrockCodecHelper codecHelper = this.player.getConnection() .getPeer() .getCodecHelper(); - // Setup item registry - SimpleDefinitionRegistry.Builder itemRegistry = SimpleDefinitionRegistry.builder(); - IntSet runtimeIds = new IntOpenHashSet(); - for (ItemDefinition definition : packet.getItemDefinitions()) { - if (runtimeIds.add(definition.getRuntimeId())) { - itemRegistry.add(definition); - } else { - this.player.getLogger().warning("[{}|{}] has duplicate item definition: {}", this.player.getName(), this.connection.getServerInfo().getServerName(), definition); - } + // Setup item registry. After 1.21.60 these are sent with ItemComponentPacket instead. + if (this.player.getProtocol().isBeforeOrEqual(ProtocolVersion.MINECRAFT_PE_1_21_50)) { + setItemDefinitions(packet.getItemDefinitions()); } - codecHelper.setItemDefinitions(itemRegistry.build()); // Setup block registry codecHelper.setBlockDefinitions(FakeDefinitionRegistry.createBlockRegistry()); // Enable runtimeId rewrite diff --git a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java index 5ec75d9..8c2a9a7 100644 --- a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java +++ b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java @@ -99,6 +99,11 @@ public class ProxiedPlayer implements CommandSender { * This value is changed by PlayerResourcePackInfoSendEvent. */ private volatile boolean acceptResourcePacks = true; + /** + * Used to determine if proxy can send ItemComponentPacket to player. + * Client will crash if ItemComponentPacket is sent twice. + */ + private volatile boolean acceptItemComponentPacket = true; /** * Additional downstream and upstream handlers can be set by plugin. * Do not set directly BedrockPacketHandler to sessions! @@ -898,6 +903,14 @@ public boolean acceptResourcePacks() { return this.acceptResourcePacks; } + public boolean acceptItemComponentPacket() { + return acceptItemComponentPacket; + } + + public void setAcceptItemComponentPacket(boolean acceptItemComponentPacket) { + this.acceptItemComponentPacket = acceptItemComponentPacket; + } + public CompressionType getCompression() { return this.compression; } From a188f38fbbdd57d750e558e3174790dd9d53303e Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 12 Feb 2025 18:55:58 +0300 Subject: [PATCH 14/45] Fix upload artifact actions (#331) --- .github/actions/build/action.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 0aec530..52c0665 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -56,10 +56,11 @@ runs: shell: bash - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: waterdog path: target/Waterdog.jar + pattern: waterdog-* + merge-multiple: true - name: Create pre-release if: ${{ inputs.create_prerelease == 'true' }} From d0899b9ea569a640a9d8ea8ffbddb0a58c579981 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 12 Feb 2025 19:01:56 +0300 Subject: [PATCH 15/45] Rewrite MovementPredictionSyncPacket --- .../waterdogpe/network/protocol/rewrite/EntityMap.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index 7b00731..7ecb68e 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -337,6 +337,11 @@ public PacketSignal handle(MovementEffectPacket packet) { return rewriteId(packet.getEntityRuntimeId(), packet::setEntityRuntimeId); } + @Override + public PacketSignal handle(MovementPredictionSyncPacket packet) { + return rewriteId(packet.getRuntimeEntityId(), packet::setRuntimeEntityId); + } + private PacketSignal rewriteMetadata(EntityDataMap metadata) { PacketSignal signal = PacketSignal.UNHANDLED; for (EntityDataType data : ENTITY_DATA_FIELDS) { From bbbf12e9e499b933dd6691198baecd6d3c0a1034 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 12 Feb 2025 19:13:41 +0300 Subject: [PATCH 16/45] Fix warnings with build actions --- .github/actions/build/action.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 52c0665..caa6a86 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -35,7 +35,7 @@ runs: distribution: adopt-hotspot - name: Setup maven repo - uses: s4u/maven-settings-action@v2.6.0 + uses: s4u/maven-settings-action@v3.1.0 if: ${{ inputs.perform_deploy == 'true' }} with: servers: | @@ -58,9 +58,8 @@ runs: - name: Upload artifacts uses: actions/upload-artifact@v4 with: + name: waterdog path: target/Waterdog.jar - pattern: waterdog-* - merge-multiple: true - name: Create pre-release if: ${{ inputs.create_prerelease == 'true' }} From ebacdeb8f0772383996dae498702b0b97fef003f Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 12 Feb 2025 20:23:45 +0300 Subject: [PATCH 17/45] Fix 1.21.60 protocol codec (#333) * Fix 1.21.60 protocol codec * Use PacketSignal.UNHANDLED instead of calling super which does the same --- .../waterdog/waterdogpe/network/protocol/ProtocolVersion.java | 3 ++- .../handler/downstream/ConnectedDownstreamHandler.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index c9156db..d7b1610 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -65,6 +65,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729; import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; +import org.cloudburstmc.protocol.bedrock.codec.v776.Bedrock_v776; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -117,7 +118,7 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_40(748, Bedrock_v748.CODEC), MINECRAFT_PE_1_21_50_29(765, 766, Bedrock_v766.CODEC), MINECRAFT_PE_1_21_50(766, Bedrock_v766.CODEC), - MINECRAFT_PE_1_21_60(776, Bedrock_v766.CODEC); + MINECRAFT_PE_1_21_60(776, Bedrock_v776.CODEC); private static final ProtocolVersion[] VALUES = values(); private static final Int2ObjectMap VERSIONS = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java index 97379cc..5477678 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java @@ -48,7 +48,7 @@ public PacketSignal handle(ItemComponentPacket packet) { if (this.player.getProtocol().isAfterOrEqual(ProtocolVersion.MINECRAFT_PE_1_21_60)) { setItemDefinitions(packet.getItems()); } - return super.handle(packet); + return PacketSignal.UNHANDLED; } @Override From ef474ede12ed3dd776ed1e28212dd8071bdf8839 Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:32:17 +0100 Subject: [PATCH 18/45] updated lombok and changed filename --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2c9e302..fa59260 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ org.projectlombok lombok - 1.18.26 + 1.18.34 compile @@ -214,7 +214,7 @@ dev.waterdog.waterdogpe.WaterdogPE - Waterdog + waterdogpe From 66cea5f3165b975c73dbe34f563031502972855b Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:32:20 +0100 Subject: [PATCH 19/45] Update ProxiedPlayer.java --- src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java index 6437f5c..50a6a11 100644 --- a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java +++ b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java @@ -930,6 +930,7 @@ public boolean acceptResourcePacks() { public Object getData(String key) { return this.data.get(key); } + public Object getData(String key, Object fallback) { if(this.hasData(key)) { return this.data.get(key); From bba15cd7e276f62b68c1bda154fdee287b1ab846 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Fri, 28 Mar 2025 01:43:02 +0300 Subject: [PATCH 20/45] Added support for 1.21.70 --- .../waterdogpe/network/protocol/ProtocolVersion.java | 5 ++++- .../waterdogpe/network/protocol/rewrite/EntityMap.java | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index d7b1610..9efa2f8 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -66,6 +66,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; import org.cloudburstmc.protocol.bedrock.codec.v776.Bedrock_v776; +import org.cloudburstmc.protocol.bedrock.codec.v786.Bedrock_v786; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -118,7 +119,9 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_40(748, Bedrock_v748.CODEC), MINECRAFT_PE_1_21_50_29(765, 766, Bedrock_v766.CODEC), MINECRAFT_PE_1_21_50(766, Bedrock_v766.CODEC), - MINECRAFT_PE_1_21_60(776, Bedrock_v776.CODEC); + MINECRAFT_PE_1_21_60(776, Bedrock_v776.CODEC), + MINECRAFT_PE_1_21_70(786, Bedrock_v786.CODEC), + ; private static final ProtocolVersion[] VALUES = values(); private static final Int2ObjectMap VERSIONS = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index 7ecb68e..f8fcf3e 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -321,6 +321,16 @@ public PacketSignal handle(ClientCheatAbilityPacket packet) { return rewriteId(packet.getUniqueEntityId(), packet::setUniqueEntityId); } + @Override + public PacketSignal handle(PlayerUpdateEntityOverridesPacket packet) { + return rewriteId(packet.getEntityUniqueId(), packet::setEntityUniqueId); + } + + @Override + public PacketSignal handle(LevelSoundEventPacket packet) { + return rewriteId(packet.getEntityUniqueId(), packet::setEntityUniqueId); + } + @Override public PacketSignal handle(AnimateEntityPacket packet) { PacketSignal signal = PacketSignal.UNHANDLED; From c14fc24a7f0f0e05f2461ee54bee81e9dbdced61 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 7 May 2025 02:14:32 +0300 Subject: [PATCH 21/45] Added 1.21.80 support --- .../waterdogpe/network/protocol/ProtocolVersion.java | 2 ++ .../waterdogpe/network/protocol/rewrite/EntityMap.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 9efa2f8..e881a0d 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -67,6 +67,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; import org.cloudburstmc.protocol.bedrock.codec.v776.Bedrock_v776; import org.cloudburstmc.protocol.bedrock.codec.v786.Bedrock_v786; +import org.cloudburstmc.protocol.bedrock.codec.v800.Bedrock_v800; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -121,6 +122,7 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_50(766, Bedrock_v766.CODEC), MINECRAFT_PE_1_21_60(776, Bedrock_v776.CODEC), MINECRAFT_PE_1_21_70(786, Bedrock_v786.CODEC), + MINECRAFT_PE_1_21_80(800, Bedrock_v800.CODEC), ; private static final ProtocolVersion[] VALUES = values(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index f8fcf3e..a01f157 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -220,6 +220,11 @@ public PacketSignal handle(InteractPacket packet) { return rewriteId(packet.getRuntimeEntityId(), packet::setRuntimeEntityId); } + @Override + public PacketSignal handle(PlayerLocationPacket packet) { + return rewriteId(packet.getTargetEntityId(), packet::setTargetEntityId); + } + @Override public PacketSignal handle(SetEntityLinkPacket packet) { EntityLinkData entityLink = packet.getEntityLink(); From f987bed993331eae955ba5dba1f51463c692fdba Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Thu, 8 May 2025 00:41:46 +0300 Subject: [PATCH 22/45] Move ItemComponentPacket handler to AbstractDownstreamHandler --- .../downstream/AbstractDownstreamHandler.java | 12 ++++++++++++ .../downstream/ConnectedDownstreamHandler.java | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java index 9b2f430..a322c27 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java @@ -49,6 +49,18 @@ public AbstractDownstreamHandler(ProxiedPlayer player, ClientConnection connecti this.connection = connection; } + @Override + public PacketSignal handle(ItemComponentPacket packet) { + if (!this.player.acceptItemComponentPacket()) { + return Signals.CANCEL; + } + player.setAcceptItemComponentPacket(false); + if (this.player.getProtocol().isAfterOrEqual(ProtocolVersion.MINECRAFT_PE_1_21_60)) { + setItemDefinitions(packet.getItems()); + } + return PacketSignal.UNHANDLED; + } + @Override public void sendProxiedBatch(BedrockBatchWrapper batch) { if (this.player.getConnection().isConnected()) { diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java index 5477678..7a174a6 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java @@ -39,18 +39,6 @@ public ConnectedDownstreamHandler(ProxiedPlayer player, ClientConnection connect super(player, connection); } - @Override - public PacketSignal handle(ItemComponentPacket packet) { - if (!this.player.acceptItemComponentPacket()) { - return Signals.CANCEL; - } - player.setAcceptItemComponentPacket(false); - if (this.player.getProtocol().isAfterOrEqual(ProtocolVersion.MINECRAFT_PE_1_21_60)) { - setItemDefinitions(packet.getItems()); - } - return PacketSignal.UNHANDLED; - } - @Override public PacketSignal handlePacket(BedrockPacket packet) { PacketSignal signal = super.handlePacket(packet); From da192af9d447960ee667c69bfd65b2b7cf68a928 Mon Sep 17 00:00:00 2001 From: Tobias Grether Date: Sat, 17 May 2025 11:56:29 +0200 Subject: [PATCH 23/45] fix: EventPriority documentation --- .../java/dev/waterdog/waterdogpe/event/EventPriority.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/event/EventPriority.java b/src/main/java/dev/waterdog/waterdogpe/event/EventPriority.java index 2790c81..41ff666 100644 --- a/src/main/java/dev/waterdog/waterdogpe/event/EventPriority.java +++ b/src/main/java/dev/waterdog/waterdogpe/event/EventPriority.java @@ -18,8 +18,8 @@ /** * Represents the Priority of an event. * Default event priority, if not specific otherwise, is NORMAL. - * HIGHEST is called first, - * LOWEST is called last. + * LOWEST is called first, + * HIGHEST is called last. */ public enum EventPriority { LOWEST, From a1de7372df288595d73a6bbf8b610c944daddec5 Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Thu, 12 Jun 2025 07:11:41 +0200 Subject: [PATCH 24/45] Fixed maven --- pom.xml | 6 +++--- src/main/java/dev/waterdog/waterdogpe/plugin/Plugin.java | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index fa59260..39e53c7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,9 +6,9 @@ Brand new Minecraft: Bedrock Edition proxy created by authors of well-known Waterdog proxy - dev.waterdog.waterdogpe - waterdog - 2.0.4-SNAPSHOT + xyz.syodo.software + syodogpe + 2.0.4 jar diff --git a/src/main/java/dev/waterdog/waterdogpe/plugin/Plugin.java b/src/main/java/dev/waterdog/waterdogpe/plugin/Plugin.java index ca5a428..ac74125 100644 --- a/src/main/java/dev/waterdog/waterdogpe/plugin/Plugin.java +++ b/src/main/java/dev/waterdog/waterdogpe/plugin/Plugin.java @@ -48,7 +48,6 @@ public abstract class Plugin { protected boolean enabled = false; private PluginYAML description; private ProxyServer proxy; - @Getter(AccessLevel.NONE) private Logger logger; private File pluginFile; private File dataFolder; From a3ae592dc8b6e6ebb93f948b9e3758f5c0854a80 Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Sat, 14 Jun 2025 08:53:02 +0200 Subject: [PATCH 25/45] Fixed Proxy Command injection --- .../downstream/AbstractDownstreamHandler.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java index a322c27..a7ffc8b 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java @@ -25,9 +25,7 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper; -import org.cloudburstmc.protocol.bedrock.data.command.CommandData; -import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumConstraint; -import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData; +import org.cloudburstmc.protocol.bedrock.data.command.*; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.netty.BedrockBatchWrapper; import org.cloudburstmc.protocol.bedrock.packet.*; @@ -87,6 +85,7 @@ public PacketSignal handle(AvailableCommandsPacket packet) { for (Command command : this.player.getProxy().getCommandMap().getCommands().values()) { if (command.getPermission() == null || this.player.hasPermission(command.getPermission())) { + packet.getCommands().stream().filter(commandData -> commandData.getName().equalsIgnoreCase(command.getName())).findFirst().ifPresent(commandData -> packet.getCommands().remove(commandData)); packet.getCommands().add(command.getCommandData()); } } @@ -114,6 +113,16 @@ public PacketSignal handle(AvailableCommandsPacket packet) { Collections.emptyList(), command.getOverloads())); } + + for(CommandData command : packet.getCommands()) { + for(CommandOverloadData overload : command.getOverloads()) { + for(CommandParamData param : overload.getOverloads()) { + if(param.getType() == null) { + param.setType(CommandParam.UNKNOWN); + } + } + } + } return PacketSignal.HANDLED; } From 02e52e1608f2c45ed49bda4b06d0c0392246aa7b Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Tue, 17 Jun 2025 00:37:05 +0300 Subject: [PATCH 26/45] Added 1.21.90 support --- pom.xml | 2 +- .../network/protocol/ProtocolVersion.java | 2 + .../network/protocol/user/HandshakeUtils.java | 45 ++++++++++++------- .../network/protocol/user/LoginData.java | 7 ++- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 2c9e302..e8d1c5e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ UTF-8 17 1.0.0.CR3-SNAPSHOT - 3.0.0.Beta6-SNAPSHOT + 3.0.0.Beta7-SNAPSHOT 2.17.1 3.23.0 4.1.101.Final diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index e881a0d..930422c 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -68,6 +68,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v776.Bedrock_v776; import org.cloudburstmc.protocol.bedrock.codec.v786.Bedrock_v786; import org.cloudburstmc.protocol.bedrock.codec.v800.Bedrock_v800; +import org.cloudburstmc.protocol.bedrock.codec.v818.Bedrock_v818; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -123,6 +124,7 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_60(776, Bedrock_v776.CODEC), MINECRAFT_PE_1_21_70(786, Bedrock_v786.CODEC), MINECRAFT_PE_1_21_80(800, Bedrock_v800.CODEC), + MINECRAFT_PE_1_21_90(818, Bedrock_v818.CODEC), ; private static final ProtocolVersion[] VALUES = values(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java index 5fa9e4b..6bfbb0c 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java @@ -28,6 +28,9 @@ import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import dev.waterdog.waterdogpe.utils.config.proxy.ProxyConfig; import org.cloudburstmc.protocol.bedrock.BedrockSession; +import org.cloudburstmc.protocol.bedrock.data.auth.AuthPayload; +import org.cloudburstmc.protocol.bedrock.data.auth.CertificateChainPayload; +import org.cloudburstmc.protocol.bedrock.data.auth.TokenPayload; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; @@ -163,27 +166,35 @@ public static boolean verifyJwt(JWSObject jws, ECPublicKey key) throws JOSEExcep } public static HandshakeEntry processHandshake(BedrockSession session, LoginPacket packet, ProtocolVersion protocol, boolean strict) throws Exception { - List chain = packet.getChain(); - if (chain.size() < 1) { - throw new IllegalArgumentException("Invalid chain data"); - } + AuthPayload authPayload = packet.getAuthPayload(); + if (authPayload instanceof CertificateChainPayload chainPayload) { + List chain = chainPayload.getChain(); + if (chain.isEmpty()) { + throw new IllegalArgumentException("Invalid chain data"); + } - boolean xboxAuth = HandshakeUtils.validateChain(chain, strict); - JsonObject payload = (JsonObject) JsonParser.parseString(SignedJWT.parse(chain.get(chain.size() - 1)).getPayload().toString()); - JsonObject extraData = HandshakeUtils.parseExtraData(packet, payload); + boolean xboxAuth = HandshakeUtils.validateChain(chain, strict); + JsonObject payload = (JsonObject) JsonParser.parseString(SignedJWT.parse(chain.get(chain.size() - 1)).getPayload().toString()); + JsonObject extraData = HandshakeUtils.parseExtraData(packet, payload); - if (!payload.has("identityPublicKey")) { - throw new RuntimeException("Identity Public Key was not found!"); - } - String identityPublicKeyString = payload.get("identityPublicKey").getAsString(); + if (!payload.has("identityPublicKey")) { + throw new RuntimeException("Identity Public Key was not found!"); + } + String identityPublicKeyString = payload.get("identityPublicKey").getAsString(); + + ECPublicKey identityPublicKey = generateKey(identityPublicKeyString); + SignedJWT clientJwt = SignedJWT.parse(packet.getClientJwt()); + if (!verifyJwt(clientJwt, identityPublicKey) && strict) { + xboxAuth = false; + } + JsonObject clientData = HandshakeUtils.parseClientData(clientJwt, extraData, session); - ECPublicKey identityPublicKey = generateKey(identityPublicKeyString); - SignedJWT extraDataJwt = SignedJWT.parse(packet.getExtra()); - if (!verifyJwt(extraDataJwt, identityPublicKey) && strict) { - xboxAuth = false; + return new HandshakeEntry(identityPublicKey, clientData, extraData, xboxAuth, protocol); + } else if (authPayload instanceof TokenPayload) { + throw new IllegalArgumentException("Token payload auth is not supported yet"); + } else { + throw new IllegalArgumentException("Invalid auth payload"); } - JsonObject clientData = HandshakeUtils.parseClientData(extraDataJwt, extraData, session); - return new HandshakeEntry(identityPublicKey, clientData, extraData, xboxAuth, protocol); } public static JsonObject parseClientData(JWSObject clientJwt, JsonObject extraData, BedrockSession session) throws Exception { diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java index 84e81a9..cc21fd5 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java @@ -19,12 +19,15 @@ import com.nimbusds.jwt.SignedJWT; import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import lombok.Builder; +import org.cloudburstmc.protocol.bedrock.data.auth.AuthType; +import org.cloudburstmc.protocol.bedrock.data.auth.CertificateChainPayload; import org.cloudburstmc.protocol.bedrock.packet.ClientCacheStatusPacket; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.RequestChunkRadiusPacket; import java.net.SocketAddress; import java.security.KeyPair; +import java.util.Collections; import java.util.UUID; /** @@ -70,8 +73,8 @@ public LoginPacket rebuildLoginPacket() { SignedJWT signedExtraData = HandshakeUtils.encodeJWT(this.keyPair, this.clientData); LoginPacket loginPacket = new LoginPacket(); - loginPacket.getChain().add(signedClientData.serialize()); - loginPacket.setExtra(signedExtraData.serialize()); + loginPacket.setAuthPayload(new CertificateChainPayload(Collections.singletonList(signedClientData.serialize()), AuthType.SELF_SIGNED)); + loginPacket.setClientJwt(signedExtraData.serialize()); loginPacket.setProtocolVersion(this.protocol.getProtocol()); return this.loginPacket = loginPacket; } From adf448b5ddb55113335934b5d094e8737e9b5bed Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Thu, 19 Jun 2025 13:02:21 +0300 Subject: [PATCH 27/45] Added support for TokenPayload --- .../network/protocol/user/HandshakeEntry.java | 5 + .../network/protocol/user/HandshakeUtils.java | 109 +++++++----------- .../network/protocol/user/LoginData.java | 3 + 3 files changed, 50 insertions(+), 67 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java index 4acf19f..62422f0 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java @@ -29,6 +29,10 @@ public class HandshakeEntry { private final ECPublicKey identityPublicKey; private final JsonObject clientData; + /** + * @deprecated Extra data will be replaced with displayName, identity and xuid fields instead. + */ + @Deprecated private final JsonObject extraData; private final boolean xboxAuthed; private ProtocolVersion protocol; @@ -94,6 +98,7 @@ public JsonObject getClientData() { return this.clientData; } + @Deprecated public JsonObject getExtraData() { return this.extraData; } diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java index 6bfbb0c..634b3e2 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java @@ -15,9 +15,7 @@ package dev.waterdog.waterdogpe.network.protocol.user; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import com.google.gson.*; import com.nimbusds.jose.*; import com.nimbusds.jose.crypto.ECDSASigner; import com.nimbusds.jose.crypto.ECDSAVerifier; @@ -28,17 +26,17 @@ import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import dev.waterdog.waterdogpe.utils.config.proxy.ProxyConfig; import org.cloudburstmc.protocol.bedrock.BedrockSession; -import org.cloudburstmc.protocol.bedrock.data.auth.AuthPayload; import org.cloudburstmc.protocol.bedrock.data.auth.CertificateChainPayload; import org.cloudburstmc.protocol.bedrock.data.auth.TokenPayload; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket; +import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; -import org.cloudburstmc.protocol.common.util.Preconditions; import javax.crypto.SecretKey; import java.net.InetSocketAddress; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.security.*; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; @@ -46,7 +44,6 @@ import java.security.spec.X509EncodedKeySpec; import java.text.ParseException; import java.util.Base64; -import java.util.Iterator; import java.util.List; import java.util.UUID; @@ -55,19 +52,15 @@ */ public class HandshakeUtils { - private static final ECPublicKey MOJANG_PUBLIC_KEY_OLD; - private static final ECPublicKey MOJANG_PUBLIC_KEY; - private static final KeyPair privateKeyPair; + private static final Gson GSON = new GsonBuilder().create(); + static { try { KeyPairGenerator generator = KeyPairGenerator.getInstance("EC"); generator.initialize(Curve.P_384.toECParameterSpec()); privateKeyPair = generator.generateKeyPair(); - - MOJANG_PUBLIC_KEY_OLD = generateKey("MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V"); - MOJANG_PUBLIC_KEY = generateKey("MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAECRXueJeTDqNRRgJi/vlRufByu/2G0i2Ebt6YMar5QX/R0DIIyrJMcUpruK4QveTfJSTp3Shlq4Gk34cD/4GUWwkv0DVuzeuB+tXija7HBxii03NHDbPAD0AKnLr2wdAp"); } catch (Exception e) { throw new RuntimeException("Unable to generate private keyPair!", e); } @@ -77,53 +70,6 @@ public static KeyPair getPrivateKeyPair() { return privateKeyPair; } - public static boolean validateChain(List chainArray, boolean strict) throws Exception { - if (strict && chainArray.size() > 3) { - // We dont expect larger chain - return false; - } - - ECPublicKey lastKey = null; - boolean authed = false; - Iterator iterator = chainArray.iterator(); - while(iterator.hasNext()){ - SignedJWT jwt = SignedJWT.parse(iterator.next()); - - URI x5u = jwt.getHeader().getX509CertURL(); - if (x5u == null) { - throw new JOSEException("Key not found"); - } - - ECPublicKey expectedKey = generateKey(jwt.getHeader().getX509CertURL().toString()); - if (lastKey == null) { - // First key is self signed - lastKey = expectedKey; - } else if (strict && !lastKey.equals(expectedKey)) { - // Make sure the previous key matches the header of the current - throw new IllegalArgumentException("Key does not match"); - } - - if (!verifyJwt(jwt, lastKey)) { - if (strict) { - throw new JOSEException("Login JWT was not valid"); - } - return false; - } - - if (MOJANG_PUBLIC_KEY.equals(lastKey) || MOJANG_PUBLIC_KEY_OLD.equals(lastKey)) { - authed = true; - } else if (authed) { - return !iterator.hasNext(); - } - - JsonObject payload = (JsonObject) JsonParser.parseString(jwt.getPayload().toString()); - Preconditions.checkArgument(payload.has("identityPublicKey"), "IdentityPublicKey node is missing in chain!"); - JsonElement ipkNode = payload.get("identityPublicKey"); - lastKey = generateKey(ipkNode.getAsString()); - } - return authed; - } - public static SignedJWT createExtraData(KeyPair pair, JsonObject extraData) { String publicKeyBase64 = Base64.getEncoder().encodeToString(pair.getPublic().getEncoded()); long timestamp = System.currentTimeMillis() / 1000; @@ -166,16 +112,47 @@ public static boolean verifyJwt(JWSObject jws, ECPublicKey key) throws JOSEExcep } public static HandshakeEntry processHandshake(BedrockSession session, LoginPacket packet, ProtocolVersion protocol, boolean strict) throws Exception { - AuthPayload authPayload = packet.getAuthPayload(); - if (authPayload instanceof CertificateChainPayload chainPayload) { + if (packet.getAuthPayload() instanceof TokenPayload) { + ChainValidationResult result = EncryptionUtils.validatePayload(packet.getAuthPayload()); + boolean xboxAuth = result.signed(); + JsonObject payload = GSON.toJsonTree(result.rawIdentityClaims()).getAsJsonObject(); + SignedJWT clientDataJwt = SignedJWT.parse(packet.getClientJwt()); + // Currently, we are still sending the legacy Certificate to downstream + // For this, we need to build the extraData manually + + // xname is the old displayName field + // xid is the old XUID field + // identity field is removed, we derive that information from xuid instead + + // titleId and sandboxId are missing now, not sure if there is a way to derive those. + + JsonObject extraData = new JsonObject(); + String playerName = payload.get("xname").getAsString(); + if (ProxyServer.getInstance().getConfiguration().isReplaceUsernameSpaces()) { + extraData.addProperty("displayName", playerName.replaceAll(" ", "_")); + } else { + extraData.addProperty("displayName", playerName); + } + String xuid = payload.get("xid").getAsString(); + extraData.addProperty("XUID", xuid); + extraData.addProperty("identity", UUID.nameUUIDFromBytes(xuid.getBytes(StandardCharsets.UTF_8)).toString()); + ECPublicKey identityPublicKey = EncryptionUtils.parseKey(result.identityClaims().identityPublicKey); + JsonObject clientData = HandshakeUtils.parseClientData(clientDataJwt, extraData, session); + SignedJWT clientJwt = SignedJWT.parse(packet.getClientJwt()); + if (!verifyJwt(clientJwt, identityPublicKey) && strict) { + xboxAuth = false; + } + return new HandshakeEntry(identityPublicKey, clientData, extraData, xboxAuth, protocol); + } else if (packet.getAuthPayload() instanceof CertificateChainPayload chainPayload) { List chain = chainPayload.getChain(); if (chain.isEmpty()) { throw new IllegalArgumentException("Invalid chain data"); } - boolean xboxAuth = HandshakeUtils.validateChain(chain, strict); - JsonObject payload = (JsonObject) JsonParser.parseString(SignedJWT.parse(chain.get(chain.size() - 1)).getPayload().toString()); - JsonObject extraData = HandshakeUtils.parseExtraData(packet, payload); + ChainValidationResult result = EncryptionUtils.validatePayload(packet.getAuthPayload()); + boolean xboxAuth = result.signed(); + JsonObject payload = GSON.toJsonTree(result.rawIdentityClaims()).getAsJsonObject(); + JsonObject extraData = HandshakeUtils.parseExtraData(payload); if (!payload.has("identityPublicKey")) { throw new RuntimeException("Identity Public Key was not found!"); @@ -190,8 +167,6 @@ public static HandshakeEntry processHandshake(BedrockSession session, LoginPacke JsonObject clientData = HandshakeUtils.parseClientData(clientJwt, extraData, session); return new HandshakeEntry(identityPublicKey, clientData, extraData, xboxAuth, protocol); - } else if (authPayload instanceof TokenPayload) { - throw new IllegalArgumentException("Token payload auth is not supported yet"); } else { throw new IllegalArgumentException("Invalid auth payload"); } @@ -208,7 +183,7 @@ public static JsonObject parseClientData(JWSObject clientJwt, JsonObject extraDa return clientData; } - public static JsonObject parseExtraData(LoginPacket packet, JsonObject payload) { + public static JsonObject parseExtraData(JsonObject payload) { JsonElement extraDataElement = payload.get("extraData"); if (!extraDataElement.isJsonObject()) { throw new IllegalStateException("Invalid 'extraData'"); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java index cc21fd5..de1e3b0 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java @@ -53,6 +53,7 @@ public class LoginData { private final KeyPair keyPair; private final JsonObject clientData; + @Deprecated private final JsonObject extraData; private LoginPacket loginPacket; @@ -73,6 +74,7 @@ public LoginPacket rebuildLoginPacket() { SignedJWT signedExtraData = HandshakeUtils.encodeJWT(this.keyPair, this.clientData); LoginPacket loginPacket = new LoginPacket(); + // Even if upstream sent TokenPayload, we use the CertificateChainPayload for compatability loginPacket.setAuthPayload(new CertificateChainPayload(Collections.singletonList(signedClientData.serialize()), AuthType.SELF_SIGNED)); loginPacket.setClientJwt(signedExtraData.serialize()); loginPacket.setProtocolVersion(this.protocol.getProtocol()); @@ -111,6 +113,7 @@ public JsonObject getClientData() { return this.clientData; } + @Deprecated public JsonObject getExtraData() { return this.extraData; } From f0101050e4421bb772768402096f52631d82b564 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Fri, 4 Jul 2025 02:09:07 +0300 Subject: [PATCH 28/45] Added 1.21.93 support --- .../waterdog/waterdogpe/network/protocol/ProtocolVersion.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 930422c..5f6b8ed 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -69,6 +69,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v786.Bedrock_v786; import org.cloudburstmc.protocol.bedrock.codec.v800.Bedrock_v800; import org.cloudburstmc.protocol.bedrock.codec.v818.Bedrock_v818; +import org.cloudburstmc.protocol.bedrock.codec.v819.Bedrock_v819; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -125,6 +126,7 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_70(786, Bedrock_v786.CODEC), MINECRAFT_PE_1_21_80(800, Bedrock_v800.CODEC), MINECRAFT_PE_1_21_90(818, Bedrock_v818.CODEC), + MINECRAFT_PE_1_21_93(819, Bedrock_v819.CODEC), ; private static final ProtocolVersion[] VALUES = values(); From 77bcb8308d637a54ce3b6f0a5a7a90c088a92988 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Tue, 5 Aug 2025 20:13:07 +0300 Subject: [PATCH 29/45] Added 1.21.100 support --- .../waterdog/waterdogpe/network/protocol/ProtocolVersion.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 5f6b8ed..8243c3b 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -70,6 +70,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v800.Bedrock_v800; import org.cloudburstmc.protocol.bedrock.codec.v818.Bedrock_v818; import org.cloudburstmc.protocol.bedrock.codec.v819.Bedrock_v819; +import org.cloudburstmc.protocol.bedrock.codec.v827.Bedrock_v827; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -127,6 +128,7 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_80(800, Bedrock_v800.CODEC), MINECRAFT_PE_1_21_90(818, Bedrock_v818.CODEC), MINECRAFT_PE_1_21_93(819, Bedrock_v819.CODEC), + MINECRAFT_PE_1_21_100(827, Bedrock_v827.CODEC), ; private static final ProtocolVersion[] VALUES = values(); From 23b6b1efa623be699734e372a61b6a612e28b7a9 Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Tue, 5 Aug 2025 21:02:00 +0200 Subject: [PATCH 30/45] Code fixes --- .../waterdogpe/network/protocol/user/HandshakeEntry.java | 8 -------- .../waterdogpe/network/protocol/user/HandshakeUtils.java | 5 +---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java index 0a08ba6..78f53cc 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java @@ -43,14 +43,6 @@ public class HandshakeEntry { @Setter private ProtocolVersion protocol; - public HandshakeEntry(ECPublicKey identityPublicKey, JsonObject clientData, JsonObject extraData, boolean xboxAuthed, ProtocolVersion protocol) { - this.identityPublicKey = identityPublicKey; - this.clientData = clientData; - this.extraData = extraData; - this.xboxAuthed = xboxAuthed; - this.protocol = protocol; - } - public LoginData buildData(BedrockServerSession session, ProxyServer proxy) throws Exception { // This is first event which exposes new player connecting to proxy. // The purpose is to change player's client data or set encryption keypair before joining first downstream. diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java index 6ecc24c..634b3e2 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java @@ -25,7 +25,6 @@ import dev.waterdog.waterdogpe.ProxyServer; import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import dev.waterdog.waterdogpe.utils.config.proxy.ProxyConfig; -import lombok.Getter; import org.cloudburstmc.protocol.bedrock.BedrockSession; import org.cloudburstmc.protocol.bedrock.data.auth.CertificateChainPayload; import org.cloudburstmc.protocol.bedrock.data.auth.TokenPayload; @@ -33,7 +32,6 @@ import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket; import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; -import org.cloudburstmc.protocol.common.util.Preconditions; import javax.crypto.SecretKey; import java.net.InetSocketAddress; @@ -46,7 +44,6 @@ import java.security.spec.X509EncodedKeySpec; import java.text.ParseException; import java.util.Base64; -import java.util.Iterator; import java.util.List; import java.util.UUID; @@ -186,7 +183,7 @@ public static JsonObject parseClientData(JWSObject clientJwt, JsonObject extraDa return clientData; } - public static JsonObject parseExtraData(LoginPacket packet, JsonObject payload) { + public static JsonObject parseExtraData(JsonObject payload) { JsonElement extraDataElement = payload.get("extraData"); if (!extraDataElement.isJsonObject()) { throw new IllegalStateException("Invalid 'extraData'"); From 3154ce350a5dceb39363dfeda9acd0d5f3ac1cae Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Mon, 18 Aug 2025 08:32:48 +0200 Subject: [PATCH 31/45] Removed spamming message when using AnyVersion Plugin on PNX --- .../protocol/handler/downstream/AbstractDownstreamHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java index a7ffc8b..b0b6716 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java @@ -185,8 +185,6 @@ protected void setItemDefinitions(Collection definitions) { for (ItemDefinition definition : definitions) { if (runtimeIds.add(definition.getRuntimeId())) { itemRegistry.add(definition); - } else { - player.getLogger().warning("[{}|{}] has duplicate item definition: {}", this.player.getName(), this.connection.getServerInfo().getServerName(), definition); } } codecHelper.setItemDefinitions(itemRegistry.build()); From 27bce8180061c0774ab52bc3ec1051677fc101ad Mon Sep 17 00:00:00 2001 From: Zwuiix <71025924+Zwuiix-cmd@users.noreply.github.com> Date: Mon, 15 Sep 2025 07:45:24 +0200 Subject: [PATCH 32/45] Add UpdateEquipPacket support to protocol handling --- .../waterdog/waterdogpe/network/protocol/ProtocolCodecs.java | 1 + .../waterdogpe/network/protocol/rewrite/EntityMap.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java index f8c8f01..0cc7768 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java @@ -113,6 +113,7 @@ public class ProtocolCodecs { HANDLED_PACKETS.add(ClientCheatAbilityPacket.class); HANDLED_PACKETS.add(ToastRequestPacket.class); HANDLED_PACKETS.add(MovementEffectPacket.class); + HANDLED_PACKETS.add(UpdateEquipPacket.class); } private static final List UPDATERS = new ObjectArrayList<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index a01f157..c437b80 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -357,6 +357,11 @@ public PacketSignal handle(MovementPredictionSyncPacket packet) { return rewriteId(packet.getRuntimeEntityId(), packet::setRuntimeEntityId); } + @Override + public PacketSignal handle(UpdateEquipPacket packet) { + return rewriteId(packet.getUniqueEntityId(), packet::setUniqueEntityId); + } + private PacketSignal rewriteMetadata(EntityDataMap metadata) { PacketSignal signal = PacketSignal.UNHANDLED; for (EntityDataType data : ENTITY_DATA_FIELDS) { From 15fab6e1791f939a42e953b0139b4bff63f7dd52 Mon Sep 17 00:00:00 2001 From: Alemiz Date: Mon, 15 Sep 2025 19:21:20 +0200 Subject: [PATCH 33/45] Pass through packet violation down to the server resolves #348 --- .../protocol/handler/upstream/AbstractUpstreamHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/AbstractUpstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/AbstractUpstreamHandler.java index 9b2bad8..39d203d 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/AbstractUpstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/AbstractUpstreamHandler.java @@ -53,7 +53,7 @@ public PacketSignal handle(ClientCacheStatusPacket packet) { @Override public final PacketSignal handle(PacketViolationWarningPacket packet) { this.player.getLogger().warning("Received violation from " + this.player.getName() + ": " + packet.toString()); - return this.cancel(); + return PacketSignal.HANDLED; } /** From 40a25fc1c6642c901838a7014bebf8d08dc9f8ae Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Sun, 28 Sep 2025 14:26:26 +0300 Subject: [PATCH 34/45] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dc0afa4..ad8db93 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # WaterdogPE -[![Build Status](https://jenkins.waterdog.dev/buildStatus/icon?job=Waterdog%2FWaterdogPE%2Fmaster)](https://jenkins.waterdog.dev/job/Waterdog/job/WaterdogPE/job/master/) +[![Build Status](https://github.com/WaterdogPE/WaterdogPE/actions/workflows/maven-build.yml/badge.svg)](https://github.com/WaterdogPE/WaterdogPE/actions?query=branch%3Amaster+is%3Acompleted+event%3Apush) [![Discord Chat](https://img.shields.io/discord/767330242078834712.svg)](https://discord.gg/QcRRzXX) WaterdogPE is a brand new Minecraft: Bedrock Edition proxy software developed by the developers of the old Waterdog From 0e432ee83273e63eb262fd35f022ee19623e13c6 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 1 Oct 2025 17:04:22 +0300 Subject: [PATCH 35/45] Added 1.21.111 support (#349) --- pom.xml | 2 +- .../defaults/PlayerDisconnectedEvent.java | 12 +- .../event/defaults/PreClientDataSetEvent.java | 40 +++-- .../connection/peer/BedrockServerSession.java | 8 +- .../network/protocol/ProtocolVersion.java | 2 + .../ConnectedDownstreamHandler.java | 1 - .../handler/downstream/InitialHandler.java | 7 +- .../downstream/SwitchDownstreamHandler.java | 3 +- .../upstream/LoginUpstreamHandler.java | 5 +- .../network/protocol/user/HandshakeEntry.java | 58 +++---- .../network/protocol/user/HandshakeUtils.java | 143 +++++++----------- .../network/protocol/user/LoginData.java | 100 +++--------- .../waterdogpe/player/ProxiedPlayer.java | 10 +- 13 files changed, 143 insertions(+), 248 deletions(-) diff --git a/pom.xml b/pom.xml index e8d1c5e..e850732 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ UTF-8 17 1.0.0.CR3-SNAPSHOT - 3.0.0.Beta7-SNAPSHOT + 3.0.0.Beta8-SNAPSHOT 2.17.1 3.23.0 4.1.101.Final diff --git a/src/main/java/dev/waterdog/waterdogpe/event/defaults/PlayerDisconnectedEvent.java b/src/main/java/dev/waterdog/waterdogpe/event/defaults/PlayerDisconnectedEvent.java index 82cb9ff..0d8c2ef 100644 --- a/src/main/java/dev/waterdog/waterdogpe/event/defaults/PlayerDisconnectedEvent.java +++ b/src/main/java/dev/waterdog/waterdogpe/event/defaults/PlayerDisconnectedEvent.java @@ -24,14 +24,20 @@ @AsyncEvent public class PlayerDisconnectedEvent extends PlayerEvent { - private final String reason; + private final CharSequence reason; - public PlayerDisconnectedEvent(ProxiedPlayer player, String reason) { + public PlayerDisconnectedEvent(ProxiedPlayer player, CharSequence reason) { super(player); this.reason = reason; } + public String getReason() { - return this.reason; + return this.getReason(String.class); + } + + public T getReason(Class type) { + return type.cast(this.reason); } + } diff --git a/src/main/java/dev/waterdog/waterdogpe/event/defaults/PreClientDataSetEvent.java b/src/main/java/dev/waterdog/waterdogpe/event/defaults/PreClientDataSetEvent.java index c82761e..5f73d6d 100644 --- a/src/main/java/dev/waterdog/waterdogpe/event/defaults/PreClientDataSetEvent.java +++ b/src/main/java/dev/waterdog/waterdogpe/event/defaults/PreClientDataSetEvent.java @@ -18,8 +18,11 @@ import com.google.gson.JsonObject; import dev.waterdog.waterdogpe.event.Event; import dev.waterdog.waterdogpe.network.connection.ProxiedConnection; +import lombok.Getter; +import lombok.Setter; import java.security.KeyPair; +import java.util.UUID; /** * Called right when we decoded the player's LoginPacket data in the handshake(HandshakeUpstreamHandler). @@ -27,35 +30,26 @@ */ public class PreClientDataSetEvent extends Event { + @Getter private final ProxiedConnection connection; + @Getter private final JsonObject clientData; - private final JsonObject extraData; + @Getter + private final String xuid; + @Getter + private final UUID uuid; + @Getter + private final String displayName; + @Setter + @Getter private KeyPair keyPair; - public PreClientDataSetEvent(JsonObject clientData, JsonObject extraData, KeyPair keyPair, ProxiedConnection playerSession) { + public PreClientDataSetEvent(JsonObject clientData, String xuid, UUID uuid, String displayName, KeyPair keyPair, ProxiedConnection playerSession) { this.clientData = clientData; - this.extraData = extraData; + this.xuid = xuid; + this.uuid = uuid; + this.displayName = displayName; this.connection = playerSession; this.keyPair = keyPair; } - - public ProxiedConnection getConnection() { - return this.connection; - } - - public JsonObject getClientData() { - return this.clientData; - } - - public JsonObject getExtraData() { - return this.extraData; - } - - public KeyPair getKeyPair() { - return this.keyPair; - } - - public void setKeyPair(KeyPair keyPair) { - this.keyPair = keyPair; - } } diff --git a/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/BedrockServerSession.java b/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/BedrockServerSession.java index 324fba2..0c362b6 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/BedrockServerSession.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/connection/peer/BedrockServerSession.java @@ -77,7 +77,7 @@ public void sendPacketImmediately(BedrockPacket packet) { } @Override - public void disconnect(String reason, boolean hideReason) { + public void disconnect(CharSequence reason, boolean hideReason) { this.checkForClosed(); DisconnectPacket packet = new DisconnectPacket(); @@ -128,8 +128,10 @@ public BedrockPacketHandler getPacketHandler() { return this.packetHandler; } - public void addDisconnectListener(Consumer listener) { - this.getPeer().getChannel().closeFuture().addListener(future -> listener.accept(this.getDisconnectReason())); + public void addDisconnectListener(Consumer listener) { + this.getPeer().getChannel().closeFuture().addListener(future -> { + listener.accept(this.getDisconnectReason()); + }); } public int getSubClientId() { diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 8243c3b..3db97c0 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -71,6 +71,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v818.Bedrock_v818; import org.cloudburstmc.protocol.bedrock.codec.v819.Bedrock_v819; import org.cloudburstmc.protocol.bedrock.codec.v827.Bedrock_v827; +import org.cloudburstmc.protocol.bedrock.codec.v844.Bedrock_v844; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -129,6 +130,7 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_90(818, Bedrock_v818.CODEC), MINECRAFT_PE_1_21_93(819, Bedrock_v819.CODEC), MINECRAFT_PE_1_21_100(827, Bedrock_v827.CODEC), + MINECRAFT_PE_1_21_111(844, Bedrock_v844.CODEC), ; private static final ProtocolVersion[] VALUES = values(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java index 7a174a6..c28004b 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/ConnectedDownstreamHandler.java @@ -17,7 +17,6 @@ import dev.waterdog.waterdogpe.network.connection.client.ClientConnection; import dev.waterdog.waterdogpe.network.connection.handler.ReconnectReason; -import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import dev.waterdog.waterdogpe.network.protocol.handler.PluginPacketHandler; import org.cloudburstmc.protocol.bedrock.PacketDirection; import org.cloudburstmc.protocol.bedrock.packet.*; diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java index d65e60a..7524f53 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/InitialHandler.java @@ -19,11 +19,7 @@ import dev.waterdog.waterdogpe.network.connection.client.ClientConnection; import dev.waterdog.waterdogpe.network.connection.handler.ReconnectReason; import dev.waterdog.waterdogpe.network.protocol.registry.FakeDefinitionRegistry; -import dev.waterdog.waterdogpe.network.protocol.user.HandshakeUtils; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper; -import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.packet.*; import dev.waterdog.waterdogpe.event.defaults.InitialServerConnectedEvent; import dev.waterdog.waterdogpe.network.serverinfo.ServerInfo; @@ -37,7 +33,6 @@ import dev.waterdog.waterdogpe.utils.types.TranslationContainer; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; import org.cloudburstmc.protocol.common.PacketSignal; -import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry; import javax.crypto.SecretKey; import java.net.URI; @@ -66,7 +61,7 @@ public final PacketSignal handle(ServerToClientHandshakePacket packet) { try { SignedJWT saltJwt = SignedJWT.parse(packet.getJwt()); URI x5u = saltJwt.getHeader().getX509CertURL(); - ECPublicKey serverKey = HandshakeUtils.generateKey(x5u.toASCIIString()); + ECPublicKey serverKey = EncryptionUtils.parseKey(x5u.toASCIIString()); SecretKey key = EncryptionUtils.getSecretKey( this.player.getLoginData().getKeyPair().getPrivate(), serverKey, diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/SwitchDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/SwitchDownstreamHandler.java index aff0e4c..1bd3729 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/SwitchDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/SwitchDownstreamHandler.java @@ -18,7 +18,6 @@ import com.nimbusds.jwt.SignedJWT; import dev.waterdog.waterdogpe.network.connection.client.ClientConnection; import dev.waterdog.waterdogpe.network.protocol.handler.TransferCallback; -import dev.waterdog.waterdogpe.network.protocol.user.HandshakeUtils; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import lombok.extern.log4j.Log4j2; import org.cloudburstmc.math.vector.Vector3f; @@ -58,7 +57,7 @@ public final PacketSignal handle(ServerToClientHandshakePacket packet) { try { SignedJWT saltJwt = SignedJWT.parse(packet.getJwt()); URI x5u = saltJwt.getHeader().getX509CertURL(); - ECPublicKey serverKey = HandshakeUtils.generateKey(x5u.toASCIIString()); + ECPublicKey serverKey = EncryptionUtils.parseKey(x5u.toASCIIString()); SecretKey key = EncryptionUtils.getSecretKey( this.player.getLoginData().getKeyPair().getPrivate(), serverKey, diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/LoginUpstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/LoginUpstreamHandler.java index e2aa4dd..6bad9ab 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/LoginUpstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/upstream/LoginUpstreamHandler.java @@ -146,6 +146,9 @@ public PacketSignal handle(LoginPacket packet) { this.session.setLogging(WaterdogPE.version().debug()); try { + this.proxy.getLogger().debug("[{}] <-> Received login with authType: {} and payloadType: {}.", this.session.getSocketAddress(), + packet.getAuthPayload().getClass().getSimpleName(), packet.getAuthPayload().getAuthType()); + handshakeEntry = HandshakeUtils.processHandshake(this.session, packet, protocol, strictAuth); if (!handshakeEntry.isXboxAuthed() && strictAuth) { this.onLoginFailed(handshakeEntry, null, "disconnectionScreen.notAuthenticated"); @@ -155,7 +158,7 @@ public PacketSignal handle(LoginPacket packet) { // Thank you Mojang: this version includes protocol changes, but protocol version was not increased. if (protocol.equals(ProtocolVersion.MINECRAFT_PE_1_19_60) && handshakeEntry.getClientData().has("GameVersion") && - ProtocolVersion.MINECRAFT_PE_1_19_62.getMinecraftVersion().equals(handshakeEntry.getClientData().get("GameVersion").getAsString())) {; + ProtocolVersion.MINECRAFT_PE_1_19_62.getMinecraftVersion().equals(handshakeEntry.getClientData().get("GameVersion").getAsString())) { handshakeEntry.setProtocol(protocol = ProtocolVersion.MINECRAFT_PE_1_19_62); this.session.getPeer().setProtocol(protocol); } diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java index 62422f0..650b47b 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java @@ -20,48 +20,54 @@ import dev.waterdog.waterdogpe.event.defaults.PreClientDataSetEvent; import dev.waterdog.waterdogpe.network.connection.peer.BedrockServerSession; import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; +import lombok.Getter; +import lombok.Setter; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; import java.security.interfaces.ECPublicKey; import java.util.UUID; +@Getter public class HandshakeEntry { private final ECPublicKey identityPublicKey; private final JsonObject clientData; - /** - * @deprecated Extra data will be replaced with displayName, identity and xuid fields instead. - */ - @Deprecated - private final JsonObject extraData; + private final String xuid; + private final UUID uuid; + private final String displayName; private final boolean xboxAuthed; + @Setter private ProtocolVersion protocol; + private final boolean isChainPayload; - public HandshakeEntry(ECPublicKey identityPublicKey, JsonObject clientData, JsonObject extraData, boolean xboxAuthed, ProtocolVersion protocol) { + public HandshakeEntry(ECPublicKey identityPublicKey, JsonObject clientData, String xuid, UUID uuid, String displayName, boolean xboxAuthed, ProtocolVersion protocol, boolean isChainPayload) { this.identityPublicKey = identityPublicKey; this.clientData = clientData; - this.extraData = extraData; + this.xuid = xuid; + this.uuid = uuid; + this.displayName = displayName; this.xboxAuthed = xboxAuthed; this.protocol = protocol; + this.isChainPayload = isChainPayload; } public LoginData buildData(BedrockServerSession session, ProxyServer proxy) throws Exception { // This is first event which exposes new player connecting to proxy. // The purpose is to change player's client data or set encryption keypair before joining first downstream. - PreClientDataSetEvent event = new PreClientDataSetEvent(this.clientData, this.extraData, EncryptionUtils.createKeyPair(), session); + PreClientDataSetEvent event = new PreClientDataSetEvent(this.clientData, this.xuid, this.uuid, this.displayName, EncryptionUtils.createKeyPair(), session); proxy.getEventManager().callEvent(event); LoginData.LoginDataBuilder builder = LoginData.builder(); - builder.displayName(this.extraData.get("displayName").getAsString()); - builder.uuid(UUID.fromString(this.extraData.get("identity").getAsString())); - builder.xuid(this.extraData.get("XUID").getAsString()); + builder.displayName(this.displayName); + builder.uuid(this.uuid); + builder.xuid(this.xuid); builder.xboxAuthed(this.xboxAuthed); builder.protocol(this.protocol); builder.joinHostname(this.clientData.get("ServerAddress").getAsString().split(":")[0]); builder.address(session.getSocketAddress()); builder.keyPair(event.getKeyPair()); builder.clientData(this.clientData); - builder.extraData(this.extraData); + builder.isChainPayload(this.isChainPayload); if (this.clientData.has("DeviceModel")) { builder.deviceModel(this.clientData.get("DeviceModel").getAsString()); } @@ -74,32 +80,4 @@ public LoginData buildData(BedrockServerSession session, ProxyServer proxy) thro return builder.build(); } - public ECPublicKey getIdentityPublicKey() { - return this.identityPublicKey; - } - - public boolean isXboxAuthed() { - return this.xboxAuthed; - } - - public String getDisplayName() { - return this.extraData.get("displayName").getAsString(); - } - - public void setProtocol(ProtocolVersion protocol) { - this.protocol = protocol; - } - - public ProtocolVersion getProtocol() { - return this.protocol; - } - - public JsonObject getClientData() { - return this.clientData; - } - - @Deprecated - public JsonObject getExtraData() { - return this.extraData; - } } diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java index 634b3e2..9826b44 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeUtils.java @@ -25,9 +25,10 @@ import dev.waterdog.waterdogpe.ProxyServer; import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import dev.waterdog.waterdogpe.utils.config.proxy.ProxyConfig; +import lombok.Getter; +import lombok.extern.log4j.Log4j2; import org.cloudburstmc.protocol.bedrock.BedrockSession; import org.cloudburstmc.protocol.bedrock.data.auth.CertificateChainPayload; -import org.cloudburstmc.protocol.bedrock.data.auth.TokenPayload; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket; import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult; @@ -36,26 +37,22 @@ import javax.crypto.SecretKey; import java.net.InetSocketAddress; import java.net.URI; -import java.nio.charset.StandardCharsets; import java.security.*; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; import java.text.ParseException; import java.util.Base64; -import java.util.List; import java.util.UUID; /** * Various utilities for parsing Handshake data */ +@Log4j2 public class HandshakeUtils { + @Getter private static final KeyPair privateKeyPair; - private static final Gson GSON = new GsonBuilder().create(); - static { try { KeyPairGenerator generator = KeyPairGenerator.getInstance("EC"); @@ -66,11 +63,7 @@ public class HandshakeUtils { } } - public static KeyPair getPrivateKeyPair() { - return privateKeyPair; - } - - public static SignedJWT createExtraData(KeyPair pair, JsonObject extraData) { + public static SignedJWT createClientDataChain(KeyPair pair, JsonObject extraData) { String publicKeyBase64 = Base64.getEncoder().encodeToString(pair.getPublic().getEncoded()); long timestamp = System.currentTimeMillis() / 1000; @@ -86,6 +79,20 @@ public static SignedJWT createExtraData(KeyPair pair, JsonObject extraData) { return encodeJWT(pair, dataChain); } + public static SignedJWT createClientDataToken(KeyPair pair, String displayName, String xuid) { + String publicKeyBase64 = Base64.getEncoder().encodeToString(pair.getPublic().getEncoded()); + long timestamp = System.currentTimeMillis() / 1000; + + JsonObject dataChain = new JsonObject(); + dataChain.addProperty("iat", timestamp); + dataChain.addProperty("exp", timestamp + 24 * 3600); + dataChain.addProperty("iss", "self"); + dataChain.addProperty("cpk", publicKeyBase64); + dataChain.addProperty("xid", xuid); + dataChain.addProperty("xname", displayName); + return encodeJWT(pair, dataChain); + } + public static SignedJWT encodeJWT(KeyPair pair, JsonObject payload) { String publicKeyBase64 = Base64.getEncoder().encodeToString(pair.getPublic().getEncoded()); URI x5u = URI.create(publicKeyBase64); @@ -99,10 +106,6 @@ public static SignedJWT encodeJWT(KeyPair pair, JsonObject payload) { } } - public static ECPublicKey generateKey(String b64) throws NoSuchAlgorithmException, InvalidKeySpecException { - return (ECPublicKey) KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(b64))); - } - public static void signJwt(JWSObject jws, ECPrivateKey key) throws JOSEException { jws.sign(new ECDSASigner(key, Curve.P_384)); } @@ -112,91 +115,49 @@ public static boolean verifyJwt(JWSObject jws, ECPublicKey key) throws JOSEExcep } public static HandshakeEntry processHandshake(BedrockSession session, LoginPacket packet, ProtocolVersion protocol, boolean strict) throws Exception { - if (packet.getAuthPayload() instanceof TokenPayload) { - ChainValidationResult result = EncryptionUtils.validatePayload(packet.getAuthPayload()); - boolean xboxAuth = result.signed(); - JsonObject payload = GSON.toJsonTree(result.rawIdentityClaims()).getAsJsonObject(); - SignedJWT clientDataJwt = SignedJWT.parse(packet.getClientJwt()); - // Currently, we are still sending the legacy Certificate to downstream - // For this, we need to build the extraData manually - - // xname is the old displayName field - // xid is the old XUID field - // identity field is removed, we derive that information from xuid instead - - // titleId and sandboxId are missing now, not sure if there is a way to derive those. - - JsonObject extraData = new JsonObject(); - String playerName = payload.get("xname").getAsString(); - if (ProxyServer.getInstance().getConfiguration().isReplaceUsernameSpaces()) { - extraData.addProperty("displayName", playerName.replaceAll(" ", "_")); - } else { - extraData.addProperty("displayName", playerName); - } - String xuid = payload.get("xid").getAsString(); - extraData.addProperty("XUID", xuid); - extraData.addProperty("identity", UUID.nameUUIDFromBytes(xuid.getBytes(StandardCharsets.UTF_8)).toString()); - ECPublicKey identityPublicKey = EncryptionUtils.parseKey(result.identityClaims().identityPublicKey); - JsonObject clientData = HandshakeUtils.parseClientData(clientDataJwt, extraData, session); - SignedJWT clientJwt = SignedJWT.parse(packet.getClientJwt()); - if (!verifyJwt(clientJwt, identityPublicKey) && strict) { - xboxAuth = false; - } - return new HandshakeEntry(identityPublicKey, clientData, extraData, xboxAuth, protocol); - } else if (packet.getAuthPayload() instanceof CertificateChainPayload chainPayload) { - List chain = chainPayload.getChain(); - if (chain.isEmpty()) { - throw new IllegalArgumentException("Invalid chain data"); - } - - ChainValidationResult result = EncryptionUtils.validatePayload(packet.getAuthPayload()); - boolean xboxAuth = result.signed(); - JsonObject payload = GSON.toJsonTree(result.rawIdentityClaims()).getAsJsonObject(); - JsonObject extraData = HandshakeUtils.parseExtraData(payload); - - if (!payload.has("identityPublicKey")) { - throw new RuntimeException("Identity Public Key was not found!"); - } - String identityPublicKeyString = payload.get("identityPublicKey").getAsString(); + ChainValidationResult result = EncryptionUtils.validatePayload(packet.getAuthPayload()); + boolean xboxAuth = result.signed(); + ChainValidationResult.IdentityClaims identityClaims = result.identityClaims(); + ChainValidationResult.IdentityData identityData = identityClaims.extraData; + ECPublicKey identityPublicKey = (ECPublicKey) identityClaims.parsedIdentityPublicKey(); + String xuid = identityData.xuid; + //UUID uuid = UUID.nameUUIDFromBytes(("pocket-auth-1-xuid:" + xuid).getBytes(StandardCharsets.UTF_8)); + UUID uuid = identityData.identity; + + SignedJWT clientDataJwt = SignedJWT.parse(packet.getClientJwt()); + JsonObject clientData = HandshakeUtils.parseClientData(clientDataJwt, xuid, session); + if (!verifyJwt(clientDataJwt, identityPublicKey) && strict) { + xboxAuth = false; + } + String displayName; + if (ProxyServer.getInstance().getConfiguration().isReplaceUsernameSpaces()) { + displayName = identityData.displayName + .replaceAll(" ", "_"); + } else { + displayName = identityData.displayName; + } - ECPublicKey identityPublicKey = generateKey(identityPublicKeyString); - SignedJWT clientJwt = SignedJWT.parse(packet.getClientJwt()); - if (!verifyJwt(clientJwt, identityPublicKey) && strict) { - xboxAuth = false; + if (xboxAuth) { + ProxyConfig config = ProxyServer.getInstance().getConfiguration(); + if (config.useLoginExtras()) { + clientData.addProperty("Waterdog_Auth", true); } - JsonObject clientData = HandshakeUtils.parseClientData(clientJwt, extraData, session); - - return new HandshakeEntry(identityPublicKey, clientData, extraData, xboxAuth, protocol); - } else { - throw new IllegalArgumentException("Invalid auth payload"); } + return new HandshakeEntry(identityPublicKey, clientData, xuid, uuid, displayName, xboxAuth, protocol, + packet.getAuthPayload() instanceof CertificateChainPayload); } - public static JsonObject parseClientData(JWSObject clientJwt, JsonObject extraData, BedrockSession session) throws Exception { + public static JsonObject parseClientData(JWSObject clientJwt, String xuid, BedrockSession session) throws Exception { JsonObject clientData = (JsonObject) JsonParser.parseString(clientJwt.getPayload().toString()); ProxyConfig config = ProxyServer.getInstance().getConfiguration(); if (config.useLoginExtras()) { // Add waterdog attributes - clientData.addProperty("Waterdog_XUID", extraData.get("XUID").getAsString()); + clientData.addProperty("Waterdog_XUID", xuid); clientData.addProperty("Waterdog_IP", ((InetSocketAddress) session.getSocketAddress()).getAddress().getHostAddress()); } return clientData; } - public static JsonObject parseExtraData(JsonObject payload) { - JsonElement extraDataElement = payload.get("extraData"); - if (!extraDataElement.isJsonObject()) { - throw new IllegalStateException("Invalid 'extraData'"); - } - - JsonObject extraData = extraDataElement.getAsJsonObject(); - if (ProxyServer.getInstance().getConfiguration().isReplaceUsernameSpaces()) { - String playerName = extraData.get("displayName").getAsString(); - extraData.addProperty("displayName", playerName.replaceAll(" ", "_")); - } - return extraData; - } - public static void processEncryption(BedrockSession session, PublicKey key) throws Exception { byte[] token = EncryptionUtils.generateRandomToken(); SecretKey encryptionKey = EncryptionUtils.getSecretKey(privateKeyPair.getPrivate(), key, token); @@ -209,4 +170,12 @@ public static void processEncryption(BedrockSession session, PublicKey key) thro session.enableEncryption(encryptionKey); }); } + + public static JsonObject createChainExtraData(String displayName, String xuid, UUID uuid) { + JsonObject extraData = new JsonObject(); + extraData.addProperty("displayName", displayName); + extraData.addProperty("XUID", xuid); + extraData.addProperty("identity", uuid.toString()); + return extraData; + } } diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java index de1e3b0..da6d1de 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java @@ -19,8 +19,12 @@ import com.nimbusds.jwt.SignedJWT; import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; import org.cloudburstmc.protocol.bedrock.data.auth.AuthType; import org.cloudburstmc.protocol.bedrock.data.auth.CertificateChainPayload; +import org.cloudburstmc.protocol.bedrock.data.auth.TokenPayload; import org.cloudburstmc.protocol.bedrock.packet.ClientCacheStatusPacket; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.RequestChunkRadiusPacket; @@ -33,7 +37,9 @@ /** * Holds relevant information passed to the proxy on the first connection (initial) in the LoginPacket. */ +@Slf4j @Builder +@Getter public class LoginData { private final String displayName; @@ -53,16 +59,17 @@ public class LoginData { private final KeyPair keyPair; private final JsonObject clientData; - @Deprecated - private final JsonObject extraData; - private LoginPacket loginPacket; + @Setter @Builder.Default private RequestChunkRadiusPacket chunkRadius = PlayerRewriteUtils.defaultChunkRadius; + @Setter @Builder.Default private ClientCacheStatusPacket cachePacket = PlayerRewriteUtils.defaultCachePacket; + private final boolean isChainPayload; + /** * Used to construct new login packet using this.clientData and this.extraData signed by this.keyPair. * This method should be called everytime client data is changed. Otherwise player will join to downstream using old data. @@ -70,68 +77,20 @@ public class LoginData { * @return new LoginPacket. */ public LoginPacket rebuildLoginPacket() { - SignedJWT signedClientData = HandshakeUtils.createExtraData(this.keyPair, this.extraData); - SignedJWT signedExtraData = HandshakeUtils.encodeJWT(this.keyPair, this.clientData); - LoginPacket loginPacket = new LoginPacket(); - // Even if upstream sent TokenPayload, we use the CertificateChainPayload for compatability - loginPacket.setAuthPayload(new CertificateChainPayload(Collections.singletonList(signedClientData.serialize()), AuthType.SELF_SIGNED)); - loginPacket.setClientJwt(signedExtraData.serialize()); + SignedJWT signedClientData = HandshakeUtils.encodeJWT(this.keyPair, this.clientData); + loginPacket.setClientJwt(signedClientData.serialize()); loginPacket.setProtocolVersion(this.protocol.getProtocol()); - return this.loginPacket = loginPacket; - } - - public String getDisplayName() { - return this.displayName; - } - - public String getXuid() { - return this.xuid; - } - - public boolean isXboxAuthed() { - return this.xboxAuthed; - } - - public UUID getUuid() { - return this.uuid; - } - - public SocketAddress getAddress() { - return this.address; - } - - public ProtocolVersion getProtocol() { - return this.protocol; - } - - public KeyPair getKeyPair() { - return this.keyPair; - } - - public JsonObject getClientData() { - return this.clientData; - } - - @Deprecated - public JsonObject getExtraData() { - return this.extraData; - } - - public String getJoinHostname() { - return this.joinHostname; - } - - public Platform getDevicePlatform() { - return devicePlatform; - } - - public String getDeviceId() { - return deviceId; - } - - public String getDeviceModel() { - return deviceModel; + if (isChainPayload) { + JsonObject extraData = HandshakeUtils.createChainExtraData(displayName, xuid, uuid); + SignedJWT signedPayload = HandshakeUtils.createClientDataChain(this.keyPair, extraData); + loginPacket.setAuthPayload(new CertificateChainPayload(Collections.singletonList(signedPayload.serialize()), AuthType.SELF_SIGNED)); + } else { + SignedJWT signedPayload = HandshakeUtils.createClientDataToken(this.keyPair, displayName, xuid); + loginPacket.setAuthPayload(new TokenPayload(signedPayload.serialize(), AuthType.SELF_SIGNED)); + } + this.loginPacket = loginPacket; + return loginPacket; } public LoginPacket getLoginPacket() { @@ -141,19 +100,4 @@ public LoginPacket getLoginPacket() { return this.loginPacket; } - public RequestChunkRadiusPacket getChunkRadius() { - return this.chunkRadius; - } - - public void setChunkRadius(RequestChunkRadiusPacket chunkRadius) { - this.chunkRadius = chunkRadius; - } - - public ClientCacheStatusPacket getCachePacket() { - return this.cachePacket; - } - - public void setCachePacket(ClientCacheStatusPacket cachePacket) { - this.cachePacket = cachePacket; - } } diff --git a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java index 8c2a9a7..bc5ddfb 100644 --- a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java +++ b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java @@ -63,7 +63,7 @@ public class ProxiedPlayer implements CommandSender { private final AtomicBoolean disconnected = new AtomicBoolean(false); private final AtomicBoolean loginCalled = new AtomicBoolean(false); private final AtomicBoolean loginCompleted = new AtomicBoolean(false); - private volatile String disconnectReason; + private volatile CharSequence disconnectReason; private final RewriteData rewriteData = new RewriteData(); private final LoginData loginData; @@ -334,7 +334,7 @@ public void disconnect(TextContainer message) { * * @param reason The disconnect reason the player will see on his disconnect screen (Supports Color Codes) */ - public void disconnect(String reason) { + public void disconnect(CharSequence reason) { if (this.loginCalled.get() && !this.loginCompleted.get()) { // Wait until PlayerLoginEvent completes this.disconnectReason = reason; @@ -920,7 +920,11 @@ public Collection getPluginPacketHandlers() { } public String getDisconnectReason() { - return this.disconnectReason; + return this.getDisconnectReason(String.class); + } + + public T getDisconnectReason(Class type) { + return type.cast(this.disconnectReason); } @Override From 506c15abfd2cb6cfcc4611a050dc607fe9738678 Mon Sep 17 00:00:00 2001 From: Buddelbubi <44944269+Buddelbubi@users.noreply.github.com> Date: Mon, 6 Oct 2025 14:18:59 +0200 Subject: [PATCH 36/45] Update HandshakeEntry.java --- .../waterdogpe/network/protocol/user/HandshakeEntry.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java index a58dbf9..650b47b 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/HandshakeEntry.java @@ -20,7 +20,6 @@ import dev.waterdog.waterdogpe.event.defaults.PreClientDataSetEvent; import dev.waterdog.waterdogpe.network.connection.peer.BedrockServerSession; import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils; @@ -29,7 +28,6 @@ import java.util.UUID; @Getter -@AllArgsConstructor public class HandshakeEntry { private final ECPublicKey identityPublicKey; From 45734ae10692ed1f0c205d20fbf4b991f69f48cb Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Tue, 28 Oct 2025 22:26:37 +0300 Subject: [PATCH 37/45] Added v1.21.120 support --- pom.xml | 2 +- .../waterdogpe/network/protocol/ProtocolVersion.java | 3 +++ .../network/protocol/rewrite/EntityMap.java | 12 ++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e850732..ee0094b 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ UTF-8 17 1.0.0.CR3-SNAPSHOT - 3.0.0.Beta8-SNAPSHOT + 3.0.0.Beta10-SNAPSHOT 2.17.1 3.23.0 4.1.101.Final diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java index 3db97c0..943c0ff 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolVersion.java @@ -72,6 +72,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v819.Bedrock_v819; import org.cloudburstmc.protocol.bedrock.codec.v827.Bedrock_v827; import org.cloudburstmc.protocol.bedrock.codec.v844.Bedrock_v844; +import org.cloudburstmc.protocol.bedrock.codec.v859.Bedrock_v859; @ToString(exclude = {"defaultCodec", "bedrockCodec"}) public enum ProtocolVersion { @@ -130,7 +131,9 @@ public enum ProtocolVersion { MINECRAFT_PE_1_21_90(818, Bedrock_v818.CODEC), MINECRAFT_PE_1_21_93(819, Bedrock_v819.CODEC), MINECRAFT_PE_1_21_100(827, Bedrock_v827.CODEC), + MINECRAFT_PE_1_21_110(843, 844, Bedrock_v844.CODEC), MINECRAFT_PE_1_21_111(844, Bedrock_v844.CODEC), + MINECRAFT_PE_1_21_120(859, Bedrock_v859.CODEC), ; private static final ProtocolVersion[] VALUES = values(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index c437b80..4cf958b 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -16,6 +16,7 @@ package dev.waterdog.waterdogpe.network.protocol.rewrite; import it.unimi.dsi.fastutil.longs.LongListIterator; +import org.cloudburstmc.protocol.bedrock.data.camera.CameraAttachToEntityInstruction; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataMap; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -362,6 +363,17 @@ public PacketSignal handle(UpdateEquipPacket packet) { return rewriteId(packet.getUniqueEntityId(), packet::setUniqueEntityId); } + @Override + public PacketSignal handle(CameraInstructionPacket packet) { + PacketSignal signal = PacketSignal.UNHANDLED; + CameraAttachToEntityInstruction attachInstruction = packet.getAttachInstruction(); + if (attachInstruction != null) { + PacketSignal returnedSignal = rewriteId(attachInstruction.getUniqueEntityId(), attachInstruction::setUniqueEntityId); + signal = mergeSignals(signal, returnedSignal); + } + return signal; + } + private PacketSignal rewriteMetadata(EntityDataMap metadata) { PacketSignal signal = PacketSignal.UNHANDLED; for (EntityDataType data : ENTITY_DATA_FIELDS) { From 3ad5402650846bba2513408e47e7c8f7db838b7f Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Tue, 28 Oct 2025 22:34:01 +0300 Subject: [PATCH 38/45] Add missing packets to HANDLED_PACKETS --- .../waterdog/waterdogpe/network/protocol/ProtocolCodecs.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java index 0cc7768..129c773 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java @@ -114,6 +114,10 @@ public class ProtocolCodecs { HANDLED_PACKETS.add(ToastRequestPacket.class); HANDLED_PACKETS.add(MovementEffectPacket.class); HANDLED_PACKETS.add(UpdateEquipPacket.class); + HANDLED_PACKETS.add(CameraInstructionPacket.class); + HANDLED_PACKETS.add(MovementPredictionSyncPacket.class); + HANDLED_PACKETS.add(PlayerUpdateEntityOverridesPacket.class); + HANDLED_PACKETS.add(PlayerLocationPacket.class); } private static final List UPDATERS = new ObjectArrayList<>(); From bd355d7ceb308950685fc2d4753e3e9dfda98809 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Tue, 28 Oct 2025 22:56:18 +0300 Subject: [PATCH 39/45] Entity ids might be negative --- .../waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java index 4cf958b..65a262b 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/rewrite/EntityMap.java @@ -378,7 +378,7 @@ private PacketSignal rewriteMetadata(EntityDataMap metadata) { PacketSignal signal = PacketSignal.UNHANDLED; for (EntityDataType data : ENTITY_DATA_FIELDS) { Long id = metadata.get(data); - if (id != null && id > 0L) { // IDs start at 1, so this is safe + if (id != null) { long rewriteId = PlayerRewriteUtils.rewriteId(id, this.rewrite.getEntityId(), this.rewrite.getOriginalEntityId()); if (rewriteId != id) { metadata.put(data, rewriteId); From 802d71eddd6b9400b14150a7165c18c13b50b025 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Tue, 28 Oct 2025 22:59:07 +0300 Subject: [PATCH 40/45] Correctly remove the server from pendingServers in all branches --- src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java index bc5ddfb..07b3e0d 100644 --- a/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java +++ b/src/main/java/dev/waterdog/waterdogpe/player/ProxiedPlayer.java @@ -230,6 +230,7 @@ public void connect(ServerInfo serverInfo) { ClientConnection connectingServer = this.getPendingConnection(); if (connectingServer != null) { if (connectingServer.getServerInfo() == targetServer) { + this.pendingServers.remove(targetServer); this.sendMessage(new TranslationContainer("waterdog.downstream.connecting", targetServer.getServerName())); return; } else { From be96175436a5e9e3a4472b5b3baf122545d25356 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 29 Oct 2025 17:41:55 +0300 Subject: [PATCH 41/45] Load camera preset definitions --- .../network/protocol/ProtocolCodecs.java | 1 + .../downstream/AbstractDownstreamHandler.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java index 129c773..ce6f084 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/ProtocolCodecs.java @@ -118,6 +118,7 @@ public class ProtocolCodecs { HANDLED_PACKETS.add(MovementPredictionSyncPacket.class); HANDLED_PACKETS.add(PlayerUpdateEntityOverridesPacket.class); HANDLED_PACKETS.add(PlayerLocationPacket.class); + HANDLED_PACKETS.add(CameraPresetsPacket.class); } private static final List UPDATERS = new ObjectArrayList<>(); diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java index a322c27..1d8fe2d 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/handler/downstream/AbstractDownstreamHandler.java @@ -25,12 +25,15 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper; +import org.cloudburstmc.protocol.bedrock.data.camera.CameraPreset; import org.cloudburstmc.protocol.bedrock.data.command.CommandData; import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumConstraint; import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleNamedDefinition; import org.cloudburstmc.protocol.bedrock.netty.BedrockBatchWrapper; import org.cloudburstmc.protocol.bedrock.packet.*; +import org.cloudburstmc.protocol.common.NamedDefinition; import org.cloudburstmc.protocol.common.PacketSignal; import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry; @@ -137,6 +140,12 @@ public PacketSignal handle(ClientCacheMissResponsePacket packet) { return PacketSignal.UNHANDLED; } + @Override + public PacketSignal handle(CameraPresetsPacket packet) { + setCameraPresetDefinitions(packet.getPresets()); + return PacketSignal.UNHANDLED; + } + protected PacketSignal onPlayStatus(PlayStatusPacket packet, Consumer failedTask, ClientConnection connection) { String message; switch (packet.getStatus()) { @@ -182,4 +191,16 @@ protected void setItemDefinitions(Collection definitions) { } codecHelper.setItemDefinitions(itemRegistry.build()); } + + protected void setCameraPresetDefinitions(Collection presets) { + BedrockCodecHelper codecHelper = this.player.getConnection() + .getPeer() + .getCodecHelper(); + SimpleDefinitionRegistry.Builder registry = SimpleDefinitionRegistry.builder(); + int id = 0; + for (CameraPreset preset : presets) { + registry.add(new SimpleNamedDefinition(preset.getIdentifier(), id++)); + } + codecHelper.setCameraPresetDefinitions(registry.build()); + } } From 2ff87429b9a1a9362f6ae40da0b14ef07c7202fd Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Fri, 31 Oct 2025 02:03:26 +0300 Subject: [PATCH 42/45] Add option to always send certificate payload to downstream --- .../waterdog/waterdogpe/network/protocol/user/LoginData.java | 3 ++- .../waterdog/waterdogpe/utils/config/proxy/ProxyConfig.java | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java index da6d1de..275b9f5 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/LoginData.java @@ -17,6 +17,7 @@ import com.google.gson.JsonObject; import com.nimbusds.jwt.SignedJWT; +import dev.waterdog.waterdogpe.ProxyServer; import dev.waterdog.waterdogpe.network.protocol.ProtocolVersion; import lombok.Builder; import lombok.Getter; @@ -81,7 +82,7 @@ public LoginPacket rebuildLoginPacket() { SignedJWT signedClientData = HandshakeUtils.encodeJWT(this.keyPair, this.clientData); loginPacket.setClientJwt(signedClientData.serialize()); loginPacket.setProtocolVersion(this.protocol.getProtocol()); - if (isChainPayload) { + if (isChainPayload || ProxyServer.getInstance().getConfiguration().useCertificatePayload()) { JsonObject extraData = HandshakeUtils.createChainExtraData(displayName, xuid, uuid); SignedJWT signedPayload = HandshakeUtils.createClientDataChain(this.keyPair, extraData); loginPacket.setAuthPayload(new CertificateChainPayload(Collections.singletonList(signedPayload.serialize()), AuthType.SELF_SIGNED)); diff --git a/src/main/java/dev/waterdog/waterdogpe/utils/config/proxy/ProxyConfig.java b/src/main/java/dev/waterdog/waterdogpe/utils/config/proxy/ProxyConfig.java index 507b46a..f4c792e 100644 --- a/src/main/java/dev/waterdog/waterdogpe/utils/config/proxy/ProxyConfig.java +++ b/src/main/java/dev/waterdog/waterdogpe/utils/config/proxy/ProxyConfig.java @@ -117,6 +117,11 @@ public class ProxyConfig extends YamlConfig { @Comment("If enabled, the proxy will pass information like XUID or IP to the downstream server using custom fields in the LoginPacket") private boolean useLoginExtras = false; + @Path("use_certificate_payload") + @Accessors(fluent = true) + @Comment("If enabled, the proxy will always send Certificate payload in the LoginPacket") + private boolean useCertificatePayload = true; + @Path("replace_username_spaces") @Comment("Replaces username spaces with underscores if enabled") private boolean replaceUsernameSpaces = false; From 1175258efa308ba4be3a339fdcb94c47bba1676b Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 5 Nov 2025 15:25:37 +0300 Subject: [PATCH 43/45] Update protocol library --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 29a7830..be45f45 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ UTF-8 17 1.0.0.CR3-SNAPSHOT - 3.0.0.Beta10-SNAPSHOT + 3.0.0.Beta11-SNAPSHOT 2.17.1 3.23.0 4.1.101.Final From 6a0f059e17a77ca721590b45c5fd82a6e59b9d62 Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 5 Nov 2025 15:30:06 +0300 Subject: [PATCH 44/45] Fix build error --- .../waterdogpe/network/protocol/user/PlayerRewriteUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/PlayerRewriteUtils.java b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/PlayerRewriteUtils.java index b246b6e..b38879a 100644 --- a/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/PlayerRewriteUtils.java +++ b/src/main/java/dev/waterdog/waterdogpe/network/protocol/user/PlayerRewriteUtils.java @@ -362,6 +362,6 @@ public static void injectEntityImmobile(ProxiedConnection session, long runtimeI } public static boolean checkForImmobileFlag(EntityDataMap dataMap) { - return dataMap != null && dataMap.getFlags() != null && dataMap.getFlags().contains(EntityFlag.NO_AI); + return dataMap != null && dataMap.getFlags() != null && dataMap.getFlags().containsKey(EntityFlag.NO_AI); } } From 4104943ad4fa1b4d79e257b9ae69b73f7bc1337e Mon Sep 17 00:00:00 2001 From: Metehan Gezer Date: Wed, 5 Nov 2025 15:46:03 +0300 Subject: [PATCH 45/45] Replace the base image with eclipse temurin --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 19f504f..c8c8e17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:17-jdk-slim +FROM eclipse-temurin:17-jdk-jammy EXPOSE 19132/tcp EXPOSE 19132/udp