From 7598918d9353e48a19e4e455b88f960455f42776 Mon Sep 17 00:00:00 2001 From: Thomas Vanmellaerts Date: Wed, 26 Sep 2018 13:00:43 +0200 Subject: [PATCH 1/4] Add chat event --- .../api/event/ResultedEvent.java | 41 +++++++++++++++ .../api/event/player/PlayerChatEvent.java | 50 +++++++++++++++++++ .../client/ClientPlaySessionHandler.java | 17 ++++++- 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java diff --git a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java index 227bbfe27..6d584be9d 100644 --- a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java @@ -111,4 +111,45 @@ public interface ResultedEvent { return new ComponentResult(false, reason); } } + + class ChatResult implements Result { + private static final ChatResult ALLOWED = new ChatResult(true, null); + private static final ChatResult DENIED = new ChatResult(false, null); + + // The server can not accept formatted text from clients! + private @Nullable String message; + private final boolean allowed; + + protected ChatResult(boolean allowed, @Nullable String message) { + this.allowed = allowed; + this.message = message; + } + + @Override + public boolean isAllowed() { + return allowed; + } + + @Override + public String toString() { + return allowed ? "allowed" : "denied"; + } + + public static ChatResult allowed() { + return ALLOWED; + } + + public static ChatResult denied() { + return DENIED; + } + + public Optional getMessage() { + return Optional.ofNullable(message); + } + + public static ChatResult message(@NonNull String message) { + Preconditions.checkNotNull(message, "message"); + return new ChatResult(true, message); + } + } } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java new file mode 100644 index 000000000..47c630936 --- /dev/null +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java @@ -0,0 +1,50 @@ +package com.velocitypowered.api.event.player; + +import com.google.common.base.Preconditions; +import com.velocitypowered.api.event.ResultedEvent; +import com.velocitypowered.api.proxy.Player; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * This event is fired once the player has been authenticated but before they connect to a server on the proxy. + */ +public class PlayerChatEvent implements ResultedEvent { + private final Player player; + private final String message; + private ChatResult result; + + public PlayerChatEvent(Player player, String message) { + this.player = Preconditions.checkNotNull(player, "player"); + this.message = Preconditions.checkNotNull(message, "message"); + this.result = (ChatResult) ChatResult.allowed(); + } + + public Player getPlayer() { + return player; + } + + public String getMessage() { + return message; + } + + @Override + public ChatResult getResult() { + return result; + } + + @Override + public void setResult(@NonNull ChatResult result) { + this.result = Preconditions.checkNotNull(result, "result"); + } + + @Override + public String toString() { + return "PlayerChatEvent{" + + "player=" + player + + ", message=" + message + + ", result=" + result + + '}'; + } + + +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index aa27bc1cf..161abf63b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -1,7 +1,9 @@ package com.velocitypowered.proxy.connection.client; +import com.velocitypowered.api.event.ResultedEvent; import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.event.player.PlayerChatEvent; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; @@ -13,8 +15,10 @@ import com.velocitypowered.proxy.protocol.packet.*; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.util.ThrowableUtils; import io.netty.buffer.ByteBuf; +import net.kyori.text.Component; import net.kyori.text.TextComponent; import net.kyori.text.format.TextColor; +import net.kyori.text.serializer.ComponentSerializers; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -93,7 +97,18 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { return; } } else { - player.getConnectedServer().getMinecraftConnection().write(chat); + PlayerChatEvent event = new PlayerChatEvent(player, msg); + server.getEventManager().fire(event) + .thenAcceptAsync(pme -> { + if (pme.getResult().equals(ResultedEvent.ChatResult.allowed())){ + player.getConnectedServer().getMinecraftConnection().write(chat); + } else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){ + Chat modifiedChat = new Chat(); + modifiedChat.setType(Chat.CHAT); + modifiedChat.setMessage(pme.getResult().getMessage().get()); + player.getConnectedServer().getMinecraftConnection().write(modifiedChat); + } + }, player.getConnectedServer().getMinecraftConnection().getChannel().eventLoop()); } return; } From d71f863045bbf8b378cf35b195c22c5567cf047c Mon Sep 17 00:00:00 2001 From: Thomas Vanmellaerts Date: Wed, 26 Sep 2018 18:25:32 +0200 Subject: [PATCH 2/4] Fire Event on spoofChatInput --- .../client/ClientPlaySessionHandler.java | 14 ++--------- .../connection/client/ConnectedPlayer.java | 3 ++- .../velocitypowered/proxy/util/EventUtil.java | 25 +++++++++++++++++++ 3 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 161abf63b..8a6d307aa 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -13,6 +13,7 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolConstants; import com.velocitypowered.proxy.protocol.packet.*; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; +import com.velocitypowered.proxy.util.EventUtil; import com.velocitypowered.proxy.util.ThrowableUtils; import io.netty.buffer.ByteBuf; import net.kyori.text.Component; @@ -97,18 +98,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { return; } } else { - PlayerChatEvent event = new PlayerChatEvent(player, msg); - server.getEventManager().fire(event) - .thenAcceptAsync(pme -> { - if (pme.getResult().equals(ResultedEvent.ChatResult.allowed())){ - player.getConnectedServer().getMinecraftConnection().write(chat); - } else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){ - Chat modifiedChat = new Chat(); - modifiedChat.setType(Chat.CHAT); - modifiedChat.setMessage(pme.getResult().getMessage().get()); - player.getConnectedServer().getMinecraftConnection().write(modifiedChat); - } - }, player.getConnectedServer().getMinecraftConnection().getChannel().eventLoop()); + EventUtil.callPlayerChatEvent(server, player, msg, chat); } return; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index cd4c55572..e2f5a1e29 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -29,6 +29,7 @@ import com.velocitypowered.proxy.connection.util.ConnectionRequestResults; import com.velocitypowered.proxy.protocol.ProtocolConstants; import com.velocitypowered.proxy.protocol.packet.*; import com.velocitypowered.proxy.server.VelocityRegisteredServer; +import com.velocitypowered.proxy.util.EventUtil; import com.velocitypowered.proxy.util.ThrowableUtils; import net.kyori.text.Component; import net.kyori.text.TextComponent; @@ -420,7 +421,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { @Override public void spoofChatInput(String input) { Preconditions.checkArgument(input.length() <= Chat.MAX_SERVERBOUND_MESSAGE_LENGTH, "input cannot be greater than " + Chat.MAX_SERVERBOUND_MESSAGE_LENGTH + " characters in length"); - connectedServer.getMinecraftConnection().write(Chat.createServerbound(input)); + EventUtil.callPlayerChatEvent(server, this, input, Chat.createServerbound(input)); } private class ConnectionRequestBuilderImpl implements ConnectionRequestBuilder { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java b/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java new file mode 100644 index 000000000..d16008824 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java @@ -0,0 +1,25 @@ +package com.velocitypowered.proxy.util; + +import com.velocitypowered.api.event.ResultedEvent; +import com.velocitypowered.api.event.player.PlayerChatEvent; +import com.velocitypowered.proxy.VelocityServer; +import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.protocol.packet.Chat; + +import javax.annotation.Nullable; + +public class EventUtil { + + public static void callPlayerChatEvent(VelocityServer server, ConnectedPlayer player, String message, Chat original){ + PlayerChatEvent event = new PlayerChatEvent(player, message); + server.getEventManager().fire(event) + .thenAcceptAsync(pme -> { + if (pme.getResult().equals(ResultedEvent.ChatResult.allowed())){ + player.getConnectedServer().getMinecraftConnection().write(original); + } else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){ + player.getConnectedServer().getMinecraftConnection().write(Chat.createServerbound(pme.getResult().getMessage().get())); + } + }, player.getConnectedServer().getMinecraftConnection().getChannel().eventLoop()); + } + +} From 3acc00de5e14a0b23ab819611c944adc9a52bc7d Mon Sep 17 00:00:00 2001 From: Thomas Vanmellaerts Date: Wed, 26 Sep 2018 19:47:38 +0200 Subject: [PATCH 3/4] Move ChatResult to PlayerChatEvent and don't call event on spoofChatInput() --- .../api/event/ResultedEvent.java | 41 --------------- .../api/event/player/PlayerChatEvent.java | 51 ++++++++++++++++++- .../client/ClientPlaySessionHandler.java | 4 -- .../connection/client/ConnectedPlayer.java | 3 +- .../velocitypowered/proxy/util/EventUtil.java | 5 +- 5 files changed, 51 insertions(+), 53 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java index 6d584be9d..227bbfe27 100644 --- a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java @@ -111,45 +111,4 @@ public interface ResultedEvent { return new ComponentResult(false, reason); } } - - class ChatResult implements Result { - private static final ChatResult ALLOWED = new ChatResult(true, null); - private static final ChatResult DENIED = new ChatResult(false, null); - - // The server can not accept formatted text from clients! - private @Nullable String message; - private final boolean allowed; - - protected ChatResult(boolean allowed, @Nullable String message) { - this.allowed = allowed; - this.message = message; - } - - @Override - public boolean isAllowed() { - return allowed; - } - - @Override - public String toString() { - return allowed ? "allowed" : "denied"; - } - - public static ChatResult allowed() { - return ALLOWED; - } - - public static ChatResult denied() { - return DENIED; - } - - public Optional getMessage() { - return Optional.ofNullable(message); - } - - public static ChatResult message(@NonNull String message) { - Preconditions.checkNotNull(message, "message"); - return new ChatResult(true, message); - } - } } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java index 47c630936..6df36fb98 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java @@ -4,11 +4,14 @@ import com.google.common.base.Preconditions; import com.velocitypowered.api.event.ResultedEvent; import com.velocitypowered.api.proxy.Player; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Optional; /** * This event is fired once the player has been authenticated but before they connect to a server on the proxy. */ -public class PlayerChatEvent implements ResultedEvent { +public class PlayerChatEvent implements ResultedEvent { private final Player player; private final String message; private ChatResult result; @@ -16,7 +19,7 @@ public class PlayerChatEvent implements ResultedEvent public PlayerChatEvent(Player player, String message) { this.player = Preconditions.checkNotNull(player, "player"); this.message = Preconditions.checkNotNull(message, "message"); - this.result = (ChatResult) ChatResult.allowed(); + this.result = ChatResult.allowed(); } public Player getPlayer() { @@ -46,5 +49,49 @@ public class PlayerChatEvent implements ResultedEvent '}'; } + /** + * Represents the result of the {@link PlayerChatEvent}. + */ + public static class ChatResult implements ResultedEvent.Result { + private static final ChatResult ALLOWED = new ChatResult(true, null); + private static final ChatResult DENIED = new ChatResult(false, null); + + // The server can not accept formatted text from clients! + private @Nullable String message; + private final boolean allowed; + + protected ChatResult(boolean allowed, @Nullable String message) { + this.allowed = allowed; + this.message = message; + } + + @Override + public boolean isAllowed() { + return allowed; + } + + @Override + public String toString() { + return allowed ? "allowed" : "denied"; + } + + public static ChatResult allowed() { + return ALLOWED; + } + + public static ChatResult denied() { + return DENIED; + } + + public Optional getMessage() { + return Optional.ofNullable(message); + } + + public static ChatResult message(@NonNull String message) { + Preconditions.checkNotNull(message, "message"); + return new ChatResult(true, message); + } + } + } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 8a6d307aa..bd315ff1e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -1,9 +1,7 @@ package com.velocitypowered.proxy.connection.client; -import com.velocitypowered.api.event.ResultedEvent; import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent; -import com.velocitypowered.api.event.player.PlayerChatEvent; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; @@ -16,10 +14,8 @@ import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.util.EventUtil; import com.velocitypowered.proxy.util.ThrowableUtils; import io.netty.buffer.ByteBuf; -import net.kyori.text.Component; import net.kyori.text.TextComponent; import net.kyori.text.format.TextColor; -import net.kyori.text.serializer.ComponentSerializers; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index e2f5a1e29..cd4c55572 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -29,7 +29,6 @@ import com.velocitypowered.proxy.connection.util.ConnectionRequestResults; import com.velocitypowered.proxy.protocol.ProtocolConstants; import com.velocitypowered.proxy.protocol.packet.*; import com.velocitypowered.proxy.server.VelocityRegisteredServer; -import com.velocitypowered.proxy.util.EventUtil; import com.velocitypowered.proxy.util.ThrowableUtils; import net.kyori.text.Component; import net.kyori.text.TextComponent; @@ -421,7 +420,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { @Override public void spoofChatInput(String input) { Preconditions.checkArgument(input.length() <= Chat.MAX_SERVERBOUND_MESSAGE_LENGTH, "input cannot be greater than " + Chat.MAX_SERVERBOUND_MESSAGE_LENGTH + " characters in length"); - EventUtil.callPlayerChatEvent(server, this, input, Chat.createServerbound(input)); + connectedServer.getMinecraftConnection().write(Chat.createServerbound(input)); } private class ConnectionRequestBuilderImpl implements ConnectionRequestBuilder { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java b/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java index d16008824..9ceaed50b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java @@ -1,20 +1,17 @@ package com.velocitypowered.proxy.util; -import com.velocitypowered.api.event.ResultedEvent; import com.velocitypowered.api.event.player.PlayerChatEvent; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.packet.Chat; -import javax.annotation.Nullable; - public class EventUtil { public static void callPlayerChatEvent(VelocityServer server, ConnectedPlayer player, String message, Chat original){ PlayerChatEvent event = new PlayerChatEvent(player, message); server.getEventManager().fire(event) .thenAcceptAsync(pme -> { - if (pme.getResult().equals(ResultedEvent.ChatResult.allowed())){ + if (pme.getResult().equals(PlayerChatEvent.ChatResult.allowed())){ player.getConnectedServer().getMinecraftConnection().write(original); } else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){ player.getConnectedServer().getMinecraftConnection().write(Chat.createServerbound(pme.getResult().getMessage().get())); From 6f4b2c83b2ef3203a0c200ca231c4473862b86d6 Mon Sep 17 00:00:00 2001 From: Thomas Vanmellaerts Date: Wed, 26 Sep 2018 19:56:47 +0200 Subject: [PATCH 4/4] Delete EventUtil --- .../client/ClientPlaySessionHandler.java | 12 ++++++++-- .../velocitypowered/proxy/util/EventUtil.java | 22 ------------------- 2 files changed, 10 insertions(+), 24 deletions(-) delete mode 100644 proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index bd315ff1e..bc0856f8c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -2,6 +2,7 @@ package com.velocitypowered.proxy.connection.client; import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.event.player.PlayerChatEvent; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; @@ -11,7 +12,6 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolConstants; import com.velocitypowered.proxy.protocol.packet.*; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; -import com.velocitypowered.proxy.util.EventUtil; import com.velocitypowered.proxy.util.ThrowableUtils; import io.netty.buffer.ByteBuf; import net.kyori.text.TextComponent; @@ -94,7 +94,15 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { return; } } else { - EventUtil.callPlayerChatEvent(server, player, msg, chat); + PlayerChatEvent event = new PlayerChatEvent(player, msg); + server.getEventManager().fire(event) + .thenAcceptAsync(pme -> { + if (pme.getResult().equals(PlayerChatEvent.ChatResult.allowed())){ + player.getConnectedServer().getMinecraftConnection().write(chat); + } else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){ + player.getConnectedServer().getMinecraftConnection().write(Chat.createServerbound(pme.getResult().getMessage().get())); + } + }, player.getConnectedServer().getMinecraftConnection().getChannel().eventLoop()); } return; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java b/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java deleted file mode 100644 index 9ceaed50b..000000000 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/EventUtil.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.velocitypowered.proxy.util; - -import com.velocitypowered.api.event.player.PlayerChatEvent; -import com.velocitypowered.proxy.VelocityServer; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import com.velocitypowered.proxy.protocol.packet.Chat; - -public class EventUtil { - - public static void callPlayerChatEvent(VelocityServer server, ConnectedPlayer player, String message, Chat original){ - PlayerChatEvent event = new PlayerChatEvent(player, message); - server.getEventManager().fire(event) - .thenAcceptAsync(pme -> { - if (pme.getResult().equals(PlayerChatEvent.ChatResult.allowed())){ - player.getConnectedServer().getMinecraftConnection().write(original); - } else if (pme.getResult().isAllowed() && pme.getResult().getMessage().isPresent()){ - player.getConnectedServer().getMinecraftConnection().write(Chat.createServerbound(pme.getResult().getMessage().get())); - } - }, player.getConnectedServer().getMinecraftConnection().getChannel().eventLoop()); - } - -}