From cc171b1928bff09075205b9bb2ea804cba894cd5 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Tue, 23 Nov 2021 16:50:18 +0100 Subject: [PATCH] More more more more more more more work --- ...hots-for-Timings-Tile-Entity-reports.patch | 0 ...Blocks-to-be-accessed-via-a-long-key.patch | 4 +- .../api/0140-Slime-Pathfinder-Events.patch | 0 .../api/0141-Add-PhantomPreSpawnEvent.patch | 0 .../api/0142-Add-More-Creeper-API.patch | 0 ...urable-sprint-interruption-on-attack.patch | 9 +- ...0194-Block-Enderpearl-Travel-Exploit.patch | 4 +- ...e-shield-blocking-delay-configurable.patch | 4 +- ...to-disable-ender-dragon-legacy-check.patch | 4 +- ...t-armor-stands-from-doing-entity-loo.patch | 4 +- ...Allow-disabling-armour-stand-ticking.patch | 4 +- ...timize-BlockPosition-helper-methods.patch} | 2 +- ...fault-mob-spawn-range-and-water-ani.patch} | 4 +- .../0249-Slime-Pathfinder-Events.patch} | 24 +- ...e-speed-for-water-flowing-over-lava.patch} | 22 +- ...51-Optimize-CraftBlockData-Creation.patch} | 4 +- .../server/0252-Optimize-MappedRegistry.patch | 39 ++ .../0253-Add-PhantomPreSpawnEvent.patch} | 16 +- .../0254-Add-More-Creeper-API.patch} | 2 +- .../0255-Inventory-removeItemAnySlot.patch} | 0 ...oadChunk-int-int-false-load-unconve.patch} | 2 +- ...more-aggressive-in-the-chunk-unload-.patch | 0 ...-max-squid-spawn-height-configurable.patch | 0 .../server/0255-Optimize-MappedRegistry.patch | 35 -- ...7-Asynchronous-chunk-IO-and-loading.patch} | 394 ++++++++---------- 25 files changed, 272 insertions(+), 305 deletions(-) rename patches/{unapplied => }/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch (100%) rename patches/{unapplied => }/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch (96%) rename patches/{unapplied => }/api/0140-Slime-Pathfinder-Events.patch (100%) rename patches/{unapplied => }/api/0141-Add-PhantomPreSpawnEvent.patch (100%) rename patches/{unapplied => }/api/0142-Add-More-Creeper-API.patch (100%) rename patches/{unapplied/server/0250-Optimize-BlockPosition-helper-methods.patch => server/0247-Optimize-BlockPosition-helper-methods.patch} (97%) rename patches/{unapplied/server/0251-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch => server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch} (83%) rename patches/{unapplied/server/0252-Slime-Pathfinder-Events.patch => server/0249-Slime-Pathfinder-Events.patch} (89%) rename patches/{unapplied/server/0253-Configurable-speed-for-water-flowing-over-lava.patch => server/0250-Configurable-speed-for-water-flowing-over-lava.patch} (74%) rename patches/{unapplied/server/0254-Optimize-CraftBlockData-Creation.patch => server/0251-Optimize-CraftBlockData-Creation.patch} (94%) create mode 100644 patches/server/0252-Optimize-MappedRegistry.patch rename patches/{unapplied/server/0256-Add-PhantomPreSpawnEvent.patch => server/0253-Add-PhantomPreSpawnEvent.patch} (86%) rename patches/{unapplied/server/0257-Add-More-Creeper-API.patch => server/0254-Add-More-Creeper-API.patch} (95%) rename patches/{unapplied/server/0258-Inventory-removeItemAnySlot.patch => server/0255-Inventory-removeItemAnySlot.patch} (100%) rename patches/{unapplied/server/0259-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch => server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch} (92%) rename patches/unapplied/{ => server}/0132-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch (100%) rename patches/unapplied/{ => server}/0170-Make-max-squid-spawn-height-configurable.patch (100%) delete mode 100644 patches/unapplied/server/0255-Optimize-MappedRegistry.patch rename patches/unapplied/server/{0260-Asynchronous-chunk-IO-and-loading.patch => 0257-Asynchronous-chunk-IO-and-loading.patch} (93%) diff --git a/patches/unapplied/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/patches/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch similarity index 100% rename from patches/unapplied/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch rename to patches/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch diff --git a/patches/unapplied/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch similarity index 96% rename from patches/unapplied/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch rename to patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch index 42ad1623e3..9f331cb08c 100644 --- a/patches/unapplied/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch +++ b/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch @@ -48,7 +48,7 @@ index 36ed248f0716f2cc465c08ab851b7d83d4c7c0a7..58728a0f0722b378efa129e26f0c822b * @return A new location where X/Y/Z are the center of the block */ diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 33558b6acc861f8b9986122c7c553f9dde22a45d..c1bdd642e870660931c3367884dcd7aa9d3e6923 100644 +index d3d0e4448135f6c0440c15e0dd3fc15c2616263a..7ed2442031cdcc429aabe91d639871566359ba53 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -90,6 +90,38 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient @@ -91,7 +91,7 @@ index 33558b6acc861f8b9986122c7c553f9dde22a45d..c1bdd642e870660931c3367884dcd7aa * Gets the highest non-empty (impassable) coordinate at the given * coordinates. diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java -index 3ca05a6e86a5329cf452041eac476e3636eec34a..18ab5cca036522df2d245f755d6c67904e6398e8 100644 +index 62ab55729e69bfac8eb4b40d877b945d95df27cd..79c0fa47a0d733d1547f8926d88169939c986d8c 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java @@ -155,6 +155,72 @@ public interface Block extends Metadatable { diff --git a/patches/unapplied/api/0140-Slime-Pathfinder-Events.patch b/patches/api/0140-Slime-Pathfinder-Events.patch similarity index 100% rename from patches/unapplied/api/0140-Slime-Pathfinder-Events.patch rename to patches/api/0140-Slime-Pathfinder-Events.patch diff --git a/patches/unapplied/api/0141-Add-PhantomPreSpawnEvent.patch b/patches/api/0141-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from patches/unapplied/api/0141-Add-PhantomPreSpawnEvent.patch rename to patches/api/0141-Add-PhantomPreSpawnEvent.patch diff --git a/patches/unapplied/api/0142-Add-More-Creeper-API.patch b/patches/api/0142-Add-More-Creeper-API.patch similarity index 100% rename from patches/unapplied/api/0142-Add-More-Creeper-API.patch rename to patches/api/0142-Add-More-Creeper-API.patch diff --git a/patches/server/0190-Configurable-sprint-interruption-on-attack.patch b/patches/server/0190-Configurable-sprint-interruption-on-attack.patch index 831511c0c6..ea49d6945d 100644 --- a/patches/server/0190-Configurable-sprint-interruption-on-attack.patch +++ b/patches/server/0190-Configurable-sprint-interruption-on-attack.patch @@ -6,19 +6,14 @@ Subject: [PATCH] Configurable sprint interruption on attack If the sprint interruption is disabled players continue sprinting when they attack entities. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9d7d9c800710fff5cf41c973463b9c2d72a3e32a..4e0f61179e3b2ae91811746d32b24998173a922c 100644 +index 9d7d9c800710fff5cf41c973463b9c2d72a3e32a..0ad0c84fd2e32d0c51f9aae777b80922a8f11a5a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -388,4 +388,14 @@ public class PaperWorldConfig { +@@ -388,4 +388,9 @@ public class PaperWorldConfig { disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); log("Creeper lingering effect: " + disableCreeperLingeringEffect); } + -+ public double squidMaxSpawnHeight; -+ private void squidMaxSpawnHeight() { -+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); -+ } -+ + public boolean disableSprintInterruptionOnAttack; + private void disableSprintInterruptionOnAttack() { + disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); diff --git a/patches/server/0194-Block-Enderpearl-Travel-Exploit.patch b/patches/server/0194-Block-Enderpearl-Travel-Exploit.patch index aaf3ffe12a..a00ff601af 100644 --- a/patches/server/0194-Block-Enderpearl-Travel-Exploit.patch +++ b/patches/server/0194-Block-Enderpearl-Travel-Exploit.patch @@ -12,10 +12,10 @@ This disables that by not saving the thrower when the chunk is unloaded. This is mainly useful for survival servers that do not allow freeform teleporting. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4e0f61179e3b2ae91811746d32b24998173a922c..a0937dd52e4a2aa1bfadcbd1ac0dc2cb26d59cf0 100644 +index 0ad0c84fd2e32d0c51f9aae777b80922a8f11a5a..760a7e667c8023cfa313d0566a6ed3b8cb2f929b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -398,4 +398,10 @@ public class PaperWorldConfig { +@@ -393,4 +393,10 @@ public class PaperWorldConfig { private void disableSprintInterruptionOnAttack() { disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); } diff --git a/patches/server/0208-Make-shield-blocking-delay-configurable.patch b/patches/server/0208-Make-shield-blocking-delay-configurable.patch index 17982e4aa2..bfad61830d 100644 --- a/patches/server/0208-Make-shield-blocking-delay-configurable.patch +++ b/patches/server/0208-Make-shield-blocking-delay-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make shield blocking delay configurable diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a0937dd52e4a2aa1bfadcbd1ac0dc2cb26d59cf0..4dce401da0e0fdf985ecb90f37b92e16cf210d25 100644 +index 760a7e667c8023cfa313d0566a6ed3b8cb2f929b..4fe89087fb7f5132ea7e4fec5fbc2885644f369e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -404,4 +404,9 @@ public class PaperWorldConfig { +@@ -399,4 +399,9 @@ public class PaperWorldConfig { disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); } diff --git a/patches/server/0215-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server/0215-Add-config-to-disable-ender-dragon-legacy-check.patch index de725de8b7..712ea1ef05 100644 --- a/patches/server/0215-Add-config-to-disable-ender-dragon-legacy-check.patch +++ b/patches/server/0215-Add-config-to-disable-ender-dragon-legacy-check.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add config to disable ender dragon legacy check diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4dce401da0e0fdf985ecb90f37b92e16cf210d25..35c6978eaf25ed505f99e42a58d388c62fde8319 100644 +index 4fe89087fb7f5132ea7e4fec5fbc2885644f369e..3a9f0d5937b9d9abd4e4941c1a3f35f202b0d84a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -409,4 +409,9 @@ public class PaperWorldConfig { +@@ -404,4 +404,9 @@ public class PaperWorldConfig { private void shieldBlockingDelay() { shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); } diff --git a/patches/server/0229-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server/0229-Option-to-prevent-armor-stands-from-doing-entity-loo.patch index 8894a2d883..a6b448d4a5 100644 --- a/patches/server/0229-Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ b/patches/server/0229-Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Option to prevent armor stands from doing entity lookups diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 35c6978eaf25ed505f99e42a58d388c62fde8319..0fd29d5854d9d6155ea590f86d4492d86afab433 100644 +index 3a9f0d5937b9d9abd4e4941c1a3f35f202b0d84a..ba3dd73edd6a577633bce0cdcc27e1b698377ff0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -414,4 +414,9 @@ public class PaperWorldConfig { +@@ -409,4 +409,9 @@ public class PaperWorldConfig { private void scanForLegacyEnderDragon() { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } diff --git a/patches/server/0231-Allow-disabling-armour-stand-ticking.patch b/patches/server/0231-Allow-disabling-armour-stand-ticking.patch index 20c255187e..d268d21fcc 100644 --- a/patches/server/0231-Allow-disabling-armour-stand-ticking.patch +++ b/patches/server/0231-Allow-disabling-armour-stand-ticking.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow disabling armour stand ticking diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0fd29d5854d9d6155ea590f86d4492d86afab433..ff6cf94dec708c6d3cac837ca03be2fe12d5e05f 100644 +index ba3dd73edd6a577633bce0cdcc27e1b698377ff0..c79b175fe28077be8a8ca28772fc8cd6f5e418b1 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -419,4 +419,10 @@ public class PaperWorldConfig { +@@ -414,4 +414,10 @@ public class PaperWorldConfig { private void armorStandEntityLookups() { armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); } diff --git a/patches/unapplied/server/0250-Optimize-BlockPosition-helper-methods.patch b/patches/server/0247-Optimize-BlockPosition-helper-methods.patch similarity index 97% rename from patches/unapplied/server/0250-Optimize-BlockPosition-helper-methods.patch rename to patches/server/0247-Optimize-BlockPosition-helper-methods.patch index 7da7f6e1d1..a366ff68c2 100644 --- a/patches/unapplied/server/0250-Optimize-BlockPosition-helper-methods.patch +++ b/patches/server/0247-Optimize-BlockPosition-helper-methods.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Optimize BlockPosition helper methods Resolves #1338 diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index ed52d042f41942ae512148fbba310093358ead68..80d8873bc2512ecde6a531e974b14e9b48402d64 100644 +index 5f23b9ab6540530acac623d2cd8e9ec5d0064f39..d38049bed6f3dc3198e687686ef4d8938c7a6b59 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java @@ -130,67 +130,84 @@ public class BlockPos extends Vec3i { diff --git a/patches/unapplied/server/0251-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch similarity index 83% rename from patches/unapplied/server/0251-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch rename to patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch index 22843d43ee..6962b666ea 100644 --- a/patches/unapplied/server/0251-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch +++ b/patches/server/0248-Restore-vanlla-default-mob-spawn-range-and-water-ani.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index c45332fa7b374e7775ca24a7065af3cb5c85d7cf..45be7d1821497f13ab0da3c4bbff7585238e902e 100644 +index 6879ceb1c1c6b276f6686333b9b61a8a00690302..ee8c84770b9b7fb9f3763e378f399da58f042b06 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -165,7 +165,7 @@ public class SpigotWorldConfig +@@ -178,7 +178,7 @@ public class SpigotWorldConfig public byte mobSpawnRange; private void mobSpawnRange() { diff --git a/patches/unapplied/server/0252-Slime-Pathfinder-Events.patch b/patches/server/0249-Slime-Pathfinder-Events.patch similarity index 89% rename from patches/unapplied/server/0252-Slime-Pathfinder-Events.patch rename to patches/server/0249-Slime-Pathfinder-Events.patch index c7b7672a75..86987afbe4 100644 --- a/patches/unapplied/server/0252-Slime-Pathfinder-Events.patch +++ b/patches/server/0249-Slime-Pathfinder-Events.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Slime Pathfinder Events diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9bdbfadfc1 100644 +index 11aefbf65b0e63777d6ed5bfdb18c7f7df30fc0e..6ec81054bcf25d99aec567d568c361eea84ed384 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java +++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java @@ -44,6 +44,12 @@ import net.minecraft.world.level.biome.Biomes; @@ -50,7 +50,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b } @Override -@@ -481,7 +493,15 @@ public class Slime extends Mob implements Enemy { +@@ -486,7 +498,15 @@ public class Slime extends Mob implements Enemy { public boolean canUse() { LivingEntity entityliving = this.slime.getTarget(); @@ -67,7 +67,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b } @Override -@@ -494,7 +514,15 @@ public class Slime extends Mob implements Enemy { +@@ -499,7 +519,15 @@ public class Slime extends Mob implements Enemy { public boolean canContinueToUse() { LivingEntity entityliving = this.slime.getTarget(); @@ -84,8 +84,8 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b } @Override -@@ -502,6 +530,13 @@ public class Slime extends Mob implements Enemy { - this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F); +@@ -517,6 +545,13 @@ public class Slime extends Mob implements Enemy { + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); } + @@ -98,7 +98,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b } private static class SlimeRandomDirectionGoal extends Goal { -@@ -517,14 +552,18 @@ public class Slime extends Mob implements Enemy { +@@ -532,7 +567,7 @@ public class Slime extends Mob implements Enemy { @Override public boolean canUse() { @@ -107,19 +107,19 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b } @Override - public void tick() { +@@ -540,6 +575,11 @@ public class Slime extends Mob implements Enemy { if (--this.nextRandomizeTime <= 0) { - this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); -- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); + this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60)); + this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); + // Paper start -+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360)); ++ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), this.chosenDegrees); + if (!this.slime.canWander || !event.callEvent()) return; + this.chosenDegrees = event.getNewYaw(); + // Paper end } ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); -@@ -542,7 +581,7 @@ public class Slime extends Mob implements Enemy { +@@ -557,7 +597,7 @@ public class Slime extends Mob implements Enemy { @Override public boolean canUse() { @@ -128,7 +128,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b } @Override -@@ -550,4 +589,15 @@ public class Slime extends Mob implements Enemy { +@@ -565,4 +605,15 @@ public class Slime extends Mob implements Enemy { ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setWantedMovement(1.0D); } } diff --git a/patches/unapplied/server/0253-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch similarity index 74% rename from patches/unapplied/server/0253-Configurable-speed-for-water-flowing-over-lava.patch rename to patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch index 63c3aa266e..e862c96478 100644 --- a/patches/unapplied/server/0253-Configurable-speed-for-water-flowing-over-lava.patch +++ b/patches/server/0250-Configurable-speed-for-water-flowing-over-lava.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable speed for water flowing over lava diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ff6cf94dec708c6d3cac837ca03be2fe12d5e05f..29703f57969b80e25ff9a4971e640f34fb212edf 100644 +index c79b175fe28077be8a8ca28772fc8cd6f5e418b1..7c538eba5d7e0112aae4c1584172233a3217ae89 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -425,4 +425,10 @@ public class PaperWorldConfig { +@@ -420,4 +420,10 @@ public class PaperWorldConfig { this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); } @@ -20,23 +20,23 @@ index ff6cf94dec708c6d3cac837ca03be2fe12d5e05f..29703f57969b80e25ff9a4971e640f34 + } } diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -index db4bcb600ab43439ef65d4510fb20d770ce9dba3..087601ffdeea97ec4cbb9959607bdcbcbae7c6fa 100644 +index c3d3c06e06a85ce926a2be69ec9d9b8a3eb9b8e2..11ebadaa2438281a54cffe025a49ee5046a71ba5 100644 --- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -@@ -26,6 +26,7 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -24,6 +24,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.material.FlowingFluid; - import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Material; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.phys.shapes.CollisionContext; -@@ -109,11 +110,27 @@ public class LiquidBlock extends Block implements BucketPickup { +@@ -107,11 +108,27 @@ public class LiquidBlock extends Block implements BucketPickup { @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { if (this.shouldSpreadLiquid(world, pos, state)) { -- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); -+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper +- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world)); ++ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper } } @@ -60,12 +60,12 @@ index db4bcb600ab43439ef65d4510fb20d770ce9dba3..087601ffdeea97ec4cbb9959607bdcbc @Override public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) { -@@ -126,7 +143,7 @@ public class LiquidBlock extends Block implements BucketPickup { +@@ -124,7 +141,7 @@ public class LiquidBlock extends Block implements BucketPickup { @Override public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { if (this.shouldSpreadLiquid(world, pos, state)) { -- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); -+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper +- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world)); ++ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper } } diff --git a/patches/unapplied/server/0254-Optimize-CraftBlockData-Creation.patch b/patches/server/0251-Optimize-CraftBlockData-Creation.patch similarity index 94% rename from patches/unapplied/server/0254-Optimize-CraftBlockData-Creation.patch rename to patches/server/0251-Optimize-CraftBlockData-Creation.patch index 92327300b9..56299c2d0d 100644 --- a/patches/unapplied/server/0254-Optimize-CraftBlockData-Creation.patch +++ b/patches/server/0251-Optimize-CraftBlockData-Creation.patch @@ -7,10 +7,10 @@ Avoids a hashmap lookup by cacheing a reference to the CraftBlockData and cloning it when one is needed. diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index adf1c04d34383d088a3fc8c06cdc8b55552c354f..a087eec747bb355afd627c6042d20440c3e43e1b 100644 +index 7d06d476d8e12bdb395488e85e34231daccbd853..987a4180a1eb902c512c2e6a36d692cbdd9b1563 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -637,6 +637,14 @@ public abstract class BlockBehaviour { +@@ -636,6 +636,14 @@ public abstract class BlockBehaviour { this.hasPostProcess = blockbase_info.hasPostProcess; this.emissiveRendering = blockbase_info.emissiveRendering; } diff --git a/patches/server/0252-Optimize-MappedRegistry.patch b/patches/server/0252-Optimize-MappedRegistry.patch new file mode 100644 index 0000000000..d3aecec586 --- /dev/null +++ b/patches/server/0252-Optimize-MappedRegistry.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Aug 2018 20:49:50 -0400 +Subject: [PATCH] Optimize MappedRegistry + +Use larger initial sizes to increase bucket capacity on the BiMap + +BiMap.get was seen to be using a good bit of CPU time. + +diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java +index 3b9eb0d19623a8a8e60f785edfd2faadba54ce84..9fd8c67f6b389350a82b341ff0a5d55f5c5c228c 100644 +--- a/src/main/java/net/minecraft/core/MappedRegistry.java ++++ b/src/main/java/net/minecraft/core/MappedRegistry.java +@@ -38,12 +38,10 @@ public class MappedRegistry extends WritableRegistry { + + protected static final Logger LOGGER = LogManager.getLogger(); + private final ObjectList byId = new ObjectArrayList(256); +- private final Object2IntMap toId = (Object2IntMap) Util.make(new Object2IntOpenCustomHashMap(Util.identityStrategy()), (object2intopencustomhashmap) -> { +- object2intopencustomhashmap.defaultReturnValue(-1); +- }); +- private final BiMap storage = HashBiMap.create(); +- private final BiMap, T> keyStorage = HashBiMap.create(); +- private final Map lifecycles = Maps.newIdentityHashMap(); ++ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map ++ private final BiMap storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ private final BiMap, T> keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ private final Map lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions + private Lifecycle elementsLifecycle; + @Nullable + protected Object[] randomCache; +@@ -51,7 +49,7 @@ public class MappedRegistry extends WritableRegistry { + + public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { + super(key, lifecycle); +- this.elementsLifecycle = lifecycle; ++ this.toId.defaultReturnValue(-1); // Paper + } + + public static MapCodec> withNameAndId(ResourceKey> key, MapCodec entryCodec) { diff --git a/patches/unapplied/server/0256-Add-PhantomPreSpawnEvent.patch b/patches/server/0253-Add-PhantomPreSpawnEvent.patch similarity index 86% rename from patches/unapplied/server/0256-Add-PhantomPreSpawnEvent.patch rename to patches/server/0253-Add-PhantomPreSpawnEvent.patch index a16956ca3c..3af8d64168 100644 --- a/patches/unapplied/server/0256-Add-PhantomPreSpawnEvent.patch +++ b/patches/server/0253-Add-PhantomPreSpawnEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add PhantomPreSpawnEvent diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26f78c4671 100644 +index c57803ba5daa33df42374aab75a7120e1a1b7c5b..451be9232eaa513ed66ff0d2b93c932317ad6729 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -172,6 +172,11 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -171,6 +171,11 @@ public class Phantom extends FlyingMob implements Enemy { } this.setPhantomSize(nbt.getInt("Size")); @@ -20,7 +20,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26 } @Override -@@ -181,6 +186,11 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -180,6 +185,11 @@ public class Phantom extends FlyingMob implements Enemy { nbt.putInt("AY", this.anchorPoint.getY()); nbt.putInt("AZ", this.anchorPoint.getZ()); nbt.putInt("Size", this.getPhantomSize()); @@ -32,7 +32,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26 } @Override -@@ -232,6 +242,14 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -231,6 +241,14 @@ public class Phantom extends FlyingMob implements Enemy { return entitysize.scale(f); } @@ -48,7 +48,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26 CIRCLE, SWOOP; diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad243112a33 100644 +index 9ac3047019ab32992530786b8ea7457a97d2299b..891c12b8cfcdc7a2915955bdd08e50b5b9465e02 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -4,6 +4,7 @@ import java.util.Iterator; @@ -59,7 +59,7 @@ index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad2 import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.ServerStatsCounter; -@@ -73,8 +74,17 @@ public class PhantomSpawner implements CustomSpawner { +@@ -71,8 +72,17 @@ public class PhantomSpawner implements CustomSpawner { int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 1); for (int l = 0; l < k; ++l) { @@ -72,12 +72,12 @@ index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad2 + continue; + } + // Paper end - Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world); + Phantom entityphantom = (Phantom) EntityType.PHANTOM.create(world); - + entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper entityphantom.moveTo(blockposition1, 0.0F, 0.0F); groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); - world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + world.addFreshEntityWithPassengers(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java index f77b83bee6eb739220b55793a0807f0267cfc8a9..c9dab70b0b284fe1c1daafd3c1f5bd08b14fa35d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java diff --git a/patches/unapplied/server/0257-Add-More-Creeper-API.patch b/patches/server/0254-Add-More-Creeper-API.patch similarity index 95% rename from patches/unapplied/server/0257-Add-More-Creeper-API.patch rename to patches/server/0254-Add-More-Creeper-API.patch index ce701d671b..d45c1b86d4 100644 --- a/patches/unapplied/server/0257-Add-More-Creeper-API.patch +++ b/patches/server/0254-Add-More-Creeper-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add More Creeper API diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -index dc7ad6f2a1ae71c411fb39460b52cd1129c928c4..bbca035b89c2334e65abc46dd76234c833ac222d 100644 +index bf7ddca34c8d9834a5b923fab30a605afa5f337a..c2dbe53f504327f153efe195c74ad28c1b89791f 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java +++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java @@ -309,7 +309,18 @@ public class Creeper extends Monster implements PowerableMob { diff --git a/patches/unapplied/server/0258-Inventory-removeItemAnySlot.patch b/patches/server/0255-Inventory-removeItemAnySlot.patch similarity index 100% rename from patches/unapplied/server/0258-Inventory-removeItemAnySlot.patch rename to patches/server/0255-Inventory-removeItemAnySlot.patch diff --git a/patches/unapplied/server/0259-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch similarity index 92% rename from patches/unapplied/server/0259-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch rename to patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch index 8de0121b8c..226777f759 100644 --- a/patches/unapplied/server/0259-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ b/patches/server/0256-Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 375c3adac2dc80f15d06e8acb11c8c451ec579e5..bccc66266739954ca5d7208d233884f5270e0064 100644 +index d72bfc263798797ca83e529c26bd2a1733c65eb4..d1ffbacdabc500bfbe3f65eed6206e499775f97a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -369,7 +369,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { diff --git a/patches/unapplied/0132-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/unapplied/server/0132-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch similarity index 100% rename from patches/unapplied/0132-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch rename to patches/unapplied/server/0132-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch diff --git a/patches/unapplied/0170-Make-max-squid-spawn-height-configurable.patch b/patches/unapplied/server/0170-Make-max-squid-spawn-height-configurable.patch similarity index 100% rename from patches/unapplied/0170-Make-max-squid-spawn-height-configurable.patch rename to patches/unapplied/server/0170-Make-max-squid-spawn-height-configurable.patch diff --git a/patches/unapplied/server/0255-Optimize-MappedRegistry.patch b/patches/unapplied/server/0255-Optimize-MappedRegistry.patch deleted file mode 100644 index 047b65a8df..0000000000 --- a/patches/unapplied/server/0255-Optimize-MappedRegistry.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Aug 2018 20:49:50 -0400 -Subject: [PATCH] Optimize MappedRegistry - -Use larger initial sizes to increase bucket capacity on the BiMap - -BiMap.get was seen to be using a good bit of CPU time. - -diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java -index 889c213205738ba637a28895977714df2d025b6d..87ea9b851531ac98a2dce66651f1730c5eb5e7d4 100644 ---- a/src/main/java/net/minecraft/core/MappedRegistry.java -+++ b/src/main/java/net/minecraft/core/MappedRegistry.java -@@ -37,7 +37,7 @@ import org.apache.logging.log4j.Logger; - public class MappedRegistry extends WritableRegistry { - protected static final Logger LOGGER = LogManager.getLogger(); - private final ObjectList byId = new ObjectArrayList<>(256); -- private final Object2IntMap toId = new Object2IntOpenCustomHashMap<>(Util.identityStrategy()); -+ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map - private final BiMap storage; - private final BiMap, T> keyStorage; - private final Map lifecycles; -@@ -48,9 +48,9 @@ public class MappedRegistry extends WritableRegistry { - public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { - super(key, lifecycle); - this.toId.defaultReturnValue(-1); -- this.storage = HashBiMap.create(); -- this.keyStorage = HashBiMap.create(); -- this.lifecycles = Maps.newIdentityHashMap(); -+ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions - this.elementsLifecycle = lifecycle; - } - diff --git a/patches/unapplied/server/0260-Asynchronous-chunk-IO-and-loading.patch b/patches/unapplied/server/0257-Asynchronous-chunk-IO-and-loading.patch similarity index 93% rename from patches/unapplied/server/0260-Asynchronous-chunk-IO-and-loading.patch rename to patches/unapplied/server/0257-Asynchronous-chunk-IO-and-loading.patch index 8ac9baec88..a95ee6af8b 100644 --- a/patches/unapplied/server/0260-Asynchronous-chunk-IO-and-loading.patch +++ b/patches/unapplied/server/0257-Asynchronous-chunk-IO-and-loading.patch @@ -3,6 +3,9 @@ From: Spottedleaf Date: Sat, 13 Jul 2019 09:23:10 -0700 Subject: [PATCH] Asynchronous chunk IO and loading +# UPDATE NOTES: RegionFileStorage and SectionStorage need resolving (will conflict on apply) +# ChunkSerializer needs the new tick lists to be saved (see added todos) + This patch re-adds a file IO thread as well as shoving de-serializing chunk NBT data onto worker threads. This patch also will shove chunk data serialization onto the same worker threads when the chunk @@ -2278,12 +2281,12 @@ index a5e438a834826161c52ca9db57d234d9ff80a591..b8bc1b9b8e8a33df90a963f9f9769292 @Override diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 70f2a946f50ca6be2ffaef8db8c1c03a729c757b..4f45ac04a219e619c13b31befd2c4e452057079c 100644 +index 4f45ac04a219e619c13b31befd2c4e452057079c..eca61ff543244dbf05db0a30c21c5bbeea2b9144 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java +++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -505,4 +505,8 @@ public final class MCUtil { - return null; - } +@@ -509,4 +509,8 @@ public final class MCUtil { + public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) { + return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status); } + + public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) { @@ -2291,22 +2294,22 @@ index 70f2a946f50ca6be2ffaef8db8c1c03a729c757b..4f45ac04a219e619c13b31befd2c4e45 + } } diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 6f30e10d59416799edbe362951ce61733e37b256..2b8b47f121b78cc5fe166c4280a327ddcf799b77 100644 +index 4ab820c43ddc79f5a280e2d4b322a667b9ba725f..e0c1e4e38ff49429a587c59afb86e95c452d52a0 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -217,6 +217,7 @@ public class Main { +@@ -227,6 +227,7 @@ public class Main { - convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object); + convertable_conversionsession.saveDataTag(iregistrycustom_dimension, (SaveData) object); */ + Class.forName(net.minecraft.world.entity.npc.VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> { DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index cb2ca56df7f2adedff2ebdd26957c23164b56255..7a7c501b1dffb4928aa74edd684d79f7fa312789 100644 +index 44f32023db3edaae107f48fd9b96baf5432417d9..a9f54a691af0cd15cbc38af8b8df3831de244aa7 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1001,7 +1001,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { return true; }); - this.flushWorker(); ++ //this.flushWorker(); // Paper - nuke IOWorker + this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour -+// this.i(); // Paper - nuke IOWorker } else { this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error -@@ -498,16 +500,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - } - -- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot -+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more - +@@ -546,17 +548,21 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider protected void tick(BooleanSupplier shouldKeepTicking) { ProfilerFiller gameprofilerfiller = this.level.getProfiler(); @@ -2387,11 +2384,18 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 if (!this.level.noSave()) { + try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper this.processUnloads(shouldKeepTicking); -+ }// Paper ++ } // Paper } gameprofilerfiller.pop(); -@@ -528,12 +534,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + +- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot ++ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more + + private void processUnloads(BooleanSupplier shouldKeepTicking) { + LongIterator longiterator = this.toDrop.iterator(); +@@ -573,12 +579,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (playerchunk != null) { this.pendingUnloads.put(j, playerchunk); this.modified = true; @@ -2402,11 +2406,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 } // Spigot end - this.scheduleUnload(j, playerchunk); -+ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb ++ //this.scheduleUnload(j, playerchunk); // Paper - move up because spigot did a dumb } } activityAccountant.endActivity(); // Spigot -@@ -547,6 +554,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -594,6 +601,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } @@ -2418,7 +2422,7 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 + ChunkPos chunkPos = chunk.getPos(); + CompoundTag poiData; + try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { -+ poiData = this.getVillagePlace().getData(chunk.getPos()); ++ poiData = this.poiManager.getData(chunk.getPos()); + } + + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z, @@ -2453,7 +2457,7 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 private void scheduleUnload(long pos, ChunkHolder holder) { CompletableFuture completablefuture = holder.getChunkToSave(); Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error -@@ -566,7 +613,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -613,7 +660,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ((LevelChunk) ichunkaccess).setLoaded(false); } @@ -2467,11 +2471,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 + LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); + this.save(ichunkaccess); + } -+ // Paper end - async chunk saving ++ // Paper end - async chunk savin if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { LevelChunk chunk = (LevelChunk) ichunkaccess; -@@ -631,19 +687,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -678,20 +734,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { @@ -2484,30 +2488,29 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 - try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings - nbttagcompound = this.readChunk(pos); - } // Paper end +- +- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings +- boolean flag = nbttagcompound.contains("Status", 8); +- +- if (flag) { +- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.poiManager, pos, nbttagcompound); + // Paper start + if (ioThrowable != null) { + com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); + } - -- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings -- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); -+ this.getVillagePlace().loadInData(pos, chunkHolder.poiData); ++ this.poiManager.loadInData(pos, chunkHolder.poiData); + chunkHolder.tasks.forEach(Runnable::run); + // Paper end -- if (flag) { -- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound); + if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async -+ + if (true) { -+ ProtoChunk protochunk = chunkHolder.protoChunk; - this.markPosition(pos, protochunk.getStatus().getChunkType()); return Either.left(protochunk); -@@ -666,7 +726,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } +@@ -713,7 +769,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.markPositionReplaceable(pos); - return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); + return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), (BlendingData) null)); - }, this.mainThreadExecutor); + // Paper start - Async chunk io + }; @@ -2537,8 +2540,8 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 + // Paper end } - private void markPositionReplaceable(ChunkPos chunkcoordintpair) { -@@ -848,6 +933,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private void markPositionReplaceable(ChunkPos pos) { +@@ -896,6 +977,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public boolean save(ChunkAccess chunk) { @@ -2546,7 +2549,7 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 this.poiManager.flush(chunk.getPos()); if (!chunk.isUnsaved()) { return false; -@@ -859,7 +945,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -907,7 +989,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkStatus chunkstatus = chunk.getStatus(); if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { @@ -2555,18 +2558,18 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 return false; } -@@ -869,9 +955,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -917,9 +999,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } this.level.getProfiler().incrementCounter("chunkSave"); - CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); +- +- this.write(chunkcoordintpair, nbttagcompound); + CompoundTag nbttagcompound; + try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper + nbttagcompound = ChunkSerializer.write(this.level, chunk); -+ } // Paper ++ } // Paper; + - -- this.write(chunkcoordintpair, nbttagcompound); + // Paper start - async chunk io + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, + null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); @@ -2574,15 +2577,15 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); return true; } catch (Exception exception) { -@@ -880,6 +973,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -928,6 +1016,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return false; } } + } // Paper } - private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { -@@ -1007,6 +1101,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private boolean isExistingChunkFull(ChunkPos pos) { +@@ -1060,6 +1149,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } @@ -2618,19 +2621,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669 @Nullable public CompoundTag readChunk(ChunkPos pos) throws IOException { CompoundTag nbttagcompound = this.read(pos); -@@ -1360,6 +1483,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - } - -+ @Deprecated public PoiManager getVillagePlace() { return this.getPoiManager(); } // Paper - OBFHELPER - protected PoiManager getPoiManager() { - return this.poiManager; - } diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a33423f61 100644 +index 212261651fd650cc895f817ccca37699d1cade8f..463cbbbe97bd421ac343ba80cc99731ff5fb4052 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -481,10 +481,128 @@ public class ServerChunkCache extends ChunkSource { +@@ -500,10 +500,128 @@ public class ServerChunkCache extends ChunkSource { return ret; } // Paper end @@ -2759,13 +2754,13 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a if (Thread.currentThread() != this.mainThread) { return (ChunkAccess) CompletableFuture.supplyAsync(() -> { return this.getChunk(x, z, leastStatus, create); -@@ -507,13 +625,18 @@ public class ServerChunkCache extends ChunkSource { +@@ -526,13 +644,18 @@ public class ServerChunkCache extends ChunkSource { } gameprofilerfiller.incrementCounter("getChunkCacheMiss"); - CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); + CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper - ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor; + ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; Objects.requireNonNull(completablefuture); if (!completablefuture.isDone()) { // Paper @@ -2774,12 +2769,12 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + // Paper end this.level.timings.syncChunkLoad.startTiming(); // Paper - chunkproviderserver_a.managedBlock(completablefuture::isDone); + chunkproviderserver_b.managedBlock(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug this.level.timings.syncChunkLoad.stopTiming(); // Paper } // Paper ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { -@@ -600,6 +723,11 @@ public class ServerChunkCache extends ChunkSource { +@@ -619,6 +742,11 @@ public class ServerChunkCache extends ChunkSource { } private CompletableFuture> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { @@ -2791,7 +2786,7 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); long k = chunkcoordintpair.toLong(); int l = 33 + ChunkStatus.getDistance(leastStatus); -@@ -997,11 +1125,12 @@ public class ServerChunkCache extends ChunkSource { +@@ -1028,11 +1156,12 @@ public class ServerChunkCache extends ChunkSource { // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task public boolean pollTask() { try { @@ -2806,10 +2801,10 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a } finally { chunkMap.callbackExecutor.run(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index afdb25743ceb404b4681ee2965fe3448f1f1b06a..e4626f6edb845ce751235c4341a608de81857603 100644 +index 29b2ddee252759c7ad17df8fe19ea08a36eb2673..807b508daaab587514cf91106df648758d6e9798 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -295,6 +295,78 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -307,6 +307,78 @@ public class ServerLevel extends Level implements WorldGenLevel { } } } @@ -2888,7 +2883,7 @@ index afdb25743ceb404b4681ee2965fe3448f1f1b06a..e4626f6edb845ce751235c4341a608de // Paper end // Add env and gen to constructor, WorldData -> WorldDataServer -@@ -368,6 +440,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -374,6 +446,8 @@ public class ServerLevel extends Level implements WorldGenLevel { this.sleepStatus = new SleepStatus(); this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit @@ -2910,10 +2905,10 @@ index 0d536d72ac918fbd403397ff369d10143ee9c204..be677d437d17b74c6188ce1bd5fc6fdc private final String name; private final Comparator comparator; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index cc1b855b09d4826f88b0c2b9c08fb901191a2108..1e3d7081467cccf09d4510907388479560f67f67 100644 +index c8a5cd52689b2cd81a2206f0f71623d784c379ce..7ed73ea4a5f7383c953ee3e28ce8f234d8ff941e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -711,6 +711,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser +@@ -710,6 +710,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper return; } @@ -2928,7 +2923,7 @@ index cc1b855b09d4826f88b0c2b9c08fb901191a2108..1e3d7081467cccf09d45109073884795 StringReader stringreader = new StringReader(packet.getCommand()); diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6fdbaf92b0 100644 +index 2a73700b0cd31e2a88c478b884de0a7f3d018259..0a1e667487e2c7849e11c0395816dc8ce20e0113 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java @@ -37,9 +37,11 @@ public class PoiManager extends SectionStorage { @@ -2937,8 +2932,8 @@ index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6f private final LongSet loadedChunks = new LongOpenHashSet(); + private final net.minecraft.server.level.ServerLevel world; // Paper - public PoiManager(File directory, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) { - super(directory, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world); + public PoiManager(Path path, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) { + super(path, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world); + this.world = (net.minecraft.server.level.ServerLevel)world; // Paper this.distanceTracker = new PoiManager.DistanceTracker(); } @@ -2999,33 +2994,19 @@ index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6f public static enum Occupancy { HAS_SPACE(PoiRecord::hasSpace), IS_OCCUPIED(PoiRecord::isOccupied), -diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java -index 3af31dc2c82c11ee78d497c5777615c17cb13c7a..3b8c04f6ffd7e6c197465aa1caf633ba92529472 100644 ---- a/src/main/java/net/minecraft/world/level/TickNextTickData.java -+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -4,7 +4,7 @@ import java.util.Comparator; - import net.minecraft.core.BlockPos; - - public class TickNextTickData { -- private static long counter; -+ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading - private final T type; - public final BlockPos pos; - public final long triggerTick; -@@ -16,7 +16,7 @@ public class TickNextTickData { - } - - public TickNextTickData(BlockPos pos, T t, long time, TickPriority priority) { -- this.c = (long)(counter++); -+ this.c = (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading - this.pos = pos.immutable(); - this.type = t; - this.triggerTick = time; diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b8221ac41 100644 +index 2fd969d1450d1251c139f3721d146fd2e191c4dd..806e6559555a6e71ef8199d4ffc5ce86a06bb871 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -67,7 +67,30 @@ public class ChunkSerializer { +@@ -62,6 +62,7 @@ import net.minecraft.world.level.lighting.LevelLightEngine; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.ticks.LevelChunkTicks; + import net.minecraft.world.ticks.ProtoChunkTicks; ++import net.minecraft.world.ticks.TickContainerAccess; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + +@@ -75,7 +76,31 @@ public class ChunkSerializer { public ChunkSerializer() {} @@ -3044,77 +3025,71 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b + } + // Paper end + - public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt) { + public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) { + // Paper start - add variant for async calls -+ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, nbt, true); ++ InProgressChunkHolder holder = loadChunk(world, poiStorage, chunkPos, nbt, true); + holder.tasks.forEach(Runnable::run); + return holder.protoChunk; + } -+ public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) { ++ ++ public static InProgressChunkHolder loadChunk(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt, boolean distinguish) { + java.util.ArrayDeque tasksToExecuteOnMain = new java.util.ArrayDeque<>(); + // Paper end - ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); - BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); - CompoundTag nbttagcompound1 = nbt.getCompound("Level"); -@@ -94,7 +117,9 @@ public class ChunkSerializer { + ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos")); + + if (!Objects.equals(chunkPos, chunkcoordintpair1)) { +@@ -92,7 +117,9 @@ public class ChunkSerializer { LevelLightEngine lightengine = chunkproviderserver.getLightEngine(); if (flag) { + tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main - lightengine.retainData(pos, true); + lightengine.retainData(chunkPos, true); + }); // Paper - delay this task since we're executing off-main } - for (int j = 0; j < nbttaglist.size(); ++j) { -@@ -110,16 +135,28 @@ public class ChunkSerializer { - achunksection[world.getSectionIndexFromSectionY(b0)] = chunksection; - } - -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main - poiStorage.checkConsistencyWithBlocks(pos, chunksection); -+ }); // Paper - delay this task since we're executing off-main - } + Registry iregistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY); +@@ -141,11 +168,21 @@ public class ChunkSerializer { if (flag) { - if (nbttagcompound2.contains("BlockLight", 7)) { -- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true); + if (nbttagcompound1.contains("BlockLight", 7)) { +- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight")), true); + // Paper start - delay this task since we're executing off-main -+ DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight")); ++ DataLayer blockLight = new DataLayer(nbttagcompound1.getByteArray("BlockLight")); + tasksToExecuteOnMain.add(() -> { + lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true); + }); + // Paper end - delay this task since we're executing off-main } - if (flag1 && nbttagcompound2.contains("SkyLight", 7)) { -- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); + if (flag1 && nbttagcompound1.contains("SkyLight", 7)) { +- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight")), true); + // Paper start - delay this task since we're executing off-main -+ DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight")); ++ DataLayer skyLight = new DataLayer(nbttagcompound1.getByteArray("SkyLight")); + tasksToExecuteOnMain.add(() -> { + lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair1, b0), skyLight, true); + }); -+ // Paper end - delay this task since we're executing off-main ++ // Paper end - delay this task since we're executing off-mai } } } -@@ -233,7 +270,7 @@ public class ChunkSerializer { +@@ -258,7 +295,7 @@ public class ChunkSerializer { } if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { -- return new ImposterProtoChunk((LevelChunk) object); -+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading +- return new ImposterProtoChunk((LevelChunk) object, false); ++ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object, false), tasksToExecuteOnMain); // Paper - Async chunk loading } else { ProtoChunk protochunk1 = (ProtoChunk) object; -@@ -272,11 +309,92 @@ public class ChunkSerializer { - protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); +@@ -297,10 +334,89 @@ public class ChunkSerializer { + protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound4.getLongArray(s1), ((ChunkAccess) object).getMinBuildHeight())); } - return protochunk1; + return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading -+ } -+ } -+ + } + } + + // Paper start - async chunk save for unload + public static final class AsyncSaveData { + public final DataLayer[] blockLight; @@ -3163,8 +3138,9 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b + skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray; + } + -+ TickList blockTickList = chunk.getBlockTicks(); ++ TickContainerAccess blockTickList = chunk.getBlockTicks(); + ++ //TODO check ChunkSerializer "block_ticks" + ListTag blockTickListSerialized; + if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) { + blockTickListSerialized = null; @@ -3172,13 +3148,14 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b + blockTickListSerialized = world.getBlockTicks().save(chunkPos); + } + -+ TickList fluidTickList = chunk.getLiquidTicks(); ++ TickContainerAccess fluidTickList = chunk.getFluidTicks(); + ++ //TODO + ListTag fluidTickListSerialized; + if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) { + fluidTickListSerialized = null; + } else { -+ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos); ++ fluidTickListSerialized = world.getFluidTicks().save(chunkPos); + } + + ListTag blockEntitiesSerialized = new ListTag(); @@ -3187,9 +3164,15 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b + if (blockEntityNbt != null) { + blockEntitiesSerialized.add(blockEntityNbt); + } - } ++ } + + return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime()); ++ } ++ + private static void logErrors(ChunkPos chunkPos, int y, String message) { + ChunkSerializer.LOGGER.error("Recoverable errors when loading section [" + chunkPos.x + ", " + y + ", " + chunkPos.z + "]: " + message); + } +@@ -310,6 +426,10 @@ public class ChunkSerializer { } public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { @@ -3199,23 +3182,21 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b + // Paper end ChunkPos chunkcoordintpair = chunk.getPos(); CompoundTag nbttagcompound = new CompoundTag(); - CompoundTag nbttagcompound1 = new CompoundTag(); -@@ -285,7 +403,7 @@ public class ChunkSerializer { - nbttagcompound.put("Level", nbttagcompound1); - nbttagcompound1.putInt("xPos", chunkcoordintpair.x); - nbttagcompound1.putInt("zPos", chunkcoordintpair.z); -- nbttagcompound1.putLong("LastUpdate", world.getGameTime()); -+ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading - nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); - nbttagcompound1.putString("Status", chunk.getStatus().getName()); - UpgradeData chunkconverter = chunk.getUpgradeData(); -@@ -304,9 +422,17 @@ public class ChunkSerializer { - LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { - return chunksection1 != null && SectionPos.blockToSectionCoord(chunksection1.bottomBlockY()) == finalI; // CraftBukkit - decompile errors - }).findFirst().orElse(LevelChunk.EMPTY_SECTION); + +@@ -318,6 +438,7 @@ public class ChunkSerializer { + nbttagcompound.putInt("yPos", chunk.getMinSection()); + nbttagcompound.putInt("zPos", chunkcoordintpair.z); + nbttagcompound.putLong("LastUpdate", world.getGameTime()); ++ nbttagcompound.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading + nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime()); + nbttagcompound.putString("Status", chunk.getStatus().getName()); + BlendingData blendingdata = chunk.getBlendingData(); +@@ -360,8 +481,17 @@ public class ChunkSerializer { + for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) { + int j = chunk.getSectionIndexFromSectionY(i); + boolean flag1 = j >= 0 && j < achunksection.length; - DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); - DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); -- + // Paper start - async chunk save for unload + DataLayer nibblearray; // block light + DataLayer nibblearray1; // sky light @@ -3227,11 +3208,11 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b + nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()]; + } + // Paper end - if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) { - CompoundTag nbttagcompound2 = new CompoundTag(); -@@ -338,8 +464,17 @@ public class ChunkSerializer { - nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); + if (flag1 || nibblearray != null || nibblearray1 != null) { + CompoundTag nbttagcompound1 = new CompoundTag(); +@@ -399,8 +529,17 @@ public class ChunkSerializer { + nbttagcompound.putBoolean("isLightOn", true); } - ListTag nbttaglist1 = new ListTag(); @@ -3248,38 +3229,24 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b + } + // Paper end - CompoundTag nbttagcompound3; + CompoundTag nbttagcompound2; -@@ -382,6 +517,10 @@ public class ChunkSerializer { - nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); - } else if (ticklist instanceof ChunkTickList) { - nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList); -+ // Paper end - } else { - nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair)); - } -@@ -392,6 +531,10 @@ public class ChunkSerializer { - nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save()); - } else if (ticklist1 instanceof ChunkTickList) { - nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.put("LiquidTicks", asyncsavedata.fluidTickList); -+ // Paper end - } else { - nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair)); - } +@@ -463,6 +602,7 @@ public class ChunkSerializer { + private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) { + long i = world.getLevelData().getGameTime(); + ++ //TODO original patch line 3259 + nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> { + return Registry.BLOCK.getKey(block).toString(); + })); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841d34ae7b0 100644 +index 0259baec1ceb911f39e733d52d232dec19577550..9fe3ab209ebbfc40dc1bf046d474296c660e38d5 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -21,27 +21,38 @@ import net.minecraft.world.level.storage.DimensionDataStorage; - +@@ -25,27 +25,38 @@ import net.minecraft.world.level.storage.DimensionDataStorage; public class ChunkStorage implements AutoCloseable { + public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493; - private final IOWorker worker; + // Paper - nuke IO worker protected final DataFixer fixerUpper; @@ -3291,7 +3258,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841 + public final RegionFileStorage regionFileCache; + // Paper end - async chunk loading - public ChunkStorage(File directory, DataFixer dataFixer, boolean dsync) { + public ChunkStorage(Path directory, DataFixer dataFixer, boolean dsync) { this.fixerUpper = dataFixer; - this.worker = new IOWorker(directory, dsync, "chunk"); + // Paper start - async chunk io @@ -3321,7 +3288,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841 if (nbt != null) { CompoundTag level = nbt.getCompound("Level"); if (level.getBoolean("TerrainPopulated")) { -@@ -77,11 +88,13 @@ public class ChunkStorage implements AutoCloseable { +@@ -80,11 +91,13 @@ public class ChunkStorage implements AutoCloseable { if (i < 1493) { nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493); if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { @@ -3335,7 +3302,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841 } } -@@ -99,22 +112,26 @@ public class ChunkStorage implements AutoCloseable { +@@ -114,23 +127,27 @@ public class ChunkStorage implements AutoCloseable { @Nullable public CompoundTag read(ChunkPos chunkPos) throws IOException { @@ -3366,20 +3333,21 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841 - this.worker.close(); + this.regionFileCache.close(); // Paper - nuke IO worker } - } + + public ChunkScanAccess chunkScanner() { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c9778c4d2d2 100644 +index 7b69007609ed421ee72ddc3d6f2a7b64888babf1..6f7bcf74b0ff42841e37f36561d6c54e1ee8c989 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -47,6 +47,7 @@ public class RegionFile implements AutoCloseable { +@@ -44,6 +44,7 @@ public class RegionFile implements AutoCloseable { private final IntBuffer timestamps; @VisibleForTesting protected final RegionBitmap usedSectors; + public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper - public RegionFile(File file, File directory, boolean dsync) throws IOException { - this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); -@@ -231,7 +232,7 @@ public class RegionFile implements AutoCloseable { + public RegionFile(Path path, Path path1, boolean dsync) throws IOException { + this(path, path1, RegionFileVersion.VERSION_DEFLATE, dsync); +@@ -228,7 +229,7 @@ public class RegionFile implements AutoCloseable { return (byteCount + 4096 - 1) / 4096; } @@ -3388,7 +3356,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97 int i = this.getOffset(pos); if (i == 0) { -@@ -398,6 +399,11 @@ public class RegionFile implements AutoCloseable { +@@ -395,6 +396,11 @@ public class RegionFile implements AutoCloseable { } public void close() throws IOException { @@ -3400,7 +3368,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97 try { this.padToFullSector(); } finally { -@@ -407,6 +413,10 @@ public class RegionFile implements AutoCloseable { +@@ -404,6 +410,10 @@ public class RegionFile implements AutoCloseable { this.file.close(); } } @@ -3410,7 +3378,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97 + } // Paper end } - + diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c89faef06 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java @@ -3418,7 +3386,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c @@ -28,11 +28,32 @@ public class RegionFileStorage implements AutoCloseable { this.sync = dsync; } - + - public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit + // Paper start + public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { @@ -3438,7 +3406,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c + // Paper end long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); - + if (regionfile != null) { + // Paper start + if (lock) { @@ -3451,7 +3419,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable @@ -50,6 +71,12 @@ public class RegionFileStorage implements AutoCloseable { RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync); - + this.regionCache.putAndMoveToFirst(i, regionfile1); + // Paper start + if (lock) { @@ -3474,23 +3442,23 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c // CraftBukkit end + try { // Paper DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); - + CompoundTag nbttagcompound; @@ -98,10 +126,14 @@ public class RegionFileStorage implements AutoCloseable { } - + return nbttagcompound; + } finally { // Paper start + regionfile.fileLock.unlock(); + } // Paper end } - + protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { - RegionFile regionfile = this.getFile(pos, false); // CraftBukkit + RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper + try { // Paper int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - + if (nbt == null) { @@ -140,9 +172,12 @@ public class RegionFileStorage implements AutoCloseable { MinecraftServer.LOGGER.error("Failed to save chunk", laste); @@ -3500,20 +3468,20 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c + regionfile.fileLock.unlock(); + } // Paper end } - + - public void close() throws IOException { + public synchronized void close() throws IOException { // Paper -> synchronized ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); ObjectIterator objectiterator = this.regionCache.values().iterator(); - + @@ -159,7 +194,7 @@ public class RegionFileStorage implements AutoCloseable { exceptionsuppressor.throwIfPresent(); } - + - public void flush() throws IOException { + public synchronized void flush() throws IOException { // Paper - synchronize ObjectIterator objectiterator = this.regionCache.values().iterator(); - + while (objectiterator.hasNext()) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e1fb5cc22 100644 @@ -3522,7 +3490,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e @@ -30,10 +30,10 @@ import net.minecraft.world.level.LevelHeightAccessor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - + -public class SectionStorage implements AutoCloseable { +public class SectionStorage extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker private static final Logger LOGGER = LogManager.getLogger(); @@ -3534,7 +3502,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e private final Function> codec; @@ -43,12 +43,13 @@ public class SectionStorage implements AutoCloseable { protected final LevelHeightAccessor levelHeightAccessor; - + public SectionStorage(File directory, Function> codecFactory, Function factory, DataFixer dataFixer, DataFixTypes dataFixTypes, boolean dsync, LevelHeightAccessor world) { + super(directory, dsync); // Paper - nuke IOWorker this.codec = codecFactory; @@ -3545,11 +3513,11 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e - this.worker = new IOWorker(directory, dsync, directory.getName()); + // Paper - remove mojang I/O thread } - + protected void tick(BooleanSupplier shouldKeepTicking) { @@ -106,13 +107,18 @@ public class SectionStorage implements AutoCloseable { } - + private void readColumn(ChunkPos chunkPos) { - this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos)); + // Paper start - expose function to load in data @@ -3559,7 +3527,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e + this.readColumn(chunkPos, NbtOps.INSTANCE, compound); + // Paper end - expose function to load in data } - + @Nullable private CompoundTag tryRead(ChunkPos pos) { try { @@ -3577,9 +3545,9 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e } else { LOGGER.error("Expected compound tag, got {}", (Object)tag); } - + } - + + // Paper start - internal get data function, copied from above + private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) { + Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); @@ -3595,9 +3563,9 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e + // Paper end private Dynamic writeColumn(ChunkPos chunkPos, DynamicOps dynamicOps) { Map map = Maps.newHashMap(); - + @@ -219,6 +238,23 @@ public class SectionStorage implements AutoCloseable { - + @Override public void close() throws IOException { - this.worker.close(); @@ -3622,7 +3590,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index bccc66266739954ca5d7208d233884f5270e0064..034c2886b4e29be40fa2e5e213a7457d803c0f55 100644 +index d1ffbacdabc500bfbe3f65eed6206e499775f97a..7f4024dbc1a0c50af9344689561de54eb35e1c98 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1811,6 +1811,34 @@ public class CraftWorld extends CraftRegionAccessor implements World {