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
*/
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 33558b6acc861f8b9986122c7c553f9dde22a45d..c1bdd642e870660931c3367884dcd7aa9d3e6923 100644
index d3d0e4448135f6c0440c15e0dd3fc15c2616263a..7ed2442031cdcc429aabe91d639871566359ba53 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -90,6 +90,38 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
@ -91,7 +91,7 @@ index 33558b6acc861f8b9986122c7c553f9dde22a45d..c1bdd642e870660931c3367884dcd7aa
* Gets the highest non-empty (impassable) coordinate at the given
* coordinates.
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java
index 3ca05a6e86a5329cf452041eac476e3636eec34a..18ab5cca036522df2d245f755d6c67904e6398e8 100644
index 62ab55729e69bfac8eb4b40d877b945d95df27cd..79c0fa47a0d733d1547f8926d88169939c986d8c 100644
--- a/src/main/java/org/bukkit/block/Block.java
+++ b/src/main/java/org/bukkit/block/Block.java
@@ -155,6 +155,72 @@ public interface Block extends Metadatable {

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.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 9d7d9c800710fff5cf41c973463b9c2d72a3e32a..4e0f61179e3b2ae91811746d32b24998173a922c 100644
index 9d7d9c800710fff5cf41c973463b9c2d72a3e32a..0ad0c84fd2e32d0c51f9aae777b80922a8f11a5a 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -388,4 +388,14 @@ public class PaperWorldConfig {
@@ -388,4 +388,9 @@ public class PaperWorldConfig {
disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false);
log("Creeper lingering effect: " + disableCreeperLingeringEffect);
}
+
+ public double squidMaxSpawnHeight;
+ private void squidMaxSpawnHeight() {
+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D);
+ }
+
+ public boolean disableSprintInterruptionOnAttack;
+ private void disableSprintInterruptionOnAttack() {
+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false);

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.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 4e0f61179e3b2ae91811746d32b24998173a922c..a0937dd52e4a2aa1bfadcbd1ac0dc2cb26d59cf0 100644
index 0ad0c84fd2e32d0c51f9aae777b80922a8f11a5a..760a7e667c8023cfa313d0566a6ed3b8cb2f929b 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -398,4 +398,10 @@ public class PaperWorldConfig {
@@ -393,4 +393,10 @@ public class PaperWorldConfig {
private void disableSprintInterruptionOnAttack() {
disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false);
}

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
index a0937dd52e4a2aa1bfadcbd1ac0dc2cb26d59cf0..4dce401da0e0fdf985ecb90f37b92e16cf210d25 100644
index 760a7e667c8023cfa313d0566a6ed3b8cb2f929b..4fe89087fb7f5132ea7e4fec5fbc2885644f369e 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -404,4 +404,9 @@ public class PaperWorldConfig {
@@ -399,4 +399,9 @@ public class PaperWorldConfig {
disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit);
log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled"));
}

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
index 4dce401da0e0fdf985ecb90f37b92e16cf210d25..35c6978eaf25ed505f99e42a58d388c62fde8319 100644
index 4fe89087fb7f5132ea7e4fec5fbc2885644f369e..3a9f0d5937b9d9abd4e4941c1a3f35f202b0d84a 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -409,4 +409,9 @@ public class PaperWorldConfig {
@@ -404,4 +404,9 @@ public class PaperWorldConfig {
private void shieldBlockingDelay() {
shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5);
}

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
index 35c6978eaf25ed505f99e42a58d388c62fde8319..0fd29d5854d9d6155ea590f86d4492d86afab433 100644
index 3a9f0d5937b9d9abd4e4941c1a3f35f202b0d84a..ba3dd73edd6a577633bce0cdcc27e1b698377ff0 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -414,4 +414,9 @@ public class PaperWorldConfig {
@@ -409,4 +409,9 @@ public class PaperWorldConfig {
private void scanForLegacyEnderDragon() {
scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true);
}

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
index 0fd29d5854d9d6155ea590f86d4492d86afab433..ff6cf94dec708c6d3cac837ca03be2fe12d5e05f 100644
index ba3dd73edd6a577633bce0cdcc27e1b698377ff0..c79b175fe28077be8a8ca28772fc8cd6f5e418b1 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -419,4 +419,10 @@ public class PaperWorldConfig {
@@ -414,4 +414,10 @@ public class PaperWorldConfig {
private void armorStandEntityLookups() {
armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true);
}

View file

@ -6,7 +6,7 @@ Subject: [PATCH] Optimize BlockPosition helper methods
Resolves #1338
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
index ed52d042f41942ae512148fbba310093358ead68..80d8873bc2512ecde6a531e974b14e9b48402d64 100644
index 5f23b9ab6540530acac623d2cd8e9ec5d0064f39..d38049bed6f3dc3198e687686ef4d8938c7a6b59 100644
--- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/src/main/java/net/minecraft/core/BlockPos.java
@@ -130,67 +130,84 @@ public class BlockPos extends Vec3i {

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
index c45332fa7b374e7775ca24a7065af3cb5c85d7cf..45be7d1821497f13ab0da3c4bbff7585238e902e 100644
index 6879ceb1c1c6b276f6686333b9b61a8a00690302..ee8c84770b9b7fb9f3763e378f399da58f042b06 100644
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
@@ -165,7 +165,7 @@ public class SpigotWorldConfig
@@ -178,7 +178,7 @@ public class SpigotWorldConfig
public byte mobSpawnRange;
private void mobSpawnRange()
{

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
index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9bdbfadfc1 100644
index 11aefbf65b0e63777d6ed5bfdb18c7f7df30fc0e..6ec81054bcf25d99aec567d568c361eea84ed384 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java
@@ -44,6 +44,12 @@ import net.minecraft.world.level.biome.Biomes;
@ -50,7 +50,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
}
@Override
@@ -481,7 +493,15 @@ public class Slime extends Mob implements Enemy {
@@ -486,7 +498,15 @@ public class Slime extends Mob implements Enemy {
public boolean canUse() {
LivingEntity entityliving = this.slime.getTarget();
@ -67,7 +67,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
}
@Override
@@ -494,7 +514,15 @@ public class Slime extends Mob implements Enemy {
@@ -499,7 +519,15 @@ public class Slime extends Mob implements Enemy {
public boolean canContinueToUse() {
LivingEntity entityliving = this.slime.getTarget();
@ -84,8 +84,8 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
}
@Override
@@ -502,6 +530,13 @@ public class Slime extends Mob implements Enemy {
this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F);
@@ -517,6 +545,13 @@ public class Slime extends Mob implements Enemy {
((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.getYRot(), this.slime.isDealsDamage());
}
+
@ -98,7 +98,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
}
private static class SlimeRandomDirectionGoal extends Goal {
@@ -517,14 +552,18 @@ public class Slime extends Mob implements Enemy {
@@ -532,7 +567,7 @@ public class Slime extends Mob implements Enemy {
@Override
public boolean canUse() {
@ -107,19 +107,19 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
}
@Override
public void tick() {
@@ -540,6 +575,11 @@ public class Slime extends Mob implements Enemy {
if (--this.nextRandomizeTime <= 0) {
this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60);
- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
+ // Paper start
+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360));
+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), this.chosenDegrees);
+ if (!this.slime.canWander || !event.callEvent()) return;
+ this.chosenDegrees = event.getNewYaw();
+ // Paper end
}
((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false);
@@ -542,7 +581,7 @@ public class Slime extends Mob implements Enemy {
@@ -557,7 +597,7 @@ public class Slime extends Mob implements Enemy {
@Override
public boolean canUse() {
@ -128,7 +128,7 @@ index 239f3a17ab8cff4e6c97044e4f8e6755abac193d..82747a12d4977ed2d26d203f690ecc9b
}
@Override
@@ -550,4 +589,15 @@ public class Slime extends Mob implements Enemy {
@@ -565,4 +605,15 @@ public class Slime extends Mob implements Enemy {
((Slime.SlimeMoveControl) this.slime.getMoveControl()).setWantedMovement(1.0D);
}
}

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
index ff6cf94dec708c6d3cac837ca03be2fe12d5e05f..29703f57969b80e25ff9a4971e640f34fb212edf 100644
index c79b175fe28077be8a8ca28772fc8cd6f5e418b1..7c538eba5d7e0112aae4c1584172233a3217ae89 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -425,4 +425,10 @@ public class PaperWorldConfig {
@@ -420,4 +420,10 @@ public class PaperWorldConfig {
this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick);
log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default");
}
@ -20,23 +20,23 @@ index ff6cf94dec708c6d3cac837ca03be2fe12d5e05f..29703f57969b80e25ff9a4971e640f34
+ }
}
diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
index db4bcb600ab43439ef65d4510fb20d770ce9dba3..087601ffdeea97ec4cbb9959607bdcbcbae7c6fa 100644
index c3d3c06e06a85ce926a2be69ec9d9b8a3eb9b8e2..11ebadaa2438281a54cffe025a49ee5046a71ba5 100644
--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
@@ -26,6 +26,7 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty;
@@ -24,6 +24,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
+import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext;
@@ -109,11 +110,27 @@ public class LiquidBlock extends Block implements BucketPickup {
@@ -107,11 +108,27 @@ public class LiquidBlock extends Block implements BucketPickup {
@Override
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) {
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world));
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
}
}
@ -60,12 +60,12 @@ index db4bcb600ab43439ef65d4510fb20d770ce9dba3..087601ffdeea97ec4cbb9959607bdcbc
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) {
@@ -126,7 +143,7 @@ public class LiquidBlock extends Block implements BucketPickup {
@@ -124,7 +141,7 @@ public class LiquidBlock extends Block implements BucketPickup {
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) {
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world));
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
}
}

View file

@ -7,10 +7,10 @@ Avoids a hashmap lookup by cacheing a reference to the CraftBlockData
and cloning it when one is needed.
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index adf1c04d34383d088a3fc8c06cdc8b55552c354f..a087eec747bb355afd627c6042d20440c3e43e1b 100644
index 7d06d476d8e12bdb395488e85e34231daccbd853..987a4180a1eb902c512c2e6a36d692cbdd9b1563 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -637,6 +637,14 @@ public abstract class BlockBehaviour {
@@ -636,6 +636,14 @@ public abstract class BlockBehaviour {
this.hasPostProcess = blockbase_info.hasPostProcess;
this.emissiveRendering = blockbase_info.emissiveRendering;
}

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
index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26f78c4671 100644
index c57803ba5daa33df42374aab75a7120e1a1b7c5b..451be9232eaa513ed66ff0d2b93c932317ad6729 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
@@ -172,6 +172,11 @@ public class Phantom extends FlyingMob implements Enemy {
@@ -171,6 +171,11 @@ public class Phantom extends FlyingMob implements Enemy {
}
this.setPhantomSize(nbt.getInt("Size"));
@ -20,7 +20,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26
}
@Override
@@ -181,6 +186,11 @@ public class Phantom extends FlyingMob implements Enemy {
@@ -180,6 +185,11 @@ public class Phantom extends FlyingMob implements Enemy {
nbt.putInt("AY", this.anchorPoint.getY());
nbt.putInt("AZ", this.anchorPoint.getZ());
nbt.putInt("Size", this.getPhantomSize());
@ -32,7 +32,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26
}
@Override
@@ -232,6 +242,14 @@ public class Phantom extends FlyingMob implements Enemy {
@@ -231,6 +241,14 @@ public class Phantom extends FlyingMob implements Enemy {
return entitysize.scale(f);
}
@ -48,7 +48,7 @@ index 7cbb16646c6c83d443deedaf425d18d6de76e314..080f6d12838faf47ead0958d6bc08f26
CIRCLE, SWOOP;
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad243112a33 100644
index 9ac3047019ab32992530786b8ea7457a97d2299b..891c12b8cfcdc7a2915955bdd08e50b5b9465e02 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
@@ -4,6 +4,7 @@ import java.util.Iterator;
@ -59,7 +59,7 @@ index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad2
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.ServerStatsCounter;
@@ -73,8 +74,17 @@ public class PhantomSpawner implements CustomSpawner {
@@ -71,8 +72,17 @@ public class PhantomSpawner implements CustomSpawner {
int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 1);
for (int l = 0; l < k; ++l) {
@ -72,12 +72,12 @@ index ee18e2826f6390ef5a29557b733fd00db5bc409f..42effcbd3ca7c38a4e8b1aa835543ad2
+ continue;
+ }
+ // Paper end
Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world);
Phantom entityphantom = (Phantom) EntityType.PHANTOM.create(world);
-
+ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper
entityphantom.moveTo(blockposition1, 0.0F, 0.0F);
groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null);
world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
world.addFreshEntityWithPassengers(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java
index f77b83bee6eb739220b55793a0807f0267cfc8a9..c9dab70b0b284fe1c1daafd3c1f5bd08b14fa35d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java

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

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

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
Subject: [PATCH] Asynchronous chunk IO and loading
# UPDATE NOTES: RegionFileStorage and SectionStorage need resolving (will conflict on apply)
# ChunkSerializer needs the new tick lists to be saved (see added todos)
This patch re-adds a file IO thread as well as shoving de-serializing
chunk NBT data onto worker threads. This patch also will shove
chunk data serialization onto the same worker threads when the chunk
@ -2278,12 +2281,12 @@ index a5e438a834826161c52ca9db57d234d9ff80a591..b8bc1b9b8e8a33df90a963f9f9769292
@Override
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 70f2a946f50ca6be2ffaef8db8c1c03a729c757b..4f45ac04a219e619c13b31befd2c4e452057079c 100644
index 4f45ac04a219e619c13b31befd2c4e452057079c..eca61ff543244dbf05db0a30c21c5bbeea2b9144 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -505,4 +505,8 @@ public final class MCUtil {
return null;
}
@@ -509,4 +509,8 @@ public final class MCUtil {
public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status);
}
+
+ public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
@ -2291,22 +2294,22 @@ index 70f2a946f50ca6be2ffaef8db8c1c03a729c757b..4f45ac04a219e619c13b31befd2c4e45
+ }
}
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 6f30e10d59416799edbe362951ce61733e37b256..2b8b47f121b78cc5fe166c4280a327ddcf799b77 100644
index 4ab820c43ddc79f5a280e2d4b322a667b9ba725f..e0c1e4e38ff49429a587c59afb86e95c452d52a0 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -217,6 +217,7 @@ public class Main {
@@ -227,6 +227,7 @@ public class Main {
convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object);
convertable_conversionsession.saveDataTag(iregistrycustom_dimension, (SaveData) object);
*/
+ Class.forName(net.minecraft.world.entity.npc.VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async
final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> {
DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::new);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index cb2ca56df7f2adedff2ebdd26957c23164b56255..7a7c501b1dffb4928aa74edd684d79f7fa312789 100644
index 44f32023db3edaae107f48fd9b96baf5432417d9..a9f54a691af0cd15cbc38af8b8df3831de244aa7 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1001,7 +1001,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -984,7 +984,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getProfileCache().save(false); // Paper
}
// Spigot end
@ -2316,10 +2319,10 @@ index cb2ca56df7f2adedff2ebdd26957c23164b56255..7a7c501b1dffb4928aa74edd684d79f7
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
index 1072998cd4b00bd74e8aed9a17fbf67e31a595cd..7e3f4bb1ce723adbea8622aec8cce73faccfc664 100644
index 303125c4d0f8f235703975eab5eccb9aa045ccf8..dbcf3e764a26c89ef10afa294e1b80575ab2113e 100644
--- a/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;
}
}
@ -2338,7 +2341,7 @@ index 1072998cd4b00bd74e8aed9a17fbf67e31a595cd..7e3f4bb1ce723adbea8622aec8cce73f
return null;
}
@@ -375,7 +387,7 @@ public class ChunkHolder {
@@ -402,7 +414,7 @@ public class ChunkHolder {
ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel);
ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel);
boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE;
@ -2348,10 +2351,10 @@ index 1072998cd4b00bd74e8aed9a17fbf67e31a595cd..7e3f4bb1ce723adbea8622aec8cce73f
ChunkHolder.FullChunkStatus playerchunk_state1 = ChunkHolder.getFullChunkStatus(this.ticketLevel);
// CraftBukkit start
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
+++ 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 {
try {
this.queueSorter.close();
@ -2359,23 +2362,17 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
this.poiManager.close();
} finally {
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(() -> {
return true;
});
- this.flushWorker();
+ //this.flushWorker(); // Paper - nuke IOWorker
+ this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
+// this.i(); // Paper - nuke IOWorker
} else {
this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> {
ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error
@@ -498,16 +500,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot
+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more
@@ -546,17 +548,21 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
protected void tick(BooleanSupplier shouldKeepTicking) {
ProfilerFiller gameprofilerfiller = this.level.getProfiler();
@ -2387,11 +2384,18 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
if (!this.level.noSave()) {
+ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper
this.processUnloads(shouldKeepTicking);
+ }// Paper
+ } // Paper
}
gameprofilerfiller.pop();
@@ -528,12 +534,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot
+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more
private void processUnloads(BooleanSupplier shouldKeepTicking) {
LongIterator longiterator = this.toDrop.iterator();
@@ -573,12 +579,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (playerchunk != null) {
this.pendingUnloads.put(j, playerchunk);
this.modified = true;
@ -2402,11 +2406,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
}
// Spigot end
- this.scheduleUnload(j, playerchunk);
+ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb
+ //this.scheduleUnload(j, playerchunk); // Paper - move up because spigot did a dumb
}
}
activityAccountant.endActivity(); // Spigot
@@ -547,6 +554,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -594,6 +601,46 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
@ -2418,7 +2422,7 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
+ ChunkPos chunkPos = chunk.getPos();
+ CompoundTag poiData;
+ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) {
+ poiData = this.getVillagePlace().getData(chunk.getPos());
+ poiData = this.poiManager.getData(chunk.getPos());
+ }
+
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z,
@ -2453,7 +2457,7 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
private void scheduleUnload(long pos, ChunkHolder holder) {
CompletableFuture<ChunkAccess> completablefuture = holder.getChunkToSave();
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);
}
@ -2467,11 +2471,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
+ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex);
+ this.save(ichunkaccess);
+ }
+ // Paper end - async chunk saving
+ // Paper end - async chunk savin
if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) {
LevelChunk chunk = (LevelChunk) ichunkaccess;
@@ -631,19 +687,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -678,20 +734,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
private CompletableFuture<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
- nbttagcompound = this.readChunk(pos);
- } // Paper end
-
- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings
- boolean flag = nbttagcompound.contains("Status", 8);
-
- if (flag) {
- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.poiManager, pos, nbttagcompound);
+ // Paper start
+ if (ioThrowable != null) {
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable);
+ }
- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings
- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8);
+ this.getVillagePlace().loadInData(pos, chunkHolder.poiData);
+ this.poiManager.loadInData(pos, chunkHolder.poiData);
+ chunkHolder.tasks.forEach(Runnable::run);
+ // Paper end
- if (flag) {
- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound);
+ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async
+
+ if (true) {
+ ProtoChunk protochunk = chunkHolder.protoChunk;
this.markPosition(pos, protochunk.getStatus().getChunkType());
return Either.left(protochunk);
@@ -666,7 +726,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
@@ -713,7 +769,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.markPositionReplaceable(pos);
return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level));
return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), (BlendingData) null));
- }, this.mainThreadExecutor);
+ // Paper start - Async chunk io
+ };
@ -2537,8 +2540,8 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
+ // Paper end
}
private void markPositionReplaceable(ChunkPos chunkcoordintpair) {
@@ -848,6 +933,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private void markPositionReplaceable(ChunkPos pos) {
@@ -896,6 +977,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public boolean save(ChunkAccess chunk) {
@ -2546,7 +2549,7 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
this.poiManager.flush(chunk.getPos());
if (!chunk.isUnsaved()) {
return false;
@@ -859,7 +945,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -907,7 +989,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
ChunkStatus chunkstatus = chunk.getStatus();
if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) {
@ -2555,18 +2558,18 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
return false;
}
@@ -869,9 +955,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -917,9 +999,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
this.level.getProfiler().incrementCounter("chunkSave");
- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk);
-
- this.write(chunkcoordintpair, nbttagcompound);
+ CompoundTag nbttagcompound;
+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper
+ nbttagcompound = ChunkSerializer.write(this.level, chunk);
+ } // Paper
+ } // Paper;
+
- this.write(chunkcoordintpair, nbttagcompound);
+ // Paper start - async chunk io
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z,
+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY);
@ -2574,15 +2577,15 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
this.markPosition(chunkcoordintpair, chunkstatus.getChunkType());
return true;
} catch (Exception exception) {
@@ -880,6 +973,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -928,6 +1016,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return false;
}
}
+ } // Paper
}
private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) {
@@ -1007,6 +1101,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private boolean isExistingChunkFull(ChunkPos pos) {
@@ -1060,6 +1149,35 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
}
@ -2618,19 +2621,11 @@ index cec5e220bcbed01f45afc75f653b5937ffea25cc..d445990c843ad86215be238c4b441669
@Nullable
public CompoundTag readChunk(ChunkPos pos) throws IOException {
CompoundTag nbttagcompound = this.read(pos);
@@ -1360,6 +1483,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
+ @Deprecated public PoiManager getVillagePlace() { return this.getPoiManager(); } // Paper - OBFHELPER
protected PoiManager getPoiManager() {
return this.poiManager;
}
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a33423f61 100644
index 212261651fd650cc895f817ccca37699d1cade8f..463cbbbe97bd421ac343ba80cc99731ff5fb4052 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -481,10 +481,128 @@ public class ServerChunkCache extends ChunkSource {
@@ -500,10 +500,128 @@ public class ServerChunkCache extends ChunkSource {
return ret;
}
// Paper end
@ -2759,13 +2754,13 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a
if (Thread.currentThread() != this.mainThread) {
return (ChunkAccess) CompletableFuture.supplyAsync(() -> {
return this.getChunk(x, z, leastStatus, create);
@@ -507,13 +625,18 @@ public class ServerChunkCache extends ChunkSource {
@@ -526,13 +644,18 @@ public class ServerChunkCache extends ChunkSource {
}
gameprofilerfiller.incrementCounter("getChunkCacheMiss");
- CompletableFuture<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
ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor;
ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor;
Objects.requireNonNull(completablefuture);
if (!completablefuture.isDone()) { // Paper
@ -2774,12 +2769,12 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a
+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1);
+ // Paper end
this.level.timings.syncChunkLoad.startTiming(); // Paper
chunkproviderserver_a.managedBlock(completablefuture::isDone);
chunkproviderserver_b.managedBlock(completablefuture::isDone);
+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug
this.level.timings.syncChunkLoad.stopTiming(); // Paper
} // Paper
ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
@@ -600,6 +723,11 @@ public class ServerChunkCache extends ChunkSource {
@@ -619,6 +742,11 @@ public class ServerChunkCache extends ChunkSource {
}
private CompletableFuture<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);
long k = chunkcoordintpair.toLong();
int l = 33 + ChunkStatus.getDistance(leastStatus);
@@ -997,11 +1125,12 @@ public class ServerChunkCache extends ChunkSource {
@@ -1028,11 +1156,12 @@ public class ServerChunkCache extends ChunkSource {
// CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
public boolean pollTask() {
try {
@ -2806,10 +2801,10 @@ index 4956a9ea1b4545d80468521afe8c5453b53768c3..1603d406b54aefdf337827df164c227a
} finally {
chunkMap.callbackExecutor.run();
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index afdb25743ceb404b4681ee2965fe3448f1f1b06a..e4626f6edb845ce751235c4341a608de81857603 100644
index 29b2ddee252759c7ad17df8fe19ea08a36eb2673..807b508daaab587514cf91106df648758d6e9798 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -295,6 +295,78 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -307,6 +307,78 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
}
}
@ -2888,7 +2883,7 @@ index afdb25743ceb404b4681ee2965fe3448f1f1b06a..e4626f6edb845ce751235c4341a608de
// Paper end
// Add env and gen to constructor, WorldData -> WorldDataServer
@@ -368,6 +440,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -374,6 +446,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.sleepStatus = new SleepStatus();
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
@ -2910,10 +2905,10 @@ index 0d536d72ac918fbd403397ff369d10143ee9c204..be677d437d17b74c6188ce1bd5fc6fdc
private final String name;
private final Comparator<T> comparator;
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index cc1b855b09d4826f88b0c2b9c08fb901191a2108..1e3d7081467cccf09d4510907388479560f67f67 100644
index c8a5cd52689b2cd81a2206f0f71623d784c379ce..7ed73ea4a5f7383c953ee3e28ce8f234d8ff941e 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -711,6 +711,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
@@ -710,6 +710,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper
return;
}
@ -2928,7 +2923,7 @@ index cc1b855b09d4826f88b0c2b9c08fb901191a2108..1e3d7081467cccf09d45109073884795
StringReader stringreader = new StringReader(packet.getCommand());
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6fdbaf92b0 100644
index 2a73700b0cd31e2a88c478b884de0a7f3d018259..0a1e667487e2c7849e11c0395816dc8ce20e0113 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
@@ -37,9 +37,11 @@ public class PoiManager extends SectionStorage<PoiSection> {
@ -2937,8 +2932,8 @@ index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6f
private final LongSet loadedChunks = new LongOpenHashSet();
+ private final net.minecraft.server.level.ServerLevel world; // Paper
public PoiManager(File directory, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) {
super(directory, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world);
public PoiManager(Path path, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) {
super(path, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world);
+ this.world = (net.minecraft.server.level.ServerLevel)world; // Paper
this.distanceTracker = new PoiManager.DistanceTracker();
}
@ -2999,33 +2994,19 @@ index 3ca8b13744b406c3e563747f0cb69647c94103df..7b1d2748328ffc1447bcacd1316f2c6f
public static enum Occupancy {
HAS_SPACE(PoiRecord::hasSpace),
IS_OCCUPIED(PoiRecord::isOccupied),
diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java
index 3af31dc2c82c11ee78d497c5777615c17cb13c7a..3b8c04f6ffd7e6c197465aa1caf633ba92529472 100644
--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java
+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java
@@ -4,7 +4,7 @@ import java.util.Comparator;
import net.minecraft.core.BlockPos;
public class TickNextTickData<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
index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b8221ac41 100644
index 2fd969d1450d1251c139f3721d146fd2e191c4dd..806e6559555a6e71ef8199d4ffc5ce86a06bb871 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -67,7 +67,30 @@ public class ChunkSerializer {
@@ -62,6 +62,7 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.ticks.LevelChunkTicks;
import net.minecraft.world.ticks.ProtoChunkTicks;
+import net.minecraft.world.ticks.TickContainerAccess;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -75,7 +76,31 @@ public class ChunkSerializer {
public ChunkSerializer() {}
@ -3044,77 +3025,71 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ }
+ // Paper end
+
public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt) {
public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) {
+ // Paper start - add variant for async calls
+ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, nbt, true);
+ InProgressChunkHolder holder = loadChunk(world, poiStorage, chunkPos, nbt, true);
+ holder.tasks.forEach(Runnable::run);
+ return holder.protoChunk;
+ }
+ public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) {
+
+ public static InProgressChunkHolder loadChunk(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt, boolean distinguish) {
+ java.util.ArrayDeque<Runnable> tasksToExecuteOnMain = new java.util.ArrayDeque<>();
+ // Paper end
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource();
CompoundTag nbttagcompound1 = nbt.getCompound("Level");
@@ -94,7 +117,9 @@ public class ChunkSerializer {
ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos"));
if (!Objects.equals(chunkPos, chunkcoordintpair1)) {
@@ -92,7 +117,9 @@ public class ChunkSerializer {
LevelLightEngine lightengine = chunkproviderserver.getLightEngine();
if (flag) {
+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main
lightengine.retainData(pos, true);
lightengine.retainData(chunkPos, true);
+ }); // Paper - delay this task since we're executing off-main
}
for (int j = 0; j < nbttaglist.size(); ++j) {
@@ -110,16 +135,28 @@ public class ChunkSerializer {
achunksection[world.getSectionIndexFromSectionY(b0)] = chunksection;
}
+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main
poiStorage.checkConsistencyWithBlocks(pos, chunksection);
+ }); // Paper - delay this task since we're executing off-main
}
Registry<Biome> iregistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
@@ -141,11 +168,21 @@ public class ChunkSerializer {
if (flag) {
if (nbttagcompound2.contains("BlockLight", 7)) {
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true);
if (nbttagcompound1.contains("BlockLight", 7)) {
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight")), true);
+ // Paper start - delay this task since we're executing off-main
+ DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight"));
+ DataLayer blockLight = new DataLayer(nbttagcompound1.getByteArray("BlockLight"));
+ tasksToExecuteOnMain.add(() -> {
+ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true);
+ });
+ // Paper end - delay this task since we're executing off-main
}
if (flag1 && nbttagcompound2.contains("SkyLight", 7)) {
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true);
if (flag1 && nbttagcompound1.contains("SkyLight", 7)) {
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight")), true);
+ // Paper start - delay this task since we're executing off-main
+ DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight"));
+ DataLayer skyLight = new DataLayer(nbttagcompound1.getByteArray("SkyLight"));
+ tasksToExecuteOnMain.add(() -> {
+ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair1, b0), skyLight, true);
+ });
+ // Paper end - delay this task since we're executing off-main
+ // Paper end - delay this task since we're executing off-mai
}
}
}
@@ -233,7 +270,7 @@ public class ChunkSerializer {
@@ -258,7 +295,7 @@ public class ChunkSerializer {
}
if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) {
- return new ImposterProtoChunk((LevelChunk) object);
+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading
- return new ImposterProtoChunk((LevelChunk) object, false);
+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object, false), tasksToExecuteOnMain); // Paper - Async chunk loading
} else {
ProtoChunk protochunk1 = (ProtoChunk) object;
@@ -272,11 +309,92 @@ public class ChunkSerializer {
protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1)));
@@ -297,10 +334,89 @@ public class ChunkSerializer {
protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound4.getLongArray(s1), ((ChunkAccess) object).getMinBuildHeight()));
}
- return protochunk1;
+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
+ }
+ }
+
}
}
+ // Paper start - async chunk save for unload
+ public static final class AsyncSaveData {
+ public final DataLayer[] blockLight;
@ -3163,8 +3138,9 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray;
+ }
+
+ TickList<Block> blockTickList = chunk.getBlockTicks();
+ TickContainerAccess<Block> blockTickList = chunk.getBlockTicks();
+
+ //TODO check ChunkSerializer "block_ticks"
+ ListTag blockTickListSerialized;
+ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) {
+ blockTickListSerialized = null;
@ -3172,13 +3148,14 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ blockTickListSerialized = world.getBlockTicks().save(chunkPos);
+ }
+
+ TickList<Fluid> fluidTickList = chunk.getLiquidTicks();
+ TickContainerAccess<Fluid> fluidTickList = chunk.getFluidTicks();
+
+ //TODO
+ ListTag fluidTickListSerialized;
+ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) {
+ fluidTickListSerialized = null;
+ } else {
+ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos);
+ fluidTickListSerialized = world.getFluidTicks().save(chunkPos);
+ }
+
+ ListTag blockEntitiesSerialized = new ListTag();
@ -3187,9 +3164,15 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ if (blockEntityNbt != null) {
+ blockEntitiesSerialized.add(blockEntityNbt);
+ }
}
+ }
+
+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime());
+ }
+
private static void logErrors(ChunkPos chunkPos, int y, String message) {
ChunkSerializer.LOGGER.error("Recoverable errors when loading section [" + chunkPos.x + ", " + y + ", " + chunkPos.z + "]: " + message);
}
@@ -310,6 +426,10 @@ public class ChunkSerializer {
}
public static CompoundTag write(ServerLevel world, ChunkAccess chunk) {
@ -3199,23 +3182,21 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ // Paper end
ChunkPos chunkcoordintpair = chunk.getPos();
CompoundTag nbttagcompound = new CompoundTag();
CompoundTag nbttagcompound1 = new CompoundTag();
@@ -285,7 +403,7 @@ public class ChunkSerializer {
nbttagcompound.put("Level", nbttagcompound1);
nbttagcompound1.putInt("xPos", chunkcoordintpair.x);
nbttagcompound1.putInt("zPos", chunkcoordintpair.z);
- nbttagcompound1.putLong("LastUpdate", world.getGameTime());
+ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading
nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime());
nbttagcompound1.putString("Status", chunk.getStatus().getName());
UpgradeData chunkconverter = chunk.getUpgradeData();
@@ -304,9 +422,17 @@ public class ChunkSerializer {
LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> {
return chunksection1 != null && SectionPos.blockToSectionCoord(chunksection1.bottomBlockY()) == finalI; // CraftBukkit - decompile errors
}).findFirst().orElse(LevelChunk.EMPTY_SECTION);
@@ -318,6 +438,7 @@ public class ChunkSerializer {
nbttagcompound.putInt("yPos", chunk.getMinSection());
nbttagcompound.putInt("zPos", chunkcoordintpair.z);
nbttagcompound.putLong("LastUpdate", world.getGameTime());
+ nbttagcompound.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading
nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime());
nbttagcompound.putString("Status", chunk.getStatus().getName());
BlendingData blendingdata = chunk.getBlendingData();
@@ -360,8 +481,17 @@ public class ChunkSerializer {
for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) {
int j = chunk.getSectionIndexFromSectionY(i);
boolean flag1 = j >= 0 && j < achunksection.length;
- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
-
+ // Paper start - async chunk save for unload
+ DataLayer nibblearray; // block light
+ DataLayer nibblearray1; // sky light
@ -3227,11 +3208,11 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()];
+ }
+ // Paper end
if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) {
CompoundTag nbttagcompound2 = new CompoundTag();
@@ -338,8 +464,17 @@ public class ChunkSerializer {
nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes());
if (flag1 || nibblearray != null || nibblearray1 != null) {
CompoundTag nbttagcompound1 = new CompoundTag();
@@ -399,8 +529,17 @@ public class ChunkSerializer {
nbttagcompound.putBoolean("isLightOn", true);
}
- ListTag nbttaglist1 = new ListTag();
@ -3248,38 +3229,24 @@ index 03190535999d30aea0428631ae576b18f5d10eb7..b8bdd69bda00ba0eb72c161d3b49101b
+ }
+ // Paper end
CompoundTag nbttagcompound3;
CompoundTag nbttagcompound2;
@@ -382,6 +517,10 @@ public class ChunkSerializer {
nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save());
} else if (ticklist instanceof ChunkTickList) {
nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save());
+ // Paper start - async chunk save for unload
+ } else if (asyncsavedata != null) {
+ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList);
+ // Paper end
} else {
nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair));
}
@@ -392,6 +531,10 @@ public class ChunkSerializer {
nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save());
} else if (ticklist1 instanceof ChunkTickList) {
nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save());
+ // Paper start - async chunk save for unload
+ } else if (asyncsavedata != null) {
+ nbttagcompound1.put("LiquidTicks", asyncsavedata.fluidTickList);
+ // Paper end
} else {
nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair));
}
@@ -463,6 +602,7 @@ public class ChunkSerializer {
private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) {
long i = world.getLevelData().getGameTime();
+ //TODO original patch line 3259
nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> {
return Registry.BLOCK.getKey(block).toString();
}));
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841d34ae7b0 100644
index 0259baec1ceb911f39e733d52d232dec19577550..9fe3ab209ebbfc40dc1bf046d474296c660e38d5 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@@ -21,27 +21,38 @@ import net.minecraft.world.level.storage.DimensionDataStorage;
@@ -25,27 +25,38 @@ import net.minecraft.world.level.storage.DimensionDataStorage;
public class ChunkStorage implements AutoCloseable {
public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493;
- private final IOWorker worker;
+ // Paper - nuke IO worker
protected final DataFixer fixerUpper;
@ -3291,7 +3258,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841
+ public final RegionFileStorage regionFileCache;
+ // Paper end - async chunk loading
public ChunkStorage(File directory, DataFixer dataFixer, boolean dsync) {
public ChunkStorage(Path directory, DataFixer dataFixer, boolean dsync) {
this.fixerUpper = dataFixer;
- this.worker = new IOWorker(directory, dsync, "chunk");
+ // Paper start - async chunk io
@ -3321,7 +3288,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841
if (nbt != null) {
CompoundTag level = nbt.getCompound("Level");
if (level.getBoolean("TerrainPopulated")) {
@@ -77,11 +88,13 @@ public class ChunkStorage implements AutoCloseable {
@@ -80,11 +91,13 @@ public class ChunkStorage implements AutoCloseable {
if (i < 1493) {
nbttagcompound = NbtUtils.update(this.fixerUpper, DataFixTypes.CHUNK, nbttagcompound, i, 1493);
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
@ -3335,7 +3302,7 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841
}
}
@@ -99,22 +112,26 @@ public class ChunkStorage implements AutoCloseable {
@@ -114,23 +127,27 @@ public class ChunkStorage implements AutoCloseable {
@Nullable
public CompoundTag read(ChunkPos chunkPos) throws IOException {
@ -3366,20 +3333,21 @@ index 8121470cdd94bde4d84f70882f3bdb3dc067cf15..6f13c7adce7d4b3d170045ea5ef2a841
- this.worker.close();
+ this.regionFileCache.close(); // Paper - nuke IO worker
}
}
public ChunkScanAccess chunkScanner() {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c9778c4d2d2 100644
index 7b69007609ed421ee72ddc3d6f2a7b64888babf1..6f7bcf74b0ff42841e37f36561d6c54e1ee8c989 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -47,6 +47,7 @@ public class RegionFile implements AutoCloseable {
@@ -44,6 +44,7 @@ public class RegionFile implements AutoCloseable {
private final IntBuffer timestamps;
@VisibleForTesting
protected final RegionBitmap usedSectors;
+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper
public RegionFile(File file, File directory, boolean dsync) throws IOException {
this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync);
@@ -231,7 +232,7 @@ public class RegionFile implements AutoCloseable {
public RegionFile(Path path, Path path1, boolean dsync) throws IOException {
this(path, path1, RegionFileVersion.VERSION_DEFLATE, dsync);
@@ -228,7 +229,7 @@ public class RegionFile implements AutoCloseable {
return (byteCount + 4096 - 1) / 4096;
}
@ -3388,7 +3356,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97
int i = this.getOffset(pos);
if (i == 0) {
@@ -398,6 +399,11 @@ public class RegionFile implements AutoCloseable {
@@ -395,6 +396,11 @@ public class RegionFile implements AutoCloseable {
}
public void close() throws IOException {
@ -3400,7 +3368,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97
try {
this.padToFullSector();
} finally {
@@ -407,6 +413,10 @@ public class RegionFile implements AutoCloseable {
@@ -404,6 +410,10 @@ public class RegionFile implements AutoCloseable {
this.file.close();
}
}
@ -3410,7 +3378,7 @@ index 84327c8fe1dc62c7b99950261a344042b4456616..298b5abbc792dd33be38acbd1c572c97
+ } // Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c89faef06 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@ -3418,7 +3386,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
@@ -28,11 +28,32 @@ public class RegionFileStorage implements AutoCloseable {
this.sync = dsync;
}
- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
+ // Paper start
+ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) {
@ -3438,7 +3406,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
+ // Paper end
long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i);
if (regionfile != null) {
+ // Paper start
+ if (lock) {
@ -3451,7 +3419,7 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable
@@ -50,6 +71,12 @@ public class RegionFileStorage implements AutoCloseable {
RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync);
this.regionCache.putAndMoveToFirst(i, regionfile1);
+ // Paper start
+ if (lock) {
@ -3474,23 +3442,23 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
// CraftBukkit end
+ try { // Paper
DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos);
CompoundTag nbttagcompound;
@@ -98,10 +126,14 @@ public class RegionFileStorage implements AutoCloseable {
}
return nbttagcompound;
+ } finally { // Paper start
+ regionfile.fileLock.unlock();
+ } // Paper end
}
protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException {
- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit
+ RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper
+ try { // Paper
int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper
if (nbt == null) {
@@ -140,9 +172,12 @@ public class RegionFileStorage implements AutoCloseable {
MinecraftServer.LOGGER.error("Failed to save chunk", laste);
@ -3500,20 +3468,20 @@ index 3d07235ad34d219c7c5fccd216a3a6935ced645c..ebb1a050beab9530942c4498335f084c
+ regionfile.fileLock.unlock();
+ } // Paper end
}
- public void close() throws IOException {
+ public synchronized void close() throws IOException { // Paper -> synchronized
ExceptionCollector<IOException> exceptionsuppressor = new ExceptionCollector<>();
ObjectIterator objectiterator = this.regionCache.values().iterator();
@@ -159,7 +194,7 @@ public class RegionFileStorage implements AutoCloseable {
exceptionsuppressor.throwIfPresent();
}
- public void flush() throws IOException {
+ public synchronized void flush() throws IOException { // Paper - synchronize
ObjectIterator objectiterator = this.regionCache.values().iterator();
while (objectiterator.hasNext()) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e1fb5cc22 100644
@ -3522,7 +3490,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
@@ -30,10 +30,10 @@ import net.minecraft.world.level.LevelHeightAccessor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-public class SectionStorage<R> implements AutoCloseable {
+public class SectionStorage<R> extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker
private static final Logger LOGGER = LogManager.getLogger();
@ -3534,7 +3502,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
private final Function<Runnable, Codec<R>> codec;
@@ -43,12 +43,13 @@ public class SectionStorage<R> implements AutoCloseable {
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) {
+ super(directory, dsync); // Paper - nuke IOWorker
this.codec = codecFactory;
@ -3545,11 +3513,11 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
- this.worker = new IOWorker(directory, dsync, directory.getName());
+ // Paper - remove mojang I/O thread
}
protected void tick(BooleanSupplier shouldKeepTicking) {
@@ -106,13 +107,18 @@ public class SectionStorage<R> implements AutoCloseable {
}
private void readColumn(ChunkPos chunkPos) {
- this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos));
+ // Paper start - expose function to load in data
@ -3559,7 +3527,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
+ this.readColumn(chunkPos, NbtOps.INSTANCE, compound);
+ // Paper end - expose function to load in data
}
@Nullable
private CompoundTag tryRead(ChunkPos pos) {
try {
@ -3577,9 +3545,9 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
} else {
LOGGER.error("Expected compound tag, got {}", (Object)tag);
}
}
+ // Paper start - internal get data function, copied from above
+ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) {
+ Dynamic<Tag> dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE);
@ -3595,9 +3563,9 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
+ // Paper end
private <T> Dynamic<T> writeColumn(ChunkPos chunkPos, DynamicOps<T> dynamicOps) {
Map<T, T> map = Maps.newHashMap();
@@ -219,6 +238,23 @@ public class SectionStorage<R> implements AutoCloseable {
@Override
public void close() throws IOException {
- this.worker.close();
@ -3622,7 +3590,7 @@ index e5e138fb23d03eb63e547e74d3e14ec9d96d8107..90f7b06bd2c558be35c4577044fa033e
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index bccc66266739954ca5d7208d233884f5270e0064..034c2886b4e29be40fa2e5e213a7457d803c0f55 100644
index d1ffbacdabc500bfbe3f65eed6206e499775f97a..7f4024dbc1a0c50af9344689561de54eb35e1c98 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1811,6 +1811,34 @@ public class CraftWorld extends CraftRegionAccessor implements World {