From 64cfcf3e4b16148cdc352d58a29e3428715b1157 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sat, 23 May 2020 17:15:40 -0400 Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) Instead of using the entire world or player list, use the distance maps to only iterate players who are even seeing the chunk the packet is originating from. This will drastically cut down on packet sending cost for worlds with lots of players in them. Closes #3437 --- Spigot-Server-Patches/0004-MC-Utils.patch | 14 ++++++ ...-packets-to-nearby-locations-sounds-.patch | 44 +++++++++++++++++++ paper | 7 +++ 3 files changed, 65 insertions(+) create mode 100644 Spigot-Server-Patches/0531-Optimize-sending-packets-to-nearby-locations-sounds-.patch diff --git a/Spigot-Server-Patches/0004-MC-Utils.patch b/Spigot-Server-Patches/0004-MC-Utils.patch index 60e3b6295..7e5e65e5f 100644 --- a/Spigot-Server-Patches/0004-MC-Utils.patch +++ b/Spigot-Server-Patches/0004-MC-Utils.patch @@ -3004,6 +3004,20 @@ index 774a8f543424853be5fc8c0367d734ddf196d7f9..d5f5a51872dfabdbb828b6c20d61893a public void b(PacketDataSerializer packetdataserializer) { this.a(); packetdataserializer.writeByte(this.i); +diff --git a/src/main/java/net/minecraft/server/DimensionManager.java b/src/main/java/net/minecraft/server/DimensionManager.java +index 5724fe6e57d3671b4978aecaf217ac4c2e0d7f82..951db04bca7ee9021a5d4707f1907b2c8f734a92 100644 +--- a/src/main/java/net/minecraft/server/DimensionManager.java ++++ b/src/main/java/net/minecraft/server/DimensionManager.java +@@ -55,7 +55,9 @@ public class DimensionManager implements MinecraftSerializable { + return this.folder.isEmpty() ? file : new File(file, this.folder); + } + ++ public WorldServer world; // Paper - store ref to world this manager is for + public WorldProvider getWorldProvider(World world) { ++ if (this.world == null) this.world = (WorldServer) world; // Paper + return (WorldProvider) this.providerFactory.apply(world, this); + } + diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java index f4863852b04c5fa55b79acabe40ce59909b9bbbd..7e01f6a1807f9885a7f4b163ce6bb626d8786a9a 100644 --- a/src/main/java/net/minecraft/server/Entity.java diff --git a/Spigot-Server-Patches/0531-Optimize-sending-packets-to-nearby-locations-sounds-.patch b/Spigot-Server-Patches/0531-Optimize-sending-packets-to-nearby-locations-sounds-.patch new file mode 100644 index 000000000..fe9acb9b6 --- /dev/null +++ b/Spigot-Server-Patches/0531-Optimize-sending-packets-to-nearby-locations-sounds-.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 23 May 2020 17:03:41 -0400 +Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) + +Instead of using the entire world or player list, use the distance +maps to only iterate players who are even seeing the chunk the packet +is originating from. + +This will drastically cut down on packet sending cost for worlds with +lots of players in them. + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 9b726de6daeba42120f3a948fbdcf080d0e72917..cc5d75049d3553e0b01068e4e0c5677fe81f8387 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -1027,11 +1027,22 @@ public abstract class PlayerList { + world = (WorldServer) entityhuman.world; + } + +- List players1 = world == null ? players : world.players; +- for (int j = 0; j < players1.size(); ++j) { +- EntityHuman entity = players1.get(j); +- if (!(entity instanceof EntityPlayer)) continue; +- EntityPlayer entityplayer = (EntityPlayer) entity; ++ // Paper start ++ if (world == null && dimensionmanager != null) { ++ world = dimensionmanager.world; ++ } ++ if (world == null) { ++ LOGGER.error("Sending packet to invalid world" + entityhuman + " " + dimensionmanager + " - " + packet.getClass().getName(), new Throwable()); ++ return; // ??? shouldn't happen... ++ } ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = world.getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); ++ if (nearbyPlayers == null) { ++ return; ++ } ++ Object[] backingSet = nearbyPlayers.getBackingSet(); ++ for (Object object : backingSet) { ++ if (!(object instanceof EntityPlayer)) continue; ++ EntityPlayer entityplayer = (EntityPlayer) object; + // Paper end + + // CraftBukkit start - Test if player receiving packet can see the source of the packet diff --git a/paper b/paper index 19a673116..687c3813e 100755 --- a/paper +++ b/paper @@ -68,6 +68,13 @@ case "$1" in ls -la Paper-Server/target/paper*.jar ) || failed=1 ;; + "pc" | "paperclip") + ( + set -e + cd "$basedir" + scripts/paperclip.sh "$basedir" || exit 1 + ) || failed=1 + ;; "make") ( if [[ "$2" = "bacon" ]] ; then