From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Mark Vainomaa Date: Sun, 17 Mar 2019 21:46:56 +0200 Subject: [PATCH] Fire event on GS4 query diff --git a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java index 51cb2644aa516a59e19fecb308d519dbc7e5fb11..e548aa0ca4e1e94ab628614b44fc11568ca3beff 100644 --- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java @@ -22,6 +22,16 @@ public class NetworkDataOutputStream { this.dataOutputStream.write(0); } + // Paper start - unchecked exception variant to use in Stream API + public void writeStringUnchecked(String string) { + try { + writeString(string); + } catch (IOException e) { + com.destroystokyo.paper.util.SneakyThrow.sneaky(e); + } + } + // Paper end + public void write(int value) throws IOException { this.dataOutputStream.write(value); } diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java index 02bb0b2df37ead741adfef38d7479ba6f691dc2d..4632e8f0d27057bf3c47057124b347237ab58111 100644 --- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java @@ -94,33 +94,52 @@ public class QueryThreadGs4 extends GenericThread { if (3 <= i && -2 == bs[0] && -3 == bs[1]) { LOGGER.debug("Packet '{}' [{}]", PktUtils.toHexString(bs[2]), socketAddress); switch(bs[2]) { - case 0: - if (!this.validChallenge(packet)) { - LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress); - return false; - } else if (15 == i) { - this.sendTo(this.buildRuleResponse(packet), packet); - LOGGER.debug("Rules [{}]", (Object)socketAddress); - } else { - NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460); - networkDataOutputStream.write(0); - networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress())); - networkDataOutputStream.writeString(this.serverName); - networkDataOutputStream.writeString("SMP"); - networkDataOutputStream.writeString(this.worldName); - networkDataOutputStream.writeString(Integer.toString(this.serverInterface.getPlayerCount())); - networkDataOutputStream.writeString(Integer.toString(this.maxPlayers)); - networkDataOutputStream.writeShort((short)this.serverPort); - networkDataOutputStream.writeString(this.hostIp); - this.sendTo(networkDataOutputStream.toByteArray(), packet); - LOGGER.debug("Status [{}]", (Object)socketAddress); - } - default: - return true; - case 9: - this.sendChallenge(packet); - LOGGER.debug("Challenge [{}]", (Object)socketAddress); - return true; + case 0: + if (!this.validChallenge(packet)) { + LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress); + return false; + } else if (15 == i) { + this.sendTo(this.buildRuleResponse(packet), packet); + LOGGER.debug("Rules [{}]", (Object)socketAddress); + } else { + NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460); + networkDataOutputStream.write(0); + networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress())); + + com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = + com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; + com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() + .motd(this.serverName) + .map(this.worldName) + .currentPlayers(this.serverInterface.getPlayerCount()) + .maxPlayers(this.maxPlayers) + .port(this.serverPort) + .hostname(this.hostIp) + .gameVersion(this.serverInterface.getServerVersion()) + .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) + .build(); + com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = + new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); + queryEvent.callEvent(); + queryResponse = queryEvent.getResponse(); + + networkDataOutputStream.writeString(queryResponse.getMotd()); + networkDataOutputStream.writeString("SMP"); + networkDataOutputStream.writeString(queryResponse.getMap()); + networkDataOutputStream.writeString(Integer.toString(queryResponse.getCurrentPlayers())); + networkDataOutputStream.writeString(Integer.toString(queryResponse.getMaxPlayers())); + networkDataOutputStream.writeShort((short) queryResponse.getPort()); + networkDataOutputStream.writeString(queryResponse.getHostname()); + // Paper end + this.sendTo(networkDataOutputStream.toByteArray(), packet); + LOGGER.debug("Status [{}]", (Object)socketAddress); + } + default: + return true; + case 9: + this.sendChallenge(packet); + LOGGER.debug("Challenge [{}]", (Object)socketAddress); + return true; } } else { LOGGER.debug("Invalid packet [{}]", (Object)socketAddress); @@ -146,37 +165,79 @@ public class QueryThreadGs4 extends GenericThread { this.rulesResponse.writeString("splitnum"); this.rulesResponse.write(128); this.rulesResponse.write(0); + // Paper start + // Pack plugins + java.util.List plugins = java.util.Collections.emptyList(); + org.bukkit.plugin.Plugin[] bukkitPlugins; + if (((net.minecraft.server.dedicated.DedicatedServer) this.serverInterface).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { + plugins = java.util.stream.Stream.of(bukkitPlugins) + .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) + .collect(java.util.stream.Collectors.toList()); + } + + com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() + .motd(this.serverName) + .map(this.worldName) + .currentPlayers(this.serverInterface.getPlayerCount()) + .maxPlayers(this.maxPlayers) + .port(this.serverPort) + .hostname(this.hostIp) + .plugins(plugins) + .players(this.serverInterface.getPlayerNames()) + .gameVersion(this.serverInterface.getServerVersion()) + .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) + .build(); + com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = + com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; + com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = + new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, packet.getAddress(), queryResponse); + queryEvent.callEvent(); + queryResponse = queryEvent.getResponse(); this.rulesResponse.writeString("hostname"); - this.rulesResponse.writeString(this.serverName); + this.rulesResponse.writeString(queryResponse.getMotd()); this.rulesResponse.writeString("gametype"); this.rulesResponse.writeString("SMP"); this.rulesResponse.writeString("game_id"); this.rulesResponse.writeString("MINECRAFT"); this.rulesResponse.writeString("version"); - this.rulesResponse.writeString(this.serverInterface.getServerVersion()); + this.rulesResponse.writeString(queryResponse.getGameVersion()); this.rulesResponse.writeString("plugins"); - this.rulesResponse.writeString(this.serverInterface.getPluginNames()); + java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); + pluginsString.append(queryResponse.getServerVersion()); + if (!queryResponse.getPlugins().isEmpty()) { + pluginsString.append(": "); + java.util.Iterator iter = queryResponse.getPlugins().iterator(); + while (iter.hasNext()) { + com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); + pluginsString.append(info.getName()); + if (info.getVersion() != null) { + pluginsString.append(' ').append(info.getVersion().replace(";", ",")); + } + if (iter.hasNext()) { + pluginsString.append(';').append(' '); + } + } + } + this.rulesResponse.writeString(pluginsString.toString()); this.rulesResponse.writeString("map"); - this.rulesResponse.writeString(this.worldName); + this.rulesResponse.writeString(queryResponse.getMap()); this.rulesResponse.writeString("numplayers"); - this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); + this.rulesResponse.writeString(Integer.toString(queryResponse.getCurrentPlayers())); this.rulesResponse.writeString("maxplayers"); - this.rulesResponse.writeString("" + this.maxPlayers); + this.rulesResponse.writeString(Integer.toString(queryResponse.getMaxPlayers())); this.rulesResponse.writeString("hostport"); - this.rulesResponse.writeString("" + this.serverPort); + this.rulesResponse.writeString(Integer.toString(queryResponse.getPort())); this.rulesResponse.writeString("hostip"); - this.rulesResponse.writeString(this.hostIp); - this.rulesResponse.write(0); - this.rulesResponse.write(1); + this.rulesResponse.writeString(queryResponse.getHostname()); + // The "meaningless data" start, copied from above + this.rulesResponse.writeInt(0); + this.rulesResponse.writeInt(1); this.rulesResponse.writeString("player_"); - this.rulesResponse.write(0); - String[] strings = this.serverInterface.getPlayerNames(); - - for(String string : strings) { - this.rulesResponse.writeString(string); - } - - this.rulesResponse.write(0); + this.rulesResponse.writeInt(0); + // "Meaningless data" end + queryResponse.getPlayers().forEach(this.rulesResponse::writeStringUnchecked); + this.rulesResponse.writeInt(0); + // Paper end return this.rulesResponse.toByteArray(); } }