diff --git a/build.gradle.kts b/build.gradle.kts index 407f27e9d..101bc900a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.core") version "1.0.0-SNAPSHOT" + id("io.papermc.paperweight.core") version "1.0.0-LOCAL-SNAPSHOT" } val mcVersion = providers.gradleProperty("mcVersion") diff --git a/patches/api-unmapped/0171-Annotation-Test-changes.patch b/patches/api/0171-Annotation-Test-changes.patch similarity index 100% rename from patches/api-unmapped/0171-Annotation-Test-changes.patch rename to patches/api/0171-Annotation-Test-changes.patch diff --git a/patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch b/patches/api/0172-Entity-getEntitySpawnReason.patch similarity index 78% rename from patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch rename to patches/api/0172-Entity-getEntitySpawnReason.patch index 080a5c318..0a38cac83 100644 --- a/patches/api-unmapped/0172-Entity-getEntitySpawnReason.patch +++ b/patches/api/0172-Entity-getEntitySpawnReason.patch @@ -10,13 +10,13 @@ persistenting Living Entity, SPAWNER for spawners, or DEFAULT since data was not stored. diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 4b1f9b0ad5dc9ad6f33fddafc376b6f983a556ef..5b382091b1466b25ad42325d5808785a8e948552 100644 +index 92927b9a90b2a4497dd572f6f752c40cf35dd8b8..4a6d58ef68b782291b4d26a8515be326481f5209 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -708,5 +708,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @NotNull - Chunk getChunk(); +@@ -711,5 +711,11 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + // TODO remove impl here + return getLocation().getChunk(); + } + + /** + * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. diff --git a/patches/api-unmapped/0173-Add-GS4-Query-event.patch b/patches/api/0173-Add-GS4-Query-event.patch similarity index 100% rename from patches/api-unmapped/0173-Add-GS4-Query-event.patch rename to patches/api/0173-Add-GS4-Query-event.patch diff --git a/patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch b/patches/api/0174-Add-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/api-unmapped/0174-Add-PlayerPostRespawnEvent.patch rename to patches/api/0174-Add-PlayerPostRespawnEvent.patch diff --git a/patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch b/patches/removed/1.17/0334-Allow-Saving-of-Oversized-Chunks.patch similarity index 98% rename from patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch rename to patches/removed/1.17/0334-Allow-Saving-of-Oversized-Chunks.patch index c23cb450e..2c2f7bdb5 100644 --- a/patches/server-remapped/0334-Allow-Saving-of-Oversized-Chunks.patch +++ b/patches/removed/1.17/0334-Allow-Saving-of-Oversized-Chunks.patch @@ -3,6 +3,8 @@ From: Aikar Date: Fri, 15 Feb 2019 01:08:19 -0500 Subject: [PATCH] Allow Saving of Oversized Chunks +Note 1.17 update: With 1.17, Entities are no longer stored in chunk slices, so this needs updating!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + The Minecraft World Region File format has a hard cap of 1MB per chunk. This is due to the fact that the header of the file format only allocates a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. diff --git a/patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch deleted file mode 100644 index 83303e9b3..000000000 --- a/patches/server-remapped/0331-Handle-Oversized-Tile-Entities-in-chunks.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 05:00:57 -0400 -Subject: [PATCH] Handle Oversized Tile Entities in chunks - -Splits out Extra Packets if too many TE's are encountered to prevent -creating too large of a packet to sed. - -Co authored by Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -index b7d303b5f51a35504888933efef74564fa01e59d..b587f774c8f88f2a1c3ea489f7e4fe0bbdeb5a41 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java -@@ -34,7 +34,15 @@ public class ClientboundLevelChunkPacket implements Packet extraPackets = new java.util.ArrayList<>(); -+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); - -+ @Override -+ public java.util.List getExtraPackets() { -+ return extraPackets; -+ } -+ // Paper end - public ClientboundLevelChunkPacket(LevelChunk chunk, int includedSectionsMask) { - ChunkPos chunkcoordintpair = chunk.getPos(); - -@@ -61,6 +69,7 @@ public class ClientboundLevelChunkPacket implements Packet> 4; - - if (this.isFullChunk() || (includedSectionsMask & 1 << j) != 0) { -+ // Paper start - improve oversized chunk data packet handling -+ if (++totalTileEntities > TE_LIMIT) { -+ ClientboundBlockEntityDataPacket updatePacket = tileentity.getUpdatePacket(); -+ if (updatePacket != null) { -+ this.extraPackets.add(updatePacket); -+ continue; -+ } -+ } -+ // Paper end - CompoundTag nbttagcompound = tileentity.getUpdateTag(); - if (tileentity instanceof SkullBlockEntity) { SkullBlockEntity.sanitizeTileEntityUUID(nbttagcompound); } // Paper - diff --git a/patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch deleted file mode 100644 index 8f0ddb740..000000000 --- a/patches/server-remapped/0339-Update-entity-Metadata-for-all-tracked-players.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AgentTroll -Date: Fri, 22 Mar 2019 22:24:03 -0700 -Subject: [PATCH] Update entity Metadata for all tracked players - - -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 49c71b21b6b88bc41ca6ddf4c76186ce522ee456..1609ab94c86e964421f996d4d46aef30f8b8e696 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -420,6 +420,12 @@ public class ServerEntity { - return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); - } - -+ // Paper start - Add broadcast method -+ void broadcast(Packet packet) { -+ this.getPacketConsumer().accept(packet); -+ } -+ // Paper end -+ - private void broadcastAndSend(Packet packet) { - this.broadcast.accept(packet); - if (this.entity instanceof ServerPlayer) { -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index d6d8d83bc16572474d56a278dd119eacc2c52476..ed4129a51351aff16455960d71a0add1b8209c02 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2286,7 +2286,14 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { - - if (event.isCancelled() || this.player.inventory.getSelected() == null || this.player.inventory.getSelected().getItem() != origItem) { - // Refresh the current entity metadata -- this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); -+ // Paper start - update entity for all players -+ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); -+ if (entity.tracker != null) { -+ entity.tracker.broadcast(packet1); -+ } else { -+ this.send(packet1); -+ } -+ // Paper end - } - - if (event.isCancelled()) { diff --git a/patches/server-remapped/0640-Fire-event-on-GS4-query.patch b/patches/server-remapped/0640-Fire-event-on-GS4-query.patch deleted file mode 100644 index a893ed5f5..000000000 --- a/patches/server-remapped/0640-Fire-event-on-GS4-query.patch +++ /dev/null @@ -1,265 +0,0 @@ -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 d10de580430d754204b36de809376538a14591e6..f6f0539a8e6edbeb1c412cee753a282b24a38046 100644 ---- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -+++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java -@@ -18,15 +18,27 @@ public class NetworkDataOutputStream { - this.dataOutputStream.write(abyte, 0, abyte.length); - } - -+ public void writeString(String string) throws IOException { this.writeString(string); } // Paper - OBFHELPER - public void writeString(String s) throws IOException { - this.dataOutputStream.writeBytes(s); - 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 writeInt(int i) throws IOException { this.write(i); } // Paper - OBFHELPER - public void write(int i) throws IOException { - this.dataOutputStream.write(i); - } - -+ public void writeShort(short i) throws IOException { this.writeShort(i); } // Paper - OBFHELPER - public void writeShort(short short0) throws IOException { - this.dataOutputStream.writeShort(Short.reverseBytes(short0)); - } -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 170d047463154bd6851199f06fe343ccb1896213..5562a3caff328bb08857b4f06a79b1e52f390fdd 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java -@@ -16,6 +16,7 @@ import java.util.Random; - import javax.annotation.Nullable; - import net.minecraft.Util; - import net.minecraft.server.ServerInterface; -+import net.minecraft.server.dedicated.DedicatedServer; - import net.minecraft.server.rcon.NetworkDataOutputStream; - import net.minecraft.server.rcon.PktUtils; - import org.apache.logging.log4j.LogManager; -@@ -26,18 +27,18 @@ public class QueryThreadGs4 extends GenericThread { - private static final Logger LOGGER = LogManager.getLogger(); - private long lastChallengeCheck; - private final int port; -- private final int serverPort; -- private final int maxPlayers; -- private final String serverName; -- private final String worldName; -+ private final int serverPort; private final int getServerPort() { return this.serverPort; } // Paper - OBFHELPER -+ private final int maxPlayers; private final int getMaxPlayers() { return this.maxPlayers; } // Paper - OBFHELPER -+ private final String serverName; private final String getMotd() { return this.serverName; } // Paper - OBFHELPER -+ private final String worldName; private final String getWorldName() { return this.worldName; } // Paper - OBFHELPER - private DatagramSocket socket; - private final byte[] buffer = new byte[1460]; -- private String hostIp; -+ private String hostIp; public final String getServerHost() { return this.hostIp; } // Paper - OBFHELPER - private String serverIp; - private final Map validChallenges; -- private final NetworkDataOutputStream rulesResponse; -+ private final NetworkDataOutputStream rulesResponse; private final NetworkDataOutputStream getCachedFullResponse() { return this.rulesResponse; } // Paper - OBFHELPER - private long lastRulesResponse; -- private final ServerInterface serverInterface; -+ private final ServerInterface serverInterface; private final ServerInterface getServer() { return this.serverInterface; } // Paper - OBFHELPER - - private QueryThreadGs4(ServerInterface server, int queryPort) { - super("Query Listener"); -@@ -107,13 +108,39 @@ public class QueryThreadGs4 extends GenericThread { - - remotestatusreply.write((int) 0); - remotestatusreply.writeBytes(this.getIdentBytes(packet.getSocketAddress())); -- remotestatusreply.writeString(this.serverName); -+ /* Paper start - GS4 Query event -+ remotestatusreply.a(this.i); -+ remotestatusreply.a("SMP"); -+ remotestatusreply.a(this.j); -+ remotestatusreply.a(Integer.toString(this.r.getPlayerCount())); -+ remotestatusreply.a(Integer.toString(this.h)); -+ remotestatusreply.a((short) this.g); -+ remotestatusreply.a(this.m); -+ */ -+ 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.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .gameVersion(this.getServer().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(); -+ remotestatusreply.writeString(queryResponse.getMotd()); - remotestatusreply.writeString("SMP"); -- remotestatusreply.writeString(this.worldName); -- remotestatusreply.writeString(Integer.toString(this.serverInterface.getPlayerCount())); -- remotestatusreply.writeString(Integer.toString(this.maxPlayers)); -- remotestatusreply.writeShort((short) this.serverPort); -- remotestatusreply.writeString(this.hostIp); -+ 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.sendTo(remotestatusreply.toByteArray(), packet); - QueryThreadGs4.LOGGER.debug("Status [{}]", socketaddress); - } -@@ -150,41 +177,115 @@ public class QueryThreadGs4 extends GenericThread { - this.rulesResponse.writeString("splitnum"); - this.rulesResponse.write((int) 128); - this.rulesResponse.write((int) 0); -- this.rulesResponse.writeString("hostname"); -- this.rulesResponse.writeString(this.serverName); -- 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("plugins"); -- this.rulesResponse.writeString(this.serverInterface.getPluginNames()); -- this.rulesResponse.writeString("map"); -- this.rulesResponse.writeString(this.worldName); -- this.rulesResponse.writeString("numplayers"); -- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); -- this.rulesResponse.writeString("maxplayers"); -- this.rulesResponse.writeString("" + this.maxPlayers); -- this.rulesResponse.writeString("hostport"); -- this.rulesResponse.writeString("" + this.serverPort); -- this.rulesResponse.writeString("hostip"); -- this.rulesResponse.writeString(this.hostIp); -- this.rulesResponse.write((int) 0); -- this.rulesResponse.write((int) 1); -- this.rulesResponse.writeString("player_"); -- this.rulesResponse.write((int) 0); -- String[] astring = this.serverInterface.getPlayerNames(); -+ /* Paper start - GS4 Query event -+ this.p.a("hostname"); -+ this.p.a(this.i); -+ this.p.a("gametype"); -+ this.p.a("SMP"); -+ this.p.a("game_id"); -+ this.p.a("MINECRAFT"); -+ this.p.a("version"); -+ this.p.a(this.r.getVersion()); -+ this.p.a("plugins"); -+ this.p.a(this.r.getPlugins()); -+ this.p.a("map"); -+ this.p.a(this.j); -+ this.p.a("numplayers"); -+ this.p.a("" + this.r.getPlayerCount()); -+ this.p.a("maxplayers"); -+ this.p.a("" + this.h); -+ this.p.a("hostport"); -+ this.p.a("" + this.g); -+ this.p.a("hostip"); -+ this.p.a(this.m); -+ this.p.a((int) 0); -+ this.p.a((int) 1); -+ this.p.a("player_"); -+ this.p.a((int) 0); -+ String[] astring = this.r.getPlayers(); - String[] astring1 = astring; - int j = astring.length; - - for (int k = 0; k < j; ++k) { - String s = astring1[k]; - -- this.rulesResponse.writeString(s); -+ this.p.a(s); - } - -- this.rulesResponse.write((int) 0); -+ this.p.a((int) 0); -+ */ -+ // Pack plugins -+ java.util.List 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.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .plugins(plugins) -+ .players(this.getServer().getPlayerNames()) -+ .gameVersion(this.getServer().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.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(": "); -+ 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.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.rulesResponse.toByteArray(); - } - } diff --git a/patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch similarity index 51% rename from patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch rename to patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch index 0dc4b2e08..a50c8d9c5 100644 --- a/patches/server-remapped/0330-Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ b/patches/server/0306-Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -28,26 +28,10 @@ and then catch exceptions and close if they fire. Part of this commit was authored by: Spottedleaf diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed0b562c1b 100644 +index 9f0537799a3cae43fb120056b8fe805a4883cc4d..5897bdb4d1372fa3d7bdc482d02f0a54d8767bda 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java -@@ -25,8 +25,15 @@ import net.minecraft.network.chat.Component; - import net.minecraft.network.chat.TranslatableComponent; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.PacketFlow; -+import net.minecraft.network.protocol.game.ClientboundBossEventPacket; -+import net.minecraft.network.protocol.game.ClientboundChatPacket; -+import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; - import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; -+import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket; -+import net.minecraft.network.protocol.game.ClientboundSetTitlesPacket; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.RunningOnDifferentThreadException; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.server.network.ServerLoginPacketListenerImpl; - import net.minecraft.util.LazyLoadedValue; -@@ -75,6 +82,10 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -87,6 +87,10 @@ public class Connection extends SimpleChannelInboundHandler> { public int protocolVersion; public java.net.InetSocketAddress virtualHost; private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); @@ -58,7 +42,7 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed // Paper end public Connection(PacketFlow side) { -@@ -98,6 +109,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -110,6 +114,7 @@ public class Connection extends SimpleChannelInboundHandler> { } public void setProtocol(ConnectionProtocol state) { @@ -66,12 +50,12 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state); this.channel.config().setAutoRead(true); Connection.LOGGER.debug("Enabled auto read"); -@@ -168,19 +180,84 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -186,19 +191,87 @@ public class Connection extends SimpleChannelInboundHandler> { Validate.notNull(listener, "packetListener", new Object[0]); this.packetListener = listener; } + // Paper start -+ public ServerPlayer getPlayer() { ++ public net.minecraft.server.level.ServerPlayer getPlayer() { + if (packetListener instanceof ServerGamePacketListenerImpl) { + return ((ServerGamePacketListenerImpl) packetListener).player; + } else { @@ -101,11 +85,15 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + // Paper start + private static boolean canSendImmediate(Connection networkManager, Packet packet) { + return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY || -+ packet instanceof ClientboundKeepAlivePacket || -+ packet instanceof ClientboundChatPacket || -+ packet instanceof ClientboundCommandSuggestionsPacket || -+ packet instanceof ClientboundSetTitlesPacket || -+ packet instanceof ClientboundBossEventPacket; ++ packet instanceof net.minecraft.network.protocol.game.ClientboundKeepAlivePacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundChatPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundClearTitlesPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket; + } + // Paper end + } @@ -128,10 +116,10 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + } + packet.onPacketDispatch(getPlayer()); + if (connected && (InnerUtil.canSendImmediate(this, packet) || ( -+ MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && ++ net.minecraft.server.MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && + (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) + ))) { -+ this.dispatchPacket(packet, callback); ++ this.send(packet, callback); + return; } + // write the packets to the queue, then flush - antixray hooks there already @@ -142,106 +130,67 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + } else { + java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); + packets.add(new Connection.PacketHolder(packet, null)); // delay the future listener until the end of the extra packets -+ + + for (int i = 0, len = extraPackets.size(); i < len;) { + Packet extra = extraPackets.get(i); + boolean end = ++i == len; + packets.add(new Connection.PacketHolder(extra, end ? callback : null)); // append listener to the end + } - + this.queue.addAll(packets); // atomic + } -+ this.sendPacketQueue(); ++ this.flushQueue(); + // Paper end } - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.sendPacket(packet, genericFutureListener); } // Paper - OBFHELPER -@@ -194,54 +271,119 @@ public class Connection extends SimpleChannelInboundHandler> { - this.channel.config().setAutoRead(false); + private void sendPacket(Packet packet, @Nullable GenericFutureListener> callback) { +@@ -226,33 +299,79 @@ public class Connection extends SimpleChannelInboundHandler> { + this.setProtocol(enumprotocol); } -+ ServerPlayer player = getPlayer(); // Paper - if (this.channel.eventLoop().inEventLoop()) { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - - ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - - if (callback != null) { - channelfuture.addListener(callback); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - } else { - this.channel.eventLoop().execute(() -> { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } - -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); - ++ // Paper start ++ net.minecraft.server.level.ServerPlayer player = getPlayer(); ++ if (!isConnected()) { ++ packet.onPacketDispatchFinish(player, null); ++ return; ++ } + - if (callback != null) { - channelfuture1.addListener(callback); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end ++ try { ++ // Paper end + ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ disconnect(new TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - }); + if (genericfuturelistener != null) { + channelfuture.addListener(genericfuturelistener); } ++ // Paper start ++ if (packet.hasFinishListener()) { ++ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); ++ } ++ // Paper end + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ // Paper start ++ } catch (Exception e) { ++ LOGGER.error("NetworkException: " + player, e); ++ disconnect(new net.minecraft.network.chat.TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage())); ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + } + + private ConnectionProtocol getCurrentProtocol() { + return (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get(); } -- private void sendPacketQueue() { this.flushQueue(); } // Paper - OBFHELPER - private void flushQueue() { - if (this.channel != null && this.channel.isOpen()) { - Queue queue = this.queue; - + // Paper start - rewrite this to be safer if ran off main thread -+ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean -+ private boolean p() { // void -> boolean ++ private boolean flushQueue() { // void -> boolean + if (!isConnected()) { + return true; + } -+ if (MCUtil.isMainThread()) { ++ if (net.minecraft.server.MCUtil.isMainThread()) { + return processQueue(); + } else if (isPending) { + // Should only happen during login/status stages @@ -262,19 +211,19 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + // But if we are not on main due to login/status, the parent is synchronized on packetQueue + java.util.Iterator iterator = this.queue.iterator(); + while (iterator.hasNext()) { -+ Connection.PacketHolder queued = iterator.next(); // poll -> peek ++ PacketHolder queued = iterator.next(); // poll -> peek + + // Fix NPE (Spigot bug caused by handleDisconnection()) + if (queued == null) { + return true; + } -+ Packet packet = queued.getPacket(); ++ Packet packet = queued.packet; + if (!packet.isReady()) { + return false; + } else { + iterator.remove(); -+ this.dispatchPacket(packet, queued.getGenericFutureListener()); ++ this.sendPacket(packet, queued.listener); } } + return true; @@ -282,26 +231,23 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed + // Paper end public void tick() { -- this.flushQueue(); -+ this.p(); - if (this.packetListener instanceof ServerLoginPacketListenerImpl) { - ((ServerLoginPacketListenerImpl) this.packetListener).tick(); - } -@@ -271,9 +413,21 @@ public class Connection extends SimpleChannelInboundHandler> { + this.flushQueue(); +@@ -289,9 +408,22 @@ public class Connection extends SimpleChannelInboundHandler> { return this.address; } + // Paper start + public void clearPacketQueue() { -+ ServerPlayer player = getPlayer(); ++ net.minecraft.server.level.ServerPlayer player = getPlayer(); + queue.forEach(queuedPacket -> { -+ Packet packet = queuedPacket.getPacket(); ++ Packet packet = queuedPacket.packet; + if (packet.hasFinishListener()) { + packet.onPacketDispatchFinish(player, null); + } + }); + queue.clear(); -+ } // Paper end ++ } ++ // Paper end public void disconnect(Component disconnectReason) { // Spigot Start this.preparing = false; @@ -309,18 +255,18 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed // Spigot End if (this.channel.isOpen()) { this.channel.close(); // We can't wait as this may be called from an event loop. -@@ -341,7 +495,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -409,7 +541,7 @@ public class Connection extends SimpleChannelInboundHandler> { public void handleDisconnection() { if (this.channel != null && !this.channel.isOpen()) { if (this.disconnectionHandled) { - Connection.LOGGER.warn("handleDisconnection() called twice"); -+ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message ++ //Connection.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message } else { this.disconnectionHandled = true; if (this.getDisconnectedReason() != null) { -@@ -349,7 +503,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -417,7 +549,7 @@ public class Connection extends SimpleChannelInboundHandler> { } else if (this.getPacketListener() != null) { - this.getPacketListener().a(new TranslatableComponent("multiplayer.disconnect.generic")); + this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic")); } - this.queue.clear(); // Free up packet queue. + clearPacketQueue(); // Paper @@ -328,67 +274,26 @@ index 3247ec5d6cf329ba0b7e6d5a6c3294dec2e34db4..fc63df21aecd4721efdb45d4744666ed final PacketListener packetListener = this.getPacketListener(); if (packetListener instanceof ServerGamePacketListenerImpl) { diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 9914a82ba0ec146ab13fe94c4dbf0ebf64926536..22db5d0d2cc33498ca40162c66aa3b5fbf2f569f 100644 +index 74bfe0d3942259c45702b099efdc4e101a4e3022..e8fcd56906d26f6dc87959e32c4c7c78cfea9658 100644 --- a/src/main/java/net/minecraft/network/protocol/Packet.java +++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -1,5 +1,6 @@ - package net.minecraft.network.protocol; - -+import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.PacketListener; -@@ -13,6 +14,20 @@ public interface Packet { +@@ -9,6 +9,19 @@ public interface Packet { void handle(T listener); // Paper start -+ + /** + * @param player Null if not at PLAY stage yet + */ -+ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} ++ default void onPacketDispatch(@javax.annotation.Nullable net.minecraft.server.level.ServerPlayer player) {} + + /** + * @param player Null if not at PLAY stage yet + * @param future Can be null if packet was cancelled + */ -+ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} ++ default void onPacketDispatchFinish(@javax.annotation.Nullable net.minecraft.server.level.ServerPlayer player, @javax.annotation.Nullable io.netty.channel.ChannelFuture future) {} + default boolean hasFinishListener() { return false; } + default boolean isReady() { return true; } + default java.util.List getExtraPackets() { return null; } - default boolean packetTooLarge(NetworkManager manager) { + default boolean packetTooLarge(net.minecraft.network.Connection manager) { return false; } -diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -index 6cb51a4fe3c11f53fbb556ce6b0d64b735254d51..d46910cfdc0aef046a0c79731a85d381953c328a 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java -@@ -16,6 +16,7 @@ import io.netty.channel.epoll.EpollServerSocketChannel; - import io.netty.channel.nio.NioEventLoopGroup; - import io.netty.channel.socket.ServerSocketChannel; - import io.netty.channel.socket.nio.NioServerSocketChannel; -+import io.netty.handler.flush.FlushConsolidationHandler; // Paper - import io.netty.handler.timeout.ReadTimeoutHandler; - import java.io.IOException; - import java.net.InetAddress; -@@ -54,10 +55,12 @@ public class ServerConnectionListener { - private final List connections = Collections.synchronizedList(Lists.newArrayList()); - // Paper start - prevent blocking on adding a new network manager while the server is ticking - private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - private void addPending() { - Connection manager = null; - while ((manager = pending.poll()) != null) { - connections.add(manager); -+ manager.isPending = false; - } - } - // Paper end -@@ -92,6 +95,7 @@ public class ServerConnectionListener { - ; - } - -+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper - channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this)).addLast("splitter", new Varint21FrameDecoder()).addLast("decoder", new PacketDecoder(PacketFlow.SERVERBOUND)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(PacketFlow.CLIENTBOUND)); - int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); - Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); diff --git a/patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch new file mode 100644 index 000000000..f02716ec0 --- /dev/null +++ b/patches/server/0307-Handle-Oversized-Tile-Entities-in-chunks.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 6 May 2020 05:00:57 -0400 +Subject: [PATCH] Handle Oversized Tile Entities in chunks + +Splits out Extra Packets if too many TE's are encountered to prevent +creating too large of a packet to sed. + +Co authored by Spottedleaf + +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 96626835fee3c0fdb452acacdc9f737ad90c08de..c28879f32b004f36ff746ea2274f91ddd9501e71 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -27,6 +27,15 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; ++ // Paper start ++ private final java.util.List extraPackets = new java.util.ArrayList<>(); ++ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); ++ ++ @Override ++ public java.util.List getExtraPackets() { ++ return extraPackets; ++ } ++ // Paper end + + public ClientboundLevelChunkPacket(LevelChunk chunk) { + ChunkPos chunkPos = chunk.getPos(); +@@ -44,9 +53,19 @@ public class ClientboundLevelChunkPacket implements Packet entry2 : chunk.getBlockEntities().entrySet()) { + BlockEntity blockEntity = entry2.getValue(); ++ // Paper start - improve oversized chunk data packet handling ++ if (++totalTileEntities > TE_LIMIT) { ++ ClientboundBlockEntityDataPacket updatePacket = blockEntity.getUpdatePacket(); ++ if (updatePacket != null) { ++ this.extraPackets.add(updatePacket); ++ continue; ++ } ++ } ++ // Paper end + CompoundTag compoundTag = blockEntity.getUpdateTag(); + if (blockEntity instanceof net.minecraft.world.level.block.entity.SkullBlockEntity) { net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeTileEntityUUID(compoundTag); } // Paper + this.blockEntitiesTags.add(compoundTag); diff --git a/patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 62% rename from patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch index 1209aa99e..5e2db5202 100644 --- a/patches/server-remapped/0332-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ b/patches/server/0308-MC-145260-Fix-Whitelist-On-Off-inconsistency.patch @@ -11,10 +11,10 @@ everything to the Whitelist object. https://github.com/PaperMC/Paper/issues/1880 diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556e5c19cdd 100644 +index 0df68991eb2ef3dabe779f42c2bf44846ac0d862..4ae234a107d16bc71425af5f2729c428f79e3db7 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -55,6 +55,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; +@@ -62,6 +62,7 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; import net.minecraft.resources.ResourceKey; @@ -22,24 +22,15 @@ index 5b71b487836cdd2ddc75b2039f4dc0177719d345..8d133d3c825f7747081de99ee67d4556 import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerAdvancements; import net.minecraft.server.ServerScoreboard; -@@ -1012,9 +1013,9 @@ public abstract class PlayerList { +@@ -996,9 +997,9 @@ public abstract class PlayerList { } public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { boolean isOp = this.ops.contains(gameprofile); - boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); -+ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); ++ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); // Paper - use isUsingWhitelist() final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); +- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); // Paper - use isUsingWhitelist() event.callEvent(); if (!event.isWhitelisted()) { if (loginEvent != null) { -@@ -1062,7 +1063,7 @@ public abstract class PlayerList { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { -- this.savePlayerFile((EntityPlayer) this.players.get(i)); -+ this.save((ServerPlayer) this.players.get(i)); - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main diff --git a/patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch b/patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch similarity index 85% rename from patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch rename to patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch index eb4f5ff56..2a8b7a4ce 100644 --- a/patches/server-remapped/0333-Set-Zombie-last-tick-at-start-of-drowning-process.patch +++ b/patches/server/0309-Set-Zombie-last-tick-at-start-of-drowning-process.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Set Zombie last tick at start of drowning process Fixes GH-1887 diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index ad4eeb15771750193a28116117992270c72a3644..6fecf4188fc0247143edc688c03e645376960687 100644 +index c60d9775230b2ff554eeb38136f8e7c32c47d8cf..ee17cba501e0cc4822bd1278d18b561c77fe9674 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -220,6 +220,7 @@ public class Zombie extends Monster { +@@ -225,6 +225,7 @@ public class Zombie extends Monster { ++this.inWaterTime; if (this.inWaterTime >= 600) { this.startUnderWaterConversion(300); diff --git a/patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 82% rename from patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch index 5fcbc4df8..d925e9aaa 100644 --- a/patches/server-remapped/0335-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch +++ b/patches/server/0310-Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 8d133d3c825f7747081de99ee67d4556e5c19cdd..728eaadd3dc619e414ec30feb38c7d4a84b2e539 100644 +index 4ae234a107d16bc71425af5f2729c428f79e3db7..ea336bdf2f15aabe74de82ef6c29b93573254e31 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1131,6 +1131,7 @@ public abstract class PlayerList { +@@ -1115,6 +1115,7 @@ public abstract class PlayerList { } public void setUsingWhiteList(boolean whitelistEnabled) { diff --git a/patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch similarity index 70% rename from patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch rename to patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch index c6e42c264..bb182f5de 100644 --- a/patches/server-remapped/0337-Use-proper-max-length-when-serialising-BungeeCord-te.patch +++ b/patches/server/0311-Use-proper-max-length-when-serialising-BungeeCord-te.patch @@ -6,26 +6,26 @@ Subject: [PATCH] Use proper max length when serialising BungeeCord text diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -index f13da9e7d014bc00fbabf0a495b548bba2f59468..002a6c7933f64405707d7d34d3e5c17584539623 100644 +index a64780b4b49d01322d8f755ff540a9622c89e983..26a229f7aa3f4425ed572e2d50730b4e978bf33e 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java -@@ -9,7 +9,7 @@ import net.minecraft.network.chat.Component; +@@ -8,7 +8,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; public class ClientboundChatPacket implements Packet { - + private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper - private Component message; + private final Component message; public net.kyori.adventure.text.Component adventure$message; // Paper public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot -@@ -43,9 +43,9 @@ public class ClientboundChatPacket implements Packet { - //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below +@@ -39,9 +39,9 @@ public class ClientboundChatPacket implements Packet { + // buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below // Paper start - don't nest if we don't need to so that we can preserve formatting if (this.components.length == 1) { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); + buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length } else { -- buf.writeByteArray(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); + buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length } // Paper end diff --git a/patches/server-remapped/0338-Entity-getEntitySpawnReason.patch b/patches/server/0312-Entity-getEntitySpawnReason.patch similarity index 67% rename from patches/server-remapped/0338-Entity-getEntitySpawnReason.patch rename to patches/server/0312-Entity-getEntitySpawnReason.patch index 18095e343..90d47b684 100644 --- a/patches/server-remapped/0338-Entity-getEntitySpawnReason.patch +++ b/patches/server/0312-Entity-getEntitySpawnReason.patch @@ -10,22 +10,22 @@ persistenting Living Entity, SPAWNER for spawners, or DEFAULT since data was not stored. diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 2ab221e5315dde4e556ee49a6962ae0091ccf616..d03b4f97102dfb88927a94ee5a5d397ac493eaa1 100644 +index 731c8e38c8daf04fee40a5ccfb0715b20f4d890f..940e6587125df1f203cdeeefc31658635badea81 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -1035,6 +1035,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl +@@ -1093,6 +1093,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl // CraftBukkit start private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot + if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper - // Paper start - if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); + if (entity.isRemoved()) { + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac2166b44576 100644 +index ea336bdf2f15aabe74de82ef6c29b93573254e31..da3100d6577166e222164c174b28020541dd8e3a 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -331,7 +331,7 @@ public abstract class PlayerList { +@@ -335,7 +335,7 @@ public abstract class PlayerList { // CraftBukkit start ServerLevel finalWorldServer = worldserver1; Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { @@ -35,10 +35,10 @@ index 728eaadd3dc619e414ec30feb38c7d4a84b2e539..4d813b6556030354f51c1ee5f18eac21 }); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f311e197f6e 100644 +index 8df9bd656374d0b43af378c61c1df7b951085b58..fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -63,6 +63,8 @@ import net.minecraft.world.InteractionHand; +@@ -67,6 +67,8 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.Nameable; import net.minecraft.world.damagesource.DamageSource; @@ -47,30 +47,30 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31 import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.Boat; -@@ -157,6 +159,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -166,6 +168,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } } }; - public List entitySlice = null; + public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper end public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -@@ -1673,6 +1676,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - tag.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - tag.put("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); +@@ -1841,6 +1844,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + nbt.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); + nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); } + if (spawnReason != null) { -+ tag.putString("Paper.SpawnReason", spawnReason.name()); ++ nbt.putString("Paper.SpawnReason", spawnReason.name()); + } // Save entity's from mob spawner status if (spawnedViaMobSpawner) { - tag.putBoolean("Paper.FromMobSpawner", true); -@@ -1811,6 +1817,26 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s + nbt.putBoolean("Paper.FromMobSpawner", true); +@@ -1983,6 +1989,26 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ if (tag.contains("Paper.SpawnReason")) { -+ String spawnReasonName = tag.getString("Paper.SpawnReason"); + spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ if (nbt.contains("Paper.SpawnReason")) { ++ String spawnReasonName = nbt.getString("Paper.SpawnReason"); + try { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); + } catch (Exception ignored) { @@ -81,7 +81,7 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31 + if (spawnedViaMobSpawner) { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; + } else if (this instanceof Mob && (this instanceof Animal || this instanceof AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) { -+ if (!tag.getBoolean("PersistenceRequired")) { ++ if (!nbt.getBoolean("PersistenceRequired")) { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; + } + } @@ -93,22 +93,22 @@ index d106118dbf4fb270f8526e40a767dd4c563a333f..6faac8773136412ca129dfa884178f31 } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index 1ce675d0d24ceb5724f5ac2d8f671e38f2735f74..3a7aec9bd2f3fd1b4a1981fb6a8c64b69e4875f8 100644 +index 12a78685848b7fd945a472902d8200ea1d50b9ec..3aadcb472ab808ee981065ddfa86be6cbf38c8d9 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java -@@ -183,6 +183,7 @@ public abstract class BaseSpawner { - // Spigot End - } +@@ -167,6 +167,7 @@ public abstract class BaseSpawner { + // Spigot End + } entity.spawnedViaMobSpawner = true; // Paper -+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper - flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { ++ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper + flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index e1bbaf620f3ed2a6cb9ce8007a78c4cee47b653e..7ad4fb57af32cc1b8278688381e1b058ed8437db 100644 +index c381ea321b0fb3498e3f101ee059ac7d42aa029a..33bc56eba4229d844e3af6ff4662d96450e929af 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -1106,5 +1106,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1163,5 +1163,10 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { public boolean fromMobSpawner() { return getHandle().spawnedViaMobSpawner; } diff --git a/patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch new file mode 100644 index 000000000..5b0902aa3 --- /dev/null +++ b/patches/server/0313-Update-entity-Metadata-for-all-tracked-players.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AgentTroll +Date: Fri, 22 Mar 2019 22:24:03 -0700 +Subject: [PATCH] Update entity Metadata for all tracked players + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 8311d921ded1c81a1f561dc13db2010d2b7ce5d6..95ac30f56a9268f14d2518974c5a52e08f40ea18 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1281,6 +1281,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + ++ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); + playerchunkmap_entitytracker.updatePlayers(this.level.players()); + if (entity instanceof ServerPlayer) { +@@ -1323,7 +1324,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunkmap_entitytracker1 != null) { + playerchunkmap_entitytracker1.broadcastRemoved(); + } +- ++ entity.tracker = null; // Paper - We're no longer tracked + } + + protected void tick() { +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index ad9bbda31a4cdb306ca40f2b99e4b815c4f136bd..28afe2f238ded241acf77c3272a44068646b9133 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -392,6 +392,12 @@ public class ServerEntity { + return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); + } + ++ // Paper start - Add broadcast method ++ void broadcast(Packet packet) { ++ this.broadcast.accept(packet); ++ } ++ // Paper end ++ + private void broadcastAndSend(Packet packet) { + this.broadcast.accept(packet); + if (this.entity instanceof ServerPlayer) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index defebf7b45e4f006fa7e575b5dbd01ac1e231d5a..6c4266d847b1181a055fa425d5734032dadabf93 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -2289,7 +2289,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + if (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem) { + // Refresh the current entity metadata +- ServerGamePacketListenerImpl.this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); ++ // Paper start - update entity for all players ++ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); ++ if (entity.tracker != null) { ++ entity.tracker.broadcast(packet1); ++ } else { ++ ServerGamePacketListenerImpl.this.send(packet1); ++ } ++ // Paper end + } + + if (event.isCancelled()) { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index fcd3e6bfb4b1d0aefcb34eaec1212b08498dd5af..a5159198003e43ce272ae73941d2be47d50eedc9 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -300,6 +300,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; + public org.bukkit.Location origin; // Paper ++ public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper - fast access to tracker + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; diff --git a/patches/server/0314-Fire-event-on-GS4-query.patch b/patches/server/0314-Fire-event-on-GS4-query.patch new file mode 100644 index 000000000..7e02bbbb3 --- /dev/null +++ b/patches/server/0314-Fire-event-on-GS4-query.patch @@ -0,0 +1,209 @@ +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(); + } + } diff --git a/patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch b/patches/server/0315-Implement-PlayerPostRespawnEvent.patch similarity index 82% rename from patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch rename to patches/server/0315-Implement-PlayerPostRespawnEvent.patch index dbfcbf2e3..f1e3ff7b6 100644 --- a/patches/server-remapped/0340-Implement-PlayerPostRespawnEvent.patch +++ b/patches/server/0315-Implement-PlayerPostRespawnEvent.patch @@ -5,11 +5,11 @@ Subject: [PATCH] Implement PlayerPostRespawnEvent diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f4bf6dba7 100644 +index da3100d6577166e222164c174b28020541dd8e3a..c7956664427ca97544d1b47992a62c95d2fc9690 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -737,9 +737,14 @@ public abstract class PlayerList { - // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed +@@ -715,9 +715,14 @@ public abstract class PlayerList { + boolean flag2 = false; + // Paper start @@ -24,7 +24,7 @@ index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); if (worldserver1 != null) { Optional optional; -@@ -790,6 +795,7 @@ public abstract class PlayerList { +@@ -768,6 +773,7 @@ public abstract class PlayerList { location = respawnEvent.getRespawnLocation(); if (!flag) entityplayer.reset(); // SPIGOT-4785 @@ -32,7 +32,7 @@ index 4d813b6556030354f51c1ee5f18eac2166b44576..7412765020854caabd32fb6f4fffcf7f } else { location.setWorld(worldserver.getWorld()); } -@@ -847,6 +853,13 @@ public abstract class PlayerList { +@@ -825,6 +831,13 @@ public abstract class PlayerList { if (entityplayer.connection.isDisconnected()) { this.save(entityplayer); } diff --git a/settings.gradle.kts b/settings.gradle.kts index 54bb95749..302bcb31a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,6 @@ pluginManagement { repositories { + mavenLocal() gradlePluginPortal() maven("https://wav.jfrog.io/artifactory/repo/") }