From 0511551203e32ecc0550ef0fceda8d5fc306725b Mon Sep 17 00:00:00 2001 From: Minecrell Date: Wed, 11 Oct 2017 19:30:51 +0200 Subject: [PATCH] Call PaperServerListPingEvent for legacy pings --- .../network/LegacyQueryHandler.java.patch | 46 ++++++++++-- .../network/PaperLegacyStatusClient.java | 75 +++++++++++++++++++ 2 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 paper-server/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java diff --git a/paper-server/patches/sources/net/minecraft/server/network/LegacyQueryHandler.java.patch b/paper-server/patches/sources/net/minecraft/server/network/LegacyQueryHandler.java.patch index ad1b63f2a3..4c9495b63b 100644 --- a/paper-server/patches/sources/net/minecraft/server/network/LegacyQueryHandler.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/network/LegacyQueryHandler.java.patch @@ -25,22 +25,33 @@ bytebuf.markReaderIndex(); boolean flag = true; -@@ -34,11 +45,12 @@ +@@ -34,11 +45,23 @@ SocketAddress socketaddress = channelhandlercontext.channel().remoteAddress(); int i = bytebuf.readableBytes(); - String s; + String s = null; // Paper -+ org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, this.server.getMotd(), this.server.getPlayerCount(), this.server.getMaxPlayers()); // CraftBukkit ++ // org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, this.server.getMotd(), this.server.getPlayerCount(), this.server.getMaxPlayers()); // CraftBukkit // Paper ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper if (i == 0) { LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress); - s = LegacyQueryHandler.createVersion0Response(this.server); -+ s = LegacyQueryHandler.createVersion0Response(this.server, event); // CraftBukkit ++ ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(net.minecraft.server.MinecraftServer.getServer(), (java.net.InetSocketAddress) socketaddress, 39, null); ++ if (event == null) { ++ channelhandlercontext.close(); ++ bytebuf.release(); ++ flag = false; ++ return; ++ } ++ s = String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", com.destroystokyo.paper.network.PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); ++ // Paper end LegacyQueryHandler.sendFlushAndClose(channelhandlercontext, LegacyQueryHandler.createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); } else { if (bytebuf.readUnsignedByte() != 1) { -@@ -46,16 +58,24 @@ +@@ -46,16 +69,35 @@ } if (bytebuf.isReadable()) { @@ -66,11 +77,22 @@ } - s = LegacyQueryHandler.createVersion1Response(this.server); -+ if (s == null) s = LegacyQueryHandler.createVersion1Response(this.server, event); // CraftBukkit // Paper ++ if (s == null) { ++ // Paper start - Call PaperServerListPingEvent and use results ++ event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(net.minecraft.server.MinecraftServer.getServer(), (java.net.InetSocketAddress) socketaddress, 127, null); // Paper ++ if (event == null) { ++ channelhandlercontext.close(); ++ bytebuf.release(); ++ flag = false; ++ return; ++ } ++ s = String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), this.server.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit ++ // Paper end ++ } LegacyQueryHandler.sendFlushAndClose(channelhandlercontext, LegacyQueryHandler.createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); } -@@ -106,14 +126,102 @@ +@@ -106,14 +148,110 @@ } } @@ -139,8 +161,16 @@ + + LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); + -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -+ Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ java.net.InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); ++ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest( ++ server, (java.net.InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); ++ if (event == null) { ++ ctx.close(); ++ return null; ++ } ++ ++ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), ++ com.destroystokyo.paper.network.PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); + return response; } diff --git a/paper-server/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/paper-server/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java new file mode 100644 index 0000000000..cc54b1c207 --- /dev/null +++ b/paper-server/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java @@ -0,0 +1,75 @@ +package com.destroystokyo.paper.network; + +import com.destroystokyo.paper.event.server.PaperServerListPingEvent; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import net.minecraft.ChatFormatting; +import net.minecraft.server.MinecraftServer; +import org.apache.commons.lang3.StringUtils; + +import java.net.InetSocketAddress; + +import javax.annotation.Nullable; + +public final class PaperLegacyStatusClient implements StatusClient { + + private final InetSocketAddress address; + private final int protocolVersion; + @Nullable private final InetSocketAddress virtualHost; + + private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { + this.address = address; + this.protocolVersion = protocolVersion; + this.virtualHost = virtualHost; + } + + @Override + public InetSocketAddress getAddress() { + return this.address; + } + + @Override + public int getProtocolVersion() { + return this.protocolVersion; + } + + @Nullable + @Override + public InetSocketAddress getVirtualHost() { + return this.virtualHost; + } + + @Override + public boolean isLegacy() { + return true; + } + + public static PaperServerListPingEvent processRequest(MinecraftServer server, + InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { + + PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, + new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); + server.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return null; + } + + return event; + } + + @SuppressWarnings("deprecation") // Valid as this is the legacy status client + public static String getMotd(PaperServerListPingEvent event) { + return getFirstLine(event.getMotd()); + } + + public static String getUnformattedMotd(PaperServerListPingEvent event) { + // Strip color codes and all other occurrences of the color char (because it's used as delimiter) + return getFirstLine(StringUtils.remove(PlainTextComponentSerializer.plainText().serialize(event.motd()), ChatFormatting.PREFIX_CODE)); + } + + private static String getFirstLine(String s) { + int pos = s.indexOf('\n'); + return pos >= 0 ? s.substring(0, pos) : s; + } + +}