From 69537b02197cb44be3497189067a96ff82e04815 Mon Sep 17 00:00:00 2001 From: Sotr Date: Fri, 8 May 2020 17:56:38 +0800 Subject: [PATCH] Updated Upstream (Paper) Upstream has released updates that appears to apply and compile correctly Paper Changes: cfed00cf Fix Light Command a6ff84ad Revert Nibble patch, causing issues still f1a8eb7f Use a finalizer for light packet instead of onPacketDone 03c9bb05 Optimize NibbleArray to use pooled buffers d0a528b1 Move delayed init down later in tick, improve accuracy of startup time cc477e6a Force Plugins that use delayed tasks for init back in their place 597263fd Don't skip full player connection tick when dead e2c23475 Revert loaded entity list (#3304) fa87db6b Move another NetworkManager util into the inner class (#3303) 841c7d18 Make loaded entity list logic more consistent (#3301) 36f34f01 Updated Upstream (Bukkit/CraftBukkit) 5ca5f131 Rebuild all patches using the new rebuild pattern 1ccff6fa Add villager reputation API 5c0bfffa Speed up rebuilding patches and reduce diff f37381ea Optimize Network Manager to not need synchronization 8f9df2ed Anti Xray cleanup 878c66f1 No-Tick view distance implementation - Closes #3196 b87743c1 Stop copy-on-write operations for updating light data 97a9c972 Optimize isOutsideRange to use distance maps b4e629a2 Use distance map to optimise entity tracker / Misc Utils d80d1517 Optimize Entity Ticking to Loaded Chunks only 31d7686d Add item slot helper methods for various inventories (#3221) 75e1e3b3 Mob Goal API c7bc393a Revert "Don't flush packet queue off main thread" 1abd2bd2 Don't flush packet queue off main thread a4ed58a9 Clean up Direct Memory Region Files Fix for different Java versions 55e35019 Set cap on JDK per-thread native byte buffer cache b5101f4f Cleanup Region Files Direct Memory on close 81e655d7 Optimize Voxel Shape Merging ed9fc11f Sync position on teleportation 9c326fce Nanothing to see here 3e9fc24b Attempt to fix FastLogin maybe 932e97f3 Rename to AsyncPlayerSendSuggestionsEvent to be consistent in naming 0dd19075 AsyncSendPlayerSuggestionsEvent Brigadier Event a9e20e5f Fix being kicked in survival for block picking - Fixes #3277 4d20537e Expose game version (#3274) 85fb0015 Validate PickItem Packet and kick for invalid - Fixes #3256 5729bc71 Special case Keep Alive packets from Anti Xray a76b7740 Improved oversized chunk data packet handling a6f78170 Use Vanilla Bed Search for non players (Villagers) 68fb98b5 Fix 2 plugin specific issues with loot drop and pathfinders 6e41f7b7 Update Activation Range 2.0 with more villager controls 57dd3971 Updated Upstream (Bukkit/CraftBukkit) a6a197b1 Bump API ASM version to follow server 5ab48ad9 Fix commodore (#3264) 87e7ee7e Improve Async Login to avoid firing in middle of Entity Ticking 8ce3dd5f [CI-SKIP] Fix Mojang API Brigadier dep - THIS IS NOT A NEW BUILD 00d760a5 Fix build due to spigot changing the build timestamp process 842e040c Updated Upstream (Bukkit/CraftBukkit/Spigot) c03260a2 Add getter and setter for villager's numberOfRestocksToday (#3231) fe366fbe null check tracker for entity metadata update - Fixes #3070 fdf41b74 Implement Brigadier Mojang API e0ea2e0e Entity Activation Range 2.0! Major improvements to restoring behavior 10396d28 Fix Tracking Range mismatch on Vehicle/Passenger checks 68994c64 Add a config to turn off Optimized TickList #3145 d847d336 Improve blocking players from opening inventories while sleeping ac4f6b50 Clean up Timings and Async Chunk Configs fcf89e85 Improve mid tick chunk loading, Fix Oversleep, other improvements ab36835c Improve random ticking behaviour - Fixes #3181 a6ac47e5 Fix numerous item duplication issues and teleport issues b7402f11 Add phantom creative and insomniac controls (#3222) 75819fac Fix Potion#toItemStack swapping the extended and upgraded constructor values (#3216) cb15cfa4 Improve Async Login so pending connections dont get exposed f275e9cb Optimize Hoppers - Major Boost - Got2GoFast! 0106485c Improvements to watchdog changes 65934b1f Fix build for last commit. 5am commits are great 3f436029 Don't process watchdog until server has fully started and ticked. 938bd972 Don't fire BlockFade on worldgen threads - Fixes #3208 509a828e Fix loading spawn chunks when async chunks is off 8a91bfd2 Improvements to async login bf698865 Revert "Re-track players that dismount from other players" 82b98418 Fix some issues with async login as well another source of sync loads aa241d2b Allow multiple callbacks to schedule for Callback Executor a2064a41 Add PlayerAttackEntityCooldownResetEvent This event is called when processing a player's attack on an entity right before their attack strength cd is reset, there are no existing events that fire within this period of time so it was impossible to capture the players attack strength via API prior to this commit. f48d4299 Allow sleeping players to float eeb2f67d Fix Bed respawn deviating too far from vanilla (#3195) 68a7b9fe Move player to spawn point if spawn in unloaded world f29c7ebd Improve async login (#3189) 9fd36824 Fix Citizens Player NPC tracking issue - Fixes #3186 --- Paper | 2 +- patches/api/0001-POM-Changes.patch | 2 +- .../api/0002-Add-server-configuration.patch | 4 +- .../api/0003-Tuinity-View-distance-api.patch | 85 - ...ix-errors-on-editors-and-add-ignores.patch | 4 +- patches/server/0002-Akarin-POM-changes.patch | 6 +- .../server/0003-Akarin-configuration.patch | 20 +- .../server/0004-Akarin-brand-changes.patch | 8 +- patches/server/0006-Disable-the-Snooper.patch | 6 +- ...0011-Remove-vanilla-profiler-callers.patch | 1251 +------------- .../0012-Asynchronous-pathfinding.patch | 12 +- .../0013-Optimizations-for-network.patch | 461 ----- ...ps-the-predicate-order-of-collision.patch} | 4 +- ...Deque-for-pendingChunkUpdates-in-Ch.patch} | 4 +- ...mize-door-interact-with-pathfinding.patch} | 0 ...16-Remove-stream-for-ender-teleport.patch} | 6 +- ...17-Cache-hashcode-for-BlockPosition.patch} | 6 +- ...nd-simplify-operation-in-pathfinder.patch} | 0 ...h => 0019-Remove-a-few-more-streams.patch} | 8 +- ...ites-to-use-NORMAL-priority-rather-.patch} | 8 +- ...tions-for-async-chunk-load-failures.patch} | 10 +- patches/server/0023-Tuinity-Util-patch.patch | 242 --- ...-player-view-distance-implementation.patch | 1499 ----------------- 23 files changed, 86 insertions(+), 3562 deletions(-) delete mode 100644 patches/api/0003-Tuinity-View-distance-api.patch delete mode 100644 patches/server/0013-Optimizations-for-network.patch rename patches/server/{0014-Swaps-the-predicate-order-of-collision.patch => 0013-Swaps-the-predicate-order-of-collision.patch} (86%) rename patches/server/{0015-Tuinity-Use-ArrayDeque-for-pendingChunkUpdates-in-Ch.patch => 0014-Tuinity-Use-ArrayDeque-for-pendingChunkUpdates-in-Ch.patch} (83%) rename patches/server/{0016-Optimize-door-interact-with-pathfinding.patch => 0015-Optimize-door-interact-with-pathfinding.patch} (100%) rename patches/server/{0017-Remove-stream-for-ender-teleport.patch => 0016-Remove-stream-for-ender-teleport.patch} (86%) rename patches/server/{0018-Cache-hashcode-for-BlockPosition.patch => 0017-Cache-hashcode-for-BlockPosition.patch} (93%) rename patches/server/{0019-Remove-stream-and-simplify-operation-in-pathfinder.patch => 0018-Remove-stream-and-simplify-operation-in-pathfinder.patch} (100%) rename patches/server/{0020-Remove-a-few-more-streams.patch => 0019-Remove-a-few-more-streams.patch} (93%) rename patches/server/{0021-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch => 0020-Tuinity-Change-writes-to-use-NORMAL-priority-rather-.patch} (92%) rename patches/server/{0022-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch => 0021-Tuinity-Log-exceptions-for-async-chunk-load-failures.patch} (88%) delete mode 100644 patches/server/0023-Tuinity-Util-patch.patch delete mode 100644 patches/server/0024-Tuinity-Per-player-view-distance-implementation.patch 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 );