From ffaee81ae114b5d0c76cdd0d3f4554297de079f7 Mon Sep 17 00:00:00 2001 From: Christopher Bohn Date: Wed, 18 Jun 2025 17:10:27 -0700 Subject: [PATCH 1/2] Improve bedrock support --- .../java/ru/bk/oharass/freedomchat/FreedomChat.java | 4 +++- .../ru/bk/oharass/freedomchat/FreedomHandler.java | 12 ++++++++++-- .../java/ru/bk/oharass/freedomchat/FreedomChat.java | 3 ++- .../ru/bk/oharass/freedomchat/FreedomHandler.java | 12 ++++++++++-- paper/src/main/resources/config.yml | 6 ++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java b/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java index d6b4a96..8ab17ba 100644 --- a/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java +++ b/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java @@ -39,13 +39,15 @@ public void onInitialize() { final boolean rewriteChat = config.node("rewrite-chat").getBoolean(true); final boolean claimSecureChatEnforced = config.node("claim-secure-chat-enforced").getBoolean(false); final boolean noChatReports = config.node("send-prevents-chat-reports-to-client").getBoolean(false); + final boolean bedrockOnly = config.node("bedrock-only").getBoolean(false); loader.save(config); handler = new FreedomHandler( this, rewriteChat, claimSecureChatEnforced, - noChatReports + noChatReports, + bedrockOnly ); } catch (final ConfigurateException e) { logger.error("An error occurred while loading this configuration: " + e.getMessage()); diff --git a/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java b/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java index f3b35b1..0642221 100644 --- a/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java +++ b/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java @@ -21,6 +21,7 @@ import ru.bk.oharass.freedomchat.rewrite.CustomServerMetadata; import java.util.Objects; +import java.util.UUID; import java.util.function.Function; @ChannelHandler.Sharable @@ -30,19 +31,21 @@ public class FreedomHandler extends MessageToByteEncoder> { private final boolean rewriteChat; private final boolean claimSecureChatEnforced; private final boolean noChatReports; + private final boolean bedrockOnly; - public FreedomHandler(final FreedomChat freedom, final boolean rewriteChat, final boolean claimSecureChatEnforced, final boolean noChatReports) { + public FreedomHandler(final FreedomChat freedom, final boolean rewriteChat, final boolean claimSecureChatEnforced, final boolean noChatReports, final boolean bedrockOnly) { final DynamicRegistryManager registryAccess = freedom.getServer().getRegistryManager(); final Function bufRegistryAccess = RegistryByteBuf.makeFactory(registryAccess); this.s2cPlayPacketCodec = PlayStateFactories.S2C.bind(bufRegistryAccess).codec(); this.rewriteChat = rewriteChat; this.claimSecureChatEnforced = claimSecureChatEnforced; this.noChatReports = noChatReports; + this.bedrockOnly = bedrockOnly; } @Override public boolean acceptOutboundMessage(final Object msg) { - return rewriteChat && msg instanceof ChatMessageS2CPacket + return (rewriteChat && msg instanceof ChatMessageS2CPacket packet && (!bedrockOnly || isBedrockPlayer(packet.sender()))) || noChatReports && msg instanceof QueryResponseS2CPacket || claimSecureChatEnforced && msg instanceof GameJoinS2CPacket; } @@ -103,4 +106,9 @@ private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, buf.writeVarInt(STATUS_RESPONSE_PACKET_ID); buf.encodeAsJson(CustomServerMetadata.CODEC, customStatus); } + + private boolean isBedrockPlayer(final UUID uuid) { + // Bedrock players use a nil uuid bit masked with their xbox user id (xuid). The version is always zero. + return uuid.version() == 0; + } } diff --git a/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java b/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java index ad1529e..a041f9a 100644 --- a/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java +++ b/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java @@ -34,7 +34,8 @@ public void onEnable() { final FreedomHandler handler = new FreedomHandler( config.getBoolean("rewrite-chat", true), config.getBoolean("claim-secure-chat-enforced", false), - config.getBoolean("send-prevents-chat-reports-to-client", false) + config.getBoolean("send-prevents-chat-reports-to-client", false), + config.getBoolean("bedrock-only", false) ); addListener(listenerKey, channel -> channel.pipeline().addAfter("packet_handler", "freedom_handler", handler)); diff --git a/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java b/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java index 870cbb1..ab35d17 100644 --- a/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java +++ b/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java @@ -22,6 +22,7 @@ import ru.bk.oharass.freedomchat.rewrite.CustomServerMetadata; import java.util.Objects; +import java.util.UUID; import java.util.function.Function; @ChannelHandler.Sharable @@ -31,19 +32,21 @@ public class FreedomHandler extends MessageToByteEncoder> { private final boolean rewriteChat; private final boolean claimSecureChatEnforced; private final boolean noChatReports; + private final boolean bedrockOnly; - public FreedomHandler(final boolean rewriteChat, final boolean claimSecureChatEnforced, final boolean noChatReports) { + public FreedomHandler(final boolean rewriteChat, final boolean claimSecureChatEnforced, final boolean noChatReports, final boolean bedrockOnly) { final RegistryAccess registryAccess = MinecraftServer.getServer().registryAccess(); final Function bufRegistryAccess = RegistryFriendlyByteBuf.decorator(registryAccess); this.s2cPlayPacketCodec = GameProtocols.CLIENTBOUND_TEMPLATE.bind(bufRegistryAccess).codec(); this.rewriteChat = rewriteChat; this.claimSecureChatEnforced = claimSecureChatEnforced; this.noChatReports = noChatReports; + this.bedrockOnly = bedrockOnly; } @Override public boolean acceptOutboundMessage(final Object msg) { - return rewriteChat && msg instanceof ClientboundPlayerChatPacket + return (rewriteChat && msg instanceof ClientboundPlayerChatPacket packet && (!bedrockOnly || isBedrockPlayer(packet.sender()))) || noChatReports && msg instanceof ClientboundStatusResponsePacket || claimSecureChatEnforced && msg instanceof ClientboundLoginPacket; } @@ -104,4 +107,9 @@ private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, buf.writeVarInt(STATUS_RESPONSE_PACKET_ID); buf.writeJsonWithCodec(CustomServerMetadata.CODEC, customStatus); } + + private boolean isBedrockPlayer(final UUID uuid) { + // Bedrock players use a nil uuid bit masked with their xbox user id (xuid). The version is always zero. + return uuid.version() == 0; + } } diff --git a/paper/src/main/resources/config.yml b/paper/src/main/resources/config.yml index 35da94c..9a868bf 100644 --- a/paper/src/main/resources/config.yml +++ b/paper/src/main/resources/config.yml @@ -17,3 +17,9 @@ claim-secure-chat-enforced: false # screen and if enforce-secure-profiles is disabled the open chat screen # for users of the client-side mod. send-prevents-chat-reports-to-client: false + +# Only enable chat rewriting for Bedrock. This can be desirable if secure chat +# is supported by the server, and you want Java players to be able to use +# features provided through the Social Interactions menu, but still want to +# support chat from Bedrock players connected through Geyser. +bedrock-only: false From 94e4d67f118bfc110027b36e6b81da1e1b3279ce Mon Sep 17 00:00:00 2001 From: Christopher Bohn Date: Thu, 19 Jun 2025 23:48:27 -0700 Subject: [PATCH 2/2] rename option to be more clear --- fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java | 2 +- paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java | 2 +- paper/src/main/resources/config.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java b/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java index 8ab17ba..bb3c4e3 100644 --- a/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java +++ b/fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java @@ -39,7 +39,7 @@ public void onInitialize() { final boolean rewriteChat = config.node("rewrite-chat").getBoolean(true); final boolean claimSecureChatEnforced = config.node("claim-secure-chat-enforced").getBoolean(false); final boolean noChatReports = config.node("send-prevents-chat-reports-to-client").getBoolean(false); - final boolean bedrockOnly = config.node("bedrock-only").getBoolean(false); + final boolean bedrockOnly = config.node("rewrite-bedrock-only").getBoolean(false); loader.save(config); handler = new FreedomHandler( diff --git a/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java b/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java index a041f9a..ee20592 100644 --- a/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java +++ b/paper/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java @@ -35,7 +35,7 @@ public void onEnable() { config.getBoolean("rewrite-chat", true), config.getBoolean("claim-secure-chat-enforced", false), config.getBoolean("send-prevents-chat-reports-to-client", false), - config.getBoolean("bedrock-only", false) + config.getBoolean("rewrite-bedrock-only", false) ); addListener(listenerKey, channel -> channel.pipeline().addAfter("packet_handler", "freedom_handler", handler)); diff --git a/paper/src/main/resources/config.yml b/paper/src/main/resources/config.yml index 9a868bf..794e252 100644 --- a/paper/src/main/resources/config.yml +++ b/paper/src/main/resources/config.yml @@ -22,4 +22,4 @@ send-prevents-chat-reports-to-client: false # is supported by the server, and you want Java players to be able to use # features provided through the Social Interactions menu, but still want to # support chat from Bedrock players connected through Geyser. -bedrock-only: false +rewrite-bedrock-only: false