diff --git a/Paper b/Paper index 0e72de1c1..cfed00cf5 160000 --- a/Paper +++ b/Paper @@ -1 +1 @@ -Subproject commit 0e72de1c18966b6dfe46c1965f1121571b34e61b +Subproject commit cfed00cf54f973a2de0f2a2646ec5dbe9ef647a1 diff --git a/patches/api/0001-POM-Changes.patch b/patches/api/0001-POM-Changes.patch index a8441d252..76abe7b48 100644 --- a/patches/api/0001-POM-Changes.patch +++ b/patches/api/0001-POM-Changes.patch @@ -6,7 +6,7 @@ Subject: [PATCH] POM Changes diff --git a/pom.xml b/pom.xml -index 2cb9714084c8a7aa1b20d445edd5be4cc206672f..d167304be5ca4d067886a9740230b25b9fa21b56 100644 +index 20c473f521e50df57065d3644398f9db777c1a24..13d0bb7355a8f6c1a33feb3be60f61aa60dd5f9c 100644 --- a/pom.xml +++ b/pom.xml @@ -3,18 +3,18 @@ diff --git a/patches/api/0002-Add-server-configuration.patch b/patches/api/0002-Add-server-configuration.patch index f057c028f..5bd9aceff 100644 --- a/patches/api/0002-Add-server-configuration.patch +++ b/patches/api/0002-Add-server-configuration.patch @@ -18,10 +18,10 @@ index 93d5a3f97a1b2b3a1cd2731d48e8ebd01d29aa91..dfb57b9db56b31205a581f26ff46496b new TimingsExport(listeners, parent, history).start(); diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9ceaac0e859e347b07fa9f4c6507a73deb280670..17a494b4ded276ae2aa16c008e424c58b3090150 100644 +index cc06492f46ba5776221cd2614c1dcd8f33cc8faf..18778456394681d1aec2850818913fbbb7bf493a 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1386,6 +1386,14 @@ public interface Server extends PluginMessageRecipient { +@@ -1396,6 +1396,14 @@ public interface Server extends PluginMessageRecipient { } // Paper end diff --git a/patches/api/0003-Tuinity-View-distance-api.patch b/patches/api/0003-Tuinity-View-distance-api.patch deleted file mode 100644 index 8b55e7c1f..000000000 --- a/patches/api/0003-Tuinity-View-distance-api.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E3=84=97=E3=84=A0=CB=8B=20=E3=84=91=E3=84=A7=CB=8A?= - -Date: Sat, 18 Apr 2020 19:53:16 +0800 -Subject: [PATCH] Tuinity View distance api - -Allow setting a view distance where entities and chunks do not tick. -This could allow some servers to look like they have a higher view -distance than they actually have. - -Also add World#setViewDistance - -diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index db18f70ec37253232fb2cfd08ccd07d13c7c457d..be92b1a3e062cb7c54d5a1ea83ea22437b8562d4 100644 ---- a/src/main/java/org/bukkit/World.java -+++ b/src/main/java/org/bukkit/World.java -@@ -3166,6 +3166,34 @@ public interface World extends PluginMessageRecipient, Metadatable { - int getViewDistance(); - // Spigot end - -+ // Tuinity start - view distance api -+ /** -+ * Sets the view distance for this world. -+ * @param viewDistance view distance in [2, 32] -+ */ -+ void setViewDistance(int viewDistance); -+ -+ /** -+ * Returns the no-tick view distance for this world. -+ *

-+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

-+ * @return The no-tick view distance for this world. -+ */ -+ int getNoTickViewDistance(); -+ -+ /** -+ * Sets the no-tick view distance for this world. -+ *

-+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

-+ * @param viewDistance view distance in [2, 32] -+ */ -+ void setNoTickViewDistance(int viewDistance); -+ // Tuinity end - view distance api -+ - // Spigot start - public class Spigot { - -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 787bb144b5918ef1e46d69cb72b84128d2b678f3..c542305c69da3b9e5c2485e3c0cdf7ec60b1239b 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -1732,6 +1732,29 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - T getClientOption(@NotNull ClientOption option); - // Paper end - -+ // Tuinity start -+ /** -+ * Returns the no-tick view distance for this player. -+ *

-+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

-+ * @return The no-tick view distance for this player. -+ */ -+ int getNoTickViewDistance(); -+ -+ /** -+ * Sets the no-tick view distance for this player. Setting to a value of -1 will default to the world no-tick -+ * view distance. -+ *

-+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not -+ * be set to tick. -+ *

-+ * @param viewDistance view distance in [2, 32] or -1 -+ */ -+ void setNoTickViewDistance(int viewDistance); -+ // Tuinity end -+ - // Spigot start - public class Spigot extends Entity.Spigot { - diff --git a/patches/server/0001-Fix-errors-on-editors-and-add-ignores.patch b/patches/server/0001-Fix-errors-on-editors-and-add-ignores.patch index aa911112a..adbd9fce1 100644 --- a/patches/server/0001-Fix-errors-on-editors-and-add-ignores.patch +++ b/patches/server/0001-Fix-errors-on-editors-and-add-ignores.patch @@ -30,10 +30,10 @@ index 9ebd7ecb7a0ac73ccacf34c097056598bb5d26e8..677ccffd00e44eff74fa588a1af0c3e5 final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -index f625da9f0968b6f41e302b628c4439198eb4ed64..3f128565b4d47ab768c9b31a57b338b5cd9c86a7 100644 +index c71ed11834557f71504de5038d3bb593824f6f95..1b943cff539df8486e639118f6bc97c9e31f57c2 100644 --- a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -@@ -134,10 +134,10 @@ public abstract class AreaMap { +@@ -164,10 +164,10 @@ public abstract class AreaMap { final int centerX = MCUtil.getCoordinateX(currPosition); final int centerZ = MCUtil.getCoordinateZ(currPosition); diff --git a/patches/server/0002-Akarin-POM-changes.patch b/patches/server/0002-Akarin-POM-changes.patch index 8fcdf36a5..26f00357e 100644 --- a/patches/server/0002-Akarin-POM-changes.patch +++ b/patches/server/0002-Akarin-POM-changes.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Akarin POM changes diff --git a/pom.xml b/pom.xml -index 55679af926485eca6bb0b9ed368a4c91c8a7e37e..19f87edb55a48b151f81f899cedbc573aec66405 100644 +index 0c0051f7f2a58d63b851e80b442acbb47ca75dfa..725edb29f55276596ff5ee9240ce3432a47cc40b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,11 @@ @@ -26,7 +26,7 @@ index 55679af926485eca6bb0b9ed368a4c91c8a7e37e..19f87edb55a48b151f81f899cedbc573 UTF-8 -@@ -21,16 +20,16 @@ +@@ -18,16 +17,16 @@ @@ -47,7 +47,7 @@ index 55679af926485eca6bb0b9ed368a4c91c8a7e37e..19f87edb55a48b151f81f899cedbc573 ${project.version} compile -@@ -143,15 +142,15 @@ +@@ -153,15 +152,15 @@ diff --git a/patches/server/0003-Akarin-configuration.patch b/patches/server/0003-Akarin-configuration.patch index acedb72e3..370569fc6 100644 --- a/patches/server/0003-Akarin-configuration.patch +++ b/patches/server/0003-Akarin-configuration.patch @@ -195,7 +195,7 @@ index 0000000000000000000000000000000000000000..2ac8f02a97429f04f3e5c9206ec228ed + +} diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java -index e62ca0543f1819259ad8720ad792fed3ef134d6a..e936dee73aa8c4b2212d0f29fa2f9825b36345e0 100644 +index b07c49f1b48cc6dedd7c2057da0ec4f6f6d446e6..15f6f2e4f9928f87f1ee96bddfe516ae1c817624 100644 --- a/src/main/java/net/minecraft/server/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/DedicatedServer.java @@ -194,6 +194,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer @@ -207,10 +207,10 @@ index e62ca0543f1819259ad8720ad792fed3ef134d6a..e936dee73aa8c4b2212d0f29fa2f9825 this.setSpawnAnimals(dedicatedserverproperties.spawnAnimals); this.setSpawnNPCs(dedicatedserverproperties.spawnNpcs); diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 09b03afffa496b7090454682495ca35147c2f8a9..8d043de794d8ce13ed7efef88cfa93e3bc9b57f8 100644 +index 0e6368d0fb3beccb492ae3867fb4e22825f928a2..58e9709743b759a610e238f8b9861fc38b06ce60 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -82,6 +82,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +@@ -88,6 +88,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray @@ -219,7 +219,7 @@ index 09b03afffa496b7090454682495ca35147c2f8a9..8d043de794d8ce13ed7efef88cfa93e3 public final co.aikar.timings.WorldTimingsHandler timings; // Paper public static BlockPosition lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; -@@ -131,6 +133,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +@@ -137,6 +139,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { this.spigotConfig = new org.spigotmc.SpigotWorldConfig( worlddata.getName() ); // Spigot this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(worlddata.getName(), this.spigotConfig); // Paper this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this.paperConfig) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray @@ -228,10 +228,10 @@ index 09b03afffa496b7090454682495ca35147c2f8a9..8d043de794d8ce13ed7efef88cfa93e3 this.world = new CraftWorld((WorldServer) this, gen, env); this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index dcc44be613119f0e2c9d7f7e76bdf641ad1ae7c0..5ce50f5fd831955b74e002c0aebcdb6e25b5af31 100644 +index b89f99a66fe2ab9ad4c956c38c9e4b1d79716c9c..7fc5eac2819fa59e4c18255af8ccf7f9be9e601d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -806,6 +806,7 @@ public final class CraftServer implements Server { +@@ -814,6 +814,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper @@ -239,7 +239,7 @@ index dcc44be613119f0e2c9d7f7e76bdf641ad1ae7c0..5ce50f5fd831955b74e002c0aebcdb6e for (WorldServer world : console.getWorlds()) { world.worldData.setDifficulty(config.difficulty); world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); -@@ -834,6 +835,7 @@ public final class CraftServer implements Server { +@@ -842,6 +843,7 @@ public final class CraftServer implements Server { } world.spigotConfig.init(); // Spigot world.paperConfig.init(); // Paper @@ -247,7 +247,7 @@ index dcc44be613119f0e2c9d7f7e76bdf641ad1ae7c0..5ce50f5fd831955b74e002c0aebcdb6e } Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper -@@ -2092,6 +2094,14 @@ public final class CraftServer implements Server { +@@ -2100,6 +2102,14 @@ public final class CraftServer implements Server { return com.destroystokyo.paper.PaperConfig.config; } @@ -263,10 +263,10 @@ index dcc44be613119f0e2c9d7f7e76bdf641ad1ae7c0..5ce50f5fd831955b74e002c0aebcdb6e public void restart() { org.spigotmc.RestartCommand.restart(); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index cb60310e63ce0f55f5e706edf9e1ef61a3732600..04694464b105aba007718e7b5933df8709d98b33 100644 +index 93340e9470b23f2d8c91338e63e95c6465e69c3c..d807195bd957b3811313ecca5588339389e064b4 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -138,6 +138,14 @@ public class Main { +@@ -139,6 +139,14 @@ public class Main { .describedAs("Yml file"); // Paper end diff --git a/patches/server/0004-Akarin-brand-changes.patch b/patches/server/0004-Akarin-brand-changes.patch index fd9a79a9e..3c1af3337 100644 --- a/patches/server/0004-Akarin-brand-changes.patch +++ b/patches/server/0004-Akarin-brand-changes.patch @@ -19,10 +19,10 @@ index cf00f35a5b7c2d2f6b6989e0855de8b882dcef50..a45e63a02759305e119a41eac55a7f40 throwable = throwable1; throw throwable1; diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a386c1ab480806003938e330ca78a8283fab37f1..4680c5b27a82df529ad15218e23ade0c467c52f6 100644 +index 1a4bc90435d0a56ab7b607c72f28772fb92049bc..888401ee7894957fba6db536cfada80294b929a4 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1545,7 +1545,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 100) { // Spigot this.snooper.a(); } -@@ -1207,6 +1209,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant extends TickListServer { // extend to avo - public void tick() { - final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); - -- this.world.getMethodProfiler().enter("cleaning"); -+ // this.world.getMethodProfiler().enter("cleaning"); // Akarin - remove caller - this.timingCleanup.startTiming(); - - this.prepare(); -@@ -282,7 +282,7 @@ public final class PaperTickList extends TickListServer { // extend to avo - this.nextTick = this.world.getTime() + 1; - - this.timingCleanup.stopTiming(); -- this.world.getMethodProfiler().exitEnter("ticking"); -+ // this.world.getMethodProfiler().exitEnter("ticking"); // Akarin - remove caller - this.timingTicking.startTiming(); - - for (final NextTickListEntry toTick : this.toTickThisTick) { -@@ -314,7 +314,7 @@ public final class PaperTickList extends TickListServer { // extend to avo - } - - this.timingTicking.stopTiming(); -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - this.timingFinished.startTiming(); - - // finished ticking, actual cleanup time diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8ba34156e7 100644 +index e2abda1bc37b9be0bae2506f0f26360693f3d30a..d6f4daeec90149ef402c2746a4a054c44f7eb21f 100644 --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -368,9 +368,9 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -449,9 +449,9 @@ public class ChunkProviderServer extends IChunkProvider { return ifLoaded; } // Paper end @@ -51,7 +20,7 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b long k = ChunkCoordIntPair.pair(i, j); IChunkAccess ichunkaccess; -@@ -384,7 +384,7 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -465,7 +465,7 @@ public class ChunkProviderServer extends IChunkProvider { } } @@ -60,7 +29,7 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b // Paper start - Chunk Load/Gen Priority boolean prevBlocking = IS_CHUNK_LOAD_BLOCKING_MAIN; IS_CHUNK_LOAD_BLOCKING_MAIN = true; -@@ -458,12 +458,16 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -539,12 +539,16 @@ public class ChunkProviderServer extends IChunkProvider { // CraftBukkit end this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); if (this.a(playerchunk, l)) { @@ -78,26 +47,26 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b if (this.a(playerchunk, l)) { throw (IllegalStateException) SystemUtils.c(new IllegalStateException("No chunk holder after ticket has been added")); } -@@ -612,33 +616,33 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -693,33 +697,33 @@ public class ChunkProviderServer extends IChunkProvider { // CraftBukkit start - modelled on below public void purgeUnload() { - this.world.getMethodProfiler().enter("purge"); -+ // this.world.getMethodProfiler().enter("purge"); // Akarin - remove caller ++ // // this.world.getMethodProfiler().enter("purge"); // Akarin - remove caller // Akarin - remove caller this.chunkMapDistance.purgeTickets(); this.tickDistanceManager(); - this.world.getMethodProfiler().exitEnter("unload"); -+ // this.world.getMethodProfiler().exitEnter("unload"); // Akarin - remove caller ++ // // this.world.getMethodProfiler().exitEnter("unload"); // Akarin - remove caller // Akarin - remove caller this.playerChunkMap.unloadChunks(() -> true); - this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller ++ // // // // // // // this.world.getMethodProfiler().exit(); // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller this.clearCache(); } // CraftBukkit end public void tick(BooleanSupplier booleansupplier) { - this.world.getMethodProfiler().enter("purge"); -+ // this.world.getMethodProfiler().enter("purge"); // Akarin - remove caller ++ // // this.world.getMethodProfiler().enter("purge"); // Akarin - remove caller // Akarin - remove caller this.world.timings.doChunkMap.startTiming(); // Spigot this.chunkMapDistance.purgeTickets(); this.world.getMinecraftServer().midTickLoadChunks(); // Paper @@ -110,25 +79,25 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b this.world.timings.chunks.stopTiming(); // Paper - timings this.world.timings.doChunkUnload.startTiming(); // Spigot - this.world.getMethodProfiler().exitEnter("unload"); -+ // this.world.getMethodProfiler().exitEnter("unload"); // Akarin - remove caller ++ // // this.world.getMethodProfiler().exitEnter("unload"); // Akarin - remove caller // Akarin - remove caller this.playerChunkMap.unloadChunks(booleansupplier); this.world.getMinecraftServer().midTickLoadChunks(); // Paper this.world.timings.doChunkUnload.stopTiming(); // Spigot - this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller ++ // // // // // // // this.world.getMethodProfiler().exit(); // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller this.clearCache(); } -@@ -652,7 +656,7 @@ public class ChunkProviderServer extends IChunkProvider { - boolean flag1 = this.world.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && !world.getPlayers().isEmpty(); // CraftBukkit - - if (!flag) { +@@ -763,7 +767,7 @@ public class ChunkProviderServer extends IChunkProvider { + player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange + } + // Paper end - optimize isOutisdeRange - this.world.getMethodProfiler().enter("pollingChunks"); + // this.world.getMethodProfiler().enter("pollingChunks"); // Akarin - remove caller int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); BlockPosition blockposition = this.world.getSpawn(); // CraftBukkit start - Other mob type spawn tick rate -@@ -663,7 +667,7 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -774,7 +778,7 @@ public class ChunkProviderServer extends IChunkProvider { boolean flag2 = spawnAnimalThisTick; // CraftBukkit end @@ -137,16 +106,16 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b this.world.timings.countNaturalMobs.startTiming(); // Paper - timings int l = this.chunkMapDistance.b(); EnumCreatureType[] aenumcreaturetype = EnumCreatureType.values(); -@@ -685,7 +689,7 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -796,7 +800,7 @@ public class ChunkProviderServer extends IChunkProvider { // Paper end this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings - this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - //Paper start - call player naturally spawn event - int chunkRange = world.spigotConfig.mobSpawnRange; - chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -@@ -701,18 +705,18 @@ public class ChunkProviderServer extends IChunkProvider { ++ // // // // // // // this.world.getMethodProfiler().exit(); // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller + // Paper - replaced by above + final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); +@@ -804,18 +808,18 @@ public class ChunkProviderServer extends IChunkProvider { if (optional.isPresent()) { Chunk chunk = (Chunk) optional.get(); @@ -156,28 +125,28 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b playerchunk.a(chunk); this.world.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings - this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller ++ // // // // // // // this.world.getMethodProfiler().exit(); // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - if (!this.playerChunkMap.isOutsideOfRange(chunkcoordintpair)) { + if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange // Paper end chunk.setInhabitedTime(chunk.getInhabitedTime() + j); - if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot + if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange - this.world.getMethodProfiler().enter("spawner"); + // this.world.getMethodProfiler().enter("spawner"); // Akarin - remove caller this.world.timings.mobSpawn.startTiming(); // Spigot EnumCreatureType[] aenumcreaturetype1 = aenumcreaturetype; int i1 = aenumcreaturetype.length; -@@ -772,7 +776,7 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -875,7 +879,7 @@ public class ChunkProviderServer extends IChunkProvider { } this.world.timings.mobSpawn.stopTiming(); // Spigot - this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller ++ // // // // // // // this.world.getMethodProfiler().exit(); // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller } this.world.timings.chunkTicks.startTiming(); // Spigot // Paper -@@ -782,15 +786,15 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -885,15 +889,15 @@ public class ChunkProviderServer extends IChunkProvider { } } }); @@ -191,12 +160,12 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller ++ // // // // // // // this.world.getMethodProfiler().exit(); // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller ++ // // // // // // // this.world.getMethodProfiler().exit(); // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller // Akarin - remove caller } this.playerChunkMap.g(); -@@ -916,7 +920,7 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -1019,7 +1023,7 @@ public class ChunkProviderServer extends IChunkProvider { @Override protected void executeTask(Runnable runnable) { @@ -205,1161 +174,3 @@ index ba6bdc40a73e4d3221cc08e947a6d629a126c5ee..bf6bf7d8c6c7e2d8572a33ed16767d8b super.executeTask(runnable); } -diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java -index 2414b0a552e5d6fb449bca163add7a9bac39e943..1b0a878d2a186bceba11b08ef28c1c040d4d78ce 100644 ---- a/src/main/java/net/minecraft/server/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/server/CommandDispatcher.java -@@ -168,7 +168,7 @@ public class CommandDispatcher { - stringreader.skip(); - } - -- commandlistenerwrapper.getServer().getMethodProfiler().enter(s); -+ // commandlistenerwrapper.getServer().getMethodProfiler().enter(s); // Akarin - remove caller - - byte b0; - -@@ -231,7 +231,7 @@ public class CommandDispatcher { - b0 = 0; - } - } finally { -- commandlistenerwrapper.getServer().getMethodProfiler().exit(); -+ // commandlistenerwrapper.getServer().getMethodProfiler().exit(); // Akarin - remove caller - } - - return b0; -diff --git a/src/main/java/net/minecraft/server/CustomFunctionData.java b/src/main/java/net/minecraft/server/CustomFunctionData.java -index ee42e1dfa493c3d7f5af8cc7b8e17e80fcb32b71..68dc7cdfbca341234245d0b8c1643f56a1beac06 100644 ---- a/src/main/java/net/minecraft/server/CustomFunctionData.java -+++ b/src/main/java/net/minecraft/server/CustomFunctionData.java -@@ -58,10 +58,10 @@ public class CustomFunctionData implements IResourcePackListener { - } - - public void tick() { -- GameProfiler gameprofiler = this.server.getMethodProfiler(); -+ // GameProfiler gameprofiler = this.server.getMethodProfiler(); // Akarin - remove caller - MinecraftKey minecraftkey = CustomFunctionData.d; - -- gameprofiler.a(minecraftkey::toString); -+ // gameprofiler.a(minecraftkey::toString); // Akarin - remove caller - Iterator iterator = this.l.iterator(); - - while (iterator.hasNext()) { -@@ -70,14 +70,14 @@ public class CustomFunctionData implements IResourcePackListener { - this.a(customfunction, this.f()); - } - -- this.server.getMethodProfiler().exit(); -+ // this.server.getMethodProfiler().exit(); // Akarin - remove caller - if (this.m) { - this.m = false; - Collection collection = this.h().b(CustomFunctionData.e).a(); - -- gameprofiler = this.server.getMethodProfiler(); -+ // gameprofiler = this.server.getMethodProfiler(); // Akarin - remove caller - minecraftkey = CustomFunctionData.e; -- gameprofiler.a(minecraftkey::toString); -+ // gameprofiler.a(minecraftkey::toString); // Akarin - remove caller - Iterator iterator1 = collection.iterator(); - - while (iterator1.hasNext()) { -@@ -86,7 +86,7 @@ public class CustomFunctionData implements IResourcePackListener { - this.a(customfunction1, this.f()); - } - -- this.server.getMethodProfiler().exit(); -+ // this.server.getMethodProfiler().exit(); // Akarin - remove caller - } - - } -@@ -121,7 +121,7 @@ public class CustomFunctionData implements IResourcePackListener { - try { - CustomFunctionData.a customfunctiondata_a = (CustomFunctionData.a) this.i.removeFirst(); - -- this.server.getMethodProfiler().a(customfunctiondata_a::toString); -+ // this.server.getMethodProfiler().a(customfunctiondata_a::toString); // Akarin - remove caller - customfunctiondata_a.a(this.i, i); - if (!this.j.isEmpty()) { - List list = Lists.reverse(this.j); -@@ -132,7 +132,7 @@ public class CustomFunctionData implements IResourcePackListener { - this.j.clear(); - } - } finally { -- this.server.getMethodProfiler().exit(); -+ // this.server.getMethodProfiler().exit(); // Akarin - remove caller - } - - ++k; -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 96a47dd1c2d3c89b4061fe96210e768c12b73ca0..98eeb2a4a09e7653a8d050df5b1c8a1d457b1e94 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -429,7 +429,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - // CraftBukkit end - - public void entityBaseTick() { -- this.world.getMethodProfiler().enter("entityBaseTick"); -+ // this.world.getMethodProfiler().enter("entityBaseTick"); // Akarin - remove caller - if (this.isPassenger() && this.getVehicle().dead) { - this.stopRiding(); - } -@@ -482,7 +482,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - - this.justCreated = false; -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - - // Paper start -@@ -597,7 +597,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - } - -- this.world.getMethodProfiler().enter("move"); -+ // this.world.getMethodProfiler().enter("move"); // Akarin - remove caller - if (this.y.g() > 1.0E-7D) { - vec3d = vec3d.h(this.y); - this.y = Vec3D.a; -@@ -606,7 +606,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - // Paper start - ignore movement changes while inactive. - if (isTemporarilyActive && !(this instanceof EntityItem) && vec3d == getMot() && enummovetype == EnumMoveType.SELF) { - setMot(Vec3D.a); -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - return; - } - // Paper end -@@ -619,8 +619,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - this.recalcPosition(); - } - -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("rest"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("rest"); // Akarin - remove caller - this.positionChanged = !MathHelper.b(vec3d.x, vec3d1.x) || !MathHelper.b(vec3d.z, vec3d1.z); - this.v = vec3d.y != vec3d1.y; - this.onGround = this.v && vec3d.y < 0.0D; -@@ -742,7 +742,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - this.fireTicks = -this.getMaxFireTicks(); - } - -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - } - -@@ -2243,7 +2243,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - - if (this.af) { - if ((true || this.world.getMinecraftServer().getAllowNether()) && !this.isPassenger() && this.ag++ >= i) { // CraftBukkit -- this.world.getMethodProfiler().enter("portal"); -+ // this.world.getMethodProfiler().enter("portal"); // Akarin - remove caller - this.ag = i; - this.portalCooldown = this.ba(); - // CraftBukkit start -@@ -2253,7 +2253,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - this.a(this.world.worldProvider.getDimensionManager().getType() == DimensionManager.NETHER ? DimensionManager.OVERWORLD : DimensionManager.NETHER); - } - // CraftBukkit end -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - - this.af = false; -@@ -2631,7 +2631,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - public Entity teleportTo(DimensionManager dimensionmanager, BlockPosition location) { - // CraftBukkit end - if (!this.world.isClientSide && !this.dead) { -- this.world.getMethodProfiler().enter("changeDimension"); -+ // this.world.getMethodProfiler().enter("changeDimension"); // Akarin - remove caller - MinecraftServer minecraftserver = this.getMinecraftServer(); - DimensionManager dimensionmanager1 = this.dimension; - WorldServer worldserver = minecraftserver.getWorldServer(dimensionmanager1); -@@ -2644,7 +2644,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - // this.dimension = dimensionmanager; - // this.decouple(); - // CraftBukkit end -- this.world.getMethodProfiler().enter("reposition"); -+ // this.world.getMethodProfiler().enter("reposition"); // Akarin - remove caller - Vec3D vec3d = this.getMot(); - float f = 0.0F; - BlockPosition blockposition = location; // CraftBukkit -@@ -2723,7 +2723,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - this.decouple(); - // CraftBukkit end - -- this.world.getMethodProfiler().exitEnter("reloading"); -+ // this.world.getMethodProfiler().exitEnter("reloading"); // Akarin - remove caller - Entity entity = this.getEntityType().a((World) worldserver1); - - if (entity != null) { -@@ -2742,10 +2742,10 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke - } - - this.dead = true; -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - worldserver.resetEmptyTime(); - worldserver1.resetEmptyTime(); -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - return entity; - } else { - return null; -diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 1991cee43d429574f2c0889f807e7cd090f7d7dd..bb20398abc65d3f7e54867bdf930480af0941ada 100644 ---- a/src/main/java/net/minecraft/server/EntityInsentient.java -+++ b/src/main/java/net/minecraft/server/EntityInsentient.java -@@ -223,13 +223,13 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - public void entityBaseTick() { - super.entityBaseTick(); -- this.world.getMethodProfiler().enter("mobBaseTick"); -+ // this.world.getMethodProfiler().enter("mobBaseTick"); // Akarin - remove caller - if (this.isAlive() && this.random.nextInt(1000) < this.e++) { - this.l(); - this.B(); - } - -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - - @Override -@@ -523,7 +523,7 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - public void movementTick() { - super.movementTick(); -- this.world.getMethodProfiler().enter("looting"); -+ // this.world.getMethodProfiler().enter("looting"); // Akarin - remove caller - if (!this.world.isClientSide && this.canPickupLoot() && this.isAlive() && !this.killed && this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { - List list = this.world.a(EntityItem.class, this.getBoundingBox().grow(1.0D, 0.0D, 1.0D)); - Iterator iterator = list.iterator(); -@@ -542,7 +542,7 @@ public abstract class EntityInsentient extends EntityLiving { - } - } - -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - - protected void a(EntityItem entityitem) { -@@ -676,30 +676,30 @@ public abstract class EntityInsentient extends EntityLiving { - return; - } - // Paper end -- this.world.getMethodProfiler().enter("sensing"); -+ // this.world.getMethodProfiler().enter("sensing"); // Akarin - remove caller - this.bw.a(); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("targetSelector"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("targetSelector"); // Akarin - remove caller - this.targetSelector.doTick(); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("goalSelector"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("goalSelector"); // Akarin - remove caller - this.goalSelector.doTick(); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("navigation"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("navigation"); // Akarin - remove caller - this.navigation.c(); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("mob tick"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("mob tick"); // Akarin - remove caller - this.mobTick(); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("controls"); -- this.world.getMethodProfiler().enter("move"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("controls"); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("move"); // Akarin - remove caller - this.moveController.a(); -- this.world.getMethodProfiler().exitEnter("look"); -+ // this.world.getMethodProfiler().exitEnter("look"); // Akarin - remove caller - this.lookController.a(); -- this.world.getMethodProfiler().exitEnter("jump"); -+ // this.world.getMethodProfiler().exitEnter("jump"); // Akarin - remove caller - this.bq.b(); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - this.K(); - } - -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index dfb9421a15ba1ca7b86146cb795a3ac5e9b8e15e..68504f798efe6e4e5ff2a0a7748b67b9d32601d4 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -242,7 +242,7 @@ public abstract class EntityLiving extends Entity { - } - - super.entityBaseTick(); -- this.world.getMethodProfiler().enter("livingEntityBaseTick"); -+ // this.world.getMethodProfiler().enter("livingEntityBaseTick"); // Akarin - remove caller - boolean flag = this instanceof EntityHuman; - - if (this.isAlive()) { -@@ -344,7 +344,7 @@ public abstract class EntityLiving extends Entity { - this.aL = this.aK; - this.lastYaw = this.yaw; - this.lastPitch = this.pitch; -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - - protected void b(BlockPosition blockposition) { -@@ -2412,10 +2412,10 @@ public abstract class EntityLiving extends Entity { - } - - this.aS += (f3 - this.aS) * 0.3F; -- this.world.getMethodProfiler().enter("headTurn"); -+ // this.world.getMethodProfiler().enter("headTurn"); // Akarin - remove caller - f2 = this.f(f1, f2); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("rangeChecks"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("rangeChecks"); // Akarin - remove caller - - while (this.yaw - this.lastYaw < -180.0F) { - this.lastYaw -= 360.0F; -@@ -2449,7 +2449,7 @@ public abstract class EntityLiving extends Entity { - this.aL += 360.0F; - } - -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - this.aT += f2; - if (this.isGliding()) { - ++this.bm; -@@ -2586,19 +2586,19 @@ public abstract class EntityLiving extends Entity { - } - - this.setMot(d4, d5, d6); -- this.world.getMethodProfiler().enter("ai"); -+ // this.world.getMethodProfiler().enter("ai"); // Akarin - remove caller - if (this.isFrozen()) { - this.jumping = false; - this.aZ = 0.0F; - this.bb = 0.0F; - } else if (this.doAITick()) { -- this.world.getMethodProfiler().enter("newAi"); -+ // this.world.getMethodProfiler().enter("newAi"); // Akarin - remove caller - this.doTick(); -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("jump"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("jump"); // Akarin - remove caller - if (this.jumping) { - if (this.N > 0.0D && (!this.onGround || this.N > 0.4D)) { - this.c(TagsFluid.WATER); -@@ -2614,23 +2614,23 @@ public abstract class EntityLiving extends Entity { - this.jumpTicks = 0; - } - -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("travel"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("travel"); // Akarin - remove caller - this.aZ *= 0.98F; - this.bb *= 0.98F; - this.n(); - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - - this.e(new Vec3D((double) this.aZ, (double) this.ba, (double) this.bb)); -- this.world.getMethodProfiler().exit(); -- this.world.getMethodProfiler().enter("push"); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller -+ // this.world.getMethodProfiler().enter("push"); // Akarin - remove caller - if (this.bn > 0) { - --this.bn; - this.a(axisalignedbb, this.getBoundingBox()); - } - - this.collideNearby(); -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - - private void n() { -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 202068314eca435abecc25b2870350c530e0fac5..b4c3dffaff5ea64d9189304c5e84c515bf40ed65 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -826,7 +826,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - double d3 = 8.0D; - float f2 = f1; - -- worldserver.getMethodProfiler().enter("moving"); -+ // worldserver.getMethodProfiler().enter("moving"); // Akarin - remove caller - if (worldserver1 == null) { } else // CraftBukkit - empty to fall through to null to event - if (dimensionmanager1 == DimensionManager.OVERWORLD && dimensionmanager == DimensionManager.NETHER) { - this.cr = this.getPositionVector(); -@@ -867,8 +867,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - // CraftBukkit end - - // this.setPositionRotation(d0, d1, d2, f1, f); // CraftBukkit - PlayerTeleportEvent handles position changes -- worldserver.getMethodProfiler().exit(); -- worldserver.getMethodProfiler().enter("placing"); -+ // worldserver.getMethodProfiler().exit(); // Akarin - remove caller -+ // worldserver.getMethodProfiler().enter("placing"); // Akarin - remove caller - double d4 = Math.min(-2.9999872E7D, worldserver1.getWorldBorder().c() + 16.0D); - double d5 = Math.min(-2.9999872E7D, worldserver1.getWorldBorder().d() + 16.0D); - double d6 = Math.min(2.9999872E7D, worldserver1.getWorldBorder().e() - 16.0D); -@@ -939,7 +939,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - // CraftBukkit end - } - -- worldserver.getMethodProfiler().exit(); -+ // worldserver.getMethodProfiler().exit(); // Akarin - remove caller - // CraftBukkit start - PlayerTeleportEvent - PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); - Bukkit.getServer().getPluginManager().callEvent(tpEvent); -diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index 6e0020ae0b4d2f2597843129b83fff0d194de337..a7a07ffc43d4e95af59da1194ae90394580bb242 100644 ---- a/src/main/java/net/minecraft/server/EntityVillager.java -+++ b/src/main/java/net/minecraft/server/EntityVillager.java -@@ -144,9 +144,9 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - - @Override - protected void mobTick() { -- this.world.getMethodProfiler().enter("brain"); -+ // this.world.getMethodProfiler().enter("brain"); // Akarin - remove caller - this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - if (!this.et() && this.bB > 0) { - --this.bB; - if (this.bB <= 0) { -diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java -index a353f3d5fa5a5f54335f73584589de3f5cb20d3e..5f976a17c7aa36286ee1132597e480f591749a45 100644 ---- a/src/main/java/net/minecraft/server/Explosion.java -+++ b/src/main/java/net/minecraft/server/Explosion.java -@@ -285,7 +285,7 @@ public class Explosion { - if (!iblockdata.isAir()) { - BlockPosition blockposition1 = blockposition.immutableCopy(); - -- this.world.getMethodProfiler().enter("explosion_blocks"); -+ // this.world.getMethodProfiler().enter("explosion_blocks"); // Akarin - remove caller - if (block.a(this) && this.world instanceof WorldServer) { - TileEntity tileentity = block.isTileEntity() ? this.world.getTileEntity(blockposition) : null; - LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).a(this.world.random).set(LootContextParameters.POSITION, blockposition).set(LootContextParameters.TOOL, ItemStack.a).setOptional(LootContextParameters.BLOCK_ENTITY, tileentity).setOptional(LootContextParameters.THIS_ENTITY, this.source); -@@ -301,7 +301,7 @@ public class Explosion { - - this.world.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 3); - block.wasExploded(this.world, blockposition, this); -- this.world.getMethodProfiler().exit(); -+ // this.world.getMethodProfiler().exit(); // Akarin - remove caller - } - } - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index df35fb8065bd0a367e2dbad75e0adca611cad6f1..fba422d39d0e4dc8a1f2fe309a4aea506d68ca1e 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -950,18 +950,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down - //MinecraftServer.LOGGER.debug("Autosave started"); // Paper - serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper -- this.methodProfiler.enter("save"); -+ // this.methodProfiler.enter("save"); // Akarin - remove caller - if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper - this.playerList.savePlayers(); - }// Paper -@@ -1195,11 +1195,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 100) { // Spigot -@@ -1211,7 +1211,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper - TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - if (true || worldserver.worldProvider.getDimensionManager() == DimensionManager.OVERWORLD || this.getAllowNether()) { // CraftBukkit -+ // Akarin start - remove caller -+ /* - this.methodProfiler.a(() -> { - return worldserver.getWorldData().getName() + " " + IRegistry.DIMENSION_TYPE.getKey(worldserver.worldProvider.getDimensionManager()); - }); -+ */ -+ // Akarin end - /* Drop global time updates - if (this.ticks % 20 == 0) { - this.methodProfiler.enter("timeSync"); -@@ -1302,7 +1306,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant iterator = this.d.iterator(); iterator.hasNext();) { - PathfinderGoalWrapped wrappedGoal = iterator.next(); -@@ -96,8 +96,8 @@ public class PathfinderGoalSelector { - } - - }); -- this.e.exit(); -- this.e.enter("goalUpdate"); -+ // this.e.exit(); // Akarin - remove caller -+ // this.e.enter("goalUpdate"); // Akarin - remove caller - // Paper start - remove streams from pathfindergoalselector - goal_update_loop: for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { - PathfinderGoalWrapped wrappedGoal = iterator.next(); -@@ -140,8 +140,8 @@ public class PathfinderGoalSelector { - wrappedGoal.c(); - } - // Paper end - remove streams from pathfindergoalselector -- this.e.exit(); -- this.e.enter("goalTick"); -+ // this.e.exit(); // Akarin - remove caller -+ // this.e.enter("goalTick"); // Akarin - remove caller - // Paper start - remove streams from pathfindergoalselector - for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { - PathfinderGoalWrapped wrappedGoal = iterator.next(); -@@ -150,7 +150,7 @@ public class PathfinderGoalSelector { - } - } - // Paper end - remove streams from pathfindergoalselector -- this.e.exit(); -+ // this.e.exit(); // Akarin - remove caller - } - - public Stream c() { -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 12639dfb94599233e24a0a8b77bc88de81b65e9b..f8ad08cccf25ef26759231c3d26b71d33d010eb8 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -537,20 +537,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot - - protected void unloadChunks(BooleanSupplier booleansupplier) { -- GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); -+ // GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); // Akarin - remove caller - - try (Timing ignored = this.world.timings.poiUnload.startTiming()) { // Paper -- gameprofilerfiller.enter("poi"); -+ // gameprofilerfiller.enter("poi"); // Akarin - remove caller - this.m.a(booleansupplier); - } // Paper -- gameprofilerfiller.exitEnter("chunk_unload"); -+ // gameprofilerfiller.exitEnter("chunk_unload"); // Akarin - remove caller - if (!this.world.isSavingDisabled()) { - try (Timing ignored = this.world.timings.chunkUnload.startTiming()) { // Paper - this.b(booleansupplier); - }// Paper - } - -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - } - - private void b(BooleanSupplier booleansupplier) { -@@ -761,7 +761,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - Async chunk io - final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { - try (Timing ignored = this.world.timings.syncChunkLoadTimer.startTimingIfSync()) { // Paper -- this.world.getMethodProfiler().c("chunkLoad"); -+ // this.world.getMethodProfiler().c("chunkLoad"); // Akarin - remove caller - if (ioThrowable != null) { - com.destroystokyo.paper.io.IOUtil.rethrow(ioThrowable); - } -@@ -824,9 +824,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - this.requestingNeighbor = prevNeighbor; // Paper - -+ // Akarin start - remove caller -+ /* - this.world.getMethodProfiler().c(() -> { - return "chunkGenerate " + chunkstatus.d(); - }); -+ */ -+ // Akarin end - return completablefuture.thenComposeAsync((either) -> { - return either.map((list) -> { // Paper - Shut up. - try { -@@ -1100,7 +1104,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -- this.world.getMethodProfiler().c("chunkSave"); -+ // this.world.getMethodProfiler().c("chunkSave"); // Akarin - remove caller - } // Paper - try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper - nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 7929fcc800064fa23b260c3ecbed75f846bb375a..6dfbbc67dd9cc60355dcf5ef751cd1a5b259be6b 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -185,7 +185,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.E = 0; - } - -- this.minecraftServer.getMethodProfiler().enter("keepAlive"); -+ // this.minecraftServer.getMethodProfiler().enter("keepAlive"); // Akarin - remove caller - // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings - // This should effectively place the keepalive handling back to "as it was" before 1.12.2 - long currentTime = SystemUtils.getMonotonicMillis(); -@@ -207,7 +207,7 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - // Paper end - -- this.minecraftServer.getMethodProfiler().exit(); -+ // this.minecraftServer.getMethodProfiler().exit(); // Akarin - remove caller - // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; - if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable -diff --git a/src/main/java/net/minecraft/server/TickListServer.java b/src/main/java/net/minecraft/server/TickListServer.java -index 3f1aa5ced697490b5481ba992cf5af5dc98b8166..a7f2dee2c424b5da66a7c86319f6fa3a6a619087 100644 ---- a/src/main/java/net/minecraft/server/TickListServer.java -+++ b/src/main/java/net/minecraft/server/TickListServer.java -@@ -65,7 +65,7 @@ public class TickListServer implements TickList { - ChunkProviderServer chunkproviderserver = this.f.getChunkProvider(); - Iterator> iterator = this.nextTickList.iterator(); - -- this.f.getMethodProfiler().enter("cleaning"); -+ // this.f.getMethodProfiler().enter("cleaning"); // Akarin - remove caller - - this.timingCleanup.startTiming(); // Paper - NextTickListEntry nextticklistentry; -@@ -86,7 +86,7 @@ public class TickListServer implements TickList { - this.timingCleanup.stopTiming(); // Paper - - this.timingTicking.startTiming(); // Paper -- this.f.getMethodProfiler().exitEnter("ticking"); -+ // this.f.getMethodProfiler().exitEnter("ticking"); // Akarin - remove caller - - while ((nextticklistentry = (NextTickListEntry) this.g.poll()) != null) { - if (chunkproviderserver.a(nextticklistentry.a)) { -@@ -105,7 +105,7 @@ public class TickListServer implements TickList { - } - } - -- this.f.getMethodProfiler().exit(); -+ // this.f.getMethodProfiler().exit(); // Akarin - remove caller - this.timingTicking.stopTiming(); // Paper - this.h.clear(); - this.g.clear(); -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 8d043de794d8ce13ed7efef88cfa93e3bc9b57f8..75605d44bc4c051a7afa327a8749a0a67790b165 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -378,9 +378,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - IBlockData iblockdata2 = this.getType(blockposition); - - if (iblockdata2 != iblockdata1 && (iblockdata2.b((IBlockAccess) this, blockposition) != iblockdata1.b((IBlockAccess) this, blockposition) || iblockdata2.h() != iblockdata1.h() || iblockdata2.g() || iblockdata1.g())) { -- this.methodProfiler.enter("queueCheckLight"); -+ // this.methodProfiler.enter("queueCheckLight"); // Akarin - remove caller - this.getChunkProvider().getLightEngine().a(blockposition); -- this.methodProfiler.exit(); -+ // this.methodProfiler.exit(); // Akarin - remove caller - } - - /* -@@ -742,9 +742,9 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public void tickBlockEntities() { -- GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); -+ // GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); // Akarin - remove caller - -- gameprofilerfiller.enter("blockEntities"); -+ // gameprofilerfiller.enter("blockEntities"); // Akarin - remove caller - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { - // Paper start - Use alternate implementation with faster contains -@@ -777,9 +777,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - if (this.chunkProvider.a(blockposition) && this.getWorldBorder().a(blockposition)) { - try { -+ // Akarin start - remove caller -+ /* - gameprofilerfiller.a(() -> { - return String.valueOf(TileEntityTypes.a(tileentity.getTileType())); - }); -+ */ -+ // Akarin end - tileentity.tickTimer.startTiming(); // Spigot - if (tileentity.getTileType().isValidBlock(this.getType(blockposition).getBlock())) { - ((ITickable) tileentity).tick(); -@@ -787,7 +791,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - tileentity.v(); - } - -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - } catch (Throwable throwable) { - if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent tile entity and entity crashes -@@ -824,7 +828,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - timings.tileEntityTick.stopTiming(); // Spigot - timings.tileEntityPending.startTiming(); // Spigot - this.tickingTileEntities = false; -- gameprofilerfiller.exitEnter("pendingBlockEntities"); -+ // gameprofilerfiller.exitEnter("pendingBlockEntities"); // Akarin - remove caller - if (!this.tileEntityListPending.isEmpty()) { - for (int i = 0; i < this.tileEntityListPending.size(); ++i) { - TileEntity tileentity1 = (TileEntity) this.tileEntityListPending.get(i); -@@ -857,7 +861,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - timings.tileEntityPending.stopTiming(); // Spigot - co.aikar.timings.TimingHistory.tileEntityTicks += this.tileEntityListTick.size(); // Paper -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - spigotConfig.currentPrimedTnt = 0; // Spigot - } - -@@ -1203,7 +1207,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - @Override - public List getEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { -- this.getMethodProfiler().c("getEntities"); -+ // this.getMethodProfiler().c("getEntities"); // Akarin - remove caller - List list = Lists.newArrayList(); - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.floor((axisalignedbb.maxX + 2.0D) / 16.0D); -@@ -1224,7 +1228,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public List a(@Nullable EntityTypes entitytypes, AxisAlignedBB axisalignedbb, Predicate predicate) { -- this.getMethodProfiler().c("getEntities"); -+ // this.getMethodProfiler().c("getEntities"); // Akarin - remove caller - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D); - int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); -@@ -1246,7 +1250,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - @Override - public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { -- this.getMethodProfiler().c("getEntities"); -+ // this.getMethodProfiler().c("getEntities"); // Akarin - remove caller - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D); - int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); -@@ -1269,7 +1273,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - @Override - public List b(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { -- this.getMethodProfiler().c("getLoadedEntities"); -+ // this.getMethodProfiler().c("getLoadedEntities"); // Akarin - remove caller - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D); - int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index a0db38b5880c849514b89f8b47648de0e5b1273f..78fdacdaf119b9c3fab477ee98089bbad5da2d73 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -274,12 +274,12 @@ public class WorldServer extends World { - } - - public void doTick(BooleanSupplier booleansupplier) { -- GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); -+ // GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); // Akarin - remove caller - - this.ticking = true; -- gameprofilerfiller.enter("world border"); -+ // gameprofilerfiller.enter("world border"); // Akarin - remove caller - this.getWorldBorder().s(); -- gameprofilerfiller.exitEnter("weather"); -+ // gameprofilerfiller.exitEnter("weather"); // Akarin - remove caller - boolean flag = this.isRaining(); - int i; - -@@ -418,11 +418,11 @@ public class WorldServer extends World { - - this.N(); - this.a(); -- gameprofilerfiller.exitEnter("chunkSource"); -+ // gameprofilerfiller.exitEnter("chunkSource"); // Akarin - remove caller - this.timings.chunkProviderTick.startTiming(); // Paper - timings - this.getChunkProvider().tick(booleansupplier); - this.timings.chunkProviderTick.stopTiming(); // Paper - timings -- gameprofilerfiller.exitEnter("tickPending"); -+ // gameprofilerfiller.exitEnter("tickPending"); // Akarin - remove caller - timings.scheduledBlocks.startTiming(); // Spigot - if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { - this.nextTickListBlock.b(); -@@ -431,7 +431,7 @@ public class WorldServer extends World { - timings.scheduledBlocks.stopTiming(); // Spigot - - this.getMinecraftServer().midTickLoadChunks(); // Paper -- gameprofilerfiller.exitEnter("raid"); -+ // gameprofilerfiller.exitEnter("raid"); // Akarin - remove caller - this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); - if (this.mobSpawnerTrader != null) { -@@ -439,13 +439,13 @@ public class WorldServer extends World { - } - this.timings.raids.stopTiming(); // Paper - timings - -- gameprofilerfiller.exitEnter("blockEvents"); -+ // gameprofilerfiller.exitEnter("blockEvents"); // Akarin - remove caller - timings.doSounds.startTiming(); // Spigot - this.ad(); - timings.doSounds.stopTiming(); // Spigot - this.getMinecraftServer().midTickLoadChunks(); // Paper - this.ticking = false; -- gameprofilerfiller.exitEnter("entities"); -+ // gameprofilerfiller.exitEnter("entities"); // Akarin - remove caller - boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players - - if (flag3) { -@@ -455,7 +455,7 @@ public class WorldServer extends World { - if (flag3 || this.emptyTime++ < 300) { - timings.tickEntities.startTiming(); // Spigot - this.worldProvider.j(); -- gameprofilerfiller.enter("global"); -+ // gameprofilerfiller.enter("global"); // Akarin - remove caller - - Entity entity; - -@@ -475,7 +475,7 @@ public class WorldServer extends World { - } - } - -- gameprofilerfiller.exitEnter("regular"); -+ // gameprofilerfiller.exitEnter("regular"); // Akarin - remove caller - this.tickingEntities = true; - ObjectIterator objectiterator = this.entitiesById.int2ObjectEntrySet().iterator(); - -@@ -497,12 +497,12 @@ public class WorldServer extends World { - } - // CraftBukkit end */ - -- gameprofilerfiller.enter("checkDespawn"); -+ // gameprofilerfiller.enter("checkDespawn"); // Akarin - remove caller - if (!entity1.dead) { - entity1.checkDespawn(); - } - -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - if (entity2 != null) { - if (!entity2.dead && entity2.w(entity1)) { - continue; -@@ -511,20 +511,24 @@ public class WorldServer extends World { - entity1.stopRiding(); - } - -- gameprofilerfiller.enter("tick"); -+ // gameprofilerfiller.enter("tick"); // Akarin - remove caller - if (!entity1.dead && !(entity1 instanceof EntityComplexPart)) { - this.a(this::entityJoinedWorld, entity1); - } - -+ // Akarin start - remove caller -+ /* - gameprofilerfiller.exit(); - gameprofilerfiller.enter("remove"); -+ */ -+ // Akarin end - if (entity1.dead) { - this.removeEntityFromChunk(entity1); - objectiterator.remove(); - this.unregisterEntity(entity1); - } - -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - } - timings.entityTick.stopTiming(); // Spigot - -@@ -548,14 +552,14 @@ public class WorldServer extends World { - } - } // Paper - timings - -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - timings.tickEntities.stopTiming(); // Spigot - this.getMinecraftServer().midTickLoadChunks(); // Paper - this.tickBlockEntities(); - this.getMinecraftServer().midTickLoadChunks(); // Paper - } - -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - } - - private void wakeupPlayers() { -@@ -574,9 +578,9 @@ public class WorldServer extends World { - boolean flag = this.isRaining(); - int j = chunkcoordintpair.d(); - int k = chunkcoordintpair.e(); -- GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); -+ // GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); - -- gameprofilerfiller.enter("thunder"); -+ // gameprofilerfiller.enter("thunder"); // Akarin - remove caller - final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change - - if (!this.paperConfig.disableThunder && flag && this.U() && this.randomTickRandom.nextInt(100000) == 0) { // Paper - Disable thunder // Paper - optimise random ticking -@@ -598,7 +602,7 @@ public class WorldServer extends World { - } - } - -- gameprofilerfiller.exitEnter("iceandsnow"); -+ // gameprofilerfiller.exitEnter("iceandsnow"); // Akarin - remove caller - if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking - // Paper start - optimise chunk ticking - this.getRandomBlockPosition(j, 0, k, 15, blockposition); -@@ -629,7 +633,7 @@ public class WorldServer extends World { - } - - // Paper start - optimise random block ticking -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - int blocks = chunk.tickingList.size(); - if (i > 0 && blocks > 0) { - if ((this.randomTickRandom.nextInt() & (16 * 16 * 256 - 1)) > blocks) { -@@ -639,12 +643,12 @@ public class WorldServer extends World { - // Note: The number of blocks that get ticked per tick still REMAIN the same. - return; - } -- gameprofilerfiller.enter("tickBlocks"); -+ // gameprofilerfiller.enter("tickBlocks"); // Akarin - remove caller - timings.chunkTicksBlocks.startTiming(); // Paper - - int toTick = i << 4; // i * 16 - -- gameprofilerfiller.enter("randomTick"); -+ // gameprofilerfiller.enter("randomTick"); // Akarin - remove caller - for (int tick = 0; tick < toTick; ++tick) { - int tickingSize = chunk.tickingList.size(); - if (tickingSize == 0) { -@@ -669,9 +673,9 @@ public class WorldServer extends World { - // TODO CHECK ON UPDATE - } - -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - timings.chunkTicksBlocks.stopTiming(); // Paper -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - // Paper end - } - } -@@ -785,15 +789,19 @@ public class WorldServer extends World { - entity.lastPitch = entity.pitch; - if (entity.inChunk) { - ++entity.ticksLived; -+ // Akarin start - remove caller -+ /* - GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); - - gameprofilerfiller.a(() -> { - return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickNonPassenger"); -+ */ -+ // Akarin end - entity.tick(); - entity.postTick(); // CraftBukkit -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - } - - this.chunkCheck(entity); -@@ -821,14 +829,18 @@ public class WorldServer extends World { - entity1.lastPitch = entity1.pitch; - if (entity1.inChunk) { - ++entity1.ticksLived; -+ // Akarin start - remove caller -+ /* - GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); - - gameprofilerfiller.a(() -> { - return IRegistry.ENTITY_TYPE.getKey(entity1.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickPassenger"); -+ */ -+ // Akarin end - entity1.passengerTick(); -- gameprofilerfiller.exit(); -+ // gameprofilerfiller.exit(); // Akarin - remove caller - } - - this.chunkCheck(entity1); -@@ -849,7 +861,7 @@ public class WorldServer extends World { - } - - public void chunkCheck(Entity entity) { -- this.getMethodProfiler().enter("chunkCheck"); -+ // this.getMethodProfiler().enter("chunkCheck"); // Akarin - remove caller - int i = MathHelper.floor(entity.locX() / 16.0D); - int j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior; - int k = MathHelper.floor(entity.locZ() / 16.0D); -@@ -866,7 +878,7 @@ public class WorldServer extends World { - } - } - -- this.getMethodProfiler().exit(); -+ // this.getMethodProfiler().exit(); // Akarin - remove caller - } - - @Override diff --git a/patches/server/0012-Asynchronous-pathfinding.patch b/patches/server/0012-Asynchronous-pathfinding.patch index 8d4054e8e..5d12f21dc 100644 --- a/patches/server/0012-Asynchronous-pathfinding.patch +++ b/patches/server/0012-Asynchronous-pathfinding.patch @@ -6,17 +6,17 @@ Subject: [PATCH] Asynchronous pathfinding diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index bb20398abc65d3f7e54867bdf930480af0941ada..cd8b462866f3f89405aabad692466483da64b49b 100644 +index 5aca7a9131787415fb2edba1ebec9601e8a56d3a..7a0f18a8f7d7cdeca9a45485f5b22353e726aae8 100644 --- a/src/main/java/net/minecraft/server/EntityInsentient.java +++ b/src/main/java/net/minecraft/server/EntityInsentient.java @@ -686,7 +686,7 @@ public abstract class EntityInsentient extends EntityLiving { this.goalSelector.doTick(); - // this.world.getMethodProfiler().exit(); // Akarin - remove caller - // this.world.getMethodProfiler().enter("navigation"); // Akarin - remove caller + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().enter("navigation"); - this.navigation.c(); + this.navigation.tickAsync(); // Akarin - Async pathfinder - // this.world.getMethodProfiler().exit(); // Akarin - remove caller - // this.world.getMethodProfiler().enter("mob tick"); // Akarin - remove caller + this.world.getMethodProfiler().exit(); + this.world.getMethodProfiler().enter("mob tick"); this.mobTick(); diff --git a/src/main/java/net/minecraft/server/Navigation.java b/src/main/java/net/minecraft/server/Navigation.java index abf450917e605972d84cb603b966feb013ae0002..4f7f40d5e7050d9b2da29c6e6efe7c5bef560d55 100644 @@ -32,7 +32,7 @@ index abf450917e605972d84cb603b966feb013ae0002..4f7f40d5e7050d9b2da29c6e6efe7c5b if (pathtype == PathType.WATER) { return false; diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java -index cd8a631d7d3c6fbdd2470635173659f0eddddae2..c134a96080b3826342f54db41e8d80981db8c101 100644 +index dc32107ec320fa54487f24c9d68ff8e5a6dea1bb..f7ea00d6ffa2000c4d0d74b5856ba66bba165d5a 100644 --- a/src/main/java/net/minecraft/server/NavigationAbstract.java +++ b/src/main/java/net/minecraft/server/NavigationAbstract.java @@ -29,6 +29,15 @@ public abstract class NavigationAbstract { diff --git a/patches/server/0013-Optimizations-for-network.patch b/patches/server/0013-Optimizations-for-network.patch deleted file mode 100644 index ea2643b02..000000000 --- a/patches/server/0013-Optimizations-for-network.patch +++ /dev/null @@ -1,461 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E3=84=97=E3=84=A0=CB=8B=20=E3=84=91=E3=84=A7=CB=8A?= - -Date: Sun, 5 Apr 2020 14:59:10 +0800 -Subject: [PATCH] Optimizations for network - - -diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -index a85466bc7e0a8aa54b9eff14077fe6c992ae2902..324af1a12a5780170f8cd6e060ff2f2f9d152c3d 100644 ---- a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -+++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -@@ -106,7 +106,7 @@ public final class StandardPaperServerListPingEventImpl extends PaperServerListP - } - - // Send response -- networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ networkManager.sendPacketAsync(new PacketStatusOutServerInfo(ping)); // Akarin - Async Sending packets - } - - } -diff --git a/src/main/java/net/minecraft/server/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java -index 0532f975b7af5b3f2916c26141221cd3701765d0..e7be1074b1b8fde3590b1323508965961824e671 100644 ---- a/src/main/java/net/minecraft/server/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/HandshakeListener.java -@@ -39,7 +39,7 @@ public class HandshakeListener implements PacketHandshakingInListener { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); - chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message -- this.b.sendPacket(new PacketLoginOutDisconnect(chatmessage)); -+ this.b.sendPacketAsync(new PacketLoginOutDisconnect(chatmessage)); // Akarin - Async Sending packets - this.b.close(chatmessage); - return; - } -@@ -66,11 +66,11 @@ public class HandshakeListener implements PacketHandshakingInListener { - - if (packethandshakinginsetprotocol.c() > SharedConstants.getGameVersion().getProtocolVersion()) { - chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -- this.b.sendPacket(new PacketLoginOutDisconnect(chatmessage)); -+ this.b.sendPacketAsync(new PacketLoginOutDisconnect(chatmessage)); - this.b.close(chatmessage); - } else if (packethandshakinginsetprotocol.c() < SharedConstants.getGameVersion().getProtocolVersion()) { - chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -- this.b.sendPacket(new PacketLoginOutDisconnect(chatmessage)); -+ this.b.sendPacketAsync(new PacketLoginOutDisconnect(chatmessage)); - this.b.close(chatmessage); - } else { - this.b.setPacketListener(new LoginListener(this.a, this.b)); -diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java -index f1222fcb2bd52b8781d0f92c94e1472fa7b1e493..522cfed4cb09bc9ecc48b6313da47f9af7a5e1d8 100644 ---- a/src/main/java/net/minecraft/server/LoginListener.java -+++ b/src/main/java/net/minecraft/server/LoginListener.java -@@ -111,6 +111,19 @@ public class LoginListener implements PacketLoginInListener { - - } - -+ // Akarin Start - Async Sending packets -+ public void disconnectAsync(IChatBaseComponent ichatbasecomponent) { -+ try { -+ LoginListener.LOGGER.info("Disconnecting {}: {}", this.d(), ichatbasecomponent.getString()); -+ this.networkManager.sendPacketAsync(new PacketLoginOutDisconnect(ichatbasecomponent)); -+ this.networkManager.close(ichatbasecomponent); -+ } catch (Exception exception) { -+ LoginListener.LOGGER.error("Error whilst disconnecting player", exception); -+ } -+ -+ } -+ // Akarin End - Async Sending packets -+ - // Paper start - Cache authenticator threads - private static final AtomicInteger threadId = new AtomicInteger(0); - private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( -@@ -192,7 +205,7 @@ public class LoginListener implements PacketLoginInListener { - this.i = packetlogininstart.b(); - if (this.server.getOnlineMode() && !this.networkManager.isLocal()) { - this.g = LoginListener.EnumProtocolState.KEY; -- this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic(), this.e)); -+ this.networkManager.sendPacketAsync(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic(), this.e)); // Akarin - Async Sending packets - } else { - // Paper start - Velocity support - if (com.destroystokyo.paper.PaperConfig.velocitySupport) { -@@ -254,7 +267,7 @@ public class LoginListener implements PacketLoginInListener { - LoginListener.this.i = LoginListener.this.a(gameprofile); - LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; - } else { -- LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.unverified_username", new Object[0])); -+ LoginListener.this.disconnectAsync(new ChatMessage("multiplayer.disconnect.unverified_username", new Object[0])); // Akarin - Async Sending packets - LoginListener.LOGGER.error("Username '{}' tried to join with an invalid session", gameprofile.getName()); - } - } catch (AuthenticationUnavailableException authenticationunavailableexception) { -@@ -267,7 +280,7 @@ public class LoginListener implements PacketLoginInListener { - if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { - LoginListener.this.disconnect(new ChatComponentText(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); - } else // Paper end -- LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.authservers_down", new Object[0])); -+ LoginListener.this.disconnectAsync(new ChatMessage("multiplayer.disconnect.authservers_down", new Object[0])); // Akarin - Async Sending packets - LoginListener.LOGGER.error("Couldn't verify username because servers are unavailable"); - } - // CraftBukkit start - catch all exceptions -@@ -376,7 +389,7 @@ public class LoginListener implements PacketLoginInListener { - return; - } - // Paper end -- this.disconnect(new ChatMessage("multiplayer.disconnect.unexpected_query_response", new Object[0])); -+ this.disconnectAsync(new ChatMessage("multiplayer.disconnect.unexpected_query_response", new Object[0])); // Akarin - Async Sending packets - } - - protected GameProfile a(GameProfile gameprofile) { -diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java -index 96a785af27e1924b0cc1959254d4ae3cdd0385a1..fd1d5fe3bf40950d5dbdd9fa79cf5828c7b42d57 100644 ---- a/src/main/java/net/minecraft/server/NetworkManager.java -+++ b/src/main/java/net/minecraft/server/NetworkManager.java -@@ -43,6 +43,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - }); - private final EnumProtocolDirection h; - private final Queue packetQueue = Queues.newConcurrentLinkedQueue(); private final Queue getPacketQueue() { return this.packetQueue; } // Paper - OBFHELPER -+ private EnumProtocol protocol; // Akarin - avoid map lookup - public Channel channel; - public SocketAddress socketAddress; public void setSpoofedRemoteAddress(SocketAddress address) { this.socketAddress = address; } // Paper - OBFHELPER - // Spigot Start -@@ -88,6 +89,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - public void setProtocol(EnumProtocol enumprotocol) { - this.channel.attr(NetworkManager.c).set(enumprotocol); -+ protocol = enumprotocol; // Akarin - avoid map lookup - this.channel.config().setAutoRead(true); - NetworkManager.LOGGER.debug("Enabled auto read"); - } -@@ -175,8 +177,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER - private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { -- EnumProtocol enumprotocol = EnumProtocol.a(packet); -- EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); -+ EnumProtocol enumprotocol = packet.protocol();//EnumProtocol.a(packet); // Akarin - avoid map lookup -+ EnumProtocol enumprotocol1 = protocol;//(EnumProtocol) this.channel.attr(NetworkManager.c).get(); // Akarin - avoid map lookup - - ++this.q; - if (enumprotocol1 != enumprotocol) { -@@ -184,7 +186,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - this.channel.config().setAutoRead(false); - } - -- if (this.channel.eventLoop().inEventLoop()) { -+ if (false && this.channel.eventLoop().inEventLoop()) { // Akarin - Async Sending packets - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } -@@ -223,30 +225,92 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - } - -- // Paper start - Async-Anti-Xray - Stop dispatching further packets and return false if the peeked packet is a chunk packet which is not ready -- private boolean sendPacketQueue() { return this.o(); } // OBFHELPER // void -> boolean -- private boolean o() { // void -> boolean -- if (this.channel != null && this.channel.isOpen()) { -- Queue queue = this.packetQueue; -- -- synchronized (this.packetQueue) { -- while (!this.packetQueue.isEmpty()) { -- NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.getPacketQueue().peek(); // poll -> peek -- -- if (networkmanager_queuedpacket != null) { // Fix NPE (Spigot bug caused by handleDisconnection()) -- if (networkmanager_queuedpacket.getPacket() instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) networkmanager_queuedpacket.getPacket()).isReady()) { // Check if the peeked packet is a chunk packet which is not ready -- return false; // Return false if the peeked packet is a chunk packet which is not ready -- } else { -- this.getPacketQueue().poll(); // poll here -- this.dispatchPacket(networkmanager_queuedpacket.getPacket(), networkmanager_queuedpacket.getGenericFutureListener()); // dispatch the packet -- } -- } -- } -+ // Akarin Start - Async Sending packets - multiple packets, copied from above -+ public void sendPacketAsync(Packet packet) { -+ EnumProtocol enumprotocol = packet.protocol(); -+ EnumProtocol enumprotocol1 = protocol; - -- } -+ ++this.q; -+ if (enumprotocol1 != enumprotocol) { -+ NetworkManager.LOGGER.debug("Disabled auto read"); -+ this.channel.config().setAutoRead(false); -+ this.setProtocol(enumprotocol); - } - -- return true; // Return true if all packets were dispatched -+ ChannelFuture channelfuture = this.channel.writeAndFlush(packet); -+ -+ channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ -+ } -+ -+ public void sendPackets(Packet packet, Packet other) { -+ EnumProtocol enumprotocol = packet.protocol(); -+ -+ ++this.q; -+ if (protocol != enumprotocol) { -+ NetworkManager.LOGGER.debug("Disabled auto read"); -+ this.channel.config().setAutoRead(false); -+ } -+ -+ this.channel.eventLoop().execute(() -> { -+ if (enumprotocol != protocol) { -+ this.setProtocol(enumprotocol); -+ } -+ -+ this.channel.write(packet).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ this.channel.write(other).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ this.channel.flush(); -+ }); -+ } -+ -+ public void sendPackets(Packet packet, Packet ...packets) { -+ EnumProtocol enumprotocol = packet.protocol(); -+ -+ ++this.q; -+ if (protocol != enumprotocol) { -+ NetworkManager.LOGGER.debug("Disabled auto read"); -+ this.channel.config().setAutoRead(false); -+ } -+ -+ this.channel.eventLoop().execute(() -> { -+ if (enumprotocol != protocol) { -+ this.setProtocol(enumprotocol); -+ } -+ -+ this.channel.write(packet).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ for (Packet pkt : packets) { -+ this.channel.write(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ } -+ -+ this.channel.flush(); -+ }); -+ } -+ // Akarin End -+ -+ // Paper start - Async-Anti-Xray - Stop dispatching further packets and return false if the peeked packet is a chunk packet which is not ready -+ private boolean sendPacketQueue() { return this.o(); } // OBFHELPER // void -> boolean -+ private boolean o() { // void -> boolean -+ if (this.channel != null && this.channel.isOpen()) { -+ Queue queue = this.packetQueue; -+ -+ synchronized (this.packetQueue) { -+ while (!this.packetQueue.isEmpty()) { -+ NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.getPacketQueue().peek(); // poll -> peek -+ -+ if (networkmanager_queuedpacket != null) { // Fix NPE (Spigot bug caused by handleDisconnection()) -+ if (networkmanager_queuedpacket.getPacket() instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) networkmanager_queuedpacket.getPacket()).isReady()) { // Check if the peeked packet is a chunk packet which is not ready -+ return false; // Return false if the peeked packet is a chunk packet which is not ready -+ } else { -+ this.getPacketQueue().poll(); // poll here -+ this.dispatchPacket(networkmanager_queuedpacket.getPacket(), networkmanager_queuedpacket.getGenericFutureListener()); // dispatch the packet -+ } -+ } -+ } -+ -+ } -+ } -+ -+ return true; // Return true if all packets were dispatched - } - // Paper end - -@@ -260,9 +324,9 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - ((PlayerConnection) this.packetListener).tick(); - } - -- if (this.channel != null) { -- if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version -- } -+ //if (this.channel != null) { // Akarin - already did -+ //if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version -+ //} - - if (this.t++ % 20 == 0) { - this.s = this.s * 0.75F + (float) this.q * 0.25F; -diff --git a/src/main/java/net/minecraft/server/Packet.java b/src/main/java/net/minecraft/server/Packet.java -index 8d0965a0535b16f19eda21b97a44464b85b05460..7e27cd280fa889f6178d46aa9f9d3a613d9702e6 100644 ---- a/src/main/java/net/minecraft/server/Packet.java -+++ b/src/main/java/net/minecraft/server/Packet.java -@@ -20,4 +20,10 @@ public interface Packet { - default boolean a() { - return false; - } -+ -+ // Akarin start - add protocol -+ default EnumProtocol protocol() { -+ return EnumProtocol.PLAY; -+ } -+ // Akarin end - } -diff --git a/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java b/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java -index 7eb230f1b27eddf48f1b12fc78877a3678d802df..d01cac0bd40a11d82fa0d6874d87ad3f576a4e20 100644 ---- a/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java -+++ b/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java -@@ -41,4 +41,11 @@ public class PacketLoginOutCustomPayload implements Packet - public void a(PacketLoginOutListener packetloginoutlistener) { - packetloginoutlistener.a(this); - } -+ -+ // Akarin start - add protocol -+ @Override -+ public EnumProtocol protocol() { -+ return EnumProtocol.LOGIN; -+ } -+ // Akarin end - } -diff --git a/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java b/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java -index b0d6342c319a48290fd8bf6aa07a16d108feae18..eeabb54c44d39197f34a7171884cc7e885bce453 100644 ---- a/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java -+++ b/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java -@@ -34,4 +34,11 @@ public class PacketLoginOutEncryptionBegin implements Packet { - public void a(PacketLoginOutListener packetloginoutlistener) { - packetloginoutlistener.a(this); - } -+ -+ // Akarin start - add protocol -+ @Override -+ public EnumProtocol protocol() { -+ return EnumProtocol.LOGIN; -+ } -+ // Akarin end - } -diff --git a/src/main/java/net/minecraft/server/PacketStatusListener.java b/src/main/java/net/minecraft/server/PacketStatusListener.java -index 4bb21c48bd50353370ec3c3546a00a5d20e4b9d8..06af567fc1fb3a2053eb4e8af6d93dbb2391616a 100644 ---- a/src/main/java/net/minecraft/server/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/PacketStatusListener.java -@@ -143,7 +143,7 @@ public class PacketStatusListener implements PacketStatusInListener { - - @Override - public void a(PacketStatusInPing packetstatusinping) { -- this.networkManager.sendPacket(new PacketStatusOutPong(packetstatusinping.b())); -+ this.networkManager.sendPacketAsync(new PacketStatusOutPong(packetstatusinping.b())); // Akarin - Async Sending packets - this.networkManager.close(PacketStatusListener.a); - } - } -diff --git a/src/main/java/net/minecraft/server/PacketStatusOutPong.java b/src/main/java/net/minecraft/server/PacketStatusOutPong.java -index 94a0da87db34ee5131686e4fa813500794ffc30d..577c6ef9cfe26d38783cd38353720b0fe457d7f5 100644 ---- a/src/main/java/net/minecraft/server/PacketStatusOutPong.java -+++ b/src/main/java/net/minecraft/server/PacketStatusOutPong.java -@@ -25,4 +25,11 @@ public class PacketStatusOutPong implements Packet { - public void a(PacketStatusOutListener packetstatusoutlistener) { - packetstatusoutlistener.a(this); - } -+ -+ // Akarin start - add protocol -+ @Override -+ public EnumProtocol protocol() { -+ return EnumProtocol.STATUS; -+ } -+ // Akarin end - } -diff --git a/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java b/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java -index 50d5fb62efa7c89c7a73ccf072a0e7e433bcc650..4da7a2c1a4f84661e1018c7233b7a52449532d5b 100644 ---- a/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java -+++ b/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java -@@ -28,4 +28,11 @@ public class PacketStatusOutServerInfo implements Packet pendingChunkUpdates = new java.util.LinkedList<>(); // PAIL pendingChunkUpdates // Paper - use a queue + private final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque<>(); // PAIL pendingChunkUpdates // Paper - use a queue // Akarin - backport Tuinity - use a better queue diff --git a/patches/server/0016-Optimize-door-interact-with-pathfinding.patch b/patches/server/0015-Optimize-door-interact-with-pathfinding.patch similarity index 100% rename from patches/server/0016-Optimize-door-interact-with-pathfinding.patch rename to patches/server/0015-Optimize-door-interact-with-pathfinding.patch diff --git a/patches/server/0017-Remove-stream-for-ender-teleport.patch b/patches/server/0016-Remove-stream-for-ender-teleport.patch similarity index 86% rename from patches/server/0017-Remove-stream-for-ender-teleport.patch rename to patches/server/0016-Remove-stream-for-ender-teleport.patch index b62a167e3..2ea029771 100644 --- a/patches/server/0017-Remove-stream-for-ender-teleport.patch +++ b/patches/server/0016-Remove-stream-for-ender-teleport.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Remove stream for ender teleport diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 46ea798509579103726772bdd014cd59b108482a..886c7af2d70ba7224f3dcfab000223104a9a86d8 100644 +index d4601ff5e7bdf871738f6f63cc4d4f239924cdc6..65cf51852b98eb4f2ed7bc4d753b9ae4a0d46c75 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java -@@ -2876,7 +2876,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -2902,7 +2902,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke WorldServer worldserver = (WorldServer) this.world; this.setPositionRotation(d0, d1, d2, this.yaw, this.pitch); @@ -17,7 +17,7 @@ index 46ea798509579103726772bdd014cd59b108482a..886c7af2d70ba7224f3dcfab00022310 worldserver.chunkCheck(entity); entity.aF = true; entity.a(Entity::teleportAndSync); -@@ -3125,6 +3125,14 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke +@@ -3151,6 +3151,14 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke public Stream cg() { return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::cg)); } diff --git a/patches/server/0018-Cache-hashcode-for-BlockPosition.patch b/patches/server/0017-Cache-hashcode-for-BlockPosition.patch similarity index 93% rename from patches/server/0018-Cache-hashcode-for-BlockPosition.patch rename to patches/server/0017-Cache-hashcode-for-BlockPosition.patch index 21479b0ce..20ed0e5fb 100644 --- a/patches/server/0018-Cache-hashcode-for-BlockPosition.patch +++ b/patches/server/0017-Cache-hashcode-for-BlockPosition.patch @@ -39,10 +39,10 @@ index c439a8d0191c8667c881b2111b8c640ca13e5e7c..cc18560431d65f13f28b45025a702afe public int compareTo(BaseBlockPosition baseblockposition) { return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index 2d07d350d2b73197b6ea73cf90ff59679da7e0e7..43e7e5c27b454db3289407f14f6568d1d8944b69 100644 +index 07813c55cdc85e08697d4126973f829ae564cf41..52b810da6af78a8df0f960d8d871fb0c22eccc4c 100644 --- a/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -439,6 +439,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali +@@ -440,6 +440,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali this.y = j; this.z = k; // Paper end @@ -50,7 +50,7 @@ index 2d07d350d2b73197b6ea73cf90ff59679da7e0e7..43e7e5c27b454db3289407f14f6568d1 return this; } -@@ -479,16 +480,19 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali +@@ -480,16 +481,19 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali public final void setX(final int x) { this.o(x); } // Paper - OBFHELPER public void o(int i) { this.x = i; // Paper change to x diff --git a/patches/server/0019-Remove-stream-and-simplify-operation-in-pathfinder.patch b/patches/server/0018-Remove-stream-and-simplify-operation-in-pathfinder.patch similarity index 100% rename from patches/server/0019-Remove-stream-and-simplify-operation-in-pathfinder.patch rename to patches/server/0018-Remove-stream-and-simplify-operation-in-pathfinder.patch diff --git a/patches/server/0020-Remove-a-few-more-streams.patch b/patches/server/0019-Remove-a-few-more-streams.patch similarity index 93% rename from patches/server/0020-Remove-a-few-more-streams.patch rename to patches/server/0019-Remove-a-few-more-streams.patch index 5466482e6..22bfdcc9d 100644 --- a/patches/server/0020-Remove-a-few-more-streams.patch +++ b/patches/server/0019-Remove-a-few-more-streams.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Remove a few more streams diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java -index 13d113aee5e174fc4558173a19a0cda23166c5e9..1890fad9ed10c514b7b5982d2c112f7dc52866a5 100644 +index 014a4142427cc6adfec2ed13d95aebcede1f1e96..c278906d795ab2c2c233dc23eb331328c089fef4 100644 --- a/src/main/java/net/minecraft/server/ChunkMapDistance.java +++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java -@@ -108,9 +108,15 @@ public abstract class ChunkMapDistance { +@@ -110,9 +110,15 @@ public abstract class ChunkMapDistance { while (longiterator.hasNext()) { long j = longiterator.nextLong(); @@ -24,7 +24,7 @@ index 13d113aee5e174fc4558173a19a0cda23166c5e9..1890fad9ed10c514b7b5982d2c112f7d PlayerChunk playerchunk = playerchunkmap.getUpdatingChunk(j); if (playerchunk == null) { -@@ -126,6 +132,22 @@ public abstract class ChunkMapDistance { +@@ -128,6 +134,22 @@ public abstract class ChunkMapDistance { }); }); } @@ -76,7 +76,7 @@ index 9c31edade247baac6811ef3ec98e88a332bcffba..eb3f45d8b707002ebeca20a6857ed414 } // Paper end diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java -index a7a07ffc43d4e95af59da1194ae90394580bb242..c9f0f7787fd73ca28b45e4c21d33d50965c65860 100644 +index 1094324d004a1841a3b67cf9de07ec1795524607..1e7be8cbac5b35cd05bf45fc3b19c7f6736c649f 100644 --- a/src/main/java/net/minecraft/server/EntityVillager.java +++ b/src/main/java/net/minecraft/server/EntityVillager.java @@ -548,11 +548,20 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation diff --git a/patches/server/0021-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch b/patches/server/0020-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch similarity index 92% rename from patches/server/0021-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch rename to patches/server/0020-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch index cc09eb4df..b7693ddb7 100644 --- a/patches/server/0021-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch +++ b/patches/server/0020-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch @@ -8,10 +8,10 @@ Should limit build up of I/O tasks, or at least properly indicate to server owners that I/O is falling behind diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index f8ad08cccf25ef26759231c3d26b71d33d010eb8..7b7e1b2b45dcfe55c4052dacdcc2ca629ca4521b 100644 +index 81bb26abc520f49de2e916cf2757ac4c710d02cd..7808dcd7e1e9a30adb441c2eb47a4410b5afa059 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -599,7 +599,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -789,7 +789,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { } com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, @@ -20,7 +20,7 @@ index f8ad08cccf25ef26759231c3d26b71d33d010eb8..7b7e1b2b45dcfe55c4052dacdcc2ca62 if (!chunk.isNeedsSaving()) { return; -@@ -633,7 +633,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -823,7 +823,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); } @@ -29,7 +29,7 @@ index f8ad08cccf25ef26759231c3d26b71d33d010eb8..7b7e1b2b45dcfe55c4052dacdcc2ca62 asyncSaveData, chunk); chunk.setLastSaved(this.world.getTime()); -@@ -1045,7 +1045,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -1232,7 +1232,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { // Paper start - async chunk io private boolean writeDataAsync(ChunkCoordIntPair chunkPos, NBTTagCompound poiData, NBTTagCompound chunkData, boolean async) { com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, diff --git a/patches/server/0022-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch b/patches/server/0021-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch similarity index 88% rename from patches/server/0022-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch rename to patches/server/0021-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch index f2ad16344..04b86c48d 100644 --- a/patches/server/0022-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch +++ b/patches/server/0021-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Tuinity Log exceptions for async chunk load failures diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index bf6bf7d8c6c7e2d8572a33ed16767d8ba34156e7..1119dd5048cbb8cdd5727e18b154ed15a9a06b63 100644 +index d6f4daeec90149ef402c2746a4a054c44f7eb21f..f3943532dca289d4ffd1dc1dc645ca1e41949958 100644 --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -326,7 +326,10 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -407,7 +407,10 @@ public class ChunkProviderServer extends IChunkProvider { // either right -> failure if (throwable != null) { @@ -21,7 +21,7 @@ index bf6bf7d8c6c7e2d8572a33ed16767d8ba34156e7..1119dd5048cbb8cdd5727e18b154ed15 } this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -@@ -336,12 +339,19 @@ public class ChunkProviderServer extends IChunkProvider { +@@ -417,12 +420,19 @@ public class ChunkProviderServer extends IChunkProvider { if (failure.isPresent()) { // failure @@ -44,10 +44,10 @@ index bf6bf7d8c6c7e2d8572a33ed16767d8ba34156e7..1119dd5048cbb8cdd5727e18b154ed15 public void addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index f56131e3a593f9c1344be07fe478364b344e63dd..0f3199ba4a228cc60db3abfa4ac926b92cbb4b4b 100644 +index 4aafad0762df44990ed9d610a59f3862bd3fe3b0..5583e26fb62d0a0e4ca8e995f609c474a6f0c4c9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2472,6 +2472,13 @@ public class CraftWorld implements World { +@@ -2476,6 +2476,13 @@ public class CraftWorld implements World { this.world.doIfNotEntityTicking(() -> ret.complete(chunk == null ? null : chunk.bukkitChunk)); }); diff --git a/patches/server/0023-Tuinity-Util-patch.patch b/patches/server/0023-Tuinity-Util-patch.patch deleted file mode 100644 index 3799ef540..000000000 --- a/patches/server/0023-Tuinity-Util-patch.patch +++ /dev/null @@ -1,242 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E3=84=97=E3=84=A0=CB=8B=20=E3=84=91=E3=84=A7=CB=8A?= - -Date: Sat, 18 Apr 2020 19:54:01 +0800 -Subject: [PATCH] Tuinity Util patch - - -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 1119dd5048cbb8cdd5727e18b154ed15a9a06b63..6a2a6e671f230fd6a8adb5e6ccec22dede740f44 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -683,11 +683,10 @@ public class ChunkProviderServer extends IChunkProvider { - EnumCreatureType[] aenumcreaturetype = EnumCreatureType.values(); - // Paper start - per player mob spawning - int[] worldMobCount; -- if (this.playerChunkMap.playerMobDistanceMap != null) { -+ // Tuinity start - use view distance map -+ if (this.world.paperConfig.perPlayerMobSpawns) { - // update distance map -- this.world.timings.playerMobDistanceMapUpdate.startTiming(); -- this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); -- this.world.timings.playerMobDistanceMapUpdate.stopTiming(); -+ // Tuinity end - use view distance map - // re-set mob counts - for (EntityPlayer player : this.world.players) { - Arrays.fill(player.mobCounts, 0); -@@ -770,9 +769,23 @@ public class ChunkProviderServer extends IChunkProvider { - - if (this.world.paperConfig.perPlayerMobSpawns) { - int minDiff = Integer.MAX_VALUE; -- for (EntityPlayer entityplayer : this.playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { -+ // Tuinity start - use view distance map -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = this.playerChunkMap.playerViewDistanceMap.getObjectsInRange(chunk.coordinateKey); -+ if (players != null) { -+ Object[] backingSet = players.getBackingSet(); -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ Object temp = backingSet[index]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer entityplayer = (EntityPlayer)temp; -+ if (entityplayer.isSpectator() || !entityplayer.affectsSpawning) { -+ continue; -+ } -+ // Tuinity end - use view distance map - minDiff = Math.min(limit - this.playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); - } -+ } // Tuinity - use view distance map - difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; - } - -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index b4c3dffaff5ea64d9189304c5e84c515bf40ed65..ec2f66ef0cc56229078dacad61cd6ab3a5c6cb11 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -110,6 +110,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -+ // Tuinity start -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSetTuinity; -+ // Tuinity end -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super((World) worldserver, gameprofile); - playerinteractmanager.player = this; -@@ -128,6 +132,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.canPickUpLoot = true; - this.maxHealthCache = this.getMaxHealth(); - this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -+ // Tuinity start -+ this.cachedSingleHashSetTuinity = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); -+ // Tuinity end - } - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. -diff --git a/src/main/java/net/minecraft/server/HeightMap.java b/src/main/java/net/minecraft/server/HeightMap.java -index 29cb545a864dea09ba52b6071f5280cdddd33808..37a6da9ee9aab7acaf2f1559917e415217444747 100644 ---- a/src/main/java/net/minecraft/server/HeightMap.java -+++ b/src/main/java/net/minecraft/server/HeightMap.java -@@ -119,6 +119,7 @@ public class HeightMap { - } - } - -+ public final int get(int x, int z) { return this.a(x, z); } // Tuinity - OBFHELPER - public int a(int i, int j) { - return this.a(c(i, j)); - } -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 7b7e1b2b45dcfe55c4052dacdcc2ca629ca4521b..2acdb72d7ee4bba043f8b083a2ed6c2ec1a5111d 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -81,7 +81,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final Int2ObjectMap trackedEntities; - private final Queue z; - int viewDistance; // Paper - private -> package private -- public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper -+ //public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper // Tuinity - replaced by view distance map - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -136,6 +136,29 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - - // Paper end -+ // Tuinity start - distance maps -+ final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledEntityPlayerSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceMap; -+ -+ void addPlayerToDistanceMapsTuinity(EntityPlayer player) { -+ this.updateMapsTuinity(player); -+ } -+ -+ void removePlayerFromDistanceMapsTuinity(EntityPlayer player) { -+ this.playerViewDistanceMap.remove(player); -+ } -+ -+ void updateDistanceMapsTuinity(EntityPlayer player) { -+ this.updateMapsTuinity(player); -+ } -+ -+ private void updateMapsTuinity(EntityPlayer player) { -+ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.locZ()); -+ -+ this.playerViewDistanceMap.update(player, chunkX, chunkZ, this.viewDistance); -+ } -+ // Tuinity end - - // Paper start - Reduce entity tracker updates on move - private double trackerUpdateDistanceSquared; -@@ -201,8 +224,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.l = supplier; - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, this.world); // Paper - this.setViewDistance(i); -- this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ //this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper // Tuinity - distance maps - this.trackerUpdateDistanceSquared = Math.pow(this.world.paperConfig.trackerUpdateDistance, 2); // Paper -+ // Tuinity start - distance maps -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets sets = this.pooledEntityPlayerSets; -+ this.playerViewDistanceMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(sets); -+ // Tuinity end - distance maps - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -213,9 +240,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int chunkZ = (int)Math.floor(entity.locZ()) >> 4; - int index = entity.getEntityType().getEnumCreatureType().ordinal(); - -- for (EntityPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { -+ // Tuinity start - use view distance map -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = this.playerViewDistanceMap.getObjectsInRange(chunkX, chunkZ); -+ if (players != null) { -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ if (player.isSpectator() || !player.affectsSpawning) { -+ continue; -+ } -+ // Tuinity end - use view distance map - ++player.mobCounts[index]; - } -+ } // Tuinity - use view distance map - } - - public int getMobCountNear(EntityPlayer entityPlayer, EnumCreatureType enumCreatureType) { -@@ -1545,7 +1586,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - this.updateMaps(entityplayer); // Paper - distance maps -- -+ this.updateDistanceMapsTuinity(entityplayer); // Tuinity - distance maps - } - - @Override -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 75605d44bc4c051a7afa327a8749a0a67790b165..7129cb0260316e166b4b15cded0e0c0b32433b7f 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1214,9 +1214,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - int k = MathHelper.floor((axisalignedbb.minZ - 2.0D) / 16.0D); - int l = MathHelper.floor((axisalignedbb.maxZ + 2.0D) / 16.0D); - -+ ChunkProviderServer chunkProvider = ((ChunkProviderServer)this.chunkProvider); // Tuinity - optimize for loaded chunks -+ - for (int i1 = i; i1 <= j; ++i1) { - for (int j1 = k; j1 <= l; ++j1) { -- Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper -+ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThread(i1, j1); // Paper // Tuinity - optimize for loaded chunks - - if (chunk != null) { - chunk.a(entity, axisalignedbb, list, predicate); -@@ -1235,9 +1237,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - int l = MathHelper.f((axisalignedbb.maxZ + 2.0D) / 16.0D); - List list = Lists.newArrayList(); - -+ ChunkProviderServer chunkProvider = ((ChunkProviderServer)this.chunkProvider); // Tuinity - optimize for loaded chunks -+ - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper -+ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThread(i1, j1); // Paper // Tuinity - optimize for loaded chunks - - if (chunk != null) { - chunk.a(entitytypes, axisalignedbb, list, predicate); -@@ -1257,10 +1261,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - int l = MathHelper.f((axisalignedbb.maxZ + 2.0D) / 16.0D); - List list = Lists.newArrayList(); - IChunkProvider ichunkprovider = this.getChunkProvider(); -+ ChunkProviderServer chunkProvider = ((ChunkProviderServer)this.chunkProvider); // Tuinity - optimize for loaded chunks - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper -+ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThread(i1, j1); // Paper // Tuinity - optimize for loaded chunks - - if (chunk != null) { - chunk.a(oclass, axisalignedbb, list, predicate); -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 78fdacdaf119b9c3fab477ee98089bbad5da2d73..4d080d74dc949ea93ce34aa1906144740b9c99f6 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -1227,6 +1227,7 @@ public class WorldServer extends World { - - this.registerEntity(entityplayer); - this.getChunkProvider().playerChunkMap.addPlayerToDistanceMaps(entityplayer); // Paper - distance maps -+ this.getChunkProvider().playerChunkMap.addPlayerToDistanceMapsTuinity(entityplayer); // Tuinity - distance maps - } - - // CraftBukkit start -@@ -1438,6 +1439,7 @@ public class WorldServer extends World { - - this.players.remove(entityplayer); - this.getChunkProvider().playerChunkMap.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps -+ this.getChunkProvider().playerChunkMap.removePlayerFromDistanceMapsTuinity(entityplayer); // Tuinity - distance maps - } - - this.getScoreboard().a(entity); diff --git a/patches/server/0024-Tuinity-Per-player-view-distance-implementation.patch b/patches/server/0024-Tuinity-Per-player-view-distance-implementation.patch deleted file mode 100644 index ddd371689..000000000 --- a/patches/server/0024-Tuinity-Per-player-view-distance-implementation.patch +++ /dev/null @@ -1,1499 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E3=84=97=E3=84=A0=CB=8B=20=E3=84=91=E3=84=A7=CB=8A?= - -Date: Sat, 18 Apr 2020 19:57:30 +0800 -Subject: [PATCH] Tuinity Per player view distance implementation - -This patch implements CraftPlayer#setViewDistance and -CraftPlayer#getViewDistance - -This patch replaces the existing system to handle player tickets -and chunk sending to players. - Most of the work is pulled by two -PlayerAreaMap's controlling: a radius for sending chunks and a radius -for adding player tickets. Currently the difference between the two -radii is just 1. -Normal vanilla has a difference of two, but this -causes issues where outer chunks in the view distance sometimes -do not send. This is because the outer radius is not guaranteed to -be at ticket level 32, which is required to be sent to players. - -The ticket manager in ChunkMapDistance for players is no longer used and -is entirely replaced by the ticket distance map. The ticket tracker also -adds a configurable chunk load rate per player. - -This patch moves the order of the distance map update in movePlayer -until after a client is sent a center section packet. This is required -to avoid the client rejecting chunks it receives when teleporting. - -diff --git a/src/main/java/io/akarin/server/Config.java b/src/main/java/io/akarin/server/Config.java -index 2ac8f02a97429f04f3e5c9206ec228edccaf24c9..13608380b24a52666c8238f109d8ab507e75debf 100644 ---- a/src/main/java/io/akarin/server/Config.java -+++ b/src/main/java/io/akarin/server/Config.java -@@ -96,6 +96,42 @@ public final class Config { - return Config.config.getDouble(path, dfl); - } - -+ public static double maxChunkSendsPerPlayer; // per second -+ -+ public static int[] maxChunkSendsPerPlayerChoice = new int[100]; -+ -+ private static void maxChunkLoadsPerPlayer() { -+ maxChunkSendsPerPlayer = Config.getDouble("target-chunk-sends-per-player-per-second", 40.0); -+ if (maxChunkSendsPerPlayer <= -1.0) { -+ maxChunkSendsPerPlayer = Integer.MAX_VALUE; -+ } else if (maxChunkSendsPerPlayer <= 1.0) { -+ maxChunkSendsPerPlayer = 1.0; -+ } else if (maxChunkSendsPerPlayer > Integer.MAX_VALUE) { -+ maxChunkSendsPerPlayer = Integer.MAX_VALUE; -+ } -+ -+ double rateTick = maxChunkSendsPerPlayer / 20.0; -+ double a = Math.floor(rateTick); -+ double b = Math.ceil(rateTick); -+ -+ // we want to spread out a and b over the interval so it's smooth -+ -+ int aInt = (int)a; -+ int bInt = (int)b; -+ double total = b; -+ maxChunkSendsPerPlayerChoice[0] = bInt; -+ -+ for (int i = 1, len = maxChunkSendsPerPlayerChoice.length; i < len; ++i) { -+ if (total / (double)i >= rateTick) { -+ total += a; -+ maxChunkSendsPerPlayerChoice[i] = aInt; -+ } else { -+ total += b; -+ maxChunkSendsPerPlayerChoice[i] = bInt; -+ } -+ } -+ } -+ - public static final class WorldConfig { - - public final String worldName; -@@ -178,6 +214,14 @@ public final class Config { - this.worldDefaults.addDefault(path, Double.valueOf(dfl)); - return this.config.getDouble(path, this.worldDefaults.getDouble(path)); - } -+ -+ public int noTickViewDistance; -+ public int maxPendingChunkLoads; -+ private void noTickViewDistance() { -+ this.noTickViewDistance = this.getInt("no-tick-view-distance", -1); -+ this.maxPendingChunkLoads = this.getInt("max-pending-chunk-loads", 1); -+ } -+ - } - - } -diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java -index 1890fad9ed10c514b7b5982d2c112f7dc52866a5..984767304e6b5270cc8f86785b755a02d78d72ed 100644 ---- a/src/main/java/net/minecraft/server/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import net.minecraft.server.MCUtil; // Tuinity - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Sets; - import com.mojang.datafixers.util.Either; -@@ -27,12 +28,12 @@ import org.apache.logging.log4j.Logger; - public abstract class ChunkMapDistance { - - private static final Logger LOGGER = LogManager.getLogger(); -- private static final int b = 33 + ChunkStatus.a(ChunkStatus.FULL) - 2; -+ private static final int b = 33 + ChunkStatus.a(ChunkStatus.FULL) - 2; public static int getPlayerTicketLevel() { return ChunkMapDistance.b; } // Tuinity - OBFHELPER - private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); - public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); - private final ChunkMapDistance.a e = new ChunkMapDistance.a(); - private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); -- private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); -+ //private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); // Tuinity - no longer used - private final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque<>(); // PAIL pendingChunkUpdates // Paper - use a queue // Akarin - backport Tuinity - use a better queue - private final ChunkTaskQueueSorter i; - private final Mailbox> j; -@@ -41,6 +42,32 @@ public abstract class ChunkMapDistance { - private final Executor m; - private long currentTick; - -+ // Tuinity start -+ protected PlayerChunkMap chunkMap; -+ protected final ChunkMapDistance.TicketTracker playerTickViewDistanceHandler = new TicketTracker(ChunkMapDistance.getPlayerTicketLevel()) { -+ @Override -+ protected int tryQueueChunk(int chunkX, int chunkZ, EntityPlayer player) { -+ long coordinate = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ PlayerChunk currentChunk = ChunkMapDistance.this.chunkMap.getUpdatingChunk(coordinate); -+ if (currentChunk != null) { -+ Chunk fullChunk = currentChunk.getFullReadyChunk(); -+ if (fullChunk != null && fullChunk.areNeighboursLoaded(2)) { -+ this.chunkReferenceMap.putIfAbsent(coordinate, LOADED_PLAYER_REFERENCE); -+ ChunkMapDistance.this.addTicket(coordinate, new Ticket<>(TicketType.PLAYER, this.ticketLevel, new ChunkCoordIntPair(chunkX, chunkZ))); -+ return QUEUED; -+ } -+ } -+ -+ return FAILED; -+ } -+ -+ @Override -+ protected int getMaxChunkLoads(EntityPlayer player) { -+ return Integer.MAX_VALUE; -+ } -+ }; -+ // Tuinity end -+ - protected ChunkMapDistance(Executor executor, Executor executor1) { - executor1.getClass(); - Mailbox mailbox = Mailbox.a("player ticket throttler", executor1::execute); -@@ -86,7 +113,7 @@ public abstract class ChunkMapDistance { - - public boolean a(PlayerChunkMap playerchunkmap) { - this.f.a(); -- this.g.a(); -+ //this.g.a(); // Tuinity - no longer used - int i = Integer.MAX_VALUE - this.e.a(Integer.MAX_VALUE); - boolean flag = i != 0; - -@@ -242,7 +269,7 @@ public abstract class ChunkMapDistance { - return new ObjectOpenHashSet(); - })).add(entityplayer); - this.f.b(i, 0, true); -- this.g.b(i, 0, true); -+ //this.g.b(i, 0, true); // Tuinity - no longer used - } - - public void b(SectionPosition sectionposition, EntityPlayer entityplayer) { -@@ -253,7 +280,7 @@ public abstract class ChunkMapDistance { - if (objectset.isEmpty()) { - this.c.remove(i); - this.f.b(i, Integer.MAX_VALUE, false); -- this.g.b(i, Integer.MAX_VALUE, false); -+ //this.g.b(i, Integer.MAX_VALUE, false); // Tuinity - no longer used - } - - } -@@ -271,9 +298,16 @@ public abstract class ChunkMapDistance { - return s; - } - -+ protected void setViewDistance(int viewDistance) { this.a(viewDistance); } // Tuinity - OBFHELPER - protected void a(int i) { -- this.g.a(i); -+ //this.g.a(i); // Tuinity - no longer used - } -+ // Tuinity start - per player view distance -+ protected void setGlobalViewDistance(int viewDistance, PlayerChunkMap chunkMap) { -+ this.chunkMap = chunkMap; -+ this.setViewDistance(viewDistance); -+ } -+ // Tuinity end - - public int b() { - this.f.a(); -@@ -354,6 +388,222 @@ public abstract class ChunkMapDistance { - } - } - -+ // Tuinity start - Per player view distance -+ abstract class TicketTracker { -+ -+ static final int LOADED_PLAYER_REFERENCE = -2; -+ -+ protected final it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap chunkReferenceMap = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(8192, 0.25f); -+ { -+ this.chunkReferenceMap.defaultReturnValue(-1); -+ } -+ protected final it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap lastLoadedRadiusByPlayer = new it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap(512, 0.5f); -+ { -+ this.lastLoadedRadiusByPlayer.defaultReturnValue(-1); -+ } -+ -+ protected final it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap pendingChunkLoadsByPlayer = new it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap(512, 0.5f); -+ protected final it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap lastChunkPositionByPlayer = new it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap(512, 0.5f); -+ { -+ this.lastChunkPositionByPlayer.defaultReturnValue(Long.MIN_VALUE); -+ } -+ -+ protected final int ticketLevel; -+ -+ public TicketTracker(int ticketLevel) { -+ this.ticketLevel = ticketLevel; -+ } -+ -+ protected final java.util.List players = new java.util.ArrayList<>(256); -+ -+ protected com.destroystokyo.paper.util.misc.PlayerAreaMap areaMap; -+ -+ static final int ALREADY_QUEUED = 0; -+ static final int QUEUED = 1; -+ static final int FAILED = 2; -+ -+ protected abstract int tryQueueChunk(int chunkX, int chunkZ, EntityPlayer player); -+ -+ protected abstract int getMaxChunkLoads(EntityPlayer player); -+ -+ public void tick() { -+ for (EntityPlayer player : this.players) { -+ int playerId = player.getId(); -+ int lastLoadedRadius = this.lastLoadedRadiusByPlayer.get(playerId); -+ int pendingChunkLoads = this.pendingChunkLoadsByPlayer.get(playerId); -+ long lastChunkPos = this.lastChunkPositionByPlayer.get(playerId); -+ long currentChunkPos = this.areaMap.getLastCoordinate(player); -+ -+ if (currentChunkPos == Long.MIN_VALUE) { -+ // not tracking for whatever reason... -+ continue; -+ } -+ -+ int newX = MCUtil.getCoordinateX(currentChunkPos); -+ int newZ = MCUtil.getCoordinateZ(currentChunkPos); -+ -+ // handle movement -+ if (currentChunkPos != lastChunkPos) { -+ this.lastChunkPositionByPlayer.put(playerId, currentChunkPos); -+ if (lastChunkPos != Long.MIN_VALUE) { -+ int oldX = MCUtil.getCoordinateX(lastChunkPos); -+ int oldZ = MCUtil.getCoordinateZ(lastChunkPos); -+ -+ int radiusDiff = Math.max(Math.abs(newX - oldX), Math.abs(newZ - oldZ)); -+ lastLoadedRadius = Math.max(-1, lastLoadedRadius - radiusDiff); -+ this.lastLoadedRadiusByPlayer.put(playerId, lastLoadedRadius); -+ } -+ } -+ -+ int maxChunkLoads = this.getMaxChunkLoads(player); -+ -+ int radius = lastLoadedRadius + 1; -+ int viewDistance = this.areaMap.getLastViewDistance(player); -+ -+ if (radius > viewDistance) { -+ // distance map will unload our chunks -+ this.lastLoadedRadiusByPlayer.put(playerId, viewDistance); -+ continue; -+ } -+ -+ if (pendingChunkLoads >= maxChunkLoads) { -+ continue; -+ } -+ -+ radius_loop: -+ for (; radius <= viewDistance; ++radius) { -+ for (int offset = 0; offset <= radius; ++offset) { -+ // try to load the chunks closest to the player by distance -+ // so instead of going left->right on the x axis, we start at the center of the view distance square -+ // and go left and right at the same time -+ -+ // try top 2 chunks -+ // top left -+ int attempt = 0; -+ if ((attempt = this.tryQueueChunk(newX - offset, newZ + radius, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // top right -+ if ((attempt = this.tryQueueChunk(newX + offset, newZ + radius, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // try bottom 2 chunks -+ -+ // bottom left -+ if ((attempt = this.tryQueueChunk(newX - offset, newZ - radius, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // bottom right -+ if ((attempt = this.tryQueueChunk(newX + offset, newZ - radius, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // try left 2 chunks -+ -+ // left down -+ if ((attempt = this.tryQueueChunk(newX - radius, newZ - offset, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // left up -+ if ((attempt = this.tryQueueChunk(newX - radius, newZ + offset, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // try right 2 chunks -+ -+ // right down -+ if ((attempt = this.tryQueueChunk(newX + radius, newZ - offset, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // right up -+ if ((attempt = this.tryQueueChunk(newX + radius, newZ + offset, player)) == QUEUED) { -+ if (++pendingChunkLoads >= maxChunkLoads) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ } -+ } -+ -+ int newLoadedRadius = radius - 1; -+ if (newLoadedRadius != lastLoadedRadius) { -+ this.lastLoadedRadiusByPlayer.put(playerId, newLoadedRadius); -+ } -+ this.pendingChunkLoadsByPlayer.put(playerId, pendingChunkLoads); -+ } -+ } -+ -+ public void addPlayer(EntityPlayer player) { -+ this.players.add(player); -+ } -+ -+ public void removePlayer(EntityPlayer player) { -+ this.players.remove(player); -+ this.lastLoadedRadiusByPlayer.remove(player.getId()); -+ this.pendingChunkLoadsByPlayer.remove(player.getId()); -+ this.lastChunkPositionByPlayer.remove(player.getId()); -+ } -+ -+ public void onChunkLoad(int chunkX, int chunkZ) { -+ long coordinate = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ int playerReference = this.chunkReferenceMap.replace(coordinate, LOADED_PLAYER_REFERENCE); -+ if (playerReference != -1) { -+ this.pendingChunkLoadsByPlayer.computeIfPresent(playerReference, (Integer keyInMap, Integer valueInMap) -> { -+ return valueInMap - 1; -+ }); -+ } -+ } -+ -+ // this is invoked if and only if there are no other players in range of the chunk. -+ public void playerMoveOutOfRange(int chunkX, int chunkZ) { -+ long coordinate = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ int playerReference = this.chunkReferenceMap.remove(coordinate); -+ if (playerReference != -1) { -+ if (playerReference != LOADED_PLAYER_REFERENCE) { -+ this.pendingChunkLoadsByPlayer.computeIfPresent(playerReference, (Integer keyInMap, Integer valueInMap) -> { -+ return valueInMap - 1; -+ }); -+ } -+ ChunkMapDistance.this.removeTicket(coordinate, new Ticket<>(TicketType.PLAYER, this.ticketLevel, new ChunkCoordIntPair(chunkX, chunkZ))); -+ } -+ } -+ } -+ // Tuinity end - per player view distance -+ - class c extends ChunkMapDistance.b { - - private int e = 0; -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 6a2a6e671f230fd6a8adb5e6ccec22dede740f44..adc2010e643eb14ccedbb0c3af9ec7e02ab0daa2 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -534,7 +534,7 @@ public class ChunkProviderServer extends IChunkProvider { - return this.serverThreadQueue.executeNext(); - } - -- private boolean tickDistanceManager() { -+ boolean tickDistanceManager() { // Tuinity - remove private - boolean flag = this.chunkMapDistance.a(this.playerChunkMap); - boolean flag1 = this.playerChunkMap.b(); - -@@ -643,6 +643,11 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMinecraftServer().midTickLoadChunks(); // Paper - this.tickDistanceManager(); - this.world.timings.doChunkMap.stopTiming(); // Spigot -+ // Tuinity start -+ this.playerChunkMap.chunkLoadScheduler.queueMaxLoads(); -+ this.playerChunkMap.getChunkMapDistanceManager().playerTickViewDistanceHandler.tick(); -+ this.playerChunkMap.chunkSendThrottler.tick(); -+ // Tuinity end - // this.world.getMethodProfiler().exitEnter("chunks"); // Akarin - remove caller - this.world.timings.chunks.startTiming(); // Paper - timings - this.tickChunks(); -diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java -index 2887cb14e4f9f90412cbf6f83c651e5866fb16b3..b9b2b053878cc21245e6bbb2174dc51c35c8e624 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java -@@ -579,9 +579,9 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, new BlockPosition(this), 0); - // Paper start -- int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ //int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API // Tuinity - per player view distance - for (EntityPlayer player : ((WorldServer)world).getPlayers()) { -- //final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ final int viewDistance = player.getEffectiveViewDistance(player.getWorldServer().getChunkProvider().playerChunkMap) << 4; // Tuinity - per player view distance - // Paper end - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); -diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index ec2f66ef0cc56229078dacad61cd6ab3a5c6cb11..def793590801b369c12b21de6116fc72028c75b1 100644 ---- a/src/main/java/net/minecraft/server/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/EntityPlayer.java -@@ -114,6 +114,33 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSetTuinity; - // Tuinity end - -+ // Tuinity start - view distance api -+ final it.unimi.dsi.fastutil.longs.LongOpenHashSet loadedChunks = new it.unimi.dsi.fastutil.longs.LongOpenHashSet(); -+ -+ boolean needsChunkCenterUpdate; -+ int viewDistance = -1; -+ public final int getRawViewDistance() { -+ return this.viewDistance; -+ } -+ public final int getEffectiveViewDistance() { -+ return this.getEffectiveViewDistance(((WorldServer)this.world).getChunkProvider().playerChunkMap); -+ } -+ public final int getEffectiveViewDistance(PlayerChunkMap chunkMap) { -+ return this.viewDistance == -1 ? chunkMap.viewDistance : this.viewDistance; -+ } -+ -+ int noTickViewDistance = -1; -+ public final int getRawNoTickViewDistance() { -+ return this.noTickViewDistance; -+ } -+ public final int getEffectiveNoTickViewDistance() { -+ return this.getEffectiveNoTickViewDistance(((WorldServer)this.world).getChunkProvider().playerChunkMap); -+ } -+ public final int getEffectiveNoTickViewDistance(PlayerChunkMap chunkMap) { -+ return this.noTickViewDistance == -1 ? chunkMap.getEffectiveNoTickViewDistance() : this.noTickViewDistance; -+ } -+ // Tuinity end - view distance api -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super((World) worldserver, gameprofile); - playerinteractmanager.player = this; -diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java -index 8977c3516b2ee9b970b6274a5c71982b019ac2a6..bace6cf36a9e888278a6c7a5c5866d9f3b9ecf87 100644 ---- a/src/main/java/net/minecraft/server/EntityWither.java -+++ b/src/main/java/net/minecraft/server/EntityWither.java -@@ -208,9 +208,9 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); - // Paper start -- int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ //int viewDistance = ((WorldServer) this.world).spigotConfig.viewDistance * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API // Tuinity - per player view distance - for (EntityPlayer player : ((WorldServer)world).getPlayers()) { -- //final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ final int viewDistance = player.getEffectiveViewDistance(player.getWorldServer().getChunkProvider().playerChunkMap) << 4; // Tuinity - per player view distance - // Paper end - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); -diff --git a/src/main/java/net/minecraft/server/HeightMap.java b/src/main/java/net/minecraft/server/HeightMap.java -index 37a6da9ee9aab7acaf2f1559917e415217444747..aa73396100adbf741ed52f457284a78c73d658c3 100644 ---- a/src/main/java/net/minecraft/server/HeightMap.java -+++ b/src/main/java/net/minecraft/server/HeightMap.java -@@ -155,7 +155,7 @@ public class HeightMap { - private final String g; - private final HeightMap.Use h; - private final Predicate i; -- private static final Map j = (Map) SystemUtils.a((Object) Maps.newHashMap(), (hashmap) -> { -+ private static final Map j = SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // Tuinity - decompile fix - HeightMap.Type[] aheightmap_type = values(); - int i = aheightmap_type.length; - -@@ -167,7 +167,7 @@ public class HeightMap { - - }); - -- private Type(String s, HeightMap.Use heightmap_use, Predicate predicate) { -+ private Type(String s, HeightMap.Use heightmap_use, Predicate predicate) { // Tuinity - decompile fix - this.g = s; - this.h = heightmap_use; - this.i = predicate; -diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java -index a9a2ce3d3f46894c3eb973df239fec088eb1b711..7ad1d23dfb7c9b008f72f62f632c7b613ebd77df 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/PlayerChunk.java -@@ -270,6 +270,7 @@ public class PlayerChunk { - return this.entityTickingFuture; - } - -+ public final CompletableFuture> getFullChunkFuture() { return this.c(); } // Tuinity - OBFHELPER - public CompletableFuture> c() { - return this.fullChunkFuture; - } -@@ -305,7 +306,7 @@ public class PlayerChunk { - } - - public void a(int i, int j, int k) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getFullReadyChunk(); // Tuinity - per player view distance - allow block updates in non-ticking chunks - - if (chunk != null) { - this.r |= 1 << (j >> 4); -@@ -325,7 +326,7 @@ public class PlayerChunk { - } - - public void a(EnumSkyBlock enumskyblock, int i) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getFullReadyChunk(); // Tuinity - per player view distance - allow block updates in non-ticking chunks - - if (chunk != null) { - chunk.setNeedsSaving(true); -@@ -415,9 +416,57 @@ public class PlayerChunk { - } - - private void a(Packet packet, boolean flag) { -- this.players.a(this.location, flag).forEach((entityplayer) -> { -- entityplayer.playerConnection.sendPacket(packet); -- }); -+ // Tuinity start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ PlayerChunkMap chunkMap = ((PlayerChunkMap)this.players); -+ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = chunkMap.playerViewDistanceBroadcastMap; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.location); -+ if (players == null) { -+ return; -+ } -+ -+ long coordinate = net.minecraft.server.MCUtil.getCoordinateKey(this.location); -+ -+ if (flag) { // flag -> border only -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ if (!player.loadedChunks.contains(coordinate)) { -+ continue; -+ } -+ -+ int viewDistance = viewDistanceMap.getLastViewDistance(player); -+ long lastPosition = viewDistanceMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(net.minecraft.server.MCUtil.getCoordinateX(lastPosition) - this.location.x); -+ int distZ = Math.abs(net.minecraft.server.MCUtil.getCoordinateZ(lastPosition) - this.location.z); -+ -+ if (Math.max(distX, distZ) == viewDistance) { -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ } else { -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ if (!player.loadedChunks.contains(coordinate)) { -+ continue; -+ } -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ -+ return; -+ // Tuinity end - per player view distance - } - - public CompletableFuture> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { -@@ -618,6 +667,9 @@ public class PlayerChunk { - - - -+ // Tuinity start - per player view distance implementation -+ PlayerChunk.this.chunkMap.getChunkMapDistanceManager().playerTickViewDistanceHandler.onChunkLoad(this.location.x, this.location.z); -+ // Tuinity end - per player view distance implementation - } - }); - // Paper end -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 2acdb72d7ee4bba043f8b083a2ed6c2ec1a5111d..16bb6c01c51906c8765158bd2baf568a6957d811 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -80,7 +80,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final PlayerMap playerMap; - public final Int2ObjectMap trackedEntities; - private final Queue z; -- int viewDistance; // Paper - private -> package private -+ int viewDistance; public final int getViewDistance() { return this.viewDistance; } // Tuinity - OBFHELPER // Paper - private -> package private - //public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper // Tuinity - replaced by view distance map - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() -@@ -111,6 +111,354 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); - -+ // Tuinity start - per player view distance -+ int noTickViewDistance; -+ public final int getRawNoTickViewDistance() { -+ return this.noTickViewDistance; -+ } -+ public final int getEffectiveNoTickViewDistance() { -+ return this.noTickViewDistance == -1 ? this.viewDistance : this.noTickViewDistance; -+ } -+ // we use this map to broadcast chunks to clients -+ // they do not render chunks without having at least neighbours in a 1 chunk radius loaded -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; -+ public final com.destroystokyo.paper.util.misc.PlayerDistanceTrackingAreaMap playerViewDistanceNoTickMap; -+ -+ final ChunkSendThrottler chunkSendThrottler = new ChunkSendThrottler(); -+ -+ public void updateViewDistance(EntityPlayer player, int viewDistance, int noTickViewDistance) { -+ player.viewDistance = viewDistance; -+ player.noTickViewDistance = noTickViewDistance; -+ -+ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.locZ()); -+ -+ int effectiveViewDistance = viewDistance == -1 ? this.viewDistance : viewDistance; -+ int effectiveNoTickViewDistance = Math.max(effectiveViewDistance, noTickViewDistance == -1 ? this.getEffectiveNoTickViewDistance() : noTickViewDistance); -+ -+ player.playerConnection.sendPacket(new PacketPlayOutViewDistance(effectiveNoTickViewDistance)); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveViewDistance); -+ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk neighbours // add an extra one for antixray -+ } -+ this.playerViewDistanceMap.update(player, chunkX, chunkZ, effectiveViewDistance); -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need chunk neighbours -+ player.needsChunkCenterUpdate = false; -+ } -+ -+ final class ChunkSendThrottler { -+ -+ static final int ALREADY_QUEUED = 0; -+ static final int QUEUED = 1; -+ static final int FAILED = 2; -+ -+ protected final it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap lastLoadedRadiusByPlayer = new it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap(512, 0.5f); -+ -+ { -+ this.lastLoadedRadiusByPlayer.defaultReturnValue(-1); -+ } -+ -+ protected final it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap lastChunkPositionByPlayer = new it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap(512, 0.5f); -+ -+ { -+ this.lastChunkPositionByPlayer.defaultReturnValue(Long.MIN_VALUE); -+ } -+ -+ protected final it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap chunkSendCountPerPlayer = new it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap(512, 0.5f); -+ -+ protected final it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap lastChunkSendStartTimePerPlayer = new it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap(512, 0.5f); -+ -+ protected final java.util.List players = new java.util.ArrayList<>(256); -+ -+ protected final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap cachedChunkPackets = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); -+ -+ void addPlayer(EntityPlayer player) { -+ this.players.add(player); -+ } -+ -+ void removePlayer(EntityPlayer player) { -+ this.players.remove(player); -+ this.lastLoadedRadiusByPlayer.remove(player.getId()); -+ this.chunkSendCountPerPlayer.remove(player.getId()); -+ this.lastChunkPositionByPlayer.remove(player.getId()); -+ player.loadedChunks.clear(); -+ } -+ -+ int trySendChunk(int chunkX, int chunkZ, EntityPlayer player) { -+ long coordinate = net.minecraft.server.MCUtil.getCoordinateKey(chunkX, chunkZ); -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(coordinate); -+ -+ if (playerChunk == null) { -+ return FAILED; -+ } -+ Chunk chunk = playerChunk.getFullReadyChunk(); -+ if (chunk == null || !chunk.areNeighboursLoaded(1)) { -+ return FAILED; -+ } -+ -+ if (!player.loadedChunks.add(coordinate)) { -+ return ALREADY_QUEUED; -+ } -+ -+ Packet[] chunkPackets = this.cachedChunkPackets.computeIfAbsent(coordinate, (long keyInMap) -> new Packet[2]); -+ PlayerChunkMap.this.sendChunk(player, chunkPackets, chunk); -+ -+ return QUEUED; -+ } -+ -+ void tick() { -+ int maxChunkSends = io.akarin.server.Config.maxChunkSendsPerPlayerChoice[MinecraftServer.currentTick % io.akarin.server.Config.maxChunkSendsPerPlayerChoice.length]; -+ for (EntityPlayer player : this.players) { -+ int playerId = player.getId(); -+ int lastLoadedRadius = this.lastLoadedRadiusByPlayer.get(playerId); -+ long lastChunkPos = this.lastChunkPositionByPlayer.get(playerId); -+ long currentChunkPos = PlayerChunkMap.this.playerViewDistanceBroadcastMap.getLastCoordinate(player); -+ -+ if (currentChunkPos == Long.MIN_VALUE) { -+ // not tracking for whatever reason... -+ continue; -+ } -+ -+ int newX = net.minecraft.server.MCUtil.getCoordinateX(currentChunkPos); -+ int newZ = net.minecraft.server.MCUtil.getCoordinateZ(currentChunkPos); -+ -+ // handle movement -+ if (currentChunkPos != lastChunkPos) { -+ this.lastChunkPositionByPlayer.put(playerId, currentChunkPos); -+ if (lastChunkPos != Long.MIN_VALUE) { -+ int oldX = net.minecraft.server.MCUtil.getCoordinateX(lastChunkPos); -+ int oldZ = net.minecraft.server.MCUtil.getCoordinateZ(lastChunkPos); -+ -+ int radiusDiff = Math.max(Math.abs(newX - oldX), Math.abs(newZ - oldZ)); -+ lastLoadedRadius = Math.max(-1, lastLoadedRadius - radiusDiff); -+ this.lastLoadedRadiusByPlayer.put(playerId, lastLoadedRadius); -+ } -+ } -+ -+ int radius = lastLoadedRadius + 1; -+ int viewDistance = PlayerChunkMap.this.playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ -+ if (radius > viewDistance) { -+ // distance map will unload our chunks -+ this.lastLoadedRadiusByPlayer.put(playerId, viewDistance); -+ continue; -+ } -+ -+ int totalChunkSends = 0; -+ -+ if (totalChunkSends >= maxChunkSends) { -+ continue; -+ } -+ -+ radius_loop: -+ for (; radius <= viewDistance; ++radius) { -+ for (int offset = 0; offset <= radius; ++offset) { -+ // try to load the chunks closest to the player by distance -+ // so instead of going left->right on the x axis, we start at the center of the view distance square -+ // and go left and right at the same time -+ -+ // try top 2 chunks -+ // top left -+ int attempt = 0; -+ if ((attempt = this.trySendChunk(newX - offset, newZ + radius, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // top right -+ if ((attempt = this.trySendChunk(newX + offset, newZ + radius, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // try bottom 2 chunks -+ -+ // bottom left -+ if ((attempt = this.trySendChunk(newX - offset, newZ - radius, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // bottom right -+ if ((attempt = this.trySendChunk(newX + offset, newZ - radius, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // try left 2 chunks -+ -+ // left down -+ if ((attempt = this.trySendChunk(newX - radius, newZ - offset, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // left up -+ if ((attempt = this.trySendChunk(newX - radius, newZ + offset, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // try right 2 chunks -+ -+ // right down -+ if ((attempt = this.trySendChunk(newX + radius, newZ - offset, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ -+ // right up -+ if ((attempt = this.trySendChunk(newX + radius, newZ + offset, player)) == QUEUED) { -+ if (++totalChunkSends >= maxChunkSends) { -+ break radius_loop; -+ } -+ } else if (attempt == FAILED) { -+ break radius_loop; -+ } -+ } -+ } -+ int newLoadedRadius = radius - 1; -+ if (newLoadedRadius != lastLoadedRadius) { -+ this.lastLoadedRadiusByPlayer.put(playerId, newLoadedRadius); -+ } -+ } -+ this.cachedChunkPackets.clear(); -+ } -+ } -+ -+ final class ChunkLoadScheduler implements com.destroystokyo.paper.util.misc.PlayerDistanceTrackingAreaMap.DistanceChangeCallback { -+ -+ // higher priroity = lower index -+ // index = distance from player -+ private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet[] queuedLoadsByPriority = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet[65]; -+ private final java.util.BitSet nonEmptyQueues = new java.util.BitSet(this.queuedLoadsByPriority.length); -+ -+ private final it.unimi.dsi.fastutil.longs.Long2LongLinkedOpenHashMap pendingLoads = new it.unimi.dsi.fastutil.longs.Long2LongLinkedOpenHashMap(64, 0.7f); -+ { -+ this.pendingLoads.defaultReturnValue(-1L); -+ } -+ -+ private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet loadedChunks = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet(8192, 0.7f); -+ -+ private long chunkLoadCounter; -+ -+ { -+ for (int i = 0, len = this.queuedLoadsByPriority.length; i < len; ++i) { -+ this.queuedLoadsByPriority[i] = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet(32, 0.7f); -+ } -+ } -+ -+ private final int maxPendingLoads; -+ -+ ChunkLoadScheduler(int maxPendingLoads) { -+ this.maxPendingLoads = maxPendingLoads; -+ } -+ -+ void queueMaxLoads() { -+ while (this.pendingLoads.size() < this.maxPendingLoads) { -+ int firstQueue = this.nonEmptyQueues.nextSetBit(0); -+ if (firstQueue == -1) { -+ // nothing left -+ return; -+ } -+ -+ long coordinate = this.queuedLoadsByPriority[firstQueue].removeFirstLong(); -+ if (this.queuedLoadsByPriority[firstQueue].isEmpty()) { -+ this.nonEmptyQueues.clear(firstQueue); -+ } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(coordinate); -+ PlayerChunkMap.this.world.getChunkProvider().addTicketAtLevel(TicketType.PLAYER, chunkPos, 33, chunkPos); -+ -+ // now hook into the load -+ -+ PlayerChunkMap.this.world.getChunkProvider().tickDistanceManager(); // bring the chunkholder up to 33 -+ PlayerChunk chunkHolder = PlayerChunkMap.this.getUpdatingChunk(coordinate); -+ -+ CompletableFuture> loadFuture = chunkHolder.getFullChunkFuture(); -+ -+ final long loadCounterExpected = this.chunkLoadCounter++; -+ -+ this.pendingLoads.put(coordinate, loadCounterExpected); -+ -+ loadFuture.thenAcceptAsync((either) -> { -+ // no matter what, try to load more chunks -+ -+ if (!ChunkLoadScheduler.this.pendingLoads.remove(coordinate, loadCounterExpected)) { -+ // something cancelled us (or we multi loaded) -+ ChunkLoadScheduler.this.queueMaxLoads(); -+ return; -+ } -+ ChunkLoadScheduler.this.loadedChunks.add(coordinate); -+ ChunkLoadScheduler.this.queueMaxLoads(); -+ }, PlayerChunkMap.this.world.getChunkProvider().serverThreadQueue).exceptionally((throwable) -> { -+ MinecraftServer.LOGGER.fatal("Failed to handle load future for player chunk load", throwable); -+ return null; -+ }); -+ } -+ } -+ -+ @Override -+ public void accept(int posX, int posZ, int oldNearestDistance, int newNearestDistance, com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state) { -+ long coordinate = net.minecraft.server.MCUtil.getCoordinateKey(posX, posZ); -+ -+ if (newNearestDistance == -1 && ((this.loadedChunks.remove(coordinate)) || (this.pendingLoads.remove(coordinate) != -1L))) { -+ // load needs to be dropped. -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(posX, posZ); -+ PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 33, chunkPos); -+ return; -+ } -+ -+ if (this.loadedChunks.contains(coordinate) || this.pendingLoads.containsKey(coordinate)) { -+ // no need to queue - we're already loaded/loading -+ return; -+ } -+ -+ if (oldNearestDistance != -1) { -+ // remove from old -+ it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet queue = this.queuedLoadsByPriority[oldNearestDistance]; -+ if (queue.remove(coordinate) && queue.isEmpty()) { -+ this.nonEmptyQueues.clear(oldNearestDistance); -+ } -+ -+ if (newNearestDistance == -1) { -+ // we're done here - removed from the queue, and there is no pending load -+ return; -+ } -+ } -+ -+ // queue the load -+ this.queuedLoadsByPriority[newNearestDistance].add(coordinate); -+ this.nonEmptyQueues.set(newNearestDistance); -+ } -+ } -+ final ChunkLoadScheduler chunkLoadScheduler; -+ -+ // Tuinity end - per player view distance -+ - void addPlayerToDistanceMaps(EntityPlayer player) { - this.updateMaps(player); - -@@ -142,10 +490,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - void addPlayerToDistanceMapsTuinity(EntityPlayer player) { - this.updateMapsTuinity(player); -+ -+ // Tuinity start - per player view distance -+ this.getChunkMapDistanceManager().playerTickViewDistanceHandler.addPlayer(player); -+ this.chunkSendThrottler.addPlayer(player); -+ // Tuinity end - per player view distance - } - - void removePlayerFromDistanceMapsTuinity(EntityPlayer player) { - this.playerViewDistanceMap.remove(player); -+ // Tuinity start - per player view distance -+ this.playerViewDistanceBroadcastMap.remove(player); -+ this.playerViewDistanceTickMap.remove(player); -+ this.playerViewDistanceNoTickMap.remove(player); -+ this.getChunkMapDistanceManager().playerTickViewDistanceHandler.removePlayer(player); -+ this.chunkSendThrottler.removePlayer(player); -+ // Tuinity end - per player view distance - } - - void updateDistanceMapsTuinity(EntityPlayer player) { -@@ -156,7 +516,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.locX()); - int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.locZ()); - -- this.playerViewDistanceMap.update(player, chunkX, chunkZ, this.viewDistance); -+ this.playerViewDistanceMap.update(player, chunkX, chunkZ, player.getEffectiveViewDistance(this)); // Tuinity - per player view distance -+ -+ // Tuinity start - per player view distance -+ int effectiveViewDistance = player.getEffectiveViewDistance(this); -+ int effectiveNoTickViewDistance = Math.max(effectiveViewDistance, player.getEffectiveNoTickViewDistance(this)); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveViewDistance); -+ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk neighbours // add an extra one for antixray -+ } -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need chunk neighbours -+ player.needsChunkCenterUpdate = false; -+ // Tuinity end - per player view distance - } - // Tuinity end - -@@ -230,6 +603,37 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - com.destroystokyo.paper.util.misc.PooledLinkedHashSets sets = this.pooledEntityPlayerSets; - this.playerViewDistanceMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(sets); - // Tuinity end - distance maps -+ // Tuinity start - per player view distance -+ this.chunkLoadScheduler = new ChunkLoadScheduler(this.world.akarinConfig.maxPendingChunkLoads); -+ this.setNoTickViewDistance(this.world.akarinConfig.noTickViewDistance); -+ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(sets, -+ null, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState != null) { -+ return; -+ } -+ PlayerChunkMap.this.chunkDistanceManager.playerTickViewDistanceHandler.playerMoveOutOfRange(rangeX, rangeZ); -+ }); -+ this.chunkDistanceManager.playerTickViewDistanceHandler.areaMap = this.playerViewDistanceTickMap; -+ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerDistanceTrackingAreaMap(sets, -+ null, -+ null, -+ this.chunkLoadScheduler); -+ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(sets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (player.needsChunkCenterUpdate) { -+ player.needsChunkCenterUpdate = false; -+ player.playerConnection.sendPacket(new PacketPlayOutViewCentre(currPosX, currPosZ)); -+ } -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), null, true, false); // unloaded, loaded -+ player.loadedChunks.remove(net.minecraft.server.MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ }); -+ // Tuinity end - per player view distance - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -1053,11 +1457,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - completablefuture1.thenAcceptAsync((either) -> { - either.mapLeft((chunk) -> { - this.u.getAndIncrement(); -- Packet[] apacket = new Packet[2]; -- -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- this.a(entityplayer, apacket, chunk); -- }); -+ // Tuinity - per player view distance - moved to full chunk load, instead of ticking load - return Either.left(chunk); - }); - }, (runnable) -> { -@@ -1161,32 +1561,39 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } // Paper - } - -- protected void setViewDistance(int i) { -- int j = MathHelper.clamp(i + 1, 3, 33); -+ public void setViewDistance(int i) { // Tuinity - make public -+ int j = MathHelper.clamp(i + 1, 3, 33) - 1; // Tuinity - we correctly handle view distance, no need to add 1 - - if (j != this.viewDistance) { - int k = this.viewDistance; - - this.viewDistance = j; -- this.chunkDistanceManager.a(this.viewDistance); -- ObjectIterator objectiterator = this.updatingChunks.values().iterator(); -- -- while (objectiterator.hasNext()) { -- PlayerChunk playerchunk = (PlayerChunk) objectiterator.next(); -- ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); -- Packet[] apacket = new Packet[2]; -+ // Tuinity start - view distance api -+ this.chunkDistanceManager.setGlobalViewDistance(this.viewDistance, this); -+ if (this.world != null && this.world.players != null) { // ... called inside constructor, where these may not be initialized -+ for (EntityPlayer player : this.world.players) { -+ this.updateViewDistance(player, player.getRawViewDistance(), player.getRawNoTickViewDistance()); -+ } -+ } -+ // Tuinity end - view distance api -+ } - -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- int l = b(chunkcoordintpair, entityplayer, true); -- boolean flag = l <= k; -- boolean flag1 = l <= this.viewDistance; -+ } - -- this.sendChunk(entityplayer, chunkcoordintpair, apacket, flag, flag1); -- }); -+ // Tuinity start - no tick view distance -+ public void setNoTickViewDistance(int noTickViewDistance) { -+ // modeled after the above -+ noTickViewDistance = noTickViewDistance < 0 ? -1 : MathHelper.clamp(noTickViewDistance, 2, 32); -+ if (this.noTickViewDistance != noTickViewDistance) { -+ this.noTickViewDistance = noTickViewDistance; -+ if (this.world != null && this.world.players != null) { // ... called inside constructor, where these may not be initialized -+ for (EntityPlayer player : this.world.players) { -+ this.updateViewDistance(player, player.getRawViewDistance(), player.getRawNoTickViewDistance()); -+ } - } - } -- - } -+ // Tuinity end - no tick view distance - - protected void sendChunk(EntityPlayer entityplayer, ChunkCoordIntPair chunkcoordintpair, Packet[] apacket, boolean flag, boolean flag1) { - if (entityplayer.world == this.world) { -@@ -1194,7 +1601,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PlayerChunk playerchunk = this.getVisibleChunk(chunkcoordintpair.pair()); - - if (playerchunk != null) { -- Chunk chunk = playerchunk.getChunk(); -+ Chunk chunk = playerchunk.getFullReadyChunk(); // Tuinity - per player view distance - - if (chunk != null) { - this.a(entityplayer, apacket, chunk); -@@ -1440,6 +1847,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - } - -+ private boolean cannotLoadChunks(EntityPlayer entityplayer) { return this.b(entityplayer); } // Tuinity - OBFHELPER - private boolean b(EntityPlayer entityplayer) { - return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); - } -@@ -1465,13 +1873,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k, l); -- -- this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], !flag, flag); -- } -+ // Tuinity start - view distance map handles this -+ if (flag) { -+ this.updateDistanceMapsTuinity(entityplayer); - } -+ // Tuinity end - view distance map handles this - - } - -@@ -1479,7 +1885,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - SectionPosition sectionposition = SectionPosition.a((Entity) entityplayer); - - entityplayer.a(sectionposition); -- entityplayer.playerConnection.sendPacket(new PacketPlayOutViewCentre(sectionposition.a(), sectionposition.c())); -+ //entityplayer.playerConnection.sendPacket(new PacketPlayOutViewCentre(sectionposition.a(), sectionposition.c())); // Tuinity - distance map handles this now - return sectionposition; - } - -@@ -1546,56 +1952,54 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int k1; - int l1; - -- if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { -- k1 = Math.min(i, i1) - this.viewDistance; -- l1 = Math.min(j, j1) - this.viewDistance; -- int i2 = Math.max(i, i1) + this.viewDistance; -- int j2 = Math.max(j, j1) + this.viewDistance; -+ // Tuinity - handled by distance map -+ this.updateMaps(entityplayer); // Paper - distance maps -+ this.updateDistanceMapsTuinity(entityplayer); // Tuinity - distance maps -+ } - -- for (int k2 = k1; k2 <= i2; ++k2) { -- for (int l2 = l1; l2 <= j2; ++l2) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k2, l2); -- boolean flag3 = a(chunkcoordintpair, i1, j1) <= this.viewDistance; -- boolean flag4 = a(chunkcoordintpair, i, j) <= this.viewDistance; -+ @Override -+ public Stream a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { -+ // Tuinity start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkcoordintpair); -+ -+ if (inRange == null) { -+ return Stream.empty(); -+ } -+ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it -+ List players = new ArrayList<>(); -+ Object[] backingSet = inRange.getBackingSet(); -+ -+ if (flag) { // flag -> border only -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); - -- this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], flag3, flag4); -+ int distX = Math.abs(net.minecraft.server.MCUtil.getCoordinateX(lastPosition) - chunkcoordintpair.x); -+ int distZ = Math.abs(net.minecraft.server.MCUtil.getCoordinateZ(lastPosition) - chunkcoordintpair.z); -+ -+ if (Math.max(distX, distZ) == viewDistance) { -+ players.add(player); - } - } - } else { -- ChunkCoordIntPair chunkcoordintpair1; -- boolean flag5; -- boolean flag6; -- -- for (k1 = i1 - this.viewDistance; k1 <= i1 + this.viewDistance; ++k1) { -- for (l1 = j1 - this.viewDistance; l1 <= j1 + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); -- flag5 = true; -- flag6 = false; -- this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], true, false); -- } -- } -- -- for (k1 = i - this.viewDistance; k1 <= i + this.viewDistance; ++k1) { -- for (l1 = j - this.viewDistance; l1 <= j + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); -- flag5 = false; -- flag6 = true; -- this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; - } -+ EntityPlayer player = (EntityPlayer)temp; -+ players.add(player); - } - } - -- this.updateMaps(entityplayer); // Paper - distance maps -- this.updateDistanceMapsTuinity(entityplayer); // Tuinity - distance maps -- } -- -- @Override -- public Stream a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { -- return this.playerMap.a(chunkcoordintpair.pair()).filter((entityplayer) -> { -- int i = b(chunkcoordintpair, entityplayer, true); -- -- return i > this.viewDistance ? false : !flag || i == this.viewDistance; -- }); -+ return players.stream(); - } - - protected void addEntity(Entity entity) { -@@ -1733,6 +2137,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Tuinity - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { - apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, true); // Paper - Anti-Xray -@@ -1866,7 +2271,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot - if (entityplayer != this.tracker) { - Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -- int i = Math.min(this.b(), (PlayerChunkMap.this.viewDistance - 1) * 16); -+ int i = Math.min(this.b(), (entityplayer.getEffectiveViewDistance(PlayerChunkMap.this)) * 16); // Tuinity - per player view distance - boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.tracker.a(entityplayer); - - if (flag) { -@@ -1877,7 +2282,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); - - if (playerchunk != null && playerchunk.getChunk() != null) { -- flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; -+ flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= (1 + PlayerChunkMap.this.playerViewDistanceTickMap.getLastViewDistance(entityplayer)); // Tuinity - per player view distance - } - } - -diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index 9ca3fdc9cf5df3651d9b9267806c9f4b566515cb..723f781b2e4d015703b0e0488893352fdcb17e86 100644 ---- a/src/main/java/net/minecraft/server/PlayerList.java -+++ b/src/main/java/net/minecraft/server/PlayerList.java -@@ -157,7 +157,7 @@ public abstract class PlayerList { - - // CraftBukkit - getType() - // Spigot - view distance -- playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), WorldData.c(worlddata.getSeed()), worlddata.isHardcore(), worldserver.worldProvider.getDimensionManager().getType(), this.getMaxPlayers(), worlddata.getType(), worldserver.spigotConfig.viewDistance, flag1, !flag)); -+ playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), WorldData.c(worlddata.getSeed()), worlddata.isHardcore(), worldserver.worldProvider.getDimensionManager().getType(), this.getMaxPlayers(), worlddata.getType(), Math.max(entityplayer.getEffectiveViewDistance(worldserver.getChunkProvider().playerChunkMap), entityplayer.getEffectiveNoTickViewDistance(worldserver.getChunkProvider().playerChunkMap)), flag1, !flag)); // Tuinity - per player view distance - entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit - // Akarin start - send multiple packets at once - /* -@@ -714,7 +714,7 @@ public abstract class PlayerList { - WorldData worlddata = worldserver.getWorldData(); - - entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(worldserver.worldProvider.getDimensionManager().getType(), WorldData.c(worldserver.getWorldData().getSeed()), worldserver.getWorldData().getType(), entityplayer1.playerInteractManager.getGameMode())); -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver.spigotConfig.viewDistance)); // Spigot -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(Math.max(entityplayer1.getEffectiveViewDistance(worldserver.getChunkProvider().playerChunkMap), entityplayer1.getEffectiveNoTickViewDistance(worldserver.getChunkProvider().playerChunkMap)))); // Spigot // Tuinity - per player view distance - entityplayer1.spawnIn(worldserver); - entityplayer1.dead = false; - entityplayer1.playerConnection.teleport(new Location(worldserver.getWorld(), entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch)); -@@ -1198,7 +1198,7 @@ public abstract class PlayerList { - - public void a(int i) { - this.viewDistance = i; -- this.sendAll(new PacketPlayOutViewDistance(i)); -+ //this.sendAll(new PacketPlayOutViewDistance(i)); // Tuinity - move into setViewDistance - Iterator iterator = this.server.getWorlds().iterator(); - - while (iterator.hasNext()) { -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 7129cb0260316e166b4b15cded0e0c0b32433b7f..804efba68124cc4e3b7acb071b3c369c682ec4ec 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -440,8 +440,13 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.b(blockposition, iblockdata1, iblockdata2); - } - -- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement -+ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Tuinity - diff on change, see below - this.notify(blockposition, iblockdata1, iblockdata, i); -+ // Tuinity start - per player view distance - allow block updates for non-ticking chunks in player view distance -+ // if copied from above -+ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(net.minecraft.server.MCUtil.getCoordinateKey(blockposition)) != null)) { -+ ((WorldServer)this).getChunkProvider().flagDirty(blockposition); -+ // Tuinity end - per player view distance - } - - if (!this.isClientSide && (i & 1) != 0) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0f3199ba4a228cc60db3abfa4ac926b92cbb4b4b..d2b9696ca4382e156125f96805d60f1285fca8bb 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2486,10 +2486,43 @@ public class CraftWorld implements World { - // Spigot start - @Override - public int getViewDistance() { -- return world.spigotConfig.viewDistance; -+ return getHandle().getChunkProvider().playerChunkMap.getViewDistance(); // Tuinity start - per player view distance - } - // Spigot end - -+ // Tuinity start - per player view distance -+ -+ -+ @Override -+ public void setViewDistance(int viewDistance) { -+ org.spigotmc.AsyncCatcher.catchOp("Cannot update view distance safely off of the main thread"); -+ if (viewDistance < 2 || viewDistance > 32) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ net.minecraft.server.PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getViewDistance()) { -+ chunkMap.setViewDistance(viewDistance); -+ } -+ } -+ -+ @Override -+ public int getNoTickViewDistance() { -+ return getHandle().getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance(); -+ } -+ -+ @Override -+ public void setNoTickViewDistance(int viewDistance) { -+ org.spigotmc.AsyncCatcher.catchOp("Cannot update view distance safely off of the main thread"); -+ if (viewDistance < 2 || viewDistance > 32) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ net.minecraft.server.PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { -+ chunkMap.setNoTickViewDistance(viewDistance); -+ } -+ } -+ // Tuinity end - per player view distance -+ - // Spigot start - private final Spigot spigot = new Spigot() - { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b76379a17ca4c1ad009acfd4407d103ecb476a4e..b767da678e6392e7411c940916417192aa458f2a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1966,13 +1966,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public int getViewDistance() { -- throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement"); // TODO -+ return getHandle().getEffectiveViewDistance(); // Tuinity - per player view distance - } - - @Override - public void setViewDistance(int viewDistance) { -- throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement"); // TODO -+ // Tuinity start - per player view distance -+ org.spigotmc.AsyncCatcher.catchOp("Cannot update view distance safely off of the main thread"); -+ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ if (viewDistance != getHandle().getRawViewDistance()) { -+ ((WorldServer)getHandle().world).getChunkProvider().playerChunkMap.updateViewDistance(getHandle(), viewDistance, getHandle().getRawNoTickViewDistance()); -+ } -+ // Tuinity end - per player view distance -+ } -+ -+ // Tuinity start - per player view distance -+ @Override -+ public int getNoTickViewDistance() { -+ return getHandle().getEffectiveNoTickViewDistance(); -+ } -+ -+ @Override -+ public void setNoTickViewDistance(int viewDistance) { -+ org.spigotmc.AsyncCatcher.catchOp("Cannot update view distance safely off of the main thread"); -+ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ if (viewDistance != getHandle().getRawNoTickViewDistance()) { -+ ((WorldServer)getHandle().world).getChunkProvider().playerChunkMap.updateViewDistance(getHandle(), getHandle().getRawViewDistance(), viewDistance); -+ } - } -+ // Tuinity end - per player view distance - - @Override - public T getClientOption(ClientOption type) { -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 795817177aae00a5157ae77b2192841c8d028732..f6e8f7d9c64bf8f34b13636e4d0e13746fd2c4f4 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -46,6 +46,7 @@ import net.minecraft.server.EntityInsentient; - import net.minecraft.server.EntityLlama; - import net.minecraft.server.EntityWaterAnimal; - // Paper end -+import net.minecraft.server.WorldServer; // Tuinity - - public class ActivationRange - { -@@ -137,14 +138,15 @@ public class ActivationRange - final int waterActivationRange = world.spigotConfig.waterActivationRange; // Paper - final ChunkProviderServer chunkProvider = (ChunkProviderServer) world.getChunkProvider(); // Paper - -- int maxRange = Math.max( monsterActivationRange, animalActivationRange ); -- maxRange = Math.max( maxRange, raiderActivationRange ); -- maxRange = Math.max( maxRange, miscActivationRange ); -- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); -+ // Tuinity start - per player view distance -+ int maxRangeTemp = Math.max( monsterActivationRange, animalActivationRange ); -+ maxRangeTemp = Math.max( maxRangeTemp, raiderActivationRange ); -+ maxRangeTemp = Math.max( maxRangeTemp, miscActivationRange ); - - for ( EntityHuman player : world.getPlayers() ) - { -- -+ final int maxRange = Math.min( ( ( player instanceof net.minecraft.server.EntityPlayer ? ((net.minecraft.server.EntityPlayer)player).getEffectiveViewDistance(((WorldServer)world).getChunkProvider().playerChunkMap) : world.spigotConfig.viewDistance ) << 4 ) - 8, maxRangeTemp ); -+ // Tuinity end - per player view distance - player.activatedTick = MinecraftServer.currentTick; - maxBB = player.getBoundingBox().grow( maxRange, 256, maxRange ); - ActivationType.MISC.boundingBox = player.getBoundingBox().grow( miscActivationRange, 256, miscActivationRange );