More more more more more more more work

This commit is contained in:
Nassim Jahnke 2021-11-23 16:50:18 +01:00 committed by MiniDigger | Martin
parent 105034367d
commit cc171b1928
25 changed files with 272 additions and 305 deletions

View file

@ -48,7 +48,7 @@ index 36ed248f0716f2cc465c08ab851b7d83d4c7c0a7..58728a0f0722b378efa129e26f0c822b
* @return A new location where X/Y/Z are the center of the block * @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 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 --- a/src/main/java/org/bukkit/World.java
+++ b/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 @@ -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 * Gets the highest non-empty (impassable) coordinate at the given
* coordinates. * coordinates.
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java 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 --- a/src/main/java/org/bukkit/block/Block.java
+++ b/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 { @@ -155,6 +155,72 @@ public interface Block extends Metadatable {

View file

@ -6,19 +6,14 @@ Subject: [PATCH] Configurable sprint interruption on attack
If the sprint interruption is disabled players continue sprinting when they attack entities. 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 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 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/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); disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false);
log("Creeper lingering effect: " + disableCreeperLingeringEffect); log("Creeper lingering effect: " + disableCreeperLingeringEffect);
} }
+ +
+ public double squidMaxSpawnHeight;
+ private void squidMaxSpawnHeight() {
+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D);
+ }
+
+ public boolean disableSprintInterruptionOnAttack; + public boolean disableSprintInterruptionOnAttack;
+ private void disableSprintInterruptionOnAttack() { + private void disableSprintInterruptionOnAttack() {
+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); + disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false);

View file

@ -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. 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 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 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/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() { private void disableSprintInterruptionOnAttack() {
disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false);
} }

View file

@ -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 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 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/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); disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit);
log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled"));
} }

View file

@ -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 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 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/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() { private void shieldBlockingDelay() {
shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5);
} }

View file

@ -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 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 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/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() { private void scanForLegacyEnderDragon() {
scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true);
} }

View file

@ -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 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 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/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() { private void armorStandEntityLookups() {
armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true);
} }

View file

@ -6,7 +6,7 @@ Subject: [PATCH] Optimize BlockPosition helper methods
Resolves #1338 Resolves #1338
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java 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 --- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/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 { @@ -130,67 +130,84 @@ public class BlockPos extends Vec3i {

View file

@ -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 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 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
+++ b/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; public byte mobSpawnRange;
private void mobSpawnRange() private void mobSpawnRange()
{ {

View file

@ -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 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 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
+++ b/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; @@ -44,6 +44,12 @@ import net.minecraft.world.level.biome.Biomes;
@ -50,7 +50,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
} }
@Override @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() { public boolean canUse() {
LivingEntity entityliving = this.slime.getTarget(); LivingEntity entityliving = this.slime.getTarget();
@ -67,7 +67,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
} }
@Override @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() { public boolean canContinueToUse() {
LivingEntity entityliving = this.slime.getTarget(); LivingEntity entityliving = this.slime.getTarget();
@ -84,8 +84,8 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
} }
@Override @Override
@@ -502,6 +530,13 @@ public class Slime extends Mob implements Enemy { @@ -517,6 +545,13 @@ public class Slime extends Mob implements Enemy {
this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F);
((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); ((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 { 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 @Override
public boolean canUse() { public boolean canUse() {
@ -107,19 +107,19 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
} }
@Override @Override
public void tick() { @@ -540,6 +575,11 @@ public class Slime extends Mob implements Enemy {
if (--this.nextRandomizeTime <= 0) { if (--this.nextRandomizeTime <= 0) {
this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
+ // Paper start + // 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; + if (!this.slime.canWander || !event.callEvent()) return;
+ this.chosenDegrees = event.getNewYaw(); + this.chosenDegrees = event.getNewYaw();
+ // Paper end + // Paper end
} }
((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); ((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 @Override
public boolean canUse() { public boolean canUse() {
@ -128,7 +128,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
} }
@Override @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); ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setWantedMovement(1.0D);
} }
} }

View file

@ -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 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 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/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); this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick);
log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); 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 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 --- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
+++ b/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.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
+import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext; 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 @Override
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) { if (this.shouldSpreadLiquid(world, pos, state)) {
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); - world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
} }
} }
@ -60,12 +60,12 @@ index db4bcb600ab43439ef65d4510fb20d770ce9dba3..087601ffdeea97ec4cbb9959607bdcbc
@Override @Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) { 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 @Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) { if (this.shouldSpreadLiquid(world, pos, state)) {
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); - world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
} }
} }

View file

