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.