diff --git a/src/main/java/io/github/_4drian3d/unsignedvelocity/UnSignedVelocity.java b/src/main/java/io/github/_4drian3d/unsignedvelocity/UnSignedVelocity.java index d3ebd39..f570d04 100644 --- a/src/main/java/io/github/_4drian3d/unsignedvelocity/UnSignedVelocity.java +++ b/src/main/java/io/github/_4drian3d/unsignedvelocity/UnSignedVelocity.java @@ -13,7 +13,10 @@ import com.velocitypowered.proxy.VelocityServer; import io.github._4drian3d.unsignedvelocity.configuration.Configuration; import io.github._4drian3d.unsignedvelocity.listener.LoadablePacketListener; -import io.github._4drian3d.unsignedvelocity.listener.packet.chat.ChatListener; +import io.github._4drian3d.unsignedvelocity.listener.packet.chat.ChatHeaderListener; +import io.github._4drian3d.unsignedvelocity.listener.packet.chat.ChatSessionListener; +import io.github._4drian3d.unsignedvelocity.listener.packet.chat.ClientChatListener; +import io.github._4drian3d.unsignedvelocity.listener.packet.chat.ServerChatListener; import io.github._4drian3d.unsignedvelocity.listener.packet.command.CommandListener; import io.github._4drian3d.unsignedvelocity.listener.packet.login.LoginListener; import io.github._4drian3d.unsignedvelocity.listener.packet.data.ServerDataListener; @@ -82,7 +85,10 @@ public void onProxyInitialize(ProxyInitializeEvent event) { Stream.of( LoginListener.class, CommandListener.class, - ChatListener.class, + ClientChatListener.class, + ServerChatListener.class, + ChatHeaderListener.class, + ChatSessionListener.class, ServerDataListener.class, ServerResponseListener.class ).map(injector::getInstance) @@ -99,6 +105,14 @@ public void onProxyInitialize(ProxyInitializeEvent event) { "<#6892bd>UnSigned | Commands: {} | Chat: {}"), configuration.removeSignedCommandInformation(), configuration.applyChatMessages()); + logger.info(miniMessage().deserialize( + "<#6892bd>Convert Player Chat Messages to System Chat Messages: {}"), configuration.convertPlayerChatToSystemChat(), + configuration.blockChatHeaderPackets(), + configuration.blockChatSessionPackets()); + logger.info(miniMessage().deserialize( + "<#6892bd>Block | <#6892bd>Chat Header Packets: {} | <#6892bd>Chat Session Packets: {}"), + configuration.blockChatHeaderPackets(), + configuration.blockChatSessionPackets()); logger.info(miniMessage().deserialize( "<#6892bd>Secure Chat Data: {} | <#6892bd>Safe Server Status: {}"), configuration.sendSecureChatData(), configuration.sendSafeServerStatus()); } diff --git a/src/main/java/io/github/_4drian3d/unsignedvelocity/configuration/Configuration.java b/src/main/java/io/github/_4drian3d/unsignedvelocity/configuration/Configuration.java index c6d30da..64a33de 100644 --- a/src/main/java/io/github/_4drian3d/unsignedvelocity/configuration/Configuration.java +++ b/src/main/java/io/github/_4drian3d/unsignedvelocity/configuration/Configuration.java @@ -15,10 +15,17 @@ public interface Configuration { boolean applyChatMessages(); + boolean convertPlayerChatToSystemChat(); + + boolean blockChatHeaderPackets(); + + boolean blockChatSessionPackets(); + boolean sendSecureChatData(); boolean sendSafeServerStatus(); + static Configuration loadConfig(final Path path) throws IOException { final Path configPath = loadFiles(path); final HoconConfigurationLoader loader = HoconConfigurationLoader.builder() @@ -33,6 +40,12 @@ static Configuration loadConfig(final Path path) throws IOException { .getBoolean(false); final boolean applyChatMessages = loaded.node("apply-chat-messages") .getBoolean(true); + final boolean convertPlayerChatToSystemChat = loaded.node("convert-player-chat-to-system-chat") + .getBoolean(false); + final boolean blockChatHeaderPackets = loaded.node("block-chat-header-packets") + .getBoolean(false); + final boolean blockChatSessionPackets = loaded.node("block-chat-session-packets") + .getBoolean(false); final boolean sendSecureChatData = loaded.node("send-secure-chat-data") .getBoolean(false); final boolean sendSafeServerStatus = loaded.node("send-safe-server-status") @@ -54,6 +67,21 @@ public boolean applyChatMessages() { return applyChatMessages; } + @Override + public boolean convertPlayerChatToSystemChat() { + return convertPlayerChatToSystemChat; + } + + @Override + public boolean blockChatHeaderPackets() { + return blockChatHeaderPackets; + } + + @Override + public boolean blockChatSessionPackets() { + return blockChatSessionPackets; + } + @Override public boolean sendSecureChatData() { return sendSecureChatData; diff --git a/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatHeaderListener.java b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatHeaderListener.java new file mode 100644 index 0000000..2a79613 --- /dev/null +++ b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatHeaderListener.java @@ -0,0 +1,33 @@ +package io.github._4drian3d.unsignedvelocity.listener.packet.chat; + +import com.github.retrooper.packetevents.event.PacketListenerAbstract; +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon; +import com.google.inject.Inject; +import io.github._4drian3d.unsignedvelocity.UnSignedVelocity; +import io.github._4drian3d.unsignedvelocity.listener.LoadablePacketListener; + +public final class ChatHeaderListener extends PacketListenerAbstract implements LoadablePacketListener { + private final UnSignedVelocity plugin; + + @Inject + public ChatHeaderListener(UnSignedVelocity plugin) { + super(PacketListenerPriority.LOWEST); + this.plugin = plugin; + } + + @Override + public boolean canBeLoaded() { + return plugin.getConfiguration().blockChatHeaderPackets(); + } + + @Override + public void onPacketReceive(final PacketReceiveEvent event) { + final PacketTypeCommon packetType = event.getPacketType(); + if (packetType == PacketType.Play.Client.CHAT_SESSION_UPDATE) { + event.setCancelled(true); + } + } +} diff --git a/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatSessionListener.java b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatSessionListener.java new file mode 100644 index 0000000..6c172c9 --- /dev/null +++ b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatSessionListener.java @@ -0,0 +1,33 @@ +package io.github._4drian3d.unsignedvelocity.listener.packet.chat; + +import com.github.retrooper.packetevents.event.PacketListenerAbstract; +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon; +import com.google.inject.Inject; +import io.github._4drian3d.unsignedvelocity.UnSignedVelocity; +import io.github._4drian3d.unsignedvelocity.listener.LoadablePacketListener; + +public final class ChatSessionListener extends PacketListenerAbstract implements LoadablePacketListener { + private final UnSignedVelocity plugin; + + @Inject + public ChatSessionListener(UnSignedVelocity plugin) { + super(PacketListenerPriority.LOWEST); + this.plugin = plugin; + } + + @Override + public boolean canBeLoaded() { + return plugin.getConfiguration().blockChatSessionPackets(); + } + + @Override + public void onPacketReceive(final PacketReceiveEvent event) { + final PacketTypeCommon packetType = event.getPacketType(); + if (packetType == PacketType.Play.Client.CHAT_SESSION_UPDATE) { + event.setCancelled(true); + } + } +} diff --git a/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatListener.java b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ClientChatListener.java similarity index 93% rename from src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatListener.java rename to src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ClientChatListener.java index 44e1d04..df41d3b 100644 --- a/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ChatListener.java +++ b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ClientChatListener.java @@ -15,11 +15,11 @@ import java.time.Instant; -public final class ChatListener extends PacketListenerAbstract implements LoadablePacketListener { +public final class ClientChatListener extends PacketListenerAbstract implements LoadablePacketListener { private final UnSignedVelocity plugin; @Inject - public ChatListener(UnSignedVelocity plugin) { + public ClientChatListener(UnSignedVelocity plugin) { super(PacketListenerPriority.LOWEST); this.plugin = plugin; } diff --git a/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ServerChatListener.java b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ServerChatListener.java new file mode 100644 index 0000000..3bfdc42 --- /dev/null +++ b/src/main/java/io/github/_4drian3d/unsignedvelocity/listener/packet/chat/ServerChatListener.java @@ -0,0 +1,67 @@ +package io.github._4drian3d.unsignedvelocity.listener.packet.chat; + +import com.github.retrooper.packetevents.event.PacketListenerAbstract; +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketSendEvent; +import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage; +import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19; +import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_1; +import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_3; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon; +import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChatMessage; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSystemChatMessage; +import com.google.inject.Inject; +import io.github._4drian3d.unsignedvelocity.UnSignedVelocity; +import io.github._4drian3d.unsignedvelocity.listener.LoadablePacketListener; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public final class ServerChatListener extends PacketListenerAbstract implements LoadablePacketListener { + private final UnSignedVelocity plugin; + + @Inject + public ServerChatListener(UnSignedVelocity plugin) { + super(PacketListenerPriority.LOWEST); + this.plugin = plugin; + } + + @Override + public boolean canBeLoaded() { + return plugin.getConfiguration().convertPlayerChatToSystemChat(); + } + + @Override + public void onPacketSend(final PacketSendEvent event) { + final PacketTypeCommon packetType = event.getPacketType(); + if (packetType == PacketType.Play.Server.CHAT_MESSAGE) { + if (event.getUser().getClientVersion().isOlderThan(ClientVersion.V_1_19)) { + return; + } + Component messageContent = getComponentFromChatPacket(event); + final WrapperPlayServerSystemChatMessage newPacket = new WrapperPlayServerSystemChatMessage(false, messageContent); + event.getUser().sendPacketSilently(newPacket); + event.setCancelled(true); + } + } + + private static @Nullable Component getComponentFromChatPacket(PacketSendEvent event) { + final WrapperPlayServerChatMessage packet = new WrapperPlayServerChatMessage(event); + ChatMessage chatMessage = packet.getMessage(); + Component messageContent = chatMessage.getChatContent(); + if (chatMessage instanceof ChatMessage_v1_19) { + messageContent = ((ChatMessage_v1_19) chatMessage).getUnsignedChatContent(); + } else if (chatMessage instanceof ChatMessage_v1_19_1) { + messageContent = ((ChatMessage_v1_19_1) chatMessage).getUnsignedChatContent(); + } else if (chatMessage instanceof ChatMessage_v1_19_3) { + Optional unsignedChatContent = ((ChatMessage_v1_19_3) chatMessage).getUnsignedChatContent(); + if (unsignedChatContent.isPresent()) { + messageContent = unsignedChatContent.get(); + } + } + return messageContent; + } +} diff --git a/src/main/resources/config.conf b/src/main/resources/config.conf index 50f075f..3a7da28 100644 --- a/src/main/resources/config.conf +++ b/src/main/resources/config.conf @@ -2,6 +2,7 @@ # Removes the player's signed key information, # so Velocity and plugins will consider this player as UnSigned. +# This only affects players with versions between 1.19 and 1.19.2. remove-signed-key-on-join = true # Allows cancellation and modification of commands for players with version 1.19.1 or higher. @@ -9,10 +10,22 @@ remove-signed-key-on-join = true # if you have any problems, first contact UnSignedVelocity support. remove-signed-command-information = true -# Allows cancellation and modification of chat messages for players with version 1.19.1 or higher. -# This option may have incompatibilities with plugins that handle chat packets on Velocity, -# if you have any problems, first contact UnSignedVelocity support. -apply-chat-messages = true +# Cancel any Server Player Chat Message and convert it to a Server System Chat Message, +# to avoid signature check and hide the red warning sign that comes with unsigned chat messages for Vanilla clients. +# This option is required if you want to use the "Send Secure Chat Data" option. +convert-player-chat-to-system-chat = false + +# Blocks any Player Chat Header packet coming from a backend server. +# This option is required if you want to use the "Send Secure Chat Data" option. +block-chat-header-packets = false + +# Blocks any Player Chat Session packet coming from the client, +# to avoid transmitting Signed Key information for players with version 1.19.3 or higher +block-chat-session-packets = false + +# This will send information to the client about whether the proxy or server has secure chat enabled. +# Not tested for functionality with pirate clients. +send-secure-chat-data = false # This will send information to the client about whether the proxy or server has secure chat enabled. # Not tested for functionality with pirate clients.