@ -7,10 +7,10 @@ Avoids a hashmap lookup by cacheing a reference to the CraftBlockData
and cloning it when one is needed. 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 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 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/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.hasPostProcess = blockbase_info.hasPostProcess;
this.emissiveRendering = blockbase_info.emissiveRendering; this.emissiveRendering = blockbase_info.emissiveRendering;
} }

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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<T> extends WritableRegistry<T> {
protected static final Logger LOGGER = LogManager.getLogger();
private final ObjectList<T> byId = new ObjectArrayList(256);
- private final Object2IntMap<T> toId = (Object2IntMap) Util.make(new Object2IntOpenCustomHashMap(Util.identityStrategy()), (object2intopencustomhashmap) -> {
- object2intopencustomhashmap.defaultReturnValue(-1);
- });
- private final BiMap<ResourceLocation, T> storage = HashBiMap.create();
- private final BiMap<ResourceKey<T>, T> keyStorage = HashBiMap.create();
- private final Map<T, Lifecycle> lifecycles = Maps.newIdentityHashMap();
+ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T> toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T>(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map
+ private final BiMap<ResourceLocation, T> storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
+ private final BiMap<ResourceKey<T>, T> keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
+ private final Map<T, Lifecycle> 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<T> extends WritableRegistry<T> {
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
super(key, lifecycle);
- this.elementsLifecycle = lifecycle;
+ this.toId.defaultReturnValue(-1); // Paper
}
public static <T> MapCodec<MappedRegistry.RegistryEntry<T>> withNameAndId(ResourceKey<? extends Registry<T>> key, MapCodec<T> entryCodec) {

View file

@ -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 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 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java
+++ b/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")); this.setPhantomSize(nbt.getInt("Size"));
@ -20,7 +20,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26
} }
@Override @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("AY", this.anchorPoint.getY());
nbt.putInt("AZ", this.anchorPoint.getZ()); nbt.putInt("AZ", this.anchorPoint.getZ());
nbt.putInt("Size", this.getPhantomSize()); nbt.putInt("Size", this.getPhantomSize());
@ -32,7 +32,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26
} }
@Override @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); return entitysize.scale(f);
} }
@ -48,7 +48,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26
CIRCLE, SWOOP; 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 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 --- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
+++ b/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; @@ -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.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.ServerStatsCounter; 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); int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 1);
for (int l = 0; l < k; ++l) { for (int l = 0; l < k; ++l) {
@ -72,12 +72,12 @@ index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad2
+ continue; + continue;
+ } + }
+ // Paper end + // Paper end
Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world); Phantom entityphantom = (Phantom) EntityType.PHANTOM.create(world);
- -
+ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper + entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper
entityphantom.moveTo(blockposition1, 0.0F, 0.0F); entityphantom.moveTo(blockposition1, 0.0F, 0.0F);
groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); 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 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 index f77b83bee6eb739220b55793a0807f0267cfc8a9..c9dab70b0b284fe1c1daafd3c1f5bd08b14fa35d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java

View file

