Paper/Spigot-Server-Patches/0371-Fire-event-on-GS4-query.patch
Spottedleaf 5c7081fecc Update upstream & fix some chunk related issues (#2177)
* Updated Upstream (Bukkit/CraftBukkit)

Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
45690fe9 SPIGOT-5047: Correct slot types for 1.14 inventories

CraftBukkit Changes:
4090d01f SPIGOT-5047: Correct slot types for 1.14 inventories
e8c08362 SPIGOT-5046: World#getLoadedChunks returning inaccessible cached chunks.
d445af3b SPIGOT-5067: Add item meta for 1.14 spawn eggs

* Bring Chunk load checks in-line with spigot

As of the last upstream merge spigot now checks ticket level status
when returning loaded chunks for a world from api. Now our checks
will respect that decision.

* Fix spawn ticket levels

Vanilla would keep the inner chunks of spawn available for ticking,
however my changes made all chunks non-ticking. Resolve by changing
ticket levels for spawn chunks inside the border to respect this
behavior.


* Make World#getChunkIfLoadedImmediately return only entity ticking chunks

Mojang appears to be using chunks with level > 33 (non-ticking chunks)
as cached chunks and not actually loaded chunks.

* Bring all loaded checks in line with spigot

Loaded chunks must be at least border  chunks, or level <= 33
2019-06-14 03:27:40 +01:00

221 lines
12 KiB
Diff

From 07e4c9acc95339fa5eaafe7a16eeda612545cdff Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
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/RemoteConnectionThread.java b/src/main/java/net/minecraft/server/RemoteConnectionThread.java
index 66bfbcf02b..d821ef9a75 100644
--- a/src/main/java/net/minecraft/server/RemoteConnectionThread.java
+++ b/src/main/java/net/minecraft/server/RemoteConnectionThread.java
@@ -15,7 +15,7 @@ public abstract class RemoteConnectionThread implements Runnable {
private static final Logger LOGGER = LogManager.getLogger();
private static final AtomicInteger i = new AtomicInteger(0);
protected boolean a;
- protected final IMinecraftServer b;
+ protected final IMinecraftServer b; protected IMinecraftServer getServer() { return this.b; } // Paper - OBFHELPER
protected final String c;
protected Thread d;
protected final int e = 5;
@@ -94,6 +94,7 @@ public abstract class RemoteConnectionThread implements Runnable {
this.b.g(s);
}
+ protected int getPlayerCount() { return this.d(); } // Paper - OBFHELPER
protected int d() {
return this.b.getPlayerCount();
}
diff --git a/src/main/java/net/minecraft/server/RemoteStatusListener.java b/src/main/java/net/minecraft/server/RemoteStatusListener.java
index a556a71334..67e94a6f07 100644
--- a/src/main/java/net/minecraft/server/RemoteStatusListener.java
+++ b/src/main/java/net/minecraft/server/RemoteStatusListener.java
@@ -21,19 +21,19 @@ public class RemoteStatusListener extends RemoteConnectionThread {
private long h;
private final int i;
- private final int j;
- private final int k;
- private final String l;
- private final String m;
+ private final int j; private int getServerPort() { return this.j; } // Paper - OBFHELPER
+ private final int k; private int getMaxPlayers() { return this.k; } // Paper - OBFHELPER
+ private final String l; private String getMotd() { return this.l; } // Paper - OBFHELPER
+ private final String m; private String getWorldName() { return this.m; } // Paper - OBFHELPER
private DatagramSocket n;
private final byte[] o = new byte[1460];
private DatagramPacket p;
private final Map<SocketAddress, String> q;
- private String r;
+ private String r; private String getServerHost() { return this.r; } // Paper - OBFHELPER
private String s;
private final Map<SocketAddress, RemoteStatusListener.RemoteStatusChallenge> t;
private final long u;
- private final RemoteStatusReply v;
+ private final RemoteStatusReply v; private RemoteStatusReply getCachedFullResponse() { return this.v; } // Paper - OBFHELPER
private long w;
public RemoteStatusListener(IMinecraftServer iminecraftserver) {
@@ -91,6 +91,7 @@ public class RemoteStatusListener extends RemoteConnectionThread {
remotestatusreply.a((int) 0);
remotestatusreply.a(this.a(datagrampacket.getSocketAddress()));
+ /* Paper start - GS4 Query event
remotestatusreply.a(this.l);
remotestatusreply.a("SMP");
remotestatusreply.a(this.m);
@@ -98,6 +99,31 @@ public class RemoteStatusListener extends RemoteConnectionThread {
remotestatusreply.a(Integer.toString(this.k));
remotestatusreply.a((short) this.j);
remotestatusreply.a(this.r);
+ */
+ 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.getMotd())
+ .map(this.getWorldName())
+ .currentPlayers(this.getPlayerCount())
+ .maxPlayers(this.getMaxPlayers())
+ .port(this.getServerPort())
+ .hostname(this.getServerHost())
+ .gameVersion(this.getServer().getVersion())
+ .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, datagrampacket.getAddress(), queryResponse);
+ queryEvent.callEvent();
+ queryResponse = queryEvent.getResponse();
+ remotestatusreply.writeString(queryResponse.getMotd());
+ remotestatusreply.writeString("SMP");
+ remotestatusreply.writeString(queryResponse.getMap());
+ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers()));
+ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers()));
+ remotestatusreply.writeShort((short) queryResponse.getPort());
+ remotestatusreply.writeString(queryResponse.getHostname());
+ // Paper end
this.a(remotestatusreply.a(), datagrampacket);
this.a("Status [" + socketaddress + "]");
}
@@ -134,6 +160,7 @@ public class RemoteStatusListener extends RemoteConnectionThread {
this.v.a("splitnum");
this.v.a((int) 128);
this.v.a((int) 0);
+ /* Paper start - GS4 Query event
this.v.a("hostname");
this.v.a(this.l);
this.v.a("gametype");
@@ -169,6 +196,79 @@ public class RemoteStatusListener extends RemoteConnectionThread {
}
this.v.a((int) 0);
+ */
+ // Pack plugins
+ java.util.List<com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation> plugins = java.util.Collections.emptyList();
+ org.bukkit.plugin.Plugin[] bukkitPlugins;
+ if(((DedicatedServer) this.getServer()).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.getMotd())
+ .map(this.getWorldName())
+ .currentPlayers(this.getPlayerCount())
+ .maxPlayers(this.getMaxPlayers())
+ .port(this.getServerPort())
+ .hostname(this.getServerHost())
+ .plugins(plugins)
+ .players(this.getServer().getPlayers())
+ .gameVersion(this.getServer().getVersion())
+ .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, datagrampacket.getAddress(), queryResponse);
+ queryEvent.callEvent();
+ queryResponse = queryEvent.getResponse();
+ this.getCachedFullResponse().writeString("hostname");
+ this.getCachedFullResponse().writeString(queryResponse.getMotd());
+ this.getCachedFullResponse().writeString("gametype");
+ this.getCachedFullResponse().writeString("SMP");
+ this.getCachedFullResponse().writeString("game_id");
+ this.getCachedFullResponse().writeString("MINECRAFT");
+ this.getCachedFullResponse().writeString("version");
+ this.getCachedFullResponse().writeString(queryResponse.getGameVersion());
+ this.getCachedFullResponse().writeString("plugins");
+ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder();
+ pluginsString.append(queryResponse.getServerVersion());
+ if(!queryResponse.getPlugins().isEmpty()) {
+ pluginsString.append(": ");
+ Iterator<com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation> 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().replaceAll(";", ","));
+ }
+ if (iter.hasNext()) {
+ pluginsString.append(';').append(' ');
+ }
+ }
+ }
+ this.getCachedFullResponse().writeString(pluginsString.toString());
+ this.getCachedFullResponse().writeString("map");
+ this.getCachedFullResponse().writeString(queryResponse.getMap());
+ this.getCachedFullResponse().writeString("numplayers");
+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers()));
+ this.getCachedFullResponse().writeString("maxplayers");
+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers()));
+ this.getCachedFullResponse().writeString("hostport");
+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort()));
+ this.getCachedFullResponse().writeString("hostip");
+ this.getCachedFullResponse().writeString(queryResponse.getHostname());
+ // The "meaningless data" start, copied from above
+ this.getCachedFullResponse().writeInt(0);
+ this.getCachedFullResponse().writeInt(1);
+ this.getCachedFullResponse().writeString("player_");
+ this.getCachedFullResponse().writeInt(0);
+ // "Meaningless data" end
+ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked);
+ this.getCachedFullResponse().writeInt(0);
+ // Paper end
return this.v.a();
}
}
diff --git a/src/main/java/net/minecraft/server/RemoteStatusReply.java b/src/main/java/net/minecraft/server/RemoteStatusReply.java
index 848b5c3f0e..73efea7e13 100644
--- a/src/main/java/net/minecraft/server/RemoteStatusReply.java
+++ b/src/main/java/net/minecraft/server/RemoteStatusReply.java
@@ -18,15 +18,27 @@ public class RemoteStatusReply {
this.b.write(abyte, 0, abyte.length);
}
+ public void writeString(String string) throws IOException { this.a(string); } // Paper - OBFHELPER
public void a(String s) throws IOException {
this.b.writeBytes(s);
this.b.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 writeInt(int i) throws IOException { this.a(i); } // Paper - OBFHELPER
public void a(int i) throws IOException {
this.b.write(i);
}
+ public void writeShort(short i) throws IOException { this.a(i); } // Paper - OBFHELPER
public void a(short short0) throws IOException {
this.b.writeShort(Short.reverseBytes(short0));
}
--
2.21.0