aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0181-Implement-extended-PaperServerListPingEvent.patch')
-rw-r--r--patches/server/0181-Implement-extended-PaperServerListPingEvent.patch250
1 files changed, 250 insertions, 0 deletions
diff --git a/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch b/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch
new file mode 100644
index 0000000000..fa4ddb2052
--- /dev/null
+++ b/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch
@@ -0,0 +1,250 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Minecrell <[email protected]>
+Date: Wed, 11 Oct 2017 15:56:26 +0200
+Subject: [PATCH] Implement extended PaperServerListPingEvent
+
+
+diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..2b10ce4ce36e519b757af96cb80921dfc3f09418
+--- /dev/null
++++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java
+@@ -0,0 +1,31 @@
++package com.destroystokyo.paper.network;
++
++import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
++import net.minecraft.server.MinecraftServer;
++import net.minecraft.server.level.ServerPlayer;
++import org.bukkit.entity.Player;
++import org.bukkit.util.CachedServerIcon;
++
++import javax.annotation.Nullable;
++
++class PaperServerListPingEventImpl extends PaperServerListPingEvent {
++
++ private final MinecraftServer server;
++
++ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) {
++ super(client, server.server.motd(), server.previewsChat(), server.getPlayerCount(), server.getMaxPlayers(),
++ server.getServerModName() + ' ' + server.getServerVersion(), protocolVersion, icon);
++ this.server = server;
++ }
++
++ @Override
++ protected final Object[] getOnlinePlayers() {
++ return this.server.getPlayerList().players.toArray();
++ }
++
++ @Override
++ protected final Player getBukkitPlayer(Object player) {
++ return ((ServerPlayer) player).getBukkitEntity();
++ }
++
++}
+diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..d926ad804355ee2fdc5910b2505e8671602acdab
+--- /dev/null
++++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java
+@@ -0,0 +1,11 @@
++package com.destroystokyo.paper.network;
++
++import net.minecraft.network.Connection;
++
++class PaperStatusClient extends PaperNetworkClient implements StatusClient {
++
++ PaperStatusClient(Connection networkManager) {
++ super(networkManager);
++ }
++
++}
+diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..4c2351b03b58511b80017b58ee9b20ab5193adc9
+--- /dev/null
++++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java
+@@ -0,0 +1,110 @@
++package com.destroystokyo.paper.network;
++
++import com.destroystokyo.paper.profile.CraftPlayerProfile;
++import com.destroystokyo.paper.profile.PlayerProfile;
++import com.google.common.base.MoreObjects;
++import com.google.common.base.Strings;
++import com.mojang.authlib.GameProfile;
++import io.papermc.paper.adventure.AdventureComponent;
++import java.util.List;
++import java.util.UUID;
++import javax.annotation.Nonnull;
++import net.minecraft.network.Connection;
++import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
++import net.minecraft.network.protocol.status.ServerStatus;
++import net.minecraft.server.MinecraftServer;
++
++public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl {
++
++ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0];
++ private static final UUID FAKE_UUID = new UUID(0, 0);
++
++ private GameProfile[] originalSample;
++
++ private StandardPaperServerListPingEventImpl(MinecraftServer server, Connection networkManager, ServerStatus ping) {
++ super(server, new PaperStatusClient(networkManager), ping.getVersion() != null ? ping.getVersion().getProtocol() : -1, server.server.getServerIcon());
++ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE
++ }
++
++ @Nonnull
++ @Override
++ public List<PlayerProfile> getPlayerSample() {
++ List<PlayerProfile> sample = super.getPlayerSample();
++
++ if (this.originalSample != null) {
++ for (GameProfile profile : this.originalSample) {
++ sample.add(CraftPlayerProfile.asBukkitCopy(profile));
++ }
++ this.originalSample = null;
++ }
++
++ return sample;
++ }
++
++ private GameProfile[] getPlayerSampleHandle() {
++ if (this.originalSample != null) {
++ return this.originalSample;
++ }
++
++ List<PlayerProfile> entries = super.getPlayerSample();
++ if (entries.isEmpty()) {
++ return EMPTY_PROFILES;
++ }
++
++ GameProfile[] profiles = new GameProfile[entries.size()];
++ for (int i = 0; i < profiles.length; i++) {
++ /*
++ * Avoid null UUIDs/names since that will make the response invalid
++ * on the client.
++ * Instead, fall back to a fake/empty UUID and an empty string as name.
++ * This can be used to create custom lines in the player list that do not
++ * refer to a specific player.
++ */
++
++ PlayerProfile profile = entries.get(i);
++ if (profile.getId() != null && profile.getName() != null) {
++ profiles[i] = CraftPlayerProfile.asAuthlib(profile);
++ } else {
++ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName()));
++ }
++ }
++
++ return profiles;
++ }
++
++ @SuppressWarnings("deprecation")
++ public static void processRequest(MinecraftServer server, Connection networkManager) {
++ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getStatus());
++ server.server.getPluginManager().callEvent(event);
++
++ // Close connection immediately if event is cancelled
++ if (event.isCancelled()) {
++ networkManager.disconnect(null);
++ return;
++ }
++
++ // Setup response
++ ServerStatus ping = new ServerStatus();
++
++ // Description
++ ping.setDescription(new AdventureComponent(event.motd()));
++
++ // Players
++ if (!event.shouldHidePlayers()) {
++ ping.setPlayers(new ServerStatus.Players(event.getMaxPlayers(), event.getNumPlayers()));
++ ping.getPlayers().setSample(event.getPlayerSampleHandle());
++ }
++
++ // Version
++ ping.setVersion(new ServerStatus.Version(event.getVersion(), event.getProtocolVersion()));
++
++ // Favicon
++ if (event.getServerIcon() != null) {
++ ping.setFavicon(event.getServerIcon().getData());
++ }
++
++ // Send response
++ networkManager.send(new ClientboundStatusResponsePacket(ping));
++ }
++
++}
+diff --git a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java
+index 67455a5ba75c9b816213e44d6872c5ddf8e27e98..23efad80934930beadf15e65781551d4ba7ff81b 100644
+--- a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java
++++ b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java
+@@ -10,7 +10,9 @@ import net.minecraft.util.GsonHelper;
+ import net.minecraft.util.LowerCaseEnumTypeAdapterFactory;
+
+ public class ClientboundStatusResponsePacket implements Packet<ClientStatusPacketListener> {
+- private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()).create();
++ private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory())
++ .registerTypeAdapter(io.papermc.paper.adventure.AdventureComponent.class, new io.papermc.paper.adventure.AdventureComponent.Serializer())
++ .create();
+ private final ServerStatus status;
+
+ public ClientboundStatusResponsePacket(ServerStatus metadata) {
+diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
+index 3bd4b16da49a730326f5b9039649eb59e3043bd0..d65423b8d7b69db79de05587efba13008602f743 100644
+--- a/src/main/java/net/minecraft/server/MinecraftServer.java
++++ b/src/main/java/net/minecraft/server/MinecraftServer.java
+@@ -2,6 +2,9 @@ package net.minecraft.server;
+
+ import com.google.common.base.Splitter;
+ import com.google.common.collect.ImmutableList;
++import co.aikar.timings.Timings;
++import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
++import com.google.common.base.Stopwatch;
+ import com.google.common.collect.Lists;
+ import com.google.common.collect.Maps;
+ import com.google.common.collect.Sets;
+@@ -1303,7 +1306,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+ this.lastServerStatus = i;
+ this.status.setPlayers(new ServerStatus.Players(this.getMaxPlayers(), this.getPlayerCount()));
+ if (!this.hidesOnlinePlayers()) {
+- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)];
++ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper
+ int j = Mth.nextInt(this.random, 0, this.getPlayerCount() - agameprofile.length);
+
+ for (int k = 0; k < agameprofile.length; ++k) {
+diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
+index a426adfba3fccf1815177e0b8065684c9497ef45..29a22da1b94d51300481c071aa16bfd8cd02178f 100644
+--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
+@@ -46,6 +46,8 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene
+ this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON);
+ } else {
+ this.hasRequestedStatus = true;
++ // Paper start - Replace everything
++ /*
+ // CraftBukkit start
+ // this.connection.send(new PacketStatusOutServerInfo(this.server.getStatus()));
+ final Object[] players = this.server.getPlayerList().players.toArray();
+@@ -150,6 +152,9 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene
+
+ this.connection.send(new ClientboundStatusResponsePacket(ping));
+ // CraftBukkit end
++ */
++ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection);
++ // Paper end
+ }
+ }
+
+diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
+index c2e3d32e51902503af88f089e366e784f42d999a..645643d102118ad4916a152abfb9ab0d02751e11 100644
+--- a/src/main/java/org/spigotmc/SpigotConfig.java
++++ b/src/main/java/org/spigotmc/SpigotConfig.java
+@@ -289,7 +289,7 @@ public class SpigotConfig
+ public static int playerSample;
+ private static void playerSample()
+ {
+- SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 );
++ SpigotConfig.playerSample = Math.max( SpigotConfig.getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts
+ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger
+ }
+