@ -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 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 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
+++ b/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 { @@ -309,7 +309,18 @@ public class Creeper extends Monster implements PowerableMob {

View file

@ -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 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 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/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 { @@ -369,7 +369,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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<T> extends WritableRegistry<T> {
protected static final Logger LOGGER = LogManager.getLogger();
private final ObjectList<T> byId = new ObjectArrayList<>(256);
- private final Object2IntMap<T> toId = new Object2IntOpenCustomHashMap<>(Util.identityStrategy());
+ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T> toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T>(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map
private final BiMap<ResourceLocation, T> storage;
private final BiMap<ResourceKey<T>, T> keyStorage;
private final Map<T, Lifecycle> lifecycles;
@@ -48,9 +48,9 @@ public class MappedRegistry<T> extends WritableRegistry<T> {
public MappedRegistry(ResourceKey<? extends Registry<T>> 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;
}

View file

@ -3,6 +3,9 @@ From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 13 Jul 2019 09:23:10 -0700 Date: Sat, 13 Jul 2019 09:23:10 -0700
Subject: [PATCH] Asynchronous chunk IO and loading 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 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 NBT data onto worker threads. This patch also will shove
chunk data serialization onto the same worker threads when the chunk chunk data serialization onto the same worker threads when the chunk
@ -2278,12 +2281,12 @@ index a5e438a834826161c52ca9db57d234d9ff80a591..b8bc1b9b8e8a33df90a963f9f9769292
@Override @Override
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java 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 --- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/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 { @@ -509,4 +509,8 @@ public final class MCUtil {
return null; 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) { + 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 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 --- a/src/main/java/net/minecraft/server/Main.java
+++ b/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 + 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) -> { 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); 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 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 --- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/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<TickTa @@ -984,7 +984,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getProfileCache().save(false); // Paper this.getProfileCache().save(false); // Paper
} }
// Spigot end // Spigot end
@ -2316,10 +2319,10 @@ index cb2ca56df7f2adedff2ebdd26957c23164b56255..7a7c501b1dffb4928aa74edd684d79f7
public String getLocalIp() { public String getLocalIp() {
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
index 1072998cd4b00bd74e8aed9a17fbf67e31a595cd..7e3f4bb1ce723adbea8622aec8cce73faccfc664 100644 index 303125c4d0f8f235703975eab5eccb9aa045ccf8..dbcf3e764a26c89ef10afa294e1b80575ab2113e 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -151,6 +151,18 @@ public class ChunkHolder { @@ -163,6 +163,18 @@ public class ChunkHolder {
return chunkstatus; return chunkstatus;
} }
} }
@ -2338,7 +2341,7 @@ index 1072998cd4b00bd74e8aed9a17fbf67e31a595cd..7e3f4bb1ce723adbea8622aec8cce73f
return null; return null;
} }
@@ -375,7 +387,7 @@ public class ChunkHolder { @@ -402,7 +414,7 @@ public class ChunkHolder {
ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel); ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel);
ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel); ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel);
boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE;
@ -2348,10 +2351,10 @@ index 1072998cd4b00bd74e8aed9a17fbf67e31a595cd..7e3f4bb1ce723adbea8622aec8cce73f
ChunkHolder.FullChunkStatus playerchunk_state1 = ChunkHolder.getFullChunkStatus(this.ticketLevel); ChunkHolder.FullChunkStatus playerchunk_state1 = ChunkHolder.getFullChunkStatus(this.ticketLevel);
// CraftBukkit start // CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b44166903bb7fda 100644 index 6af70073e1ee0290ec30392153c2c18dfeffa0e8..9aa0df8c92744e1651254f427dd8d1fc904172d5 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java --- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -447,6 +447,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -492,6 +492,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public void close() throws IOException { public void close() throws IOException {
try { try {
this.queueSorter.close(); this.queueSorter.close();
@ -2359,23 +2362,17 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
this.poiManager.close(); this.poiManager.close();
} finally { } finally {
super.close(); super.close();
@@ -483,7 +484,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -528,7 +529,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.processUnloads(() -> { this.processUnloads(() -> {
return true; return true;
}); });
- this.flushWorker(); - this.flushWorker();
+ //this.flushWorker(); // Paper - nuke IOWorker
+ this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour + this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
+// this.i(); // Paper - nuke IOWorker
} else { } else {
this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> {
ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error
@@ -498,16 +500,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -546,17 +548,21 @@ 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
protected void tick(BooleanSupplier shouldKeepTicking) { protected void tick(BooleanSupplier shouldKeepTicking) {
ProfilerFiller gameprofilerfiller = this.level.getProfiler(); ProfilerFiller gameprofilerfiller = this.level.getProfiler();
@ -2387,11 +2384,18 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
if (!this.level.noSave()) { if (!this.level.noSave()) {
+ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper + try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper
this.processUnloads(shouldKeepTicking); this.processUnloads(shouldKeepTicking);
+ }// Paper + } // Paper
} }
gameprofilerfiller.pop(); 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) { if (playerchunk != null) {
this.pendingUnloads.put(j, playerchunk); this.pendingUnloads.put(j, playerchunk);
this.modified = true; this.modified = true;
@ -2402,11 +2406,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
} }
// Spigot end // Spigot end
- this.scheduleUnload(j, playerchunk); - 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 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(); + ChunkPos chunkPos = chunk.getPos();
+ CompoundTag poiData; + CompoundTag poiData;
+ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { + 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, + 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) { private void scheduleUnload(long pos, ChunkHolder holder) {
CompletableFuture<ChunkAccess> completablefuture = holder.getChunkToSave(); CompletableFuture<ChunkAccess> completablefuture = holder.getChunkToSave();
Consumer<ChunkAccess> consumer = (ichunkaccess) -> { // CraftBukkit - decompile error Consumer<ChunkAccess> 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); ((LevelChunk) ichunkaccess).setLoaded(false);
} }
@ -2467,11 +2471,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
+ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); + LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex);
+ this.save(ichunkaccess); + this.save(ichunkaccess);
+ } + }
+ // Paper end - async chunk saving + // Paper end - async chunk savin
if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) {
LevelChunk chunk = (LevelChunk) ichunkaccess; 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<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> scheduleChunkLoad(ChunkPos pos) { private CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> scheduleChunkLoad(ChunkPos pos) {
@ -2484,30 +2488,29 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
- try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings - try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings
- nbttagcompound = this.readChunk(pos); - nbttagcompound = this.readChunk(pos);
- } // Paper end - } // 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 + // Paper start
+ if (ioThrowable != null) { + if (ioThrowable != null) {
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); + com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable);
+ } + }
+ this.poiManager.loadInData(pos, chunkHolder.poiData);
- 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);
+ chunkHolder.tasks.forEach(Runnable::run); + chunkHolder.tasks.forEach(Runnable::run);
+ // Paper end + // 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 (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async
+
+ if (true) { + if (true) {
+ ProtoChunk protochunk = chunkHolder.protoChunk;
this.markPosition(pos, protochunk.getStatus().getChunkType()); this.markPosition(pos, protochunk.getStatus().getChunkType());
return Either.left(protochunk); 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); 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); - }, this.mainThreadExecutor);
+ // Paper start - Async chunk io + // Paper start - Async chunk io
+ }; + };
@ -2537,8 +2540,8 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
+ // Paper end + // Paper end
} }
private void markPositionReplaceable(ChunkPos chunkcoordintpair) { private void markPositionReplaceable(ChunkPos pos) {
@@ -848,6 +933,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -896,6 +977,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
} }
public boolean save(ChunkAccess chunk) { public boolean save(ChunkAccess chunk) {
@ -2546,7 +2549,7 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
this.poiManager.flush(chunk.getPos()); this.poiManager.flush(chunk.getPos());
if (!chunk.isUnsaved()) { if (!chunk.isUnsaved()) {
return false; 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(); ChunkStatus chunkstatus = chunk.getStatus();
if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) {
@ -2555,18 +2558,18 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
return false; 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"); this.level.getProfiler().incrementCounter("chunkSave");
- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); - CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk);
-
- this.write(chunkcoordintpair, nbttagcompound);
+ CompoundTag nbttagcompound; + CompoundTag nbttagcompound;
+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper + try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper
+ nbttagcompound = ChunkSerializer.write(this.level, chunk); + nbttagcompound = ChunkSerializer.write(this.level, chunk);
+ } // Paper + } // Paper;
+ +
- this.write(chunkcoordintpair, nbttagcompound);
+ // Paper start - async chunk io + // Paper start - async chunk io
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z,
+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); + null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY);
@ -2574,15 +2577,15 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); this.markPosition(chunkcoordintpair, chunkstatus.getChunkType());
return true; return true;
} catch (Exception exception) { } 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; return false;
} }
} }
+ } // Paper + } // Paper
} }
private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { private boolean isExistingChunkFull(ChunkPos pos) {
@@ -1007,6 +1101,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -1060,6 +1149,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
} }
} }
@ -2618,19 +2621,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
@Nullable @Nullable
public CompoundTag readChunk(ChunkPos pos) throws IOException { public CompoundTag readChunk(ChunkPos pos) throws IOException {
CompoundTag nbttagcompound = this.read(pos); 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 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 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/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; return ret;
} }
// Paper end // Paper end
@ -2759,13 +2754,13 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a
if (Thread.currentThread() != this.mainThread) { if (Thread.currentThread() != this.mainThread) {
return (ChunkAccess) CompletableFuture.supplyAsync(() -> { return (ChunkAccess) CompletableFuture.supplyAsync(() -> {
return this.getChunk(x, z, leastStatus, create); 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"); gameprofilerfiller.incrementCounter("getChunkCacheMiss");
- CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); - CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create);
+ CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper + CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper
ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor; ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor;
Objects.requireNonNull(completablefuture); Objects.requireNonNull(completablefuture);
if (!completablefuture.isDone()) { // Paper if (!completablefuture.isDone()) { // Paper
@ -2774,12 +2769,12 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a
+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1);
+ // Paper end + // Paper end
this.level.timings.syncChunkLoad.startTiming(); // Paper 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 + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug
this.level.timings.syncChunkLoad.stopTiming(); // Paper this.level.timings.syncChunkLoad.stopTiming(); // Paper
} // Paper } // Paper
ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { 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<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { private CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
@ -2791,7 +2786,7 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a
ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ);
long k = chunkcoordintpair.toLong(); long k = chunkcoordintpair.toLong();
int l = 33 + ChunkStatus.getDistance(leastStatus); 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 // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
public boolean pollTask() { public boolean pollTask() {
try { try {
@ -2806,10 +2801,10 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a
} finally { } finally {
chunkMap.callbackExecutor.run(); 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 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 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/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 // Paper end
// Add env and gen to constructor, WorldData -> WorldDataServer // 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.sleepStatus = new SleepStatus();
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
@ -2910,10 +2905,10 @@ index 0d536d72ac918fbd403397ff369d10143ee9c204..be677d437d17b74c6188ce1bd5fc6fdc
private final String name; private final String name;
private final Comparator<T> comparator; private final Comparator<T> comparator;
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 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 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/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 server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper
return; return;
} }
@ -2928,7 +2923,7 @@ index cc1b855b09d4826f88b0c2b9c08fb901191a2108..1e3d7081467cccf09d45109073884795
StringReader stringreader = new StringReader(packet.getCommand()); 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 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 --- 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 +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
@@ -37,9 +37,11 @@ public class PoiManager extends SectionStorage<PoiSection> { @@ -37,9 +37,11 @@ public class PoiManager extends SectionStorage<PoiSection> {
@ -2937,8 +2932,8 @@ index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6f
private final LongSet loadedChunks = new LongOpenHashSet(); private final LongSet loadedChunks = new LongOpenHashSet();
+ private final net.minecraft.server.level.ServerLevel world; // Paper + private final net.minecraft.server.level.ServerLevel world; // Paper
public PoiManager(File directory, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) { public PoiManager(Path path, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) {
super(directory, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world); super(path, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world);
+ this.world = (net.minecraft.server.level.ServerLevel)world; // Paper + this.world = (net.minecraft.server.level.ServerLevel)world; // Paper
this.distanceTracker = new PoiManager.DistanceTracker(); this.distanceTracker = new PoiManager.DistanceTracker();
} }
@ -2999,33 +2994,19 @@ index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6f
public static enum Occupancy { public static enum Occupancy {
HAS_SPACE(PoiRecord::hasSpace), HAS_SPACE(PoiRecord::hasSpace),
IS_OCCUPIED(PoiRecord::isOccupied), 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<T> {
- 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<T> {
}
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 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 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/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() {} public ChunkSerializer() {}
@ -3044,77 +3025,71 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ } + }
+ // Paper end + // 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 + // 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); + holder.tasks.forEach(Runnable::run);
+ return holder.protoChunk; + 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<Runnable> tasksToExecuteOnMain = new java.util.ArrayDeque<>(); + java.util.ArrayDeque<Runnable> tasksToExecuteOnMain = new java.util.ArrayDeque<>();
+ // Paper end + // Paper end
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos"));
BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource();
CompoundTag nbttagcompound1 = nbt.getCompound("Level"); if (!Objects.equals(chunkPos, chunkcoordintpair1)) {
@@ -94,7 +117,9 @@ public class ChunkSerializer { @@ -92,7 +117,9 @@ public class ChunkSerializer {
LevelLightEngine lightengine = chunkproviderserver.getLightEngine(); LevelLightEngine lightengine = chunkproviderserver.getLightEngine();
if (flag) { if (flag) {
+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main + 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 + }); // Paper - delay this task since we're executing off-main
} }
for (int j = 0; j < nbttaglist.size(); ++j) { Registry<Biome> iregistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
@@ -110,16 +135,28 @@ public class ChunkSerializer { @@ -141,11 +168,21 @@ 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
}
if (flag) { if (flag) {
if (nbttagcompound2.contains("BlockLight", 7)) { if (nbttagcompound1.contains("BlockLight", 7)) {
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true); - 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 + // 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(() -> { + tasksToExecuteOnMain.add(() -> {
+ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true); + lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true);
+ }); + });
+ // Paper end - delay this task since we're executing off-main + // Paper end - delay this task since we're executing off-main
} }
if (flag1 && nbttagcompound2.contains("SkyLight", 7)) { if (flag1 && nbttagcompound1.contains("SkyLight", 7)) {
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); - 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 + // 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(() -> { + tasksToExecuteOnMain.add(() -> {
+ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair1, b0), skyLight, true); + 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) { if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) {
- return new ImposterProtoChunk((LevelChunk) object); - return new ImposterProtoChunk((LevelChunk) object, false);
+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading + return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object, false), tasksToExecuteOnMain); // Paper - Async chunk loading
} else { } else {
ProtoChunk protochunk1 = (ProtoChunk) object; ProtoChunk protochunk1 = (ProtoChunk) object;
@@ -272,11 +309,92 @@ public class ChunkSerializer { @@ -297,10 +334,89 @@ public class ChunkSerializer {
protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound4.getLongArray(s1), ((ChunkAccess) object).getMinBuildHeight()));
} }
- return protochunk1; - return protochunk1;
+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading + return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
+ } }
+ } }
+
+ // Paper start - async chunk save for unload + // Paper start - async chunk save for unload
+ public static final class AsyncSaveData { + public static final class AsyncSaveData {
+ public final DataLayer[] blockLight; + public final DataLayer[] blockLight;
@ -3163,8 +3138,9 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray; + skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray;
+ } + }
+ +
+ TickList<Block> blockTickList = chunk.getBlockTicks(); + TickContainerAccess<Block> blockTickList = chunk.getBlockTicks();
+ +
+ //TODO check ChunkSerializer "block_ticks"
+ ListTag blockTickListSerialized; + ListTag blockTickListSerialized;
+ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) { + if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) {
+ blockTickListSerialized = null; + blockTickListSerialized = null;
@ -3172,13 +3148,14 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ blockTickListSerialized = world.getBlockTicks().save(chunkPos); + blockTickListSerialized = world.getBlockTicks().save(chunkPos);
+ } + }
+ +
+ TickList<Fluid> fluidTickList = chunk.getLiquidTicks(); + TickContainerAccess<Fluid> fluidTickList = chunk.getFluidTicks();
+ +
+ //TODO
+ ListTag fluidTickListSerialized; + ListTag fluidTickListSerialized;
+ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) { + if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) {
+ fluidTickListSerialized = null; + fluidTickListSerialized = null;
+ } else { + } else {
+ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos); + fluidTickListSerialized = world.getFluidTicks().save(chunkPos);
+ } + }
+ +
+ ListTag blockEntitiesSerialized = new ListTag(); + ListTag blockEntitiesSerialized = new ListTag();
@ -3187,9 +3164,15 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ if (blockEntityNbt != null) { + if (blockEntityNbt != null) {
+ blockEntitiesSerialized.add(blockEntityNbt); + blockEntitiesSerialized.add(blockEntityNbt);
+ } + }
} + }
+ +
+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime()); + 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) { public static CompoundTag write(ServerLevel world, ChunkAccess chunk) {
@ -3199,23 +3182,21 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ // Paper end + // Paper end
ChunkPos chunkcoordintpair = chunk.getPos(); ChunkPos chunkcoordintpair = chunk.getPos();
CompoundTag nbttagcompound = new CompoundTag(); CompoundTag nbttagcompound = new CompoundTag();
CompoundTag nbttagcompound1 = new CompoundTag();
@@ -285,7 +403,7 @@ public class ChunkSerializer { @@ -318,6 +438,7 @@ public class ChunkSerializer {
nbttagcompound.put("Level", nbttagcompound1); nbttagcompound.putInt("yPos", chunk.getMinSection());
nbttagcompound1.putInt("xPos", chunkcoordintpair.x); nbttagcompound.putInt("zPos", chunkcoordintpair.z);
nbttagcompound1.putInt("zPos", chunkcoordintpair.z); nbttagcompound.putLong("LastUpdate", world.getGameTime());
- nbttagcompound1.putLong("LastUpdate", world.getGameTime()); + nbttagcompound.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading
+ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime());
nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); nbttagcompound.putString("Status", chunk.getStatus().getName());
nbttagcompound1.putString("Status", chunk.getStatus().getName()); BlendingData blendingdata = chunk.getBlendingData();
UpgradeData chunkconverter = chunk.getUpgradeData(); @@ -360,8 +481,17 @@ public class ChunkSerializer {
@@ -304,9 +422,17 @@ public class ChunkSerializer { for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) {
LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { int j = chunk.getSectionIndexFromSectionY(i);
return chunksection1 != null && SectionPos.blockToSectionCoord(chunksection1.bottomBlockY()) == finalI; // CraftBukkit - decompile errors boolean flag1 = j >= 0 && j < achunksection.length;
}).findFirst().orElse(LevelChunk.EMPTY_SECTION);
- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); - DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); - DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
-
+ // Paper start - async chunk save for unload + // Paper start - async chunk save for unload
+ DataLayer nibblearray; // block light + DataLayer nibblearray; // block light
+ DataLayer nibblearray1; // sky light + DataLayer nibblearray1; // sky light
@ -3227,11 +3208,11 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()]; + nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()];
+ } + }
+ // Paper end + // Paper end
if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) {
CompoundTag nbttagcompound2 = new CompoundTag();
@@ -338,8 +464,17 @@ public class ChunkSerializer { if (flag1 || nibblearray != null || nibblearray1 != null) {
nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); CompoundTag nbttagcompound1 = new CompoundTag();
@@ -399,8 +529,17 @@ public class ChunkSerializer {
nbttagcompound.putBoolean("isLightOn", true);
} }
- ListTag nbttaglist1 = new ListTag(); - ListTag nbttaglist1 = new ListTag();
@ -3248,38 +3229,24 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ } + }
+ // Paper end + // Paper end
CompoundTag nbttagcompound3; CompoundTag nbttagcompound2;
@@ -382,6 +517,10 @@ public class ChunkSerializer { @@ -463,6 +602,7 @@ public class ChunkSerializer {
nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) {
} else if (ticklist instanceof ChunkTickList) { long i = world.getLevelData().getGameTime();
nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save());
+ // Paper start - async chunk save for unload + //TODO original patch line 3259
+ } else if (asyncsavedata != null) { nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> {
+ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList); return Registry.BLOCK.getKey(block).toString();
+ // 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));
}
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 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 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/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 class ChunkStorage implements AutoCloseable {
public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493;
- private final IOWorker worker; - private final IOWorker worker;
+ // Paper - nuke IO worker + // Paper - nuke IO worker
protected final DataFixer fixerUpper; protected final DataFixer fixerUpper;
@ -3291,7 +3258,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841
+ public final RegionFileStorage regionFileCache; + public final RegionFileStorage regionFileCache;
+ // Paper end - async chunk loading + // 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.fixerUpper = dataFixer;
- this.worker = new IOWorker(directory, dsync, "chunk"); - this.worker = new IOWorker(directory, dsync, "chunk");
+ // Paper start - async chunk io + // Paper start - async chunk io
@ -3321,7 +3288,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841
if (nbt != null) { if (nbt != null) {
CompoundTag level = nbt.getCompound("Level"); CompoundTag level = nbt.getCompound("Level");
if (level.getBoolean("TerrainPopulated")) { 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) { if (i < 1493) {
nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493); nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493);
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { 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 @Nullable
public CompoundTag read(ChunkPos chunkPos) throws IOException { public CompoundTag read(ChunkPos chunkPos) throws IOException {
@ -3366,20 +3333,21 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841
- this.worker.close(); - this.worker.close();
+ this.regionFileCache.close(); // Paper - nuke IO worker + 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 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 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/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; private final IntBuffer timestamps;
@VisibleForTesting @VisibleForTesting
protected final RegionBitmap usedSectors; protected final RegionBitmap usedSectors;
+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper + 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 { public RegionFile(Path path, Path path1, boolean dsync) throws IOException {
this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); this(path, path1, RegionFileVersion.VERSION_DEFLATE, dsync);
@@ -231,7 +232,7 @@ public class RegionFile implements AutoCloseable { @@ -228,7 +229,7 @@ public class RegionFile implements AutoCloseable {
return (byteCount + 4096 - 1) / 4096; return (byteCount + 4096 - 1) / 4096;
} }
@ -3388,7 +3356,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97
int i = this.getOffset(pos); int i = this.getOffset(pos);
if (i == 0) { 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 { public void close() throws IOException {
@ -3400,7 +3368,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97
try { try {
this.padToFullSector(); this.padToFullSector();
} finally { } finally {
@@ -407,6 +413,10 @@ public class RegionFile implements AutoCloseable { @@ -404,6 +410,10 @@ public class RegionFile implements AutoCloseable {
this.file.close(); this.file.close();
} }
} }
@ -3410,7 +3378,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97
+ } // Paper end + } // 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 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 index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c89faef06 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java --- 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 { @@ -28,11 +28,32 @@ public class RegionFileStorage implements AutoCloseable {
this.sync = dsync; this.sync = dsync;
} }
- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit - public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
+ // Paper start + // Paper start
+ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { + public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) {
@ -3438,7 +3406,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
+ // Paper end + // Paper end
long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i);
if (regionfile != null) { if (regionfile != null) {
+ // Paper start + // Paper start
+ if (lock) { + if (lock) {
@ -3451,7 +3419,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable
@@ -50,6 +71,12 @@ public class RegionFileStorage implements AutoCloseable { @@ -50,6 +71,12 @@ public class RegionFileStorage implements AutoCloseable {
RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync); RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync);
this.regionCache.putAndMoveToFirst(i, regionfile1); this.regionCache.putAndMoveToFirst(i, regionfile1);
+ // Paper start + // Paper start
+ if (lock) { + if (lock) {
@ -3474,23 +3442,23 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
// CraftBukkit end // CraftBukkit end
+ try { // Paper + try { // Paper
DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos);
CompoundTag nbttagcompound; CompoundTag nbttagcompound;
@@ -98,10 +126,14 @@ public class RegionFileStorage implements AutoCloseable { @@ -98,10 +126,14 @@ public class RegionFileStorage implements AutoCloseable {
} }
return nbttagcompound; return nbttagcompound;
+ } finally { // Paper start + } finally { // Paper start
+ regionfile.fileLock.unlock(); + regionfile.fileLock.unlock();
+ } // Paper end + } // Paper end
} }
protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException {
- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit - RegionFile regionfile = this.getFile(pos, false); // CraftBukkit
+ RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper + RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper
+ try { // Paper + try { // Paper
int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper
if (nbt == null) { if (nbt == null) {
@@ -140,9 +172,12 @@ public class RegionFileStorage implements AutoCloseable { @@ -140,9 +172,12 @@ public class RegionFileStorage implements AutoCloseable {
MinecraftServer.LOGGER.error("Failed to save chunk", laste); MinecraftServer.LOGGER.error("Failed to save chunk", laste);
@ -3500,20 +3468,20 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
+ regionfile.fileLock.unlock(); + regionfile.fileLock.unlock();
+ } // Paper end + } // Paper end
} }
- public void close() throws IOException { - public void close() throws IOException {
+ public synchronized void close() throws IOException { // Paper -> synchronized + public synchronized void close() throws IOException { // Paper -> synchronized
ExceptionCollector<IOException> exceptionsuppressor = new ExceptionCollector<>(); ExceptionCollector<IOException> exceptionsuppressor = new ExceptionCollector<>();
ObjectIterator objectiterator = this.regionCache.values().iterator(); ObjectIterator objectiterator = this.regionCache.values().iterator();
@@ -159,7 +194,7 @@ public class RegionFileStorage implements AutoCloseable { @@ -159,7 +194,7 @@ public class RegionFileStorage implements AutoCloseable {
exceptionsuppressor.throwIfPresent(); exceptionsuppressor.throwIfPresent();
} }
- public void flush() throws IOException { - public void flush() throws IOException {
+ public synchronized void flush() throws IOException { // Paper - synchronize + public synchronized void flush() throws IOException { // Paper - synchronize
ObjectIterator objectiterator = this.regionCache.values().iterator(); ObjectIterator objectiterator = this.regionCache.values().iterator();
while (objectiterator.hasNext()) { 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 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 index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e1fb5cc22 100644
@ -3522,7 +3490,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
@@ -30,10 +30,10 @@ import net.minecraft.world.level.LevelHeightAccessor; @@ -30,10 +30,10 @@ import net.minecraft.world.level.LevelHeightAccessor;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
-public class SectionStorage<R> implements AutoCloseable { -public class SectionStorage<R> implements AutoCloseable {
+public class SectionStorage<R> extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker +public class SectionStorage<R> extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
@ -3534,7 +3502,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
private final Function<Runnable, Codec<R>> codec; private final Function<Runnable, Codec<R>> codec;
@@ -43,12 +43,13 @@ public class SectionStorage<R> implements AutoCloseable { @@ -43,12 +43,13 @@ public class SectionStorage<R> implements AutoCloseable {
protected final LevelHeightAccessor levelHeightAccessor; protected final LevelHeightAccessor levelHeightAccessor;
public SectionStorage(File directory, Function<Runnable, Codec<R>> codecFactory, Function<Runnable, R> factory, DataFixer dataFixer, DataFixTypes dataFixTypes, boolean dsync, LevelHeightAccessor world) { public SectionStorage(File directory, Function<Runnable, Codec<R>> codecFactory, Function<Runnable, R> factory, DataFixer dataFixer, DataFixTypes dataFixTypes, boolean dsync, LevelHeightAccessor world) {
+ super(directory, dsync); // Paper - nuke IOWorker + super(directory, dsync); // Paper - nuke IOWorker
this.codec = codecFactory; this.codec = codecFactory;
@ -3545,11 +3513,11 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
- this.worker = new IOWorker(directory, dsync, directory.getName()); - this.worker = new IOWorker(directory, dsync, directory.getName());
+ // Paper - remove mojang I/O thread + // Paper - remove mojang I/O thread
} }
protected void tick(BooleanSupplier shouldKeepTicking) { protected void tick(BooleanSupplier shouldKeepTicking) {
@@ -106,13 +107,18 @@ public class SectionStorage<R> implements AutoCloseable { @@ -106,13 +107,18 @@ public class SectionStorage<R> implements AutoCloseable {
} }
private void readColumn(ChunkPos chunkPos) { private void readColumn(ChunkPos chunkPos) {
- this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos)); - this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos));
+ // Paper start - expose function to load in data + // Paper start - expose function to load in data
@ -3559,7 +3527,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
+ this.readColumn(chunkPos, NbtOps.INSTANCE, compound); + this.readColumn(chunkPos, NbtOps.INSTANCE, compound);
+ // Paper end - expose function to load in data + // Paper end - expose function to load in data
} }
@Nullable @Nullable
private CompoundTag tryRead(ChunkPos pos) { private CompoundTag tryRead(ChunkPos pos) {
try { try {
@ -3577,9 +3545,9 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
} else { } else {
LOGGER.error("Expected compound tag, got {}", (Object)tag); LOGGER.error("Expected compound tag, got {}", (Object)tag);
} }
} }
+ // Paper start - internal get data function, copied from above + // Paper start - internal get data function, copied from above
+ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) { + private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) {
+ Dynamic<Tag> dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); + Dynamic<Tag> dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE);
@ -3595,9 +3563,9 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
+ // Paper end + // Paper end
private <T> Dynamic<T> writeColumn(ChunkPos chunkPos, DynamicOps<T> dynamicOps) { private <T> Dynamic<T> writeColumn(ChunkPos chunkPos, DynamicOps<T> dynamicOps) {
Map<T, T> map = Maps.newHashMap(); Map<T, T> map = Maps.newHashMap();
@@ -219,6 +238,23 @@ public class SectionStorage<R> implements AutoCloseable { @@ -219,6 +238,23 @@ public class SectionStorage<R> implements AutoCloseable {
@Override @Override
public void close() throws IOException { public void close() throws IOException {
- this.worker.close(); - this.worker.close();
@ -3622,7 +3590,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
+ // Paper end + // Paper end
} }
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java 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 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/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 { @@ -1811,6 +1811,34 @@ public class CraftWorld extends CraftRegionAccessor implements World {