b2d81e21c5
In previous MC versions, we had a rather simple internal scheduler for delayed tasks that would just keep pushing task back until desired tick was reached. The method it called to schedule the task changed behavior in 1.14, and now this scheduler is not working nowhere near what it was supposed to be doing. This was causing long delayed task to eat up CPU (In Oversleep for example) Rewrite this to just use the CraftScheduler for scheduling delayed tasks. Once this was fixed, it became quite clear the code that delayed ticket additions for chunks based on distance was clearly not right, as it was tested on the previous broken logic. So the ticket delay process has been vastly revamped to be even smarter. Chunks behind the player can load slower than the chunks in front of the player. We also can delay ticket adding until one of its neighbors has loaded, as this lets us get a smoother spiral out for the chunks (minus frustum intent). Additionally on frustum previous commit inadvertently broke frustum trying to fix an issue when the real fix lied elsewhere, so restore chunk priority so it works again.
73 lines
3.8 KiB
Diff
73 lines
3.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
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 6daca5c0ffd1d84f9a25cd106e8992a055dfb912..c03395ce824ec1305b3cabb63343922d32a02b85 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerList.java
|
|
@@ -1030,11 +1030,30 @@ public abstract class PlayerList {
|
|
world = (WorldServer) entityhuman.world;
|
|
}
|
|
|
|
- List<? extends EntityHuman> 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 || world.chunkProvider == 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...
|
|
+ }
|
|
+ PlayerChunkMap chunkMap = world.chunkMap;
|
|
+ Object[] backingSet;
|
|
+ if (chunkMap == null) {
|
|
+ // Really shouldn't happen...
|
|
+ backingSet = world.players.toArray();
|
|
+ } else {
|
|
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4);
|
|
+ if (nearbyPlayers == null) {
|
|
+ return;
|
|
+ }
|
|
+ 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/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
|
index 9e32e2db10f5faaa3c5f4adc5cbc2c1a2e4d3073..854c97bddb711ed252c2ae8398247641fdfb10be 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
|
@@ -70,6 +70,7 @@ public class WorldServer extends World {
|
|
}
|
|
}
|
|
// Paper end
|
|
+ public final PlayerChunkMap chunkMap; // Paper
|
|
private final MinecraftServer server;
|
|
private final WorldNBTStorage dataManager;
|
|
public boolean savingDisabled;
|
|
@@ -208,6 +209,8 @@ public class WorldServer extends World {
|
|
}, gameprofilerfiller, false, gen, env);
|
|
this.pvpMode = minecraftserver.getPVP();
|
|
worlddata.world = this;
|
|
+ if (chunkProvider == null) { chunkMap = null; new Throwable("World created without a ChunkProvider!").printStackTrace(); } // Paper - figure out if something weird happened here
|
|
+ else chunkMap = ((ChunkProviderServer) chunkProvider).playerChunkMap;
|
|
// CraftBukkit end
|
|
if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) {
|
|
this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { // Paper - optimise TickListServer
|