aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSpottedleaf <[email protected]>2024-10-24 08:18:20 -0700
committerSpottedleaf <[email protected]>2024-10-25 11:25:09 -0700
commitecf4d9715e235c8d26202404c66642ca7e90aa68 (patch)
treeee52ec90cec283475af937df40e7b142e6965d2b
parent47258a71184e0b3c919e2f224cf2aca985722ddf (diff)
downloadPaper-ecf4d9715e235c8d26202404c66642ca7e90aa68.tar.gz
Paper-ecf4d9715e235c8d26202404c66642ca7e90aa68.zip
Begin fixing issues
See diff in the update text file
-rw-r--r--moonrise_update_1_21_2.txt10
-rw-r--r--patches/server/0821-fixup-ConcurrentUtil.patch (renamed from patches/server/1069-fixup-ConcurrentUtil.patch)0
-rw-r--r--patches/server/0822-fixup-MC-Utils.patch (renamed from patches/server/1070-fixup-MC-Utils.patch)262
-rw-r--r--patches/server/0823-fixup-MC-Utils.patch117
-rw-r--r--patches/server/0824-fixup-Paper-config-files.patch87
-rw-r--r--patches/server/0825-Rewrite-dataconverter-system.patch (renamed from patches/unapplied/server/0982-Rewrite-dataconverter-system.patch)1588
-rw-r--r--patches/server/0826-Moonrise-optimisation-patches.patch (renamed from patches/unapplied/server/0981-Moonrise-optimisation-patches.patch)2217
-rw-r--r--patches/server/0827-fixup-Optimize-BlockPosition-helper-methods.patch (renamed from patches/server/1072-fixup-Optimize-BlockPosition-helper-methods.patch)14
-rw-r--r--patches/server/0828-fixup-Moonrise-optimisation-patches.patch (renamed from patches/server/1073-fixup-Moonrise-optimisation-patches.patch)778
-rw-r--r--patches/server/1071-Revert-Custom-table-implementation-for-blockstate-st.patch345
-rw-r--r--patches/unapplied/server/1005-Custom-table-implementation-for-blockstate-state-loo.patch343
11 files changed, 2910 insertions, 2851 deletions
diff --git a/moonrise_update_1_21_2.txt b/moonrise_update_1_21_2.txt
index f7067cc556..d6a3d5df42 100644
--- a/moonrise_update_1_21_2.txt
+++ b/moonrise_update_1_21_2.txt
@@ -13,12 +13,7 @@ add notes to moonrise patch:
todo:
- double check that the misc changes commit on dev/1.21.2 moonrise is applied
- implement platformhooks
-- delete old block state table patch
-- in StateHolder, implement getNullableValue from blockstate_propertyaccess
-- ChunkEntitySlices getChunkEntities(), callEntitiesLoadEvent(), callEntitiesUnloadEvent()
- in ChunkEntitySlices, implement modifySavedEntities() by copying from old
-- in ChunkEntitySlices, implement unload() Entity.setRemoved()
-- change PersistentEntitySectionManager addEntity chunk system call to have event=true
- implement PlayerChunkUnloadEvent in PlatformHooks#onChunkUnWatch
- make sure chunk pos is passed in PlatformHooks#postLoadProtoChunk
- implement chunk_system.ChunkMapMixin diff from reference
@@ -32,11 +27,10 @@ todo:
- implement chunk_system.ServerLevelMixin diff from reference
- implement chunk_tick_iteration
- implement collisions.ServerExplosionMixin diff from reference
-- implement modifyEntityTrackingRange with org.spigotmc.TrackingRange.getEntityTrackingRange
-- implement random_ticking.BiomeMixin diff from reference
- implement starlight.LevelLightEngineMixin diff from reference
- implement starlight.ThreadedLevelLightEngineMixin diff from reference
- implement starlight.ChunkSerializerMixin diff from reference
- implement starlight.SerializableChunkData$SectionData diff from reference
- implement starlight.SerializableChunkDataMixin diff from reference
-
+- unfuck the chtunk system config diff
+- chunk system: move get entity lookup reroute into the folia scheduler api patch
diff --git a/patches/server/1069-fixup-ConcurrentUtil.patch b/patches/server/0821-fixup-ConcurrentUtil.patch
index 60d57a1656..60d57a1656 100644
--- a/patches/server/1069-fixup-ConcurrentUtil.patch
+++ b/patches/server/0821-fixup-ConcurrentUtil.patch
diff --git a/patches/server/1070-fixup-MC-Utils.patch b/patches/server/0822-fixup-MC-Utils.patch
index b68d600395..cc014ce7e8 100644
--- a/patches/server/1070-fixup-MC-Utils.patch
+++ b/patches/server/0822-fixup-MC-Utils.patch
@@ -6,16 +6,16 @@ Subject: [PATCH] fixup! MC Utils
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java b/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java
new file mode 100644
-index 0000000000000000000000000000000000000000..69a20e9d72b02f28b349f24fd0ea08736888e642
+index 0000000000000000000000000000000000000000..3c5ed66328ccf94c4744a191a7c63562dd08158d
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java
@@ -0,0 +1,115 @@
+package ca.spottedleaf.moonrise.common;
+
-+import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
+import com.mojang.datafixers.DataFixer;
+import net.minecraft.core.BlockPos;
+import net.minecraft.nbt.CompoundTag;
++import net.minecraft.server.level.ChunkHolder;
+import net.minecraft.server.level.GenerationChunkHolder;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
@@ -56,7 +56,7 @@ index 0000000000000000000000000000000000000000..69a20e9d72b02f28b349f24fd0ea0873
+
+ public boolean allowAsyncTicketUpdates();
+
-+ public void onChunkHolderTicketChange(final ServerLevel world, final NewChunkHolder holder, final int oldLevel, final int newLevel);
++ public void onChunkHolderTicketChange(final ServerLevel world, final ChunkHolder holder, final int oldLevel, final int newLevel);
+
+ public void chunkUnloadFromWorld(final LevelChunk chunk);
+
@@ -685,7 +685,7 @@ index ab093b0e8ac6f762921eb1d15f5217345c4eba05..bb44de17a37082e57f2292a4f470740b
}
}
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java
-index 0abba00741b39b69a7f167e5d2670f2565c9a752..b61611351bf23efc1e90bab8a850ebbe6ffdd516 100644
+index da323a1105347d5cf4b946df10ded78a953236f2..94bba2b71918d79f54b3e28c35e76098ba0afd8c 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java
@@ -1,6 +1,7 @@
@@ -694,11 +694,11 @@ index 0abba00741b39b69a7f167e5d2670f2565c9a752..b61611351bf23efc1e90bab8a850ebbe
-import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
+import ca.spottedleaf.concurrentutil.util.Priority;
+import ca.spottedleaf.moonrise.common.PlatformHooks;
- import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
- import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
- import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
-@@ -23,27 +24,27 @@ public final class ChunkSystem {
- private static final Logger LOGGER = LogUtils.getLogger();
+ import com.mojang.logging.LogUtils;
+ import net.minecraft.server.level.ChunkHolder;
+ import net.minecraft.server.level.FullChunkStatus;
+@@ -24,15 +25,15 @@ public final class ChunkSystem {
+ }
public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
- scheduleChunkTask(level, chunkX, chunkZ, run, PrioritisedExecutor.Priority.NORMAL);
@@ -707,30 +707,50 @@ index 0abba00741b39b69a7f167e5d2670f2565c9a752..b61611351bf23efc1e90bab8a850ebbe
- public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final PrioritisedExecutor.Priority priority) {
+ public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final Priority priority) {
- ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkTask(chunkX, chunkZ, run, priority);
+ level.chunkSource.mainThreadProcessor.execute(run);
}
public static void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final boolean gen,
- final ChunkStatus toStatus, final boolean addTicket, final PrioritisedExecutor.Priority priority,
+ final ChunkStatus toStatus, final boolean addTicket, final Priority priority,
final Consumer<ChunkAccess> onComplete) {
- ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(chunkX, chunkZ, gen, toStatus, addTicket, priority, onComplete);
- }
+ if (gen) {
+ scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
+@@ -59,7 +60,7 @@ public final class ChunkSystem {
+ private static long chunkLoadCounter = 0L;
public static void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final ChunkStatus toStatus,
- final boolean addTicket, final PrioritisedExecutor.Priority priority, final Consumer<ChunkAccess> onComplete) {
+ final boolean addTicket, final Priority priority, final Consumer<ChunkAccess> onComplete) {
- ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
+ if (!org.bukkit.Bukkit.isPrimaryThread()) {
+ scheduleChunkTask(level, chunkX, chunkZ, () -> {
+ scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
+@@ -113,13 +114,13 @@ public final class ChunkSystem {
+ }
+ loadCallback.accept(result.orElse(null));
+ }, (final Runnable r) -> {
+- scheduleChunkTask(level, chunkX, chunkZ, r, PrioritisedExecutor.Priority.HIGHEST);
++ scheduleChunkTask(level, chunkX, chunkZ, r, Priority.HIGHEST);
+ });
}
public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
final FullChunkStatus toStatus, final boolean addTicket,
- final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) {
+ final Priority priority, final Consumer<LevelChunk> onComplete) {
- ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleTickingState(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
+ // This method goes unused until the chunk system rewrite
+ if (toStatus == FullChunkStatus.INACCESSIBLE) {
+ throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
+@@ -196,7 +197,7 @@ public final class ChunkSystem {
+ }
+ loadCallback.accept(result.orElse(null));
+ }, (final Runnable r) -> {
+- scheduleChunkTask(level, chunkX, chunkZ, r, PrioritisedExecutor.Priority.HIGHEST);
++ scheduleChunkTask(level, chunkX, chunkZ, r, Priority.HIGHEST);
+ });
}
-@@ -67,7 +68,10 @@ public final class ChunkSystem {
+@@ -220,7 +221,10 @@ public final class ChunkSystem {
return getUpdatingChunkHolderCount(level) != 0;
}
@@ -1002,6 +1022,211 @@ index af9623240ff2d389aa7090623f507720e7dbab7d..efda2688ae1254a82ba7f6bf8bf597ef
}
public static int getMaxLightSection(final LevelHeightAccessor world) {
+diff --git a/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..6f2dc0900dbf13a02410682eecda56cea4481346
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+@@ -0,0 +1,199 @@
++package ca.spottedleaf.moonrise.paper;
++
++import ca.spottedleaf.moonrise.common.PlatformHooks;
++import com.mojang.datafixers.DataFixer;
++import net.minecraft.core.BlockPos;
++import net.minecraft.nbt.CompoundTag;
++import net.minecraft.server.level.ChunkHolder;
++import net.minecraft.server.level.GenerationChunkHolder;
++import net.minecraft.server.level.ServerLevel;
++import net.minecraft.server.level.ServerPlayer;
++import net.minecraft.util.datafix.DataFixTypes;
++import net.minecraft.world.entity.Entity;
++import net.minecraft.world.level.BlockGetter;
++import net.minecraft.world.level.ChunkPos;
++import net.minecraft.world.level.Level;
++import net.minecraft.world.level.block.state.BlockState;
++import net.minecraft.world.level.chunk.ChunkAccess;
++import net.minecraft.world.level.chunk.LevelChunk;
++import net.minecraft.world.level.chunk.ProtoChunk;
++import net.minecraft.world.level.chunk.storage.SerializableChunkData;
++import net.minecraft.world.level.entity.EntityTypeTest;
++import net.minecraft.world.phys.AABB;
++import java.util.List;
++import java.util.function.Predicate;
++
++public final class PaperHooks implements PlatformHooks {
++
++ @Override
++ public String getBrand() {
++ return "Paper";
++ }
++
++ @Override
++ public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos) {
++ return blockState.getLightEmission();
++ }
++
++ @Override
++ public Predicate<BlockState> maybeHasLightEmission() {
++ return (final BlockState state) -> {
++ return state.getLightEmission() != 0;
++ };
++ }
++
++ @Override
++ public boolean hasCurrentlyLoadingChunk() {
++ return false;
++ }
++
++ @Override
++ public LevelChunk getCurrentlyLoadingChunk(final GenerationChunkHolder holder) {
++ return null;
++ }
++
++ @Override
++ public void setCurrentlyLoading(final GenerationChunkHolder holder, final LevelChunk levelChunk) {
++
++ }
++
++ @Override
++ public void chunkFullStatusComplete(final LevelChunk newChunk, final ProtoChunk original) {
++
++ }
++
++ @Override
++ public boolean allowAsyncTicketUpdates() {
++ return true;
++ }
++
++ @Override
++ public void onChunkHolderTicketChange(final ServerLevel world, final ChunkHolder holder, final int oldLevel, final int newLevel) {
++
++ }
++
++ @Override
++ public void chunkUnloadFromWorld(final LevelChunk chunk) {
++
++ }
++
++ @Override
++ public void chunkSyncSave(final ServerLevel world, final ChunkAccess chunk, final SerializableChunkData data) {
++
++ }
++
++ @Override
++ public void onChunkWatch(final ServerLevel world, final LevelChunk chunk, final ServerPlayer player) {
++
++ }
++
++ @Override
++ public void onChunkUnWatch(final ServerLevel world, final ChunkPos chunk, final ServerPlayer player) {
++
++ }
++
++ @Override
++ public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate, final List<Entity> into) {
++
++ }
++
++ @Override
++ public <T extends Entity> void addToGetEntities(final Level world, final EntityTypeTest<Entity, T> entityTypeTest, final AABB boundingBox, final Predicate<? super T> predicate, final List<? super T> into, final int maxCount) {
++
++ }
++
++ @Override
++ public void entityMove(final Entity entity, final long oldSection, final long newSection) {
++
++ }
++
++ @Override
++ public boolean screenEntity(final ServerLevel world, final Entity entity, final boolean fromDisk, final boolean event) {
++ return true;
++ }
++
++ @Override
++ public boolean configFixMC224294() {
++ return true;
++ }
++
++ @Override
++ public boolean configAutoConfigSendDistance() {
++
++ }
++
++ @Override
++ public double configPlayerMaxLoadRate() {
++
++ }
++
++ @Override
++ public double configPlayerMaxGenRate() {
++
++ }
++
++ @Override
++ public double configPlayerMaxSendRate() {
++
++ }
++
++ @Override
++ public int configPlayerMaxConcurrentLoads() {
++
++ }
++
++ @Override
++ public int configPlayerMaxConcurrentGens() {
++
++ }
++
++ @Override
++ public long configAutoSaveInterval() {
++
++ }
++
++ @Override
++ public int configMaxAutoSavePerTick() {
++
++ }
++
++ @Override
++ public boolean configFixMC159283() {
++ return true;
++ }
++
++ @Override
++ public boolean forceNoSave(final ChunkAccess chunk) {
++ return chunk instanceof LevelChunk levelChunk && levelChunk.mustNotSave;
++ }
++
++ @Override
++ public CompoundTag convertNBT(final DataFixTypes type, final DataFixer dataFixer, final CompoundTag nbt, final int fromVersion, final int toVersion) {
++ return type.update(dataFixer, nbt, fromVersion, toVersion);
++ }
++
++ @Override
++ public boolean hasMainChunkLoadHook() {
++ return false;
++ }
++
++ @Override
++ public void mainChunkLoad(final ChunkAccess chunk, final SerializableChunkData chunkData) {
++
++ }
++
++ @Override
++ public List<Entity> modifySavedEntities(final ServerLevel world, final int chunkX, final int chunkZ, final List<Entity> entities) {
++ return entities;
++ }
++
++ @Override
++ public void unloadEntity(final Entity entity) {
++ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK, org.bukkit.event.entity.EntityRemoveEvent.Cause.UNLOAD);
++ }
++
++ @Override
++ public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
++ return org.spigotmc.TrackingRange.getEntityTrackingRange(entity, currentRange);
++ }
++}
diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
index 6baa313b8201ed23193d7885c85606b0899ade3c..3eb38271b6ca26099b2da04c2d969e32fd72b2af 100644
--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
@@ -1029,3 +1254,10 @@ index 6baa313b8201ed23193d7885c85606b0899ade3c..3eb38271b6ca26099b2da04c2d969e32
}
// Paper end - chunk system hooks
if (!this.addEntityUuid(entity)) {
+diff --git a/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
+new file mode 100644
+index 0000000000000000000000000000000000000000..e57c3ca79677b1dfe7cf3db36f0406de7ea5bd0a
+--- /dev/null
++++ b/src/main/resources/META-INF/services/ca.spottedleaf.moonrise.common.PlatformHooks
+@@ -0,0 +1 @@
++ca.spottedleaf.moonrise.paper.PaperHooks
diff --git a/patches/server/0823-fixup-MC-Utils.patch b/patches/server/0823-fixup-MC-Utils.patch
new file mode 100644
index 0000000000..ea91946273
--- /dev/null
+++ b/patches/server/0823-fixup-MC-Utils.patch
@@ -0,0 +1,117 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+Date: Wed, 23 Oct 2024 22:13:41 -0700
+Subject: [PATCH] fixup! MC Utils
+
+
+diff --git a/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java b/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java
+index 3c5ed66328ccf94c4744a191a7c63562dd08158d..deb64f7ebebcf6de91ffe0542d6b449a4db64da0 100644
+--- a/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java
++++ b/src/main/java/ca/spottedleaf/moonrise/common/PlatformHooks.java
+@@ -1,5 +1,6 @@
+ package ca.spottedleaf.moonrise.common;
+
++import com.mojang.datafixers.DSL;
+ import com.mojang.datafixers.DataFixer;
+ import net.minecraft.core.BlockPos;
+ import net.minecraft.nbt.CompoundTag;
+@@ -7,7 +8,6 @@ import net.minecraft.server.level.ChunkHolder;
+ import net.minecraft.server.level.GenerationChunkHolder;
+ import net.minecraft.server.level.ServerLevel;
+ import net.minecraft.server.level.ServerPlayer;
+-import net.minecraft.util.datafix.DataFixTypes;
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.level.BlockGetter;
+ import net.minecraft.world.level.ChunkPos;
+@@ -88,7 +88,7 @@ public interface PlatformHooks {
+ // support for CB chunk mustNotSave
+ public boolean forceNoSave(final ChunkAccess chunk);
+
+- public CompoundTag convertNBT(final DataFixTypes type, final DataFixer dataFixer, final CompoundTag nbt,
++ public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
+ final int fromVersion, final int toVersion);
+
+ public boolean hasMainChunkLoadHook();
+@@ -99,6 +99,8 @@ public interface PlatformHooks {
+
+ public void unloadEntity(final Entity entity);
+
++ public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk);
++
+ public int modifyEntityTrackingRange(final Entity entity, final int currentRange);
+
+ public static final class Holder {
+diff --git a/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+index 6f2dc0900dbf13a02410682eecda56cea4481346..ee514a767f69de69d86e1e88d70fe37c4ab84277 100644
+--- a/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
++++ b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+@@ -1,14 +1,16 @@
+ package ca.spottedleaf.moonrise.paper;
+
+ import ca.spottedleaf.moonrise.common.PlatformHooks;
++import com.mojang.datafixers.DSL;
+ import com.mojang.datafixers.DataFixer;
++import com.mojang.serialization.Dynamic;
+ import net.minecraft.core.BlockPos;
+ import net.minecraft.nbt.CompoundTag;
++import net.minecraft.nbt.NbtOps;
+ import net.minecraft.server.level.ChunkHolder;
+ import net.minecraft.server.level.GenerationChunkHolder;
+ import net.minecraft.server.level.ServerLevel;
+ import net.minecraft.server.level.ServerPlayer;
+-import net.minecraft.util.datafix.DataFixTypes;
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.level.BlockGetter;
+ import net.minecraft.world.level.ChunkPos;
+@@ -168,8 +170,11 @@ public final class PaperHooks implements PlatformHooks {
+ }
+
+ @Override
+- public CompoundTag convertNBT(final DataFixTypes type, final DataFixer dataFixer, final CompoundTag nbt, final int fromVersion, final int toVersion) {
+- return type.update(dataFixer, nbt, fromVersion, toVersion);
++ public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
++ final int fromVersion, final int toVersion) {
++ return (CompoundTag)dataFixer.update(
++ type, new Dynamic<>(NbtOps.INSTANCE, nbt), fromVersion, toVersion
++ ).getValue();
+ }
+
+ @Override
+@@ -192,6 +197,11 @@ public final class PaperHooks implements PlatformHooks {
+ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK, org.bukkit.event.entity.EntityRemoveEvent.Cause.UNLOAD);
+ }
+
++ @Override
++ public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
++ net.minecraft.world.level.chunk.status.ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
++ }
++
+ @Override
+ public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
+ return org.spigotmc.TrackingRange.getEntityTrackingRange(entity, currentRange);
+diff --git a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java
+index f18c2b85ed9541f646f157184221e333d0ae58bd..aff4c3d63a97d5bbde004a616f7e14fca59b5ab9 100644
+--- a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java
++++ b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java
+@@ -168,7 +168,7 @@ public class ChunkStatusTasks {
+ }, context.mainThreadExecutor());
+ }
+
+- private static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities) {
++ public static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities) { // Paper - public
+ if (!entities.isEmpty()) {
+ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities
+ world.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(entities, world, EntitySpawnReason.LOAD).filter((entity) -> {
+diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
+index 3eb38271b6ca26099b2da04c2d969e32fd72b2af..5aa74c00a61282830d82359eae2b114e2a48b6d9 100644
+--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
++++ b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java
+@@ -97,7 +97,7 @@ public class PersistentEntitySectionManager<T extends EntityAccess> implements A
+ // I don't want to know why this is a generic type.
+ Entity entityCasted = (Entity)entity;
+ boolean wasRemoved = entityCasted.isRemoved();
+- boolean screened = ca.spottedleaf.moonrise.common.util.ChunkSystem.screenEntity((net.minecraft.server.level.ServerLevel)entityCasted.level(), entityCasted, existing, false);
++ boolean screened = ca.spottedleaf.moonrise.common.util.ChunkSystem.screenEntity((net.minecraft.server.level.ServerLevel)entityCasted.level(), entityCasted, existing, true);
+ if ((!wasRemoved && entityCasted.isRemoved()) || !screened) {
+ // removed by callback
+ return false;
diff --git a/patches/server/0824-fixup-Paper-config-files.patch b/patches/server/0824-fixup-Paper-config-files.patch
new file mode 100644
index 0000000000..a5c6d251af
--- /dev/null
+++ b/patches/server/0824-fixup-Paper-config-files.patch
@@ -0,0 +1,87 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+Date: Thu, 24 Oct 2024 08:11:12 -0700
+Subject: [PATCH] fixup! Paper config files
+
+
+diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
+index 73e8a524925ed6f2580d3bd01616646fabafda78..4bfe7e987450afa433fcad1847f6130654769416 100644
+--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
++++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
+@@ -30,6 +30,45 @@ public class GlobalConfiguration extends ConfigurationPart {
+ public static GlobalConfiguration get() {
+ return instance;
+ }
++
++ public ChunkLoadingBasic chunkLoadingBasic;
++
++ public class ChunkLoadingBasic extends ConfigurationPart {
++ @Comment("The maximum rate in chunks per second that the server will send to any individual player. Set to -1 to disable this limit.")
++ public double playerMaxChunkSendRate = 75.0;
++
++ @Comment(
++ "The maximum rate at which chunks will load for any individual player. " +
++ "Note that this setting also affects chunk generations, since a chunk load is always first issued to test if a" +
++ "chunk is already generated. Set to -1 to disable this limit."
++ )
++ public double playerMaxChunkLoadRate = 100.0;
++
++ @Comment("The maximum rate at which chunks will generate for any individual player. Set to -1 to disable this limit.")
++ public double playerMaxChunkGenerateRate = -1.0;
++ }
++
++ public ChunkLoadingAdvanced chunkLoadingAdvanced;
++
++ public class ChunkLoadingAdvanced extends ConfigurationPart {
++ @Comment(
++ "Set to true if the server will match the chunk send radius that clients have configured" +
++ "in their view distance settings if the client is less-than the server's send distance."
++ )
++ public boolean autoConfigSendDistance = true;
++
++ @Comment(
++ "Specifies the maximum amount of concurrent chunk loads that an individual player can have." +
++ "Set to 0 to let the server configure it automatically per player, or set it to -1 to disable the limit."
++ )
++ public int playerMaxConcurrentChunkLoads = 0;
++
++ @Comment(
++ "Specifies the maximum amount of concurrent chunk generations that an individual player can have." +
++ "Set to 0 to let the server configure it automatically per player, or set it to -1 to disable the limit."
++ )
++ public int playerMaxConcurrentChunkGenerates = 0;
++ }
+ static void set(GlobalConfiguration instance) {
+ GlobalConfiguration.instance = instance;
+ }
+@@ -145,21 +184,6 @@ public class GlobalConfiguration extends ConfigurationPart {
+ public int incomingPacketThreshold = 300;
+ }
+
+- public ChunkLoading chunkLoading;
+-
+- public class ChunkLoading extends ConfigurationPart {
+- public int minLoadRadius = 2;
+- public int maxConcurrentSends = 2;
+- public boolean autoconfigSendDistance = true;
+- public double targetPlayerChunkSendRate = 100.0;
+- public double globalMaxChunkSendRate = -1.0;
+- public boolean enableFrustumPriority = false;
+- public double globalMaxChunkLoadRate = -1.0;
+- public double playerMaxConcurrentLoads = 20.0;
+- public double globalMaxConcurrentLoads = 500.0;
+- public double playerMaxChunkLoadRate = -1.0;
+- }
+-
+ public UnsupportedSettings unsupportedSettings;
+
+ public class UnsupportedSettings extends ConfigurationPart {
+@@ -218,7 +242,7 @@ public class GlobalConfiguration extends ConfigurationPart {
+
+ @PostProcess
+ private void postProcess() {
+- //io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.init(this);
++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler.init(this);
+ }
+ }
+
diff --git a/patches/unapplied/server/0982-Rewrite-dataconverter-system.patch b/patches/server/0825-Rewrite-dataconverter-system.patch
index b5c09ba076..173d97a5b2 100644
--- a/patches/unapplied/server/0982-Rewrite-dataconverter-system.patch
+++ b/patches/server/0825-Rewrite-dataconverter-system.patch
@@ -196,10 +196,10 @@ index 0000000000000000000000000000000000000000..a27d3d41109271834b6c37fa22d4b80d
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersionRegistry.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersionRegistry.java
new file mode 100644
-index 0000000000000000000000000000000000000000..69b5f9fe20c09ac0e72205ba8e4475c2dfea8313
+index 0000000000000000000000000000000000000000..056801570c6756a4b484633d79080aed740832a8
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersionRegistry.java
-@@ -0,0 +1,431 @@
+@@ -0,0 +1,440 @@
+package ca.spottedleaf.dataconverter.minecraft;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
@@ -233,216 +233,225 @@ index 0000000000000000000000000000000000000000..69b5f9fe20c09ac0e72205ba8e4475c2
+ // Note: Some of these are nameless.
+ // Unless a data version is specified here, it will NOT have converters ran for it. Please add them on update!
+ final int[] converterVersions = new int[] {
-+ 99,
-+ 100,
-+ 101,
-+ 102,
-+ 105,
-+ 106,
-+ 107,
-+ 108,
-+ 109,
-+ 110,
-+ 111,
-+ 113,
-+ 135,
-+ 143,
-+ 147,
-+ 165,
-+ 501,
-+ 502,
-+ 505,
-+ 700,
-+ 701,
-+ 702,
-+ 703,
-+ 704,
-+ 705,
-+ 804,
-+ 806,
-+ 808,
-+ 808,
-+ 813,
-+ 816,
-+ 820,
-+ 1022,
-+ 1125,
-+ 1344,
-+ 1446,
-+ 1450,
-+ 1451,
-+ 1451,
-+ 1451,
-+ 1451,
-+ 1451,
-+ 1451,
-+ 1451,
-+ 1451,
-+ 1451,
-+ 1456,
-+ 1458,
-+ 1460,
-+ 1466,
-+ 1470,
-+ 1474,
-+ 1475,
-+ 1480,
-+ 1481,
-+ 1483,
-+ 1484,
-+ 1486,
-+ 1487,
-+ 1488,
-+ 1490,
-+ 1492,
-+ 1494,
-+ 1496,
-+ 1500,
-+ 1501,
-+ 1502,
-+ 1506,
-+ 1510,
-+ 1514,
-+ 1515,
-+ 1624,
-+ 1800,
-+ 1801,
-+ 1802,
-+ 1803,
-+ 1904,
-+ 1905,
-+ 1906,
-+ 1909,
-+ 1911,
-+ 1914,
-+ 1917,
-+ 1918,
-+ 1920,
-+ 1925,
-+ 1928,
-+ 1929,
-+ 1931,
-+ 1936,
-+ 1946,
-+ 1948,
-+ 1953,
-+ 1955,
-+ 1961,
-+ 1963,
-+ 2100,
-+ 2202,
-+ 2209,
-+ 2211,
-+ 2218,
-+ 2501,
-+ 2502,
-+ 2503,
-+ 2505,
-+ 2508,
-+ 2509,
-+ 2511,
-+ 2514,
-+ 2516,
-+ 2518,
-+ 2519,
-+ 2522,
-+ 2523,
-+ 2527,
-+ 2528,
-+ 2529,
-+ 2531,
-+ 2533,
-+ 2535,
-+ 2538,
-+ 2550,
-+ 2551,
-+ 2552,
-+ 2553,
-+ 2558,
-+ 2568,
-+ 2671,
-+ 2679,
-+ 2680,
-+ 2684,
-+ 2686,
-+ 2688,
-+ 2690,
-+ 2691,
-+ 2693,
-+ 2696,
-+ 2700,
-+ 2701,
-+ 2702,
-+ 2704,
-+ 2707,
-+ 2710,
-+ 2717,
-+ 2825,
-+ 2831,
-+ 2832,
-+ 2833,
-+ 2838,
-+ 2841,
-+ 2842,
-+ 2843,
-+ 2846,
-+ 2852,
-+ 2967,
-+ 2970,
-+ 3077,
-+ 3078,
-+ 3081,
-+ 3082,
-+ 3083,
-+ 3084,
-+ 3086,
-+ 3087,
-+ 3088,
-+ 3090,
-+ 3093,
-+ 3094,
-+ 3097,
-+ 3108,
-+ 3201,
-+ 3203,
-+ 3204,
-+ 3209,
-+ 3214,
-+ 3319,
-+ 3322,
-+ 3438,
-+ 3439,
-+ 3440,
-+ 3441,
-+ 3447,
-+ 3448,
-+ 3450,
-+ 3451,
-+ 3459,
-+ 3564,
-+ 3565,
-+ 3566,
-+ 3568,
-+ 3683,
-+ 3685,
-+ 3692,
-+ 3800,
-+ 3803,
-+ 3807,
-+ 3808,
-+ 3809,
-+ 3812,
-+ 3813,
-+ 3814,
-+ 3818,
-+ 3820,
-+ 3825,
-+ 3828,
-+ 3833,
-+ 3939,
-+ 3943,
-+ 3945
-+ // All up to 1.21
++ 99,
++ 100,
++ 101,
++ 102,
++ 105,
++ 106,
++ 107,
++ 108,
++ 109,
++ 110,
++ 111,
++ 113,
++ 135,
++ 143,
++ 147,
++ 165,
++ 501,
++ 502,
++ 505,
++ 700,
++ 701,
++ 702,
++ 703,
++ 704,
++ 705,
++ 804,
++ 806,
++ 808,
++ 808,
++ 813,
++ 816,
++ 820,
++ 1022,
++ 1125,
++ 1344,
++ 1446,
++ 1450,
++ 1451,
++ 1451,
++ 1451,
++ 1451,
++ 1451,
++ 1451,
++ 1451,
++ 1451,
++ 1451,
++ 1456,
++ 1458,
++ 1460,
++ 1466,
++ 1470,
++ 1474,
++ 1475,
++ 1480,
++ 1481,
++ 1483,
++ 1484,
++ 1486,
++ 1487,
++ 1488,
++ 1490,
++ 1492,
++ 1494,
++ 1496,
++ 1500,
++ 1501,
++ 1502,
++ 1506,
++ 1510,
++ 1514,
++ 1515,
++ 1624,
++ 1800,
++ 1801,
++ 1802,
++ 1803,
++ 1904,
++ 1905,
++ 1906,
++ 1909,
++ 1911,
++ 1914,
++ 1917,
++ 1918,
++ 1920,
++ 1925,
++ 1928,
++ 1929,
++ 1931,
++ 1936,
++ 1946,
++ 1948,
++ 1953,
++ 1955,
++ 1961,
++ 1963,
++ 2100,
++ 2202,
++ 2209,
++ 2211,
++ 2218,
++ 2501,
++ 2502,
++ 2503,
++ 2505,
++ 2508,
++ 2509,
++ 2511,
++ 2514,
++ 2516,
++ 2518,
++ 2519,
++ 2522,
++ 2523,
++ 2527,
++ 2528,
++ 2529,
++ 2531,
++ 2533,
++ 2535,
++ 2538,
++ 2550,
++ 2551,
++ 2552,
++ 2553,
++ 2558,
++ 2568,
++ 2671,
++ 2679,
++ 2680,
++ 2684,
++ 2686,
++ 2688,
++ 2690,
++ 2691,
++ 2693,
++ 2696,
++ 2700,
++ 2701,
++ 2702,
++ 2704,
++ 2707,
++ 2710,
++ 2717,
++ 2825,
++ 2831,
++ 2832,
++ 2833,
++ 2838,
++ 2841,
++ 2842,
++ 2843,
++ 2846,
++ 2852,
++ 2967,
++ 2970,
++ 3077,
++ 3078,
++ 3081,
++ 3082,
++ 3083,
++ 3084,
++ 3086,
++ 3087,
++ 3088,
++ 3090,
++ 3093,
++ 3094,
++ 3097,
++ 3108,
++ 3201,
++ 3203,
++ 3204,
++ 3209,
++ 3214,
++ 3319,
++ 3322,
++ 3438,
++ 3439,
++ 3440,
++ 3441,
++ 3447,
++ 3448,
++ 3450,
++ 3451,
++ 3459,
++ 3564,
++ 3565,
++ 3566,
++ 3568,
++ 3683,
++ 3685,
++ 3692,
++ 3800,
++ 3803,
++ 3807,
++ 3808,
++ 3809,
++ 3812,
++ 3813,
++ 3814,
++ 3818,
++ 3820,
++ 3825,
++ 3828,
++ 3833,
++ 3939,
++ 3943,
++ 3945,
++ 4054,
++ 4055,
++ 4057,
++ 4059,
++ 4061,
++ 4064,
++ 4067,
++ 4068,
++ 4081,
++ // All up to 1.21.3
+ };
+ Arrays.sort(converterVersions);
+
@@ -633,10 +642,10 @@ index 0000000000000000000000000000000000000000..69b5f9fe20c09ac0e72205ba8e4475c2
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersions.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersions.java
new file mode 100644
-index 0000000000000000000000000000000000000000..fe546060bd27eda27931d9757831f0e4f043e31d
+index 0000000000000000000000000000000000000000..aaa45b3f97b4e67ca04ad9739d3f0197bec46671
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersions.java
-@@ -0,0 +1,539 @@
+@@ -0,0 +1,558 @@
+package ca.spottedleaf.dataconverter.minecraft;
+
+@SuppressWarnings("unused")
@@ -1161,18 +1170,37 @@ index 0000000000000000000000000000000000000000..fe546060bd27eda27931d9757831f0e4
+ public static final int V1_20_5 = 3837;
+ public static final int V1_20_6_RC1 = 3838;
+ public static final int V1_20_6 = 3839;
-+ public static final int V2418WA = 3940;
-+ public static final int V2419WA = 3941;
-+ public static final int V2419WB = 3942;
-+ public static final int V2420WA = 3944;
-+ public static final int V2421WA = 3946;
-+ public static final int V2421WB = 3947;
-+ public static final int V_1_21_PRE1 = 3948;
-+ public static final int V_1_21_PRE2 = 3949;
-+ public static final int V_1_21_PRE3 = 3950;
-+ public static final int V_1_21_PRE4 = 3951;
-+ public static final int V_1_21_RC1 = 3952;
-+ public static final int V_1_21 = 3953;
++ public static final int V24W18A = 3940;
++ public static final int V24W19A = 3941;
++ public static final int V24W19B = 3942;
++ public static final int V24W20A = 3944;
++ public static final int V24W21A = 3946;
++ public static final int V24W21B = 3947;
++ public static final int V1_21_PRE1 = 3948;
++ public static final int V1_21_PRE2 = 3949;
++ public static final int V1_21_PRE3 = 3950;
++ public static final int V1_21_PRE4 = 3951;
++ public static final int V1_21_RC1 = 3952;
++ public static final int V1_21 = 3953;
++ public static final int V1_21_RC = 3954;
++ public static final int V1_21_1 = 3955;
++ public static final int V24W33A = 4058;
++ public static final int V24W34A = 4060;
++ public static final int V24W35A = 4062;
++ public static final int V24W36A = 4063;
++ public static final int V24W37A = 4065;
++ public static final int V24W38A = 4066;
++ public static final int V24W39A = 4069;
++ public static final int V24W40A = 4072;
++ public static final int V1_21_2_PRE1 = 4073;
++ public static final int V1_21_2_PRE2 = 4074;
++ public static final int V1_21_2_PRE3 = 4075;
++ public static final int V1_21_2_PRE4 = 4076;
++ public static final int V1_21_2_PRE5 = 4077;
++ public static final int V1_21_2_RC1 = 4078;
++ public static final int V1_21_2_RC2 = 4079;
++ public static final int V1_21_2 = 4080;
++ public static final int V1_21_3 = 4082;
+
+ private MCVersions() {}
+}
@@ -1260,10 +1288,10 @@ index 0000000000000000000000000000000000000000..b2a4d16e6a2f9d71dbfa692922671581
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractAttributesRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractAttributesRename.java
new file mode 100644
-index 0000000000000000000000000000000000000000..c465036923656e8c974cc447bb57169b1a882e88
+index 0000000000000000000000000000000000000000..f227c0565a0c475fcb06991b485507d50bbd2ad0
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractAttributesRename.java
-@@ -0,0 +1,57 @@
+@@ -0,0 +1,60 @@
+package ca.spottedleaf.dataconverter.minecraft.converters.attributes;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
@@ -1281,6 +1309,72 @@ index 0000000000000000000000000000000000000000..c465036923656e8c974cc447bb57169b
+ }
+
+ public static void register(final int version, final int versionStep, final Function<String, String> renamer) {
++ MCTypeRegistry.DATA_COMPONENTS.addStructureConverter(new DataConverter<>(version, versionStep) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final MapType<String> attributeModifiers = data.getMap("minecraft:attribute_modifiers");
++ if (attributeModifiers == null) {
++ return null;
++ }
++
++ final ListType modifiers = attributeModifiers.getList("modifiers", ObjectType.MAP);
++ if (modifiers == null) {
++ return null;
++ }
++
++ for (int i = 0, len = modifiers.size(); i < len; ++i) {
++ RenameHelper.renameString(modifiers.getMap(i), "type", renamer);
++ }
++
++ return null;
++ }
++ });
++
++ final DataConverter<MapType<String>, MapType<String>> entityConverter = new DataConverter<>(version, versionStep) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final ListType modifiers = data.getList("attributes", ObjectType.MAP);
++ if (modifiers == null) {
++ return null;
++ }
++
++ for (int i = 0, len = modifiers.size(); i < len; ++i) {
++ RenameHelper.renameString(modifiers.getMap(i), "id", renamer);
++ }
++
++ return null;
++ }
++ };
++
++ MCTypeRegistry.ENTITY.addStructureConverter(entityConverter);
++ MCTypeRegistry.PLAYER.addStructureConverter(entityConverter);
++ }
++
++ private ConverterAbstractAttributesRename() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractOldAttributesRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractOldAttributesRename.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..1b871c78e77015d0216a0ecc61aa05689ccfab10
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractOldAttributesRename.java
+@@ -0,0 +1,57 @@
++package ca.spottedleaf.dataconverter.minecraft.converters.attributes;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.types.ListType;
++import ca.spottedleaf.dataconverter.types.MapType;
++import ca.spottedleaf.dataconverter.types.ObjectType;
++import java.util.function.Function;
++
++public final class ConverterAbstractOldAttributesRename {
++
++ public static void register(final int version, final Function<String, String> renamer) {
++ register(version, 0, renamer);
++ }
++
++ public static void register(final int version, final int versionStep, final Function<String, String> renamer) {
+ final DataConverter<MapType<String>, MapType<String>> entityConverter = new DataConverter<>(version, versionStep) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
@@ -1319,7 +1413,7 @@ index 0000000000000000000000000000000000000000..c465036923656e8c974cc447bb57169b
+ });
+ }
+
-+ private ConverterAbstractAttributesRename() {}
++ private ConverterAbstractOldAttributesRename() {}
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/blockname/ConverterAbstractBlockRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/blockname/ConverterAbstractBlockRename.java
new file mode 100644
@@ -9245,15 +9339,16 @@ index 0000000000000000000000000000000000000000..075574f33476882ddc6787e3b8bac864
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/MCTypeRegistry.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/MCTypeRegistry.java
new file mode 100644
-index 0000000000000000000000000000000000000000..f4d7700ab53753dd5ac3222fbfd7bdd11b48197c
+index 0000000000000000000000000000000000000000..11f5081f0cfb6f0f16689c68836b1f2962a0321c
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/MCTypeRegistry.java
-@@ -0,0 +1,303 @@
+@@ -0,0 +1,325 @@
+package ca.spottedleaf.dataconverter.minecraft.datatypes;
+
+import ca.spottedleaf.dataconverter.minecraft.versions.*;
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
++import java.text.DecimalFormat;
+
+public final class MCTypeRegistry {
+
@@ -9303,12 +9398,20 @@ index 0000000000000000000000000000000000000000..f4d7700ab53753dd5ac3222fbfd7bdd1
+ public static final MCValueType DATACONVERTER_CUSTOM_TYPE_COMMAND = new MCValueType("DC_Custom/Command");
+
+ static {
++ LOGGER.info("Initialising converters for DataConverter...");
++
++ final long start = System.nanoTime();
+ try {
+ registerAll();
+ } catch (final Throwable thr) {
+ LOGGER.error(LogUtils.FATAL_MARKER, "Failed to register data converters", thr);
+ throw new RuntimeException(thr);
+ }
++ final long end = System.nanoTime();
++
++ final DecimalFormat oneDecimalFormat = new DecimalFormat("#,##0.0");
++
++ LOGGER.info("Finished initialising converters for DataConverter in " + oneDecimalFormat.format((double)(end - start) / 1.0E6) + "ms");
+ }
+
+ private static void registerAll() {
@@ -9548,6 +9651,19 @@ index 0000000000000000000000000000000000000000..f4d7700ab53753dd5ac3222fbfd7bdd1
+ V3939.register();
+ V3943.register();
+ V3945.register();
++ // V1.21.2
++ V4054.register();
++ V4055.register();
++ V4057.register();
++ V4059.register();
++ V4061.register();
++ V4064.register();
++ V4067.register();
++ V4068.register();
++ V4070.register();
++ V4071.register();
++ // V1.21.3
++ V4081.register();
+ }
+
+ private MCTypeRegistry() {}
@@ -9707,10 +9823,10 @@ index 0000000000000000000000000000000000000000..7f88487e7db589070512fafef1eb243a
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/util/ComponentUtils.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/util/ComponentUtils.java
new file mode 100644
-index 0000000000000000000000000000000000000000..7f8f9d002b286f166d6e59bbf77aff74af10731c
+index 0000000000000000000000000000000000000000..17ded002b5546de8be4a5238c20ccfda460a98bb
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/util/ComponentUtils.java
-@@ -0,0 +1,78 @@
+@@ -0,0 +1,82 @@
+package ca.spottedleaf.dataconverter.minecraft.util;
+
+import com.google.gson.JsonElement;
@@ -9741,6 +9857,10 @@ index 0000000000000000000000000000000000000000..7f8f9d002b286f166d6e59bbf77aff74
+ }
+
+ public static String retrieveTranslationString(final String possibleJson) {
++ if (possibleJson == null) {
++ return null;
++ }
++
+ try {
+ final JsonElement element = JsonParser.parseString(possibleJson);
+
@@ -9958,10 +10078,10 @@ index 0000000000000000000000000000000000000000..91b1d0be9d697a4fa8bc5b448b329df1
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V101.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V101.java
new file mode 100644
-index 0000000000000000000000000000000000000000..96ea4669d6ad893ba52af045082f9ccb90fe90bf
+index 0000000000000000000000000000000000000000..32d54d5960088b547b3ca09bff28b0752dddd77c
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V101.java
-@@ -0,0 +1,38 @@
+@@ -0,0 +1,45 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
@@ -9996,6 +10116,13 @@ index 0000000000000000000000000000000000000000..96ea4669d6ad893ba52af045082f9ccb
+ return null;
+ }
+ });
++ MCTypeRegistry.ENTITY.addConverterForId("Villager", new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ data.setBoolean("CanPickUpLoot", true);
++ return null;
++ }
++ });
+ }
+
+ private V101() {}
@@ -10094,10 +10221,10 @@ index 0000000000000000000000000000000000000000..00bb3cff8f3d220d65a18f9b82b4b536
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1022.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1022.java
new file mode 100644
-index 0000000000000000000000000000000000000000..c1510d9167f466d3b7e3756353224f12f3876442
+index 0000000000000000000000000000000000000000..4f35484ed524dbf09cf9e8b1bb999fc98ec0bb0f
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1022.java
-@@ -0,0 +1,41 @@
+@@ -0,0 +1,43 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
@@ -10113,6 +10240,8 @@ index 0000000000000000000000000000000000000000..c1510d9167f466d3b7e3756353224f12
+ MCTypeRegistry.PLAYER.addStructureWalker(VERSION, (final MapType<String> data, final long fromVersion, final long toVersion) -> {
+ WalkerUtils.convert(MCTypeRegistry.ENTITY, data.getMap("RootVehicle"), "Entity", fromVersion, toVersion);
+
++ WalkerUtils.convertList(MCTypeRegistry.ENTITY, data, "ender_pearls", fromVersion, toVersion);
++
+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "Inventory", fromVersion, toVersion);
+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "EnderItems", fromVersion, toVersion);
+
@@ -10882,10 +11011,10 @@ index 0000000000000000000000000000000000000000..b735165f9b296730b77339875255aa98
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V135.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V135.java
new file mode 100644
-index 0000000000000000000000000000000000000000..1c9f754332d8a2299b7e2e5565882da52948d3a9
+index 0000000000000000000000000000000000000000..b003819eb395039dca8141179b57632e90db1d4d
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V135.java
-@@ -0,0 +1,60 @@
+@@ -0,0 +1,62 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
@@ -10933,6 +11062,8 @@ index 0000000000000000000000000000000000000000..1c9f754332d8a2299b7e2e5565882da5
+ WalkerUtils.convert(MCTypeRegistry.ENTITY, rootVehicle, "Entity", fromVersion, toVersion);
+ }
+
++ WalkerUtils.convertList(MCTypeRegistry.ENTITY, data, "ender_pearls", fromVersion, toVersion);
++
+ return null;
+ });
+
@@ -16279,14 +16410,14 @@ index 0000000000000000000000000000000000000000..9a4d47d78596e2275745673f31f772f0
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2523.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2523.java
new file mode 100644
-index 0000000000000000000000000000000000000000..af295e8800b6eb5c13bbb88d21b391e5cc4bee1a
+index 0000000000000000000000000000000000000000..7777d83d63dc177f0bac72290ed2e5c3cbd028be
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2523.java
@@ -0,0 +1,41 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
-+import ca.spottedleaf.dataconverter.minecraft.converters.attributes.ConverterAbstractAttributesRename;
++import ca.spottedleaf.dataconverter.minecraft.converters.attributes.ConverterAbstractOldAttributesRename;
+import com.google.common.collect.ImmutableMap;
+import java.util.HashMap;
+import java.util.Map;
@@ -16319,7 +16450,7 @@ index 0000000000000000000000000000000000000000..af295e8800b6eb5c13bbb88d21b391e5
+ );
+
+ public static void register() {
-+ ConverterAbstractAttributesRename.register(VERSION, RENAMES::get);
++ ConverterAbstractOldAttributesRename.register(VERSION, RENAMES::get);
+ }
+
+ private V2523() {}
@@ -22437,14 +22568,14 @@ index 0000000000000000000000000000000000000000..920d7734d883d74e8334102b22cabce2
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3814.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3814.java
new file mode 100644
-index 0000000000000000000000000000000000000000..d3b156129452202aea1f3b9f32142c91b64dc777
+index 0000000000000000000000000000000000000000..c4cc52620afb728533efe988bf2066ffc947f2d6
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3814.java
@@ -0,0 +1,21 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.minecraft.MCVersions;
-+import ca.spottedleaf.dataconverter.minecraft.converters.attributes.ConverterAbstractAttributesRename;
++import ca.spottedleaf.dataconverter.minecraft.converters.attributes.ConverterAbstractOldAttributesRename;
+import java.util.HashMap;
+import java.util.Map;
+
@@ -22457,7 +22588,7 @@ index 0000000000000000000000000000000000000000..d3b156129452202aea1f3b9f32142c91
+ Map.of("minecraft:horse.jump_strength", "minecraft:generic.jump_strength")
+ );
+
-+ ConverterAbstractAttributesRename.register(VERSION, renames::get);
++ ConverterAbstractOldAttributesRename.register(VERSION, renames::get);
+ }
+
+ private V3814() {}
@@ -23116,10 +23247,10 @@ index 0000000000000000000000000000000000000000..f752bb2fca2e4cd438c0540460912d4b
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3833.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3833.java
new file mode 100644
-index 0000000000000000000000000000000000000000..4581b9ce0734e552fd8810239e7b86f8b43513c5
+index 0000000000000000000000000000000000000000..f097881401855137f5d4ac25ba1468e635a702b5
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3833.java
-@@ -0,0 +1,37 @@
+@@ -0,0 +1,36 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
@@ -23141,7 +23272,6 @@ index 0000000000000000000000000000000000000000..4581b9ce0734e552fd8810239e7b86f8
+ return null;
+ }
+
-+
+ final String id = NamespaceUtil.correctNamespace(item.getString("id", "minecraft:air"));
+ final int count = item.getInt("count", 0);
+
@@ -23217,7 +23347,7 @@ index 0000000000000000000000000000000000000000..632c8008484e844d962405c6ef8fb9f0
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3943.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3943.java
new file mode 100644
-index 0000000000000000000000000000000000000000..b769abe8c469b15983b433fb9b7de9f41528a4f9
+index 0000000000000000000000000000000000000000..1cd426cf78d62d428406caa319cc5c8649e7f36c
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3943.java
@@ -0,0 +1,34 @@
@@ -23230,7 +23360,7 @@ index 0000000000000000000000000000000000000000..b769abe8c469b15983b433fb9b7de9f4
+
+public final class V3943 {
+
-+ private static final int VERSION = MCVersions.V2419WB + 1;
++ private static final int VERSION = MCVersions.V24W19B + 1;
+
+ public static void register() {
+ MCTypeRegistry.OPTIONS.addStructureConverter(new DataConverter<>(VERSION) {
@@ -23257,10 +23387,10 @@ index 0000000000000000000000000000000000000000..b769abe8c469b15983b433fb9b7de9f4
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3945.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3945.java
new file mode 100644
-index 0000000000000000000000000000000000000000..aaeb3b9006b9ae2a8d3a28158bc17d05be0ba2fa
+index 0000000000000000000000000000000000000000..74c13c46390e4533a9eb2c8ae5d9846db55efa94
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3945.java
-@@ -0,0 +1,246 @@
+@@ -0,0 +1,244 @@
+package ca.spottedleaf.dataconverter.minecraft.versions;
+
+import ca.spottedleaf.dataconverter.converters.DataConverter;
@@ -23279,7 +23409,7 @@ index 0000000000000000000000000000000000000000..aaeb3b9006b9ae2a8d3a28158bc17d05
+
+public final class V3945 {
+
-+ private static final int VERSION = MCVersions.V2420WA + 1;
++ private static final int VERSION = MCVersions.V24W20A + 1;
+
+ private static final Map<UUID, String> UUID_TO_ID = new HashMap<>(
+ ImmutableMap.<UUID, String>builder()
@@ -23397,9 +23527,7 @@ index 0000000000000000000000000000000000000000..aaeb3b9006b9ae2a8d3a28158bc17d05
+ return retList;
+ }
+
-+
+ public static void register() {
-+
+ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) {
+ @Override
+ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
@@ -23507,6 +23635,745 @@ index 0000000000000000000000000000000000000000..aaeb3b9006b9ae2a8d3a28158bc17d05
+
+ private V3945() {}
+}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4054.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4054.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..d65e05285ef238aa8c6d660aa42fcd69e07d9430
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4054.java
+@@ -0,0 +1,46 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.minecraft.util.ComponentUtils;
++import ca.spottedleaf.dataconverter.types.MapType;
++
++public final class V4054 {
++
++ private static final int VERSION = MCVersions.V1_21_1 + 99;
++
++ public static void register() {
++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:banner", new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ convertComponents(data.getMap("components"));
++ return null;
++ }
++ });
++ MCTypeRegistry.ITEM_STACK.addConverterForId("minecraft:white_banner", new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ convertComponents(data.getMap("components"));
++ return null;
++ }
++ });
++ }
++
++ private static void convertComponents(final MapType<String> components) {
++ if (components == null) {
++ return;
++ }
++
++ final String itemNameKey = ComponentUtils.retrieveTranslationString(components.getString("minecraft:item_name"));
++
++ if (!"block.minecraft.ominous_banner".equals(itemNameKey)) {
++ return;
++ }
++
++ components.setString("minecraft:rarity", "uncommon");
++ components.setString("minecraft:item_name", ComponentUtils.createTranslatableComponent("block.minecraft.ominous_banner"));
++ }
++
++ private V4054() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4055.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4055.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..45b141a651d954554fcca68f36c0b3344328d902
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4055.java
+@@ -0,0 +1,41 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.converters.attributes.ConverterAbstractAttributesRename;
++import ca.spottedleaf.dataconverter.util.NamespaceUtil;
++
++public final class V4055 {
++
++ private static final int VERSION = MCVersions.V1_21_1 + 100;
++
++ private static final Prefix[] PREFIXES_TO_REMOVE = new Prefix[] {
++ new Prefix("generic."),
++ new Prefix("horse."),
++ new Prefix("player."),
++ new Prefix("zombie.")
++ };
++
++ private static record Prefix(String raw, String namespaced) {
++ public Prefix(final String raw) {
++ this(raw, NamespaceUtil.correctNamespace(raw));
++ }
++ }
++
++ public static void register() {
++ ConverterAbstractAttributesRename.register(VERSION, (final String input) -> {
++ final String namespacedInput = NamespaceUtil.correctNamespace(input);
++
++ for (final Prefix prefix : PREFIXES_TO_REMOVE) {
++ if (!namespacedInput.startsWith(prefix.namespaced())) {
++ continue;
++ }
++
++ return "minecraft:".concat(namespacedInput.substring(prefix.namespaced().length()));
++ }
++
++ return null;
++ });
++ }
++
++ private V4055() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4057.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4057.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..b0949ac2035662ba1c943b4bfab2f19e985e6864
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4057.java
+@@ -0,0 +1,33 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.types.MapType;
++
++public final class V4057 {
++
++ private static final int VERSION = MCVersions.V1_21_1 + 102;
++
++ public static void register() {
++ MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final MapType<String> carvingMasks = data.getMap("CarvingMasks");
++ if (carvingMasks == null) {
++ return null;
++ }
++ data.remove("CarvingMasks");
++
++ final long[] airMask = carvingMasks.getLongs("AIR");
++ if (airMask != null) {
++ data.setLongs("carving_mask", airMask);
++ }
++
++ return null;
++ }
++ });
++ }
++
++ private V4057() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4059.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4059.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0047a20dab2ffd6b39a8bcb8ed9f3878f20e31c2
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4059.java
+@@ -0,0 +1,128 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.converters.datatypes.DataWalker;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils;
++import ca.spottedleaf.dataconverter.types.ListType;
++import ca.spottedleaf.dataconverter.types.MapType;
++import ca.spottedleaf.dataconverter.types.ObjectType;
++import ca.spottedleaf.dataconverter.types.TypeUtil;
++
++public final class V4059 {
++
++ private static final int VERSION = MCVersions.V24W33A + 1;
++
++ public static void register() {
++ // previous version: 3818.3
++ MCTypeRegistry.DATA_COMPONENTS.addStructureWalker(VERSION, new DataWalker<>() {
++ private static void walkBlockPredicates(final MapType<String> root, final long fromVersion, final long toVersion) {
++ if (root.hasKey("blocks", ObjectType.STRING)) {
++ WalkerUtils.convert(MCTypeRegistry.BLOCK_NAME, root, "blocks", fromVersion, toVersion);
++ } else if (root.hasKey("blocks", ObjectType.LIST)) {
++ WalkerUtils.convertList(MCTypeRegistry.BLOCK_NAME, root, "blocks", fromVersion, toVersion);
++ }
++ }
++
++ @Override
++ public MapType<String> walk(final MapType<String> root, final long fromVersion, final long toVersion) {
++ WalkerUtils.convertListPath(MCTypeRegistry.ENTITY, root, "minecraft:bees", "entity_data", fromVersion, toVersion);
++
++ WalkerUtils.convert(MCTypeRegistry.TILE_ENTITY, root, "minecraft:block_entity_data", fromVersion, toVersion);
++ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, root, "minecraft:bundle_contents", fromVersion, toVersion);
++
++ final MapType<String> canBreak = root.getMap("minecraft:can_break");
++ if (canBreak != null) {
++ final ListType predicates = canBreak.getList("predicates", ObjectType.MAP);
++ if (predicates != null) {
++ for (int i = 0, len = predicates.size(); i < len; ++i) {
++ walkBlockPredicates(predicates.getMap(i), fromVersion, toVersion);
++ }
++ }
++ // Not handled by DFU: simple encoding does not require "predicates"
++ walkBlockPredicates(canBreak, fromVersion, toVersion);
++ }
++
++ final MapType<String> canPlaceOn = root.getMap("minecraft:can_place_on");
++ if (canPlaceOn != null) {
++ final ListType predicates = canPlaceOn.getList("predicates", ObjectType.MAP);
++ if (predicates != null) {
++ for (int i = 0, len = predicates.size(); i < len; ++i) {
++ walkBlockPredicates(predicates.getMap(i), fromVersion, toVersion);
++ }
++ }
++ // Not handled by DFU: simple encoding does not require "predicates"
++ walkBlockPredicates(canPlaceOn, fromVersion, toVersion);
++ }
++
++ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, root, "minecraft:charged_projectiles", fromVersion, toVersion);
++ WalkerUtils.convertListPath(MCTypeRegistry.ITEM_STACK, root, "minecraft:container", "item", fromVersion, toVersion);
++ WalkerUtils.convert(MCTypeRegistry.ENTITY, root, "minecraft:entity_data", fromVersion, toVersion);
++ WalkerUtils.convertList(MCTypeRegistry.ITEM_NAME, root, "minecraft:pot_decorations", fromVersion, toVersion);
++ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, root, "minecraft:use_remainder", fromVersion, toVersion);
++
++ final MapType<String> equippable = root.getMap("minecraft:equippable");
++ if (equippable != null) {
++ WalkerUtils.convert(MCTypeRegistry.ENTITY_NAME, equippable, "allowed_entities", fromVersion, toVersion);
++ WalkerUtils.convertList(MCTypeRegistry.ENTITY_NAME, equippable, "allowed_entities", fromVersion, toVersion);
++ }
++
++ return null;
++ }
++ });
++
++ MCTypeRegistry.DATA_COMPONENTS.addStructureConverter(new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final MapType<String> food = data.getMap("minecraft:food");
++ if (food == null) {
++ return null;
++ }
++
++ final TypeUtil typeUtil = data.getTypeUtil();
++
++ final float eatSeconds = food.getFloat("eat_seconds", 1.6F);
++
++ final ListType oldEffects = food.getList("effects", ObjectType.MAP);
++ final ListType newEffects = typeUtil.createEmptyList();
++ if (oldEffects != null) {
++ for (int i = 0, len = oldEffects.size(); i < len; ++i) {
++ final MapType<String> oldEffect = oldEffects.getMap(i);
++
++ final MapType<String> newEffect = typeUtil.createEmptyMap();
++ newEffects.addMap(newEffect);
++
++ newEffect.setString("type", "minecraft:apply_effects");
++
++ final Object oldEffectEffect = oldEffect.getGeneric("effect");
++ final ListType newEffectEffects = typeUtil.createEmptyList();
++ newEffectEffects.addGeneric(oldEffectEffect);
++ newEffect.setList("effects", newEffectEffects);
++
++ newEffect.setFloat("probability", oldEffect.getFloat("probability", 1.0F));
++ }
++ }
++
++ final Object convertsTo = food.getGeneric("using_converts_to");
++ if (convertsTo != null) {
++ data.setGeneric("minecraft:use_remainder", convertsTo);
++ }
++
++ food.remove("eat_seconds");
++ food.remove("effects");
++ food.remove("using_converts_to");
++
++ final MapType<String> consumable = typeUtil.createEmptyMap();
++ data.setMap("minecraft:consumable", consumable);
++
++ consumable.setFloat("consume_seconds", eatSeconds);
++ consumable.setList("on_consume_effects", newEffects);
++
++ return null;
++ }
++ });
++ }
++
++ private V4059() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4061.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4061.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..630263a61b5db4207c1a5051e3e2249ab3dd3957
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4061.java
+@@ -0,0 +1,112 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.types.MapType;
++import ca.spottedleaf.dataconverter.types.nbt.NBTMapType;
++import com.mojang.brigadier.exceptions.CommandSyntaxException;
++import com.mojang.datafixers.util.Pair;
++import net.minecraft.nbt.CompoundTag;
++import net.minecraft.nbt.TagParser;
++import java.util.HashMap;
++import java.util.Map;
++
++public final class V4061 {
++
++ private static final int VERSION = MCVersions.V24W34A + 1;
++
++ private static final Map<Pair<MapType<String>, MapType<String>>, String> CONVERT_MAP = new HashMap<>();
++ static {
++ addConversion("trial_chamber/breeze", "{simultaneous_mobs: 1.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:breeze\"}}, weight: 1}], ticks_between_spawn: 20, total_mobs: 2.0f, total_mobs_added_per_player: 1.0f}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], simultaneous_mobs: 2.0f, total_mobs: 4.0f}");
++ addConversion("trial_chamber/melee/husk", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:husk\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], spawn_potentials: [{data: {entity: {id: \"minecraft:husk\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_melee\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/melee/spider", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:spider\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}],simultaneous_mobs: 4.0f, total_mobs: 12.0f}");
++ addConversion("trial_chamber/melee/zombie", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:zombie\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}],spawn_potentials: [{data: {entity: {id: \"minecraft:zombie\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_melee\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/ranged/poison_skeleton", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:bogged\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}],spawn_potentials: [{data: {entity: {id: \"minecraft:bogged\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_ranged\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/ranged/skeleton", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:skeleton\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], spawn_potentials: [{data: {entity: {id: \"minecraft:skeleton\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_ranged\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/ranged/stray", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:stray\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], spawn_potentials: [{data: {entity: {id: \"minecraft:stray\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_ranged\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/slow_ranged/poison_skeleton", "{simultaneous_mobs: 4.0f, simultaneous_mobs_added_per_player: 2.0f, spawn_potentials: [{data: {entity: {id: \"minecraft:bogged\"}}, weight: 1}], ticks_between_spawn: 160}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], spawn_potentials: [{data: {entity: {id: \"minecraft:bogged\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_ranged\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/slow_ranged/skeleton", "{simultaneous_mobs: 4.0f, simultaneous_mobs_added_per_player: 2.0f, spawn_potentials: [{data: {entity: {id: \"minecraft:skeleton\"}}, weight: 1}], ticks_between_spawn: 160}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], spawn_potentials: [{data: {entity: {id: \"minecraft:skeleton\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_ranged\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/slow_ranged/stray", "{simultaneous_mobs: 4.0f, simultaneous_mobs_added_per_player: 2.0f, spawn_potentials: [{data: {entity: {id: \"minecraft:stray\"}}, weight: 1}], ticks_between_spawn: 160}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}],spawn_potentials: [{data: {entity: {id: \"minecraft:stray\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_ranged\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/small_melee/baby_zombie", "{simultaneous_mobs: 2.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {IsBaby: 1b, id: \"minecraft:zombie\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], spawn_potentials: [{data: {entity: {IsBaby: 1b, id: \"minecraft:zombie\"}, equipment: {loot_table: \"minecraft:equipment/trial_chamber_melee\", slot_drop_chances: 0.0f}}, weight: 1}]}");
++ addConversion("trial_chamber/small_melee/cave_spider", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:cave_spider\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], simultaneous_mobs: 4.0f, total_mobs: 12.0f}");
++ addConversion("trial_chamber/small_melee/silverfish", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {id: \"minecraft:silverfish\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], simultaneous_mobs: 4.0f, total_mobs: 12.0f}");
++ addConversion("trial_chamber/small_melee/slime", "{simultaneous_mobs: 3.0f, simultaneous_mobs_added_per_player: 0.5f, spawn_potentials: [{data: {entity: {Size: 1, id: \"minecraft:slime\"}}, weight: 3}, {data: {entity: {Size: 2, id: \"minecraft:slime\"}}, weight: 1}], ticks_between_spawn: 20}", "{loot_tables_to_eject: [{data: \"minecraft:spawners/ominous/trial_chamber/key\", weight: 3}, {data: \"minecraft:spawners/ominous/trial_chamber/consumables\", weight: 7}], simultaneous_mobs: 4.0f, total_mobs: 12.0f}");
++ }
++
++ private static void addConversion(final String keyPath, final String normalsNBT, final String ominoussNBT) {
++ final String fullKey = "minecraft:".concat(keyPath);
++
++ final CompoundTag normalNBT = parseNBT(normalsNBT);
++ final MapType<String> normalMapType = new NBTMapType(normalNBT);
++ final CompoundTag ominousNBT = parseNBT(ominoussNBT);
++
++ final CompoundTag ominousMerged = normalNBT.copy().merge(ominousNBT);
++
++ CONVERT_MAP.put(Pair.of(normalMapType, new NBTMapType(ominousNBT)), fullKey);
++ CONVERT_MAP.put(Pair.of(normalMapType, new NBTMapType(ominousMerged)), fullKey);
++ CONVERT_MAP.put(Pair.of(normalMapType, new NBTMapType(removeDefaults(ominousMerged.copy()))), fullKey);
++ }
++
++ private static CompoundTag parseNBT(final String sNBT) {
++ try {
++ return TagParser.parseTag(sNBT);
++ } catch (final CommandSyntaxException ex) {
++ throw new IllegalArgumentException("Failed to parse NBT: " + sNBT, ex);
++ }
++ }
++
++ private static CompoundTag removeDefaults(final CompoundTag config) {
++ if (config.getInt("spawn_range") == 4) {
++ config.remove("spawn_range");
++ }
++
++ if (config.getFloat("total_mobs") == 6.0F) {
++ config.remove("total_mobs");
++ }
++
++ if (config.getFloat("simultaneous_mobs") == 2.0F) {
++ config.remove("simultaneous_mobs");
++ }
++
++ if (config.getFloat("total_mobs_added_per_player") == 2.0F) {
++ config.remove("total_mobs_added_per_player");
++ }
++
++ if (config.getFloat("simultaneous_mobs_added_per_player") == 1.0F) {
++ config.remove("simultaneous_mobs_added_per_player");
++ }
++
++ if (config.getInt("ticks_between_spawn") == 40) {
++ config.remove("ticks_between_spawn");
++ }
++
++ return config;
++ }
++
++ public static void register() {
++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:trial_spawner", new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final MapType<String> normalConfig = data.getMap("normal_config");
++ final MapType<String> ominousConfig = data.getMap("ominous_config");
++
++ if (normalConfig == null || ominousConfig == null) {
++ return null;
++ }
++
++ final String newKey = CONVERT_MAP.get(new Pair<>(normalConfig, ominousConfig));
++ if (newKey == null) {
++ return null;
++ }
++
++ data.setString("normal_config", newKey.concat("/normal"));
++ data.setString("ominous_config", newKey.concat("/ominous"));
++
++ return null;
++ }
++ });
++ }
++
++ private V4061() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4064.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4064.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..85eb8f37f89faed8b366c1d1c850b028bfcb2164
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4064.java
+@@ -0,0 +1,36 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.types.MapType;
++
++public final class V4064 {
++
++ private static final int VERSION = MCVersions.V24W36A + 1;
++
++ public static void register() {
++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final MapType<String> components = data.getMap("components");
++ if (components == null) {
++ return null;
++ }
++
++ if (components.hasKey("minecraft:fire_resistant")) {
++ components.remove("minecraft:fire_resistant");
++
++ final MapType<String> damageResistant = components.getTypeUtil().createEmptyMap();
++ components.setMap("minecraft:damage_resistant", damageResistant);
++
++ damageResistant.setString("types", "#minecraft:is_fire");
++ }
++
++ return null;
++ }
++ });
++ }
++
++ private V4064() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4067.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4067.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..855c5a99951996ffe4eabb24a69321043cce41d7
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4067.java
+@@ -0,0 +1,143 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.converters.leveldat.ConverterRemoveFeatureFlag;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists;
++import ca.spottedleaf.dataconverter.types.MapType;
++import java.util.Arrays;
++import java.util.HashMap;
++import java.util.HashSet;
++import java.util.Map;
++
++public final class V4067 {
++
++ private static final int VERSION = MCVersions.V24W38A + 1;
++
++ private static final record BoatType(String name, String suffix) {}
++ private static final BoatType[] BOAT_TYPES = new BoatType[] {
++ new BoatType("oak", "boat"),
++ new BoatType("spruce", "boat"),
++ new BoatType("birch", "boat"),
++ new BoatType("jungle", "boat"),
++ new BoatType("acacia", "boat"),
++ new BoatType("cherry", "boat"),
++ new BoatType("dark_oak", "boat"),
++ new BoatType("mangrove", "boat"),
++ new BoatType("bamboo", "raft")
++ };
++
++ private static void registerChestBoat(final String id) {
++ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("Items"));
++ }
++
++ public static void register() {
++ // minecraft:oak_boat is a simple entity
++ // minecraft:spruce_boat is a simple entity
++ // minecraft:birch_boat is a simple entity
++ // minecraft:jungle_boat is a simple entity
++ // minecraft:acacia_boat is a simple entity
++ // minecraft:cherry_boat is a simple entity
++ // minecraft:dark_oak_boat is a simple entity
++ // minecraft:mangrove_boat is a simple entity
++ // minecraft:bamboo_raft is a simple entity
++
++ registerChestBoat("minecraft:oak_chest_boat");
++ registerChestBoat("minecraft:spruce_chest_boat");
++ registerChestBoat("minecraft:birch_chest_boat");
++ registerChestBoat("minecraft:jungle_chest_boat");
++ registerChestBoat("minecraft:acacia_chest_boat");
++ registerChestBoat("minecraft:cherry_chest_boat");
++ registerChestBoat("minecraft:dark_oak_chest_boat");
++ registerChestBoat("minecraft:mangrove_chest_boat");
++ registerChestBoat("minecraft:bamboo_chest_raft");
++
++ // we do not update V704 to set the new boat types, as the new ids are only registered here
++ // if we updated V704 to set the new boat types, then the registered walkers for the chest_boat would not run before
++ // V4067 as they are only registered here
++
++ // to ensure that the id is correctly set eventually, we will force Type to the correct value based on the item id
++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) {
++ private static final Map<String, String> BOAT_TYPES_BY_ITEM_ID = new HashMap<>();
++ static {
++ for (final BoatType boatType : BOAT_TYPES) {
++ BOAT_TYPES_BY_ITEM_ID.put(boatType.name() + "_" + boatType.suffix(), boatType.name());
++ BOAT_TYPES_BY_ITEM_ID.put(boatType.name() + "_chest_" + boatType.suffix(), boatType.name());
++ }
++ }
++
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final String id = data.getString("id");
++ final String boatType = BOAT_TYPES_BY_ITEM_ID.get(id);
++
++ if (boatType == null) {
++ return null;
++ }
++
++ final MapType<String> components = data.getMap("components");
++ if (components == null) {
++ return null;
++ }
++
++ final MapType<String> entityData = components.getMap("minecraft:entity_data");
++ if (entityData == null) {
++ return null;
++ }
++
++ entityData.setString("Type", boatType);
++
++ return null;
++ }
++ });
++
++ MCTypeRegistry.ENTITY.addStructureConverter(new DataConverter<>(VERSION) {
++ private static final Map<String, String> NORMAL_REMAPPING = new HashMap<>(BOAT_TYPES.length);
++ static {
++ for (final BoatType type : BOAT_TYPES) {
++ NORMAL_REMAPPING.put(type.name(), type.name() + "_" + type.suffix());
++ }
++ }
++ private static final Map<String, String> CHEST_REMAPPING = new HashMap<>(BOAT_TYPES.length);
++ static {
++ for (final BoatType type : BOAT_TYPES) {
++ CHEST_REMAPPING.put(type.name(), type.name() + "_chest_" + type.suffix());
++ }
++ }
++
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final String id = data.getString("id");
++ if (id == null) {
++ // wat
++ return null;
++ }
++
++ final boolean normalBoat = id.equals("minecraft:boat");
++ final boolean chestBoat = id.equals("minecraft:chest_boat");
++
++ if (!normalBoat && !chestBoat) {
++ return null;
++ }
++
++ final String type = data.getString("Type");
++ data.remove("Type");
++
++ if (normalBoat) {
++ data.setString("id", NORMAL_REMAPPING.getOrDefault(type, "minecraft:oak_boat"));
++ } else {
++ data.setString("id", CHEST_REMAPPING.getOrDefault(type, "minecraft:oak_chest_boat"));
++ }
++
++ return null;
++ }
++ });
++
++ MCTypeRegistry.LEVEL.addStructureConverter(
++ new ConverterRemoveFeatureFlag(VERSION, new HashSet<>(Arrays.asList("minecraft:bundle")))
++ );
++ }
++
++ private V4067() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4068.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4068.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..3de9862f083e6a2a687b42eef36746aa846cc745
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4068.java
+@@ -0,0 +1,64 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.types.MapType;
++import ca.spottedleaf.dataconverter.types.TypeUtil;
++import com.google.common.escape.Escaper;
++import com.google.common.escape.Escapers;
++
++public final class V4068 {
++ public static final Escaper ESCAPER = Escapers.builder().addEscape('"', "\\\"").addEscape('\\', "\\\\").build();
++
++ private static final int VERSION = MCVersions.V24W38A + 2;
++
++ private static void convertLock(final MapType<String> root, final String srcPath, final String dstPath) {
++ if (root == null) {
++ return;
++ }
++
++ final Object lockGeneric = root.getGeneric(srcPath);
++ if (lockGeneric == null) {
++ return;
++ }
++
++ final TypeUtil typeUtil = root.getTypeUtil();
++
++ final MapType<String> newLock = typeUtil.createEmptyMap();
++ root.remove(srcPath);
++ root.setMap(dstPath, newLock);
++
++ if (lockGeneric instanceof String lock) {
++ final MapType<String> lockComponents = typeUtil.createEmptyMap();
++ newLock.setMap("components", lockComponents);
++
++ lockComponents.setString("minecraft:custom_name", ESCAPER.escape(lock));
++ }
++ }
++
++ public static void register() {
++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ final MapType<String> components = data.getMap("components");
++ if (components == null) {
++ return null;
++ }
++
++ convertLock(components, "minecraft:lock", "minecraft:lock");
++
++ return null;
++ }
++ });
++ MCTypeRegistry.TILE_ENTITY.addStructureConverter(new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ convertLock(data, "Lock", "lock");
++ return null;
++ }
++ });
++ }
++
++ private V4068() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4070.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4070.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..b85673d792d4b1c317d312ba607a0d30c2f57ea9
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4070.java
+@@ -0,0 +1,22 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists;
++
++public final class V4070 {
++
++ private static final int VERSION = MCVersions.V24W39A + 1;
++
++ private static void registerChestBoat(final String id) {
++ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("Items"));
++ }
++
++ public static void register() {
++ // minecraft:pale_oak_boat is a simple entity
++
++ registerChestBoat("minecraft:pale_oak_chest_boat");
++ }
++
++ private V4070() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4071.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4071.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..3b0855353f40e8ce54b86305152aa35af9154c6f
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4071.java
+@@ -0,0 +1,21 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++
++public final class V4071 {
++
++ private static final int VERSION = MCVersions.V24W39A + 2;
++
++ private static void registerMob(final String id) {
++ V100.registerEquipment(VERSION, 0, id);
++ }
++
++ public static void register() {
++ registerMob("minecraft:creaking");
++ registerMob("minecraft:creaking_transient");
++
++ // minecraft:creaking_heart is a simple tile entity? not sure what the difference is between remainder and optional
++ }
++
++ private V4071() {}
++}
+diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4081.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4081.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..22eae4d39c3887ef4991fd21856c32c43c543f88
+--- /dev/null
++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V4081.java
+@@ -0,0 +1,27 @@
++package ca.spottedleaf.dataconverter.minecraft.versions;
++
++import ca.spottedleaf.dataconverter.converters.DataConverter;
++import ca.spottedleaf.dataconverter.minecraft.MCVersions;
++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry;
++import ca.spottedleaf.dataconverter.types.MapType;
++
++public final class V4081 {
++
++ private static final int VERSION = MCVersions.V1_21_2 + 1;
++
++ public static void register() {
++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:salmon", new DataConverter<>(VERSION) {
++ @Override
++ public MapType<String> convert(final MapType<String> data, final long sourceVersion, final long toVersion) {
++ if ("large".equals(data.getString("type"))) {
++ return null;
++ }
++
++ data.setString("type", "medium");
++ return null;
++ }
++ });
++ }
++
++ private V4081() {}
++}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V501.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V501.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7a4d6446b7765ac485af82df660aafab05955bf
@@ -28106,10 +28973,10 @@ index 0000000000000000000000000000000000000000..62c0f4073aff301bf5b3187e0d4446fd
+}
diff --git a/src/main/java/ca/spottedleaf/dataconverter/util/CommandArgumentUpgrader.java b/src/main/java/ca/spottedleaf/dataconverter/util/CommandArgumentUpgrader.java
new file mode 100644
-index 0000000000000000000000000000000000000000..6f2a30eed4e9741a128b5a171edef6abedab7362
+index 0000000000000000000000000000000000000000..40da70d5cf584a9730f9fe81c355cf8513fba475
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/dataconverter/util/CommandArgumentUpgrader.java
-@@ -0,0 +1,491 @@
+@@ -0,0 +1,592 @@
+package ca.spottedleaf.dataconverter.util;
+
+import ca.spottedleaf.dataconverter.minecraft.MCDataConverter;
@@ -28156,6 +29023,7 @@ index 0000000000000000000000000000000000000000..6f2a30eed4e9741a128b5a171edef6ab
+import net.minecraft.commands.arguments.ComponentArgument;
+import net.minecraft.commands.arguments.CompoundTagArgument;
+import net.minecraft.commands.arguments.ResourceLocationArgument;
++import net.minecraft.commands.arguments.blocks.BlockStateArgument;
+import net.minecraft.commands.arguments.coordinates.Vec3Argument;
+import net.minecraft.commands.arguments.item.ItemArgument;
+import net.minecraft.core.Holder;
@@ -28186,6 +29054,7 @@ index 0000000000000000000000000000000000000000..6f2a30eed4e9741a128b5a171edef6ab
+ return new CommandArgumentUpgrader(functionPermissionLevel, builder -> {
+ builder.registerReplacement(ItemArgument.class, (argument, ctx) -> new ItemParser_1_20_4());
+ builder.registerReplacement(ComponentArgument.class, (argument, ctx) -> new ComponentParser_1_20_4());
++ builder.registerReplacement(BlockStateArgument.class, (argument, ctx) -> new BlockStateParser_1_20_4());
+ builder.registerExtraCommand(CommandArgumentUpgrader::registerSummon_1_20_4_to_1_20_5);
+ });
+ }
@@ -28367,6 +29236,105 @@ index 0000000000000000000000000000000000000000..6f2a30eed4e9741a128b5a171edef6ab
+ }
+ }
+
++ private static class BlockStateParser_1_20_4 implements ArgumentType<UpgradedArgument> {
++ @Override
++ public UpgradedArgument parse(final StringReader reader) throws CommandSyntaxException {
++ String block = ResourceLocation.read(reader).toString();
++
++ StringBuilder properties = new StringBuilder();
++ if (reader.canRead() && reader.peek() == '[') {
++ char c;
++ do {
++ c = reader.read();
++ properties.append(c);
++ } while (reader.canRead() && c != ']');
++ }
++
++ if (!reader.canRead() || reader.peek() != '{') {
++ return new UpgradedArgument(block + properties);
++ }
++
++ CompoundTag tag = new TagParser(reader).readStruct();
++ boolean missId = !tag.contains("id", Tag.TAG_STRING);
++ if (missId) { // Data converter can't upgrade tile entities without it
++ tag.putString("id", CommandArgumentUpgrader.blockToTileEntity(block));
++ }
++ tag = MCDataConverter.convertTag(
++ MCTypeRegistry.TILE_ENTITY, tag, MCVersions.V1_20_4, SharedConstants.getCurrentVersion().getDataVersion().getVersion()
++ );
++ if (missId) {
++ tag.remove("id");
++ }
++
++ return new UpgradedArgument(block + properties + tag);
++ }
++ }
++
++ private static String blockToTileEntity(String block) {
++ return switch (block) {
++ case "minecraft:acacia_sign", "minecraft:jungle_wall_sign", "minecraft:oak_sign",
++ "minecraft:cherry_sign", "minecraft:birch_wall_sign", "minecraft:dark_oak_sign",
++ "minecraft:mangrove_wall_sign", "minecraft:cherry_wall_sign", "minecraft:jungle_sign",
++ "minecraft:mangrove_sign", "minecraft:spruce_wall_sign", "minecraft:crimson_sign",
++ "minecraft:oak_wall_sign", "minecraft:crimson_wall_sign", "minecraft:bamboo_sign",
++ "minecraft:warped_wall_sign", "minecraft:bamboo_wall_sign", "minecraft:acacia_wall_sign",
++ "minecraft:spruce_sign", "minecraft:warped_sign", "minecraft:dark_oak_wall_sign",
++ "minecraft:birch_sign"
++ -> "minecraft:sign";
++ case "minecraft:acacia_hanging_sign", "minecraft:crimson_wall_hanging_sign",
++ "minecraft:jungle_wall_hanging_sign", "minecraft:dark_oak_wall_hanging_sign",
++ "minecraft:crimson_hanging_sign", "minecraft:bamboo_wall_hanging_sign",
++ "minecraft:bamboo_hanging_sign", "minecraft:oak_wall_hanging_sign",
++ "minecraft:cherry_wall_hanging_sign", "minecraft:warped_wall_hanging_sign",
++ "minecraft:birch_hanging_sign", "minecraft:mangrove_hanging_sign",
++ "minecraft:birch_wall_hanging_sign", "minecraft:jungle_hanging_sign",
++ "minecraft:cherry_hanging_sign", "minecraft:spruce_hanging_sign",
++ "minecraft:warped_hanging_sign", "minecraft:mangrove_wall_hanging_sign",
++ "minecraft:spruce_wall_hanging_sign", "minecraft:dark_oak_hanging_sign",
++ "minecraft:oak_hanging_sign", "minecraft:acacia_wall_hanging_sign"
++ -> "minecraft:hanging_sign";
++ case "minecraft:spawner" -> "minecraft:mob_spawner";
++ case "minecraft:moving_piston" -> "minecraft:piston";
++ case "minecraft:skeleton_skull" , "minecraft:skeleton_wall_skull", "minecraft:player_wall_head",
++ "minecraft:creeper_wall_head", "minecraft:zombie_head", "minecraft:wither_skeleton_skull",
++ "minecraft:creeper_head", "minecraft:wither_skeleton_wall_skull", "minecraft:dragon_head",
++ "minecraft:piglin_wall_head", "minecraft:dragon_wall_head", "minecraft:player_head",
++ "minecraft:zombie_wall_head", "minecraft:piglin_head"
++ -> "minecraft:skull";
++ case "minecraft:black_banner", "minecraft:orange_wall_banner", "minecraft:gray_wall_banner",
++ "minecraft:magenta_banner", "minecraft:red_banner", "minecraft:brown_wall_banner",
++ "minecraft:pink_banner", "minecraft:light_blue_banner", "minecraft:cyan_wall_banner",
++ "minecraft:purple_banner", "minecraft:brown_banner", "minecraft:light_gray_wall_banner",
++ "minecraft:black_wall_banner", "minecraft:gray_banner", "minecraft:yellow_wall_banner",
++ "minecraft:light_gray_banner", "minecraft:red_wall_banner", "minecraft:light_blue_wall_banner",
++ "minecraft:pink_wall_banner", "minecraft:white_banner", "minecraft:green_wall_banner",
++ "minecraft:white_wall_banner", "minecraft:magenta_wall_banner", "minecraft:green_banner",
++ "minecraft:orange_banner", "minecraft:blue_wall_banner", "minecraft:cyan_banner",
++ "minecraft:purple_wall_banner", "minecraft:lime_wall_banner", "minecraft:yellow_banner",
++ "minecraft:lime_banner", "minecraft:blue_banner"
++ -> "minecraft:banner";
++ case "minecraft:repeating_command_block", "minecraft:chain_command_block"
++ -> "minecraft:command_block";
++ case "minecraft:brown_shulker_box", "minecraft:light_blue_shulker_box", "minecraft:white_shulker_box",
++ "minecraft:green_shulker_box", "minecraft:black_shulker_box", "minecraft:lime_shulker_box",
++ "minecraft:pink_shulker_box", "minecraft:light_gray_shulker_box", "minecraft:magenta_shulker_box",
++ "minecraft:orange_shulker_box", "minecraft:purple_shulker_box", "minecraft:cyan_shulker_box",
++ "minecraft:yellow_shulker_box", "minecraft:red_shulker_box", "minecraft:blue_shulker_box",
++ "minecraft:gray_shulker_box"
++ -> "minecraft:shulker_box";
++ case "minecraft:purple_bed", "minecraft:light_blue_bed", "minecraft:yellow_bed",
++ "minecraft:orange_bed", "minecraft:light_gray_bed", "minecraft:red_bed",
++ "minecraft:gray_bed", "minecraft:brown_bed", "minecraft:cyan_bed", "minecraft:magenta_bed",
++ "minecraft:green_bed", "minecraft:white_bed", "minecraft:black_bed", "minecraft:blue_bed",
++ "minecraft:pink_bed", "minecraft:lime_bed"
++ -> "minecraft:bed";
++ case "minecraft:soul_campfire" -> "minecraft:campfire";
++ case "minecraft:bee_nest" -> "minecraft:beehive";
++ case "minecraft:suspicious_sand", "minecraft:suspicious_gravel" -> "minecraft:brushable_block";
++ default -> block;
++ };
++ }
++
+ // important: leadingSlash should not just be the result of a startsWith on command,
+ // it should reflect whether the command use is in a place that will skip a leading slash when parsing
+ public String upgradeCommandArguments(final String command, final boolean leadingSlash) {
@@ -28557,7 +29525,7 @@ index 0000000000000000000000000000000000000000..6f2a30eed4e9741a128b5a171edef6ab
+ new HolderLookup.Provider() {
+
+ @Override
-+ public Stream<ResourceKey<? extends Registry<?>>> listRegistries() {
++ public Stream<ResourceKey<? extends Registry<?>>> listRegistryKeys() {
+ return Stream.of();
+ }
+
@@ -29218,52 +30186,72 @@ index 0000000000000000000000000000000000000000..5a6536377c9c1e1753e930ff2a6bb98e
+ return correct.equals(value) ? null : correct;
+ }
+}
-diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java
-index 49160a30b8e19e5c5ada811fbcae2a05959524f3..5fca5dc7cdfa976bcc58dfcf0d14abb78a931475 100644
---- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java
-+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java
-@@ -25,13 +25,21 @@ public final class ChunkSystemConverters {
- public static CompoundTag convertPoiCompoundTag(final CompoundTag data, final ServerLevel world) {
- final int dataVersion = getDataVersion(data, DEFAULT_POI_DATA_VERSION);
-
-- return DataFixTypes.POI_CHUNK.update(world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
-+ // Paper start - dataconverter
-+ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
-+ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.POI_CHUNK, data, dataVersion, getCurrentVersion()
-+ );
-+ // Paper end - dataconverter
- }
-
- public static CompoundTag convertEntityChunkCompoundTag(final CompoundTag data, final ServerLevel world) {
- final int dataVersion = getDataVersion(data, DEFAULT_ENTITY_CHUNK_DATA_VERSION);
-
-- return DataFixTypes.ENTITY_CHUNK.update(world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
-+ // Paper start - dataconverter
-+ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
-+ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY_CHUNK, data, dataVersion, getCurrentVersion()
-+ );
-+ // Paper end - dataconverter
- }
-
- private ChunkSystemConverters() {}
+diff --git a/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+index ee514a767f69de69d86e1e88d70fe37c4ab84277..be60439c43b887f0143e7713689fd2773066ba73 100644
+--- a/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
++++ b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+@@ -172,6 +172,43 @@ public final class PaperHooks implements PlatformHooks {
+ @Override
+ public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
+ final int fromVersion, final int toVersion) {
++ // Paper start - optimise data conversion
++ if (type == net.minecraft.util.datafix.fixes.References.PLAYER) {
++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.PLAYER, nbt, fromVersion, toVersion
++ );
++ }
++ if (type == net.minecraft.util.datafix.fixes.References.CHUNK) {
++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, nbt, fromVersion, toVersion
++ );
++ }
++ if (type == net.minecraft.util.datafix.fixes.References.STRUCTURE) {
++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.STRUCTURE, nbt, fromVersion, toVersion
++ );
++ }
++ if (type == net.minecraft.util.datafix.fixes.References.POI_CHUNK) {
++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.POI_CHUNK, nbt, fromVersion, toVersion
++ );
++ }
++ if (type == net.minecraft.util.datafix.fixes.References.ENTITY_CHUNK) {
++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY_CHUNK, nbt, fromVersion, toVersion
++ );
++ }
++ if (type == net.minecraft.util.datafix.fixes.References.ITEM_STACK) {
++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK, nbt, fromVersion, toVersion
++ );
++ }
++ if (type == net.minecraft.util.datafix.fixes.References.ENTITY || type == net.minecraft.util.datafix.fixes.References.ENTITY_TREE) {
++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY, nbt, fromVersion, toVersion
++ );
++ }
++ // Paper end - optimise data conversion
+ return (CompoundTag)dataFixer.update(
+ type, new Dynamic<>(NbtOps.INSTANCE, nbt), fromVersion, toVersion
+ ).getValue();
diff --git a/src/main/java/net/minecraft/data/structures/StructureUpdater.java b/src/main/java/net/minecraft/data/structures/StructureUpdater.java
-index 6082d2a4dda21e1b1a9154629aaf0b282b154a42..d8fe611bb4e121dfe96ccd5b8e7949f91eeba023 100644
+index 967cae22838fc23c3404777fd5f9d0b63885eb90..6e7c06008b392846acb84f2b061118a597680627 100644
--- a/src/main/java/net/minecraft/data/structures/StructureUpdater.java
+++ b/src/main/java/net/minecraft/data/structures/StructureUpdater.java
@@ -27,7 +27,7 @@ public class StructureUpdater implements SnbtToNbt.Filter {
- LOGGER.warn("SNBT Too old, do not forget to update: {} < {}: {}", i, 3937, name);
+ LOGGER.warn("SNBT Too old, do not forget to update: {} < {}: {}", i, 4053, name);
}
- CompoundTag compoundTag = DataFixTypes.STRUCTURE.updateToCurrentVersion(DataFixers.getDataFixer(), nbt, i);
+ CompoundTag compoundTag = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.STRUCTURE, nbt, i, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper
- structureTemplate.load(BuiltInRegistries.BLOCK.asLookup(), compoundTag);
+ structureTemplate.load(BuiltInRegistries.BLOCK, compoundTag);
return structureTemplate.save(new CompoundTag());
}
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 0cdc224656a2baa09b7dfbb249b6a96320ac43e0..8c270fee6ecdfbf2bf214428c6f7fcebc2087719 100644
+index 7d5e2e6e96ea9017334dddade54a9dcb37518642..092f7b6bba4e1291f76c2c09155f33803e93eb04 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
-@@ -96,7 +96,7 @@ public class ChunkStorage implements AutoCloseable, ca.spottedleaf.moonrise.patc
+@@ -86,7 +86,7 @@ public class ChunkStorage implements AutoCloseable {
} else {
try {
// CraftBukkit start
@@ -29272,7 +30260,7 @@ index 0cdc224656a2baa09b7dfbb249b6a96320ac43e0..8c270fee6ecdfbf2bf214428c6f7fceb
CompoundTag level = nbttagcompound.getCompound("Level");
if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) {
ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource();
-@@ -108,7 +108,7 @@ public class ChunkStorage implements AutoCloseable, ca.spottedleaf.moonrise.patc
+@@ -98,7 +98,7 @@ public class ChunkStorage implements AutoCloseable {
// CraftBukkit end
if (i < 1493) {
@@ -29281,7 +30269,7 @@ index 0cdc224656a2baa09b7dfbb249b6a96320ac43e0..8c270fee6ecdfbf2bf214428c6f7fceb
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
LegacyStructureDataHandler persistentstructurelegacy = this.getLegacyStructureHandler(resourcekey, supplier);
-@@ -128,7 +128,7 @@ public class ChunkStorage implements AutoCloseable, ca.spottedleaf.moonrise.patc
+@@ -116,7 +116,7 @@ public class ChunkStorage implements AutoCloseable {
// Spigot end
ChunkStorage.injectDatafixingContext(nbttagcompound, resourcekey, optional);
@@ -29291,7 +30279,7 @@ index 0cdc224656a2baa09b7dfbb249b6a96320ac43e0..8c270fee6ecdfbf2bf214428c6f7fceb
if (stopBelowZero) {
nbttagcompound.putString("Status", net.minecraft.core.registries.BuiltInRegistries.CHUNK_STATUS.getKey(ChunkStatus.SPAWN).toString());
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
-index aafb05c5e63903f5790a6bcb862c8d79588be5a6..c5085ebf4e801837010f3750c5e89576bb0c27a5 100644
+index e0e843f4f69013379ed70cb63d9b4f72163b828b..578d270d5b7efb9ac8f5dde539170f6021e2b786 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
@@ -32,13 +32,30 @@ public class SimpleRegionStorage implements AutoCloseable {
@@ -29329,10 +30317,10 @@ index aafb05c5e63903f5790a6bcb862c8d79588be5a6..c5085ebf4e801837010f3750c5e89576
public CompletableFuture<Void> synchronize(boolean sync) {
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
-index 3694c5d2d522216cd2e6e91e502a56a08595ca84..9d282c263151c51cae84f8db00f6b8fa742fbad3 100644
+index 5f354b333a39b873915bedd57b647355ae5bdf56..c3586281c9594769593a6027ea0a78f7c76c0262 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
-@@ -158,7 +158,7 @@ public class StructureCheck {
+@@ -151,7 +151,7 @@ public class StructureCheck {
CompoundTag compoundTag2;
try {
@@ -29355,7 +30343,7 @@ index 05a76f9d18638f10218161450470f07524b723ac..3ab22c384bb8a7772d389977a61d0e28
}
diff --git a/src/main/java/net/minecraft/world/level/storage/LevelStorageSource.java b/src/main/java/net/minecraft/world/level/storage/LevelStorageSource.java
-index e69d805701def93466ad7fa94f019ec4610efb47..427ee4d6f12a7abd8da0c65e0b9081b25824df40 100644
+index b5abdd1498a3d19559149c30ba959aa2bcf0246c..0c2e827f4ee53ed2723da60f08a6cf96769bbdfa 100644
--- a/src/main/java/net/minecraft/world/level/storage/LevelStorageSource.java
+++ b/src/main/java/net/minecraft/world/level/storage/LevelStorageSource.java
@@ -277,12 +277,21 @@ public class LevelStorageSource {
@@ -29396,10 +30384,10 @@ index b54a3741cd3ba615c83c98985cb4b3c4c586ed7a..b148cf247acdd36f856d0495cde4cc5a
return nbttagcompound;
});
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
-index 6e8838245b0792b15fd9788f2ce11f6503d0e070..9f2ddd47dc0658db2f95ef80543fb9a4d2f94f9f 100644
+index a5a3a0f0460252415c243dfe3019d103b9589c5b..e44ae64ef7cddbcee8c2f37e6606b2257c16bf65 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
-@@ -511,7 +511,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
+@@ -490,7 +490,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data);
final int dataVersion = compound.getInt("DataVersion");
@@ -29408,7 +30396,7 @@ index 6e8838245b0792b15fd9788f2ce11f6503d0e070..9f2ddd47dc0658db2f95ef80543fb9a4
return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(MinecraftServer.getServer().registryAccess(), compound).orElseThrow());
}
-@@ -532,7 +532,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
+@@ -511,7 +511,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data);
int dataVersion = compound.getInt("DataVersion");
diff --git a/patches/unapplied/server/0981-Moonrise-optimisation-patches.patch b/patches/server/0826-Moonrise-optimisation-patches.patch
index 0a8d66874e..452ab610f1 100644
--- a/patches/unapplied/server/0981-Moonrise-optimisation-patches.patch
+++ b/patches/server/0826-Moonrise-optimisation-patches.patch
@@ -9,17 +9,21 @@ Currently includes:
- Collision optimisations
- Random block ticking optimisations
- Chunk tick iteration optimisations
+ - Bitstorage optimisations
+ - Block/Biome Palette read optimisations
+ - StateHolder (BlockState/FluidState) property access optimisations
+ - Basic Fluid property read optimisations
See https://github.com/Tuinity/Moonrise
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java
-index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f2565c9a752 100644
+index 94bba2b71918d79f54b3e28c35e76098ba0afd8c..b61611351bf23efc1e90bab8a850ebbe6ffdd516 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java
-@@ -1,6 +1,10 @@
- package ca.spottedleaf.moonrise.common.util;
+@@ -2,6 +2,10 @@ package ca.spottedleaf.moonrise.common.util;
- import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor;
+ import ca.spottedleaf.concurrentutil.util.Priority;
+ import ca.spottedleaf.moonrise.common.PlatformHooks;
+import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
+import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
+import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
@@ -27,7 +31,7 @@ index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f25
import com.mojang.logging.LogUtils;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.FullChunkStatus;
-@@ -17,203 +21,46 @@ import java.util.function.Consumer;
+@@ -18,203 +22,46 @@ import java.util.function.Consumer;
public final class ChunkSystem {
private static final Logger LOGGER = LogUtils.getLogger();
@@ -38,16 +42,16 @@ index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f25
- }
public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
- scheduleChunkTask(level, chunkX, chunkZ, run, PrioritisedExecutor.Priority.NORMAL);
+ scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL);
}
- public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final PrioritisedExecutor.Priority priority) {
+ public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final Priority priority) {
- level.chunkSource.mainThreadProcessor.execute(run);
+ ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkTask(chunkX, chunkZ, run, priority);
}
public static void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final boolean gen,
- final ChunkStatus toStatus, final boolean addTicket, final PrioritisedExecutor.Priority priority,
+ final ChunkStatus toStatus, final boolean addTicket, final Priority priority,
final Consumer<ChunkAccess> onComplete) {
- if (gen) {
- scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
@@ -75,7 +79,7 @@ index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f25
-
- private static long chunkLoadCounter = 0L;
public static void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final ChunkStatus toStatus,
- final boolean addTicket, final PrioritisedExecutor.Priority priority, final Consumer<ChunkAccess> onComplete) {
+ final boolean addTicket, final Priority priority, final Consumer<ChunkAccess> onComplete) {
- if (!org.bukkit.Bukkit.isPrimaryThread()) {
- scheduleChunkTask(level, chunkX, chunkZ, () -> {
- scheduleChunkLoad(level, chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
@@ -129,14 +133,14 @@ index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f25
- }
- loadCallback.accept(result.orElse(null));
- }, (final Runnable r) -> {
-- scheduleChunkTask(level, chunkX, chunkZ, r, PrioritisedExecutor.Priority.HIGHEST);
+- scheduleChunkTask(level, chunkX, chunkZ, r, Priority.HIGHEST);
- });
+ ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
}
public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
final FullChunkStatus toStatus, final boolean addTicket,
- final PrioritisedExecutor.Priority priority, final Consumer<LevelChunk> onComplete) {
+ final Priority priority, final Consumer<LevelChunk> onComplete) {
- // This method goes unused until the chunk system rewrite
- if (toStatus == FullChunkStatus.INACCESSIBLE) {
- throw new IllegalArgumentException("Cannot wait for INACCESSIBLE status");
@@ -213,7 +217,7 @@ index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f25
- }
- loadCallback.accept(result.orElse(null));
- }, (final Runnable r) -> {
-- scheduleChunkTask(level, chunkX, chunkZ, r, PrioritisedExecutor.Priority.HIGHEST);
+- scheduleChunkTask(level, chunkX, chunkZ, r, Priority.HIGHEST);
- });
+ ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleTickingState(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
}
@@ -239,7 +243,7 @@ index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f25
}
public static boolean hasAnyChunkHolders(final ServerLevel level) {
-@@ -232,52 +79,85 @@ public final class ChunkSystem {
+@@ -236,52 +83,85 @@ public final class ChunkSystem {
}
@@ -342,6 +346,19 @@ index da323a1105347d5cf4b946df10ded78a953236f2..0abba00741b39b69a7f167e5d2670f25
}
private ChunkSystem() {}
+diff --git a/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+index be60439c43b887f0143e7713689fd2773066ba73..dc17aa5a0937c13d431e41779f241f2e81b11656 100644
+--- a/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
++++ b/src/main/java/ca/spottedleaf/moonrise/paper/PaperHooks.java
+@@ -236,7 +236,7 @@ public final class PaperHooks implements PlatformHooks {
+
+ @Override
+ public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
+- net.minecraft.world.level.chunk.status.ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
++ net.minecraft.world.level.chunk.status.ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities(), chunk.getPos()); // Paper - rewrite chunk system - add ChunkPos param
+ }
+
+ @Override
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingBitStorage.java b/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingBitStorage.java
new file mode 100644
index 0000000000000000000000000000000000000000..aef4fc0d3c272febe675d1ac846b88e58b4e7533
@@ -4719,10 +4736,10 @@ index 0000000000000000000000000000000000000000..fd35e4db0c8fec8f86b8743bcc2b15ed
+}
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/storage/ChunkSystemSectionStorage.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/storage/ChunkSystemSectionStorage.java
new file mode 100644
-index 0000000000000000000000000000000000000000..3f5edb756beb9c31b6f591a24b778d6ac2b0bf51
+index 0000000000000000000000000000000000000000..fb87d7ece6ebccfd0ffd2f1a609b45a0d2461d9e
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/storage/ChunkSystemSectionStorage.java
-@@ -0,0 +1,21 @@
+@@ -0,0 +1,17 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.level.storage;
+
+import com.mojang.serialization.Dynamic;
@@ -4735,10 +4752,6 @@ index 0000000000000000000000000000000000000000..3f5edb756beb9c31b6f591a24b778d6a
+
+public interface ChunkSystemSectionStorage {
+
-+ public CompoundTag moonrise$read(final int chunkX, final int chunkZ) throws IOException;
-+
-+ public void moonrise$write(final int chunkX, final int chunkZ, final CompoundTag data) throws IOException;
-+
+ public RegionFileStorage moonrise$getRegionStorage();
+
+ public void moonrise$close() throws IOException;
@@ -22216,10 +22229,10 @@ index 0000000000000000000000000000000000000000..85950a1aa732ab8c01ad28bec9e0de14
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
-index 450a1cc8f1624dce2daf52210d017e0732b1bdf7..a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca 100644
+index b3f3408a986ae513c06e3b16b82e1c80d4604cd2..9bd509915b391e9d382fe47798e2c345b6e59a9a 100644
--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
+++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
-@@ -31,6 +31,45 @@ public class GlobalConfiguration extends ConfigurationPart {
+@@ -30,6 +30,45 @@ public class GlobalConfiguration extends ConfigurationPart {
public static GlobalConfiguration get() {
return instance;
}
@@ -22265,7 +22278,7 @@ index 450a1cc8f1624dce2daf52210d017e0732b1bdf7..a9dd0e5216e95afd98fd2200d110e2cc
static void set(GlobalConfiguration instance) {
GlobalConfiguration.instance = instance;
}
-@@ -146,21 +185,6 @@ public class GlobalConfiguration extends ConfigurationPart {
+@@ -145,21 +184,6 @@ public class GlobalConfiguration extends ConfigurationPart {
public int incomingPacketThreshold = 300;
}
@@ -22287,7 +22300,7 @@ index 450a1cc8f1624dce2daf52210d017e0732b1bdf7..a9dd0e5216e95afd98fd2200d110e2cc
public UnsupportedSettings unsupportedSettings;
public class UnsupportedSettings extends ConfigurationPart {
-@@ -219,7 +243,7 @@ public class GlobalConfiguration extends ConfigurationPart {
+@@ -218,7 +242,7 @@ public class GlobalConfiguration extends ConfigurationPart {
@PostProcess
private void postProcess() {
@@ -22313,10 +22326,10 @@ index 0000000000000000000000000000000000000000..8424cf9d4617b4732d44cc460d25b044
+
+}
diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java
-index 03c45ee77276462818a6f774b5945b25924aa3f0..f15dd2ccb99ade10ac1e49b63e6f4080bd39b3c9 100644
+index 3fde5abde736b2c19d8819d9aec0397a0245ccd1..6548302d4983bf48cc6bc2b7f4833dc76b59fa5e 100644
--- a/src/main/java/net/minecraft/core/Direction.java
+++ b/src/main/java/net/minecraft/core/Direction.java
-@@ -27,7 +27,7 @@ import org.joml.Quaternionf;
+@@ -28,7 +28,7 @@ import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.joml.Vector4f;
@@ -22325,7 +22338,7 @@ index 03c45ee77276462818a6f774b5945b25924aa3f0..f15dd2ccb99ade10ac1e49b63e6f4080
DOWN(0, 1, -1, "down", Direction.AxisDirection.NEGATIVE, Direction.Axis.Y, new Vec3i(0, -1, 0)),
UP(1, 0, -1, "up", Direction.AxisDirection.POSITIVE, Direction.Axis.Y, new Vec3i(0, 1, 0)),
NORTH(2, 3, 2, "north", Direction.AxisDirection.NEGATIVE, Direction.Axis.Z, new Vec3i(0, 0, -1)),
-@@ -60,6 +60,46 @@ public enum Direction implements StringRepresentable {
+@@ -62,6 +62,46 @@ public enum Direction implements StringRepresentable {
private final int adjY;
private final int adjZ;
// Paper end - Perf: Inline shift direction fields
@@ -22372,7 +22385,7 @@ index 03c45ee77276462818a6f774b5945b25924aa3f0..f15dd2ccb99ade10ac1e49b63e6f4080
private Direction(
final int id,
-@@ -134,14 +174,13 @@ public enum Direction implements StringRepresentable {
+@@ -147,14 +187,13 @@ public enum Direction implements StringRepresentable {
}
public Quaternionf getRotation() {
@@ -22394,7 +22407,7 @@ index 03c45ee77276462818a6f774b5945b25924aa3f0..f15dd2ccb99ade10ac1e49b63e6f4080
}
public int get3DDataValue() {
-@@ -165,7 +204,7 @@ public enum Direction implements StringRepresentable {
+@@ -178,7 +217,7 @@ public enum Direction implements StringRepresentable {
}
public Direction getOpposite() {
@@ -22403,7 +22416,7 @@ index 03c45ee77276462818a6f774b5945b25924aa3f0..f15dd2ccb99ade10ac1e49b63e6f4080
}
public Direction getClockWise(Direction.Axis axis) {
-@@ -551,4 +590,17 @@ public enum Direction implements StringRepresentable {
+@@ -600,4 +639,17 @@ public enum Direction implements StringRepresentable {
return this.faces.length;
}
}
@@ -22422,7 +22435,7 @@ index 03c45ee77276462818a6f774b5945b25924aa3f0..f15dd2ccb99ade10ac1e49b63e6f4080
+ // Paper end - optimise collisions
}
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
-index c33f85b570f159ab465b5a10a8044a81f2797f43..244a19ecd0234fa1d7a6ecfea20751595688605d 100644
+index fc6ce3485dc890f5105a37fe3e344a1460867556..e114e687f2f4503546687fd6792226a643af8793 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -320,6 +320,7 @@ public class Main {
@@ -22434,19 +22447,19 @@ index c33f85b570f159ab465b5a10a8044a81f2797f43..244a19ecd0234fa1d7a6ecfea2075159
DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, worldLoader.get(), thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::createFromGameruleRadius);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076e01f6694 100644
+index 53c9be615a0f2939cd989e24e304e81e6e27f39d..7c388e230c4a88edf6212dd8990e8238d3265ebf 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -198,7 +198,7 @@ import org.bukkit.event.server.ServerLoadEvent;
+@@ -205,7 +205,7 @@ import org.bukkit.event.server.ServerLoadEvent;
import co.aikar.timings.MinecraftTimings; // Paper
--public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource, AutoCloseable {
-+public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource, AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer { // Paper - rewrite chunk system
+-public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource {
++public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource, ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer { // Paper - rewrite chunk system
private static MinecraftServer SERVER; // Paper
public static final Logger LOGGER = LogUtils.getLogger();
-@@ -321,7 +321,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -332,7 +332,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) {
AtomicReference<S> atomicreference = new AtomicReference();
@@ -22455,7 +22468,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
((MinecraftServer) atomicreference.get()).runServer();
}, "Server thread");
-@@ -340,6 +340,77 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -351,6 +351,77 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return s0;
}
@@ -22533,7 +22546,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
public MinecraftServer(OptionSet options, WorldLoader.DataLoadContext worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) {
super("Server");
SERVER = this; // Paper - better singleton
-@@ -656,7 +727,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -673,7 +744,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.forceDifficulty();
for (ServerLevel worldserver : this.getAllLevels()) {
this.prepareLevels(worldserver.getChunkSource().chunkMap.progressListener, worldserver);
@@ -22542,7 +22555,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld()));
}
-@@ -869,6 +940,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -883,6 +954,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public abstract boolean shouldRconBroadcast();
public boolean saveAllChunks(boolean suppressLogs, boolean flush, boolean force) {
@@ -22554,7 +22567,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
boolean flag3 = false;
for (Iterator iterator = this.getAllLevels().iterator(); iterator.hasNext(); flag3 = true) {
-@@ -878,7 +954,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -892,7 +968,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
MinecraftServer.LOGGER.info("Saving chunks for level '{}'/{}", worldserver, worldserver.dimension().location());
}
@@ -22563,7 +22576,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
}
// CraftBukkit start - moved to WorldServer.save
-@@ -979,7 +1055,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -993,7 +1069,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -22572,7 +22585,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
return worldserver1.getChunkSource().chunkMap.hasWork();
})) {
this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND;
-@@ -996,19 +1072,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -1010,19 +1086,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.waitUntilNextTick();
}
@@ -22593,7 +22606,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
this.isSaving = false;
this.resources.close();
-@@ -1028,6 +1092,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -1042,6 +1106,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Spigot end
@@ -22601,21 +22614,21 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
}
public String getLocalIp() {
-@@ -1201,6 +1266,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
- this.tickServer(flag ? () -> {
- return false;
- } : this::haveTime);
-+ // Paper start - rewrite chunk system
-+ final Throwable crash = this.chunkSystemCrash;
-+ if (crash != null) {
-+ this.chunkSystemCrash = null;
-+ throw new RuntimeException("Chunk system crash propagated to tick()", crash);
-+ }
-+ // Paper end - rewrite chunk system
- this.profiler.popPush("nextTickWait");
- this.mayHaveDelayedTasks = true;
- this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + i, this.nextTickTimeNanos);
-@@ -1390,6 +1462,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -1212,6 +1277,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+ this.tickServer(flag ? () -> {
+ return false;
+ } : this::haveTime);
++ // Paper start - rewrite chunk system
++ final Throwable crash = this.chunkSystemCrash;
++ if (crash != null) {
++ this.chunkSystemCrash = null;
++ throw new RuntimeException("Chunk system crash propagated to tick()", crash);
++ }
++ // Paper end - rewrite chunk system
+ this.tickFrame.end();
+ gameprofilerfiller.popPush("nextTickWait");
+ this.mayHaveDelayedTasks = true;
+@@ -1428,6 +1500,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private boolean pollTaskInternal() {
if (super.pollTask()) {
@@ -22623,16 +22636,7 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
return true;
} else {
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
-@@ -1591,7 +1664,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
- // Paper start - Folia scheduler API
- ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick();
- getAllLevels().forEach(level -> {
-- for (final Entity entity : level.getEntities().getAll()) {
-+ for (final Entity entity : level.moonrise$getEntityLookup().getAllCopy()) { // Paper - rewrite chunk system
- if (entity.isRemoved()) {
- continue;
- }
-@@ -2653,6 +2726,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+@@ -2696,6 +2769,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
@@ -22647,10 +22651,10 @@ index a093f29a0b75b5a9e2db2238698d2f3f4ac14ed1..999e9c8f842423e6f1a3e80902e9d076
public boolean isDebugging() {
return false;
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-index 0761d5bc5f2813bb4a9f664ac7a05b9744d0a778..7d2896918ff5fed37e5de5a22c37b0c7f32634a8 100644
+index eb9dab7be7da11ab1c4046a7fc4a29d5bddf31d2..c066e93994f4f9ab2ac00163e25d4bb1f186c526 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-@@ -476,7 +476,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
+@@ -459,7 +459,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
return world.dimension() == net.minecraft.world.level.Level.NETHER ? this.getProperties().allowNether : true;
}
@@ -22685,7 +22689,7 @@ index 0761d5bc5f2813bb4a9f664ac7a05b9744d0a778..7d2896918ff5fed37e5de5a22c37b0c7
}
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
-index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a69c4a43d 100644
+index b9ab241b930edc63a39dbbcf14cd0b5edacb9ea9..8e2c0def0d158bdacfa0d455be82db24cc4bdf64 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -32,46 +32,125 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
@@ -22845,7 +22849,7 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
return this.getFullChunkNowUnchecked();
}
-@@ -89,63 +168,64 @@ public class ChunkHolder extends GenerationChunkHolder {
+@@ -89,59 +168,60 @@ public class ChunkHolder extends GenerationChunkHolder {
// CraftBukkit end
public CompletableFuture<ChunkResult<LevelChunk>> getTickingChunkFuture() {
@@ -22911,11 +22915,12 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
}
public boolean isReadyForSaving() {
-- return this.getGenerationRefCount() == 0 && this.saveSync.isDone();
+- return this.saveSync.isDone();
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
- private void addSaveDependency(CompletableFuture<?> savingFuture) {
+ @Override
+ protected void addSaveDependency(CompletableFuture<?> savingFuture) {
- if (this.saveSync.isDone()) {
- this.saveSync = savingFuture;
- } else {
@@ -22927,22 +22932,16 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
}
- public void blockChanged(BlockPos pos) {
-- LevelChunk chunk = this.getTickingChunk();
-+ LevelChunk chunk = this.playersSentChunkTo.size() == 0 ? null : this.getChunkToSend(); // Paper - rewrite chunk system
-
- if (chunk != null) {
- int i = this.levelHeightAccessor.getSectionIndex(pos.getY());
-@@ -165,7 +245,7 @@ public class ChunkHolder extends GenerationChunkHolder {
-
- if (ichunkaccess != null) {
- ichunkaccess.setUnsaved(true);
+@@ -172,7 +252,7 @@ public class ChunkHolder extends GenerationChunkHolder {
+ return false;
+ } else {
+ ichunkaccess.markUnsaved();
- LevelChunk chunk = this.getTickingChunk();
+ LevelChunk chunk = this.getChunkToSend(); // Paper - rewrite chunk system
- if (chunk != null) {
- int j = this.lightEngine.getMinLightSection();
-@@ -191,7 +271,7 @@ public class ChunkHolder extends GenerationChunkHolder {
+ if (chunk == null) {
+ return false;
+@@ -207,7 +287,7 @@ public class ChunkHolder extends GenerationChunkHolder {
List list;
if (!this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) {
@@ -22951,7 +22950,7 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
if (!list.isEmpty()) {
ClientboundLightUpdatePacket packetplayoutlightupdate = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, this.skyChangedLightSectionFilter, this.blockChangedLightSectionFilter);
-@@ -203,7 +283,7 @@ public class ChunkHolder extends GenerationChunkHolder {
+@@ -219,7 +299,7 @@ public class ChunkHolder extends GenerationChunkHolder {
}
if (this.hasChangedSections) {
@@ -22960,7 +22959,7 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
for (int i = 0; i < this.changedBlocksPerSection.length; ++i) {
ShortSet shortset = this.changedBlocksPerSection[i];
-@@ -269,201 +349,40 @@ public class ChunkHolder extends GenerationChunkHolder {
+@@ -285,201 +365,48 @@ public class ChunkHolder extends GenerationChunkHolder {
@Override
public int getTicketLevel() {
@@ -23006,10 +23005,10 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
-- // CraftBukkit start
-- // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
-- // SPIGOT-7780: Moved out of updateFutures to call all chunk unload events before calling updateHighestAllowedStatus for all chunks
-- protected void callEventIfUnloading(ChunkMap playerchunkmap) {
+ // CraftBukkit start
+ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
+ // SPIGOT-7780: Moved out of updateFutures to call all chunk unload events before calling updateHighestAllowedStatus for all chunks
+ protected void callEventIfUnloading(ChunkMap playerchunkmap) {
- FullChunkStatus oldFullChunkStatus = ChunkLevel.fullStatus(this.oldTicketLevel);
- FullChunkStatus newFullChunkStatus = ChunkLevel.fullStatus(this.ticketLevel);
- boolean oldIsFull = oldFullChunkStatus.isOrAfter(FullChunkStatus.FULL);
@@ -23022,7 +23021,7 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
- // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick
- // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag.
- // These actions may however happen deferred, so we manually set the needsSaving flag already here.
-- chunk.setUnsaved(true);
+- chunk.markUnsaved();
- chunk.unloadCallback();
- });
- }
@@ -23035,9 +23034,10 @@ index 43513325b7052d388a63d63bd3a4edff48cf23c2..4db96543e2072e47040bb25a9d97ea6a
- // Run callback right away if the future was already done
- playerchunkmap.callbackExecutor.run();
- }
-- }
-- // CraftBukkit end
--
++ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
+ }
+ // CraftBukkit end
+
protected void updateFutures(ChunkMap chunkLoadingManager, Executor executor) {
- FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel);
- FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel);
@@ -23189,10 +23189,10 @@ index d9ad32acdf46a43a649334a3b736aeb7b3af21d1..fae17a075d7efaf24d916877dd5968eb
public static final int RADIUS_AROUND_FULL_CHUNK = FULL_CHUNK_STEP.accumulatedDependencies().getRadius();
public static final int MAX_LEVEL = 33 + RADIUS_AROUND_FULL_CHUNK;
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6d23b639c 100644
+index ec19eb88705a07db45f1a3541571fb7f43efb5a9..60adb0caf3d6f03a57fc55303852070107f1736e 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -122,10 +122,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -125,10 +125,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public static final int MIN_VIEW_DISTANCE = 2;
public static final int MAX_VIEW_DISTANCE = 32;
public static final int FORCED_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING);
@@ -23204,13 +23204,12 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
public final ServerLevel level;
private final ThreadedLevelLightEngine lightEngine;
private final BlockableEventLoop<Runnable> mainThreadExecutor;
-@@ -135,21 +132,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -138,22 +135,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private final PoiManager poiManager;
public final LongSet toDrop;
private boolean modified;
-- private final ChunkTaskPriorityQueueSorter queueSorter;
-- private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> worldgenMailbox;
-- private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> mainThreadMailbox;
+- private final ChunkTaskDispatcher worldgenTaskDispatcher;
+- private final ChunkTaskDispatcher lightTaskDispatcher;
+ // Paper - rewrite chunk system
public final ChunkProgressListener progressListener;
private final ChunkStatusUpdateListener chunkStatusListener;
@@ -23221,8 +23220,10 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
private final PlayerMap playerMap;
public final Int2ObjectMap<ChunkMap.TrackedEntity> entityMap;
private final Long2ByteMap chunkTypeCache;
- private final Long2LongMap chunkSaveCooldowns;
+- private final Long2LongMap nextChunkSaveTime;
+- private final LongSet chunksToEagerlySave;
- private final Queue<Runnable> unloadQueue;
+- private final AtomicInteger activeChunkWrites;
+ // Paper - rewrite chunk system
public int serverViewDistance;
- private final WorldGenContext worldGenContext;
@@ -23230,7 +23231,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
// CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback()
public final CallbackExecutor callbackExecutor = new CallbackExecutor();
-@@ -174,22 +169,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -178,24 +171,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper start
public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) {
@@ -23250,32 +23251,32 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
this.playerMap = new PlayerMap();
this.entityMap = new Int2ObjectOpenHashMap();
this.chunkTypeCache = new Long2ByteOpenHashMap();
- this.chunkSaveCooldowns = new Long2LongOpenHashMap();
+- this.nextChunkSaveTime = new Long2LongOpenHashMap();
+- this.chunksToEagerlySave = new LongLinkedOpenHashSet();
- this.unloadQueue = Queues.newConcurrentLinkedQueue();
+- this.activeChunkWrites = new AtomicInteger();
+ // Paper - rewrite chunk system
Path path = session.getDimensionPath(world.dimension());
this.storageName = path.getFileName().toString();
-@@ -220,15 +213,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -223,14 +211,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.chunkStatusListener = chunkStatusChangeListener;
- ProcessorMailbox<Runnable> threadedmailbox1 = ProcessorMailbox.create(executor, "light");
+ ConsecutiveExecutor consecutiveexecutor1 = new ConsecutiveExecutor(executor, "light");
-- this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE);
-- this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false);
-- this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false);
-- this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false));
-+ // Paper - rewrite chunk system
-+ this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, null); // Paper - rewrite chunk system
+- this.worldgenTaskDispatcher = new ChunkTaskDispatcher(consecutiveexecutor, executor);
+- this.lightTaskDispatcher = new ChunkTaskDispatcher(consecutiveexecutor1, executor);
+- this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), consecutiveexecutor1, this.lightTaskDispatcher);
++ this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), consecutiveexecutor1, null); // Paper - rewrite chunk system
this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor);
this.overworldDataStorage = persistentStateManagerFactory;
this.poiManager = new PoiManager(new RegionStorageInfo(session.getLevelId(), world.dimension(), "poi"), path.resolve("poi"), dataFixer, dsync, iregistrycustom, world.getServer(), world);
this.setServerViewDistance(viewDistance);
-- this.worldGenContext = new WorldGenContext(world, chunkGenerator, structureTemplateManager, this.lightEngine, this.mainThreadMailbox);
-+ this.worldGenContext = new WorldGenContext(world, chunkGenerator, structureTemplateManager, this.lightEngine, null); // Paper - rewrite chunk system
+- this.worldGenContext = new WorldGenContext(world, chunkGenerator, structureTemplateManager, this.lightEngine, mainThreadExecutor, this::setChunkUnsaved);
++ this.worldGenContext = new WorldGenContext(world, chunkGenerator, structureTemplateManager, this.lightEngine, null, this::setChunkUnsaved); // Paper - rewrite chunk system
}
- // Paper start
-@@ -259,23 +250,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ private void setChunkUnsaved(ChunkPos pos) {
+@@ -265,23 +251,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
boolean isChunkTracked(ServerPlayer player, int chunkX, int chunkZ) {
@@ -23301,7 +23302,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
}
protected ThreadedLevelLightEngine getLightEngine() {
-@@ -284,20 +263,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -290,20 +264,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@Nullable
protected ChunkHolder getUpdatingChunkIfPresent(long pos) {
@@ -23331,7 +23332,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
}
public String getChunkDebugData(ChunkPos chunkPos) {
-@@ -326,55 +307,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -332,56 +308,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
private CompletableFuture<ChunkResult<List<ChunkAccess>>> getChunkRangeFuture(ChunkHolder centerChunk, int margin, IntFunction<ChunkStatus> distanceToStatus) {
@@ -23342,27 +23343,28 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- return chunkresult.map(List::of);
- });
- } else {
-- List<CompletableFuture<ChunkResult<ChunkAccess>>> list = new ArrayList();
+- int j = Mth.square(margin * 2 + 1);
+- List<CompletableFuture<ChunkResult<ChunkAccess>>> list = new ArrayList(j);
- ChunkPos chunkcoordintpair = centerChunk.getPos();
-
-- for (int j = -margin; j <= margin; ++j) {
-- for (int k = -margin; k <= margin; ++k) {
-- int l = Math.max(Math.abs(k), Math.abs(j));
-- long i1 = ChunkPos.asLong(chunkcoordintpair.x + k, chunkcoordintpair.z + j);
-- ChunkHolder playerchunk1 = this.getUpdatingChunkIfPresent(i1);
+- for (int k = -margin; k <= margin; ++k) {
+- for (int l = -margin; l <= margin; ++l) {
+- int i1 = Math.max(Math.abs(l), Math.abs(k));
+- long j1 = ChunkPos.asLong(chunkcoordintpair.x + l, chunkcoordintpair.z + k);
+- ChunkHolder playerchunk1 = this.getUpdatingChunkIfPresent(j1);
-
- if (playerchunk1 == null) {
- return ChunkMap.UNLOADED_CHUNK_LIST_FUTURE;
- }
-
-- ChunkStatus chunkstatus1 = (ChunkStatus) distanceToStatus.apply(l);
+- ChunkStatus chunkstatus1 = (ChunkStatus) distanceToStatus.apply(i1);
-
- list.add(playerchunk1.scheduleChunkGenerationTask(chunkstatus1, this));
- }
- }
-
- return Util.sequence(list).thenApply((list1) -> {
-- List<ChunkAccess> list2 = Lists.newArrayList();
+- List<ChunkAccess> list2 = new ArrayList(list1.size());
- Iterator iterator = list1.iterator();
-
- while (iterator.hasNext()) {
@@ -23388,17 +23390,17 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
}
public ReportedException debugFuturesAndCreateReportedException(IllegalStateException exception, String details) {
-@@ -404,90 +337,23 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -411,49 +338,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public CompletableFuture<ChunkResult<LevelChunk>> prepareEntityTickingChunk(ChunkHolder holder) {
- return this.getChunkRangeFuture(holder, 2, (i) -> {
- return ChunkStatus.FULL;
-- }).thenApplyAsync((chunkresult) -> {
+- }).thenApply((chunkresult) -> {
- return chunkresult.map((list) -> {
- return (LevelChunk) list.get(list.size() / 2);
- });
-- }, this.mainThreadExecutor);
+- });
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
@@ -23424,7 +23426,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- if (holder != null) {
- holder.setTicketLevel(level);
- } else {
-- holder = new ChunkHolder(new ChunkPos(pos), level, this.level, this.lightEngine, this.queueSorter, this);
+- holder = new ChunkHolder(new ChunkPos(pos), level, this.level, this.lightEngine, this::onLevelChange, this);
- // Paper start
- ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkHolderCreate(this.level, holder);
- // Paper end
@@ -23439,16 +23441,20 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
+ private void onLevelChange(ChunkPos pos, IntSupplier levelGetter, int targetLevel, IntConsumer levelSetter) {
+@@ -463,52 +353,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+
@Override
public void close() throws IOException {
- try {
-- this.queueSorter.close();
+- this.worldgenTaskDispatcher.close();
+- this.lightTaskDispatcher.close();
- this.poiManager.close();
- } finally {
- super.close();
- }
--
+ throw new UnsupportedOperationException("Use ServerChunkCache#close"); // Paper - rewrite chunk system
+
}
protected void saveAllChunks(boolean flush) {
@@ -23471,103 +23477,119 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- });
- } while (mutableboolean.isTrue());
-
+- this.poiManager.flushAll();
- this.processUnloads(() -> {
- return true;
- });
- this.flushWorker();
- } else {
-- ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level).forEach(this::saveChunkIfNeeded);
-- }
+- this.nextChunkSaveTime.clear();
+- long i = Util.getMillis();
+- Iterator<ChunkHolder> objectiterator = ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level).iterator(); // Paper
-
+- while (objectiterator.hasNext()) {
+- ChunkHolder playerchunk = (ChunkHolder) objectiterator.next();
+-
+- this.saveChunkIfNeeded(playerchunk, i);
+- }
+- }
++ // Paper start - rewrite chunk system
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.saveAllChunks(
+ flush, false, false
+ );
++ // Paper end - rewrite chunk system
+
}
- protected void tick(BooleanSupplier shouldKeepTicking) {
-@@ -504,133 +370,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -526,143 +380,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public boolean hasWork() {
-- return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || ca.spottedleaf.moonrise.common.util.ChunkSystem.hasAnyChunkHolders(this.level) || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); // Paper
+- return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || ca.spottedleaf.moonrise.common.util.ChunkSystem.hasAnyChunkHolders(this.level) || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.worldgenTaskDispatcher.hasWork() || this.lightTaskDispatcher.hasWork() || this.distanceManager.hasTickets();
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
private void processUnloads(BooleanSupplier shouldKeepTicking) {
-- LongIterator longiterator = this.toDrop.iterator();
-- int i = 0;
--
-- while (longiterator.hasNext() && (shouldKeepTicking.getAsBoolean() || i < 200 || this.toDrop.size() > 2000)) {
-- long j = longiterator.nextLong();
-- ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.get(j);
+- for (LongIterator longiterator = this.toDrop.iterator(); longiterator.hasNext(); longiterator.remove()) {
+- long i = longiterator.nextLong();
+- ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.get(i);
-
- if (playerchunk != null) {
-- if (playerchunk.getGenerationRefCount() != 0) {
-- continue;
-- }
--
-- this.updatingChunkMap.remove(j);
-- this.pendingUnloads.put(j, playerchunk);
+- this.updatingChunkMap.remove(i);
+- this.pendingUnloads.put(i, playerchunk);
- this.modified = true;
-- ++i;
-- this.scheduleUnload(j, playerchunk);
+- this.scheduleUnload(i, playerchunk);
- }
--
-- longiterator.remove();
- }
-
-- int k = Math.max(0, this.unloadQueue.size() - 2000);
+- int j = Math.max(0, this.unloadQueue.size() - 2000);
-
- Runnable runnable;
-
-- while ((shouldKeepTicking.getAsBoolean() || k > 0) && (runnable = (Runnable) this.unloadQueue.poll()) != null) {
-- --k;
+- while ((j > 0 || shouldKeepTicking.getAsBoolean()) && (runnable = (Runnable) this.unloadQueue.poll()) != null) {
+- --j;
- runnable.run();
- }
-
-- int l = 0;
-- Iterator<ChunkHolder> objectiterator = ca.spottedleaf.moonrise.common.util.ChunkSystem.getVisibleChunkHolders(this.level).iterator(); // Paper
+- this.saveChunksEagerly(shouldKeepTicking);
++ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.processUnloads(); // Paper - rewrite chunk system
++ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.autoSave(); // Paper - rewrite chunk system
+ }
+
+ private void saveChunksEagerly(BooleanSupplier shouldKeepTicking) {
+- long i = Util.getMillis();
+- int j = 0;
+- LongIterator longiterator = this.chunksToEagerlySave.iterator();
-
-- while (l < 20 && shouldKeepTicking.getAsBoolean() && objectiterator.hasNext()) {
-- if (this.saveChunkIfNeeded((ChunkHolder) objectiterator.next())) {
-- ++l;
+- while (j < 20 && this.activeChunkWrites.get() < 128 && shouldKeepTicking.getAsBoolean() && longiterator.hasNext()) {
+- long k = longiterator.nextLong();
+- ChunkHolder playerchunk = (ChunkHolder) this.visibleChunkMap.get(k);
+- ChunkAccess ichunkaccess = playerchunk != null ? playerchunk.getLatestChunk() : null;
+-
+- if (ichunkaccess != null && ichunkaccess.isUnsaved()) {
+- if (this.saveChunkIfNeeded(playerchunk, i)) {
+- ++j;
+- longiterator.remove();
+- }
+- } else {
+- longiterator.remove();
- }
- }
-+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.processUnloads(); // Paper - rewrite chunk system
-+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.autoSave(); // Paper - rewrite chunk system
++ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
- private void scheduleUnload(long pos, ChunkHolder holder) {
-- CompletableFuture completablefuture = holder.getSaveSyncFuture();
+ private void scheduleUnload(long pos, ChunkHolder chunk) {
+- CompletableFuture<?> completablefuture = chunk.getSaveSyncFuture();
- Runnable runnable = () -> {
-- if (!holder.isReadyForSaving()) {
-- this.scheduleUnload(pos, holder);
-- } else {
-- ChunkAccess ichunkaccess = holder.getLatestChunk();
+- CompletableFuture<?> completablefuture1 = chunk.getSaveSyncFuture();
-
+- if (completablefuture1 != completablefuture) {
+- this.scheduleUnload(pos, chunk);
+- } else {
+- ChunkAccess ichunkaccess = chunk.getLatestChunk();
- // Paper start
- boolean removed;
-- if ((removed = this.pendingUnloads.remove(pos, holder)) && ichunkaccess != null) {
-- ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkHolderDelete(this.level, holder);
+- if ((removed = this.pendingUnloads.remove(pos, chunk)) && ichunkaccess != null) {
+- ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkHolderDelete(this.level, chunk);
- // Paper end
- LevelChunk chunk;
-
- if (ichunkaccess instanceof LevelChunk) {
-- chunk = (LevelChunk) ichunkaccess;
-- chunk.setLoaded(false);
+- chunk1 = (LevelChunk) ichunkaccess;
+- chunk1.setLoaded(false);
- }
-
- this.save(ichunkaccess);
- if (ichunkaccess instanceof LevelChunk) {
-- chunk = (LevelChunk) ichunkaccess;
-- this.level.unload(chunk);
+- chunk1 = (LevelChunk) ichunkaccess;
+- this.level.unload(chunk1);
- }
-
- this.lightEngine.updateChunkStatus(ichunkaccess.getPos());
- this.lightEngine.tryScheduleUpdate();
- this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null);
-- this.chunkSaveCooldowns.remove(ichunkaccess.getPos().toLong());
+- this.nextChunkSaveTime.remove(ichunkaccess.getPos().toLong());
- } else if (removed) { // Paper start
- ca.spottedleaf.moonrise.common.util.ChunkSystem.onChunkHolderDelete(this.level, holder);
- } // Paper end
@@ -23579,7 +23601,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- Objects.requireNonNull(this.unloadQueue);
- completablefuture.thenRunAsync(runnable, queue::add).whenComplete((ovoid, throwable) -> {
- if (throwable != null) {
-- ChunkMap.LOGGER.error("Failed to save chunk {}", holder.getPos(), throwable);
+- ChunkMap.LOGGER.error("Failed to save chunk {}", chunk.getPos(), throwable);
- }
-
- });
@@ -23598,20 +23620,25 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
}
private CompletableFuture<ChunkAccess> scheduleChunkLoad(ChunkPos pos) {
-- return this.readChunk(pos).thenApply((optional) -> {
-- return optional.filter((nbttagcompound) -> {
-- boolean flag = ChunkMap.isChunkDataValid(nbttagcompound);
+- CompletableFuture<Optional<SerializableChunkData>> completablefuture = this.readChunk(pos).thenApplyAsync((optional) -> {
+- return optional.map((nbttagcompound) -> {
+- SerializableChunkData serializablechunkdata = SerializableChunkData.parse(this.level, this.level.registryAccess(), nbttagcompound);
-
-- if (!flag) {
+- if (serializablechunkdata == null) {
- ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", pos);
- }
-
-- return flag;
+- return serializablechunkdata;
- });
+- }, Util.backgroundExecutor().forName("parseChunk"));
+- CompletableFuture<?> completablefuture1 = this.poiManager.prefetch(pos);
+-
+- return completablefuture.thenCombine(completablefuture1, (optional, object) -> {
+- return optional;
- }).thenApplyAsync((optional) -> {
-- this.level.getProfiler().incrementCounter("chunkLoad");
+- Profiler.get().incrementCounter("chunkLoad");
- if (optional.isPresent()) {
-- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.poiManager, this.storageInfo(), pos, (CompoundTag) optional.get());
+- ProtoChunk protochunk = ((SerializableChunkData) optional.get()).read(this.level, this.poiManager, this.storageInfo(), pos);
-
- this.markPosition(pos, protochunk.getPersistedStatus().getChunkType());
- return protochunk;
@@ -23624,8 +23651,8 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
- private static boolean isChunkDataValid(CompoundTag nbt) {
-@@ -690,137 +448,44 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ private ChunkAccess handleChunkLoadFailure(Throwable throwable, ChunkPos chunkPos) {
+@@ -718,139 +458,43 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@Override
public GenerationChunkHolder acquireGeneration(long pos) {
@@ -23690,16 +23717,22 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
- private void runGenerationTask(ChunkGenerationTask chunkLoader) {
-- this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkLoader.getCenter(), () -> {
-- CompletableFuture<?> completablefuture = chunkLoader.runUntilWait();
+ private void runGenerationTask(ChunkGenerationTask loader) {
+- GenerationChunkHolder generationchunkholder = loader.getCenter();
+- ChunkTaskDispatcher chunktaskdispatcher = this.worldgenTaskDispatcher;
+- Runnable runnable = () -> {
+- CompletableFuture<?> completablefuture = loader.runUntilWait();
-
- if (completablefuture != null) {
- completablefuture.thenRun(() -> {
-- this.runGenerationTask(chunkLoader);
+- this.runGenerationTask(loader);
- });
- }
-- }));
+- };
+- long i = generationchunkholder.getPos().toLong();
+-
+- Objects.requireNonNull(generationchunkholder);
+- chunktaskdispatcher.submit(runnable, i, generationchunkholder::getQueueLevel);
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
@@ -23716,24 +23749,21 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- });
- CompletableFuture<ChunkResult<LevelChunk>> completablefuture1 = completablefuture.thenApplyAsync((chunkresult) -> {
- return chunkresult.map((list) -> {
-- return (LevelChunk) list.get(list.size() / 2);
-- });
-- }, (runnable) -> {
-- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
-- }).thenApplyAsync((chunkresult) -> {
-- return chunkresult.ifSuccess((chunk) -> {
-- chunk.postProcessGeneration();
+- LevelChunk chunk = (LevelChunk) list.get(list.size() / 2);
+-
+- chunk.postProcessGeneration(this.level);
- this.level.startTickingChunk(chunk);
- CompletableFuture<?> completablefuture2 = holder.getSendSyncFuture();
-
- if (completablefuture2.isDone()) {
-- this.onChunkReadyToSend(chunk);
+- this.onChunkReadyToSend(holder, chunk);
- } else {
- completablefuture2.thenAcceptAsync((object) -> {
-- this.onChunkReadyToSend(chunk);
+- this.onChunkReadyToSend(holder, chunk);
- }, this.mainThreadExecutor);
- }
-
+- return chunk;
- });
- }, this.mainThreadExecutor);
-
@@ -23745,7 +23775,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
- private void onChunkReadyToSend(LevelChunk chunk) {
+ private void onChunkReadyToSend(ChunkHolder chunkHolder, LevelChunk chunk) {
- ChunkPos chunkcoordintpair = chunk.getPos();
- Iterator iterator = this.playerMap.getAllPlayers().iterator();
-
@@ -23756,44 +23786,44 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- ChunkMap.markChunkPendingToSend(entityplayer, chunk);
- }
- }
+-
+- this.level.getChunkSource().onChunkReadyToSend(chunkHolder);
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
-
}
public CompletableFuture<ChunkResult<LevelChunk>> prepareAccessibleChunk(ChunkHolder holder) {
-- return this.getChunkRangeFuture(holder, 1, ChunkLevel::getStatusAroundFullChunk).thenApplyAsync((chunkresult) -> {
+- return this.getChunkRangeFuture(holder, 1, ChunkLevel::getStatusAroundFullChunk).thenApply((chunkresult) -> {
- return chunkresult.map((list) -> {
- return (LevelChunk) list.get(list.size() / 2);
- });
-- }, (runnable) -> {
-- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
- });
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
public int getTickingGenerated() {
-@@ -828,135 +493,84 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -858,143 +502,83 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
- private boolean saveChunkIfNeeded(ChunkHolder chunkHolder) {
+ private boolean saveChunkIfNeeded(ChunkHolder chunkHolder, long currentTime) {
- if (chunkHolder.wasAccessibleSinceLastSave() && chunkHolder.isReadyForSaving()) {
- ChunkAccess ichunkaccess = chunkHolder.getLatestChunk();
-
- if (!(ichunkaccess instanceof ImposterProtoChunk) && !(ichunkaccess instanceof LevelChunk)) {
- return false;
+- } else if (!ichunkaccess.isUnsaved()) {
+- return false;
- } else {
-- long i = ichunkaccess.getPos().toLong();
-- long j = this.chunkSaveCooldowns.getOrDefault(i, -1L);
-- long k = System.currentTimeMillis();
+- long j = ichunkaccess.getPos().toLong();
+- long k = this.nextChunkSaveTime.getOrDefault(j, -1L);
-
-- if (k < j) {
+- if (currentTime < k) {
- return false;
- } else {
- boolean flag = this.save(ichunkaccess);
-
- chunkHolder.refreshAccessibility();
- if (flag) {
-- this.chunkSaveCooldowns.put(i, k + 10000L);
+- this.nextChunkSaveTime.put(j, currentTime + 10000L);
- }
-
- return flag;
@@ -23807,10 +23837,9 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
public boolean save(ChunkAccess chunk) {
- this.poiManager.flush(chunk.getPos());
-- if (!chunk.isUnsaved()) {
+- if (!chunk.tryMarkSaved()) {
- return false;
- } else {
-- chunk.setUnsaved(false);
- ChunkPos chunkcoordintpair = chunk.getPos();
-
- try {
@@ -23826,11 +23855,20 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- }
- }
-
-- this.level.getProfiler().incrementCounter("chunkSave");
-- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk);
+- Profiler.get().incrementCounter("chunkSave");
+- this.activeChunkWrites.incrementAndGet();
+- SerializableChunkData serializablechunkdata = SerializableChunkData.copyOf(this.level, chunk);
-
-- this.write(chunkcoordintpair, nbttagcompound).exceptionally((throwable) -> {
-- this.level.getServer().reportChunkSaveFailure(throwable, this.storageInfo(), chunkcoordintpair);
+- Objects.requireNonNull(serializablechunkdata);
+- CompletableFuture<CompoundTag> completablefuture = CompletableFuture.supplyAsync(serializablechunkdata::write, Util.backgroundExecutor());
+-
+- Objects.requireNonNull(completablefuture);
+- this.write(chunkcoordintpair, completablefuture::join).handle((ovoid, throwable) -> {
+- if (throwable != null) {
+- this.level.getServer().reportChunkSaveFailure(throwable, this.storageInfo(), chunkcoordintpair);
+- }
+-
+- this.activeChunkWrites.decrementAndGet();
- return null;
- });
- this.markPosition(chunkcoordintpair, chunkstatus.getChunkType());
@@ -23863,7 +23901,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
- return false;
- }
-
-- ChunkType chunktype = ChunkSerializer.getChunkTypeFromTag(nbttagcompound);
+- ChunkType chunktype = SerializableChunkData.getChunkTypeFromTag(nbttagcompound);
-
- return this.markPosition(pos, chunktype) == 1;
- }
@@ -23917,8 +23955,8 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
private static void dropChunk(ServerPlayer player, ChunkPos pos) {
- player.connection.chunkSender.dropChunk(player, pos);
+ // Paper - rewrite chunk system
- }
-
++ }
++
+ // Paper start - rewrite chunk system
+ @Override
+ public CompletableFuture<Optional<CompoundTag>> read(final ChunkPos pos) {
@@ -23954,13 +23992,12 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
+ @Override
+ public void flushWorker() {
+ ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.flush();
-+ }
+ }
+ // Paper end - rewrite chunk system
-+
+
@Nullable
public LevelChunk getChunkToSend(long pos) {
- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos);
-@@ -1022,7 +636,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1061,7 +645,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
// CraftBukkit start
@@ -23969,7 +24006,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator().getTypeNameForDataFixer(), chunkcoordintpair, this.level);
// CraftBukkit end
}
-@@ -1113,19 +727,21 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1172,19 +756,21 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.updatePlayerPos(player);
if (!flag1) {
this.distanceManager.addPlayer(SectionPos.of((EntityAccess) player), player);
@@ -23993,7 +24030,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
}
}
-@@ -1137,17 +753,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1196,17 +782,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void move(ServerPlayer player) {
@@ -24012,7 +24049,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
SectionPos sectionposition = player.getLastSectionPos();
SectionPos sectionposition1 = SectionPos.of((EntityAccess) player);
-@@ -1157,6 +763,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1216,6 +792,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (flag2 || flag != flag1) {
this.updatePlayerPos(player);
@@ -24020,7 +24057,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
if (!flag) {
this.distanceManager.removePlayer(sectionposition, player);
}
-@@ -1173,70 +780,30 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1232,70 +809,30 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.playerMap.unIgnorePlayer(player);
}
@@ -24102,7 +24139,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
}
public void addEntity(Entity entity) {
-@@ -1263,6 +830,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1322,6 +859,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas());
this.entityMap.put(entity.getId(), playerchunkmap_entitytracker);
@@ -24115,7 +24152,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
playerchunkmap_entitytracker.updatePlayers(this.level.players());
if (entity instanceof ServerPlayer) {
ServerPlayer entityplayer = (ServerPlayer) entity;
-@@ -1303,16 +876,49 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1362,16 +905,49 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
playerchunkmap_entitytracker1.broadcastRemoved();
}
@@ -24155,7 +24192,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
+ continue;
+ }
+ ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity)tracker).moonrise$clearPlayers();
-+ }
+ }
+ }
+ // Paper end - optimise entity tracker
+
@@ -24164,13 +24201,13 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
+ if (true) {
+ this.newTrackerTick();
+ return;
- }
++ }
+ // Paper end - optimise entity tracker
+ // Paper - rewrite chunk system
List<ServerPlayer> list = Lists.newArrayList();
List<ServerPlayer> list1 = this.level.players();
-@@ -1419,27 +1025,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1478,27 +1054,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void waitForLightBeforeSending(ChunkPos centerPos, int radius) {
@@ -24208,7 +24245,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
}
@Nullable
-@@ -1455,7 +1059,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1514,7 +1088,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
}
@@ -24217,7 +24254,7 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
public final ServerEntity serverEntity;
final Entity entity;
-@@ -1463,6 +1067,84 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1522,6 +1096,84 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
SectionPos lastSectionPos;
public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
@@ -24303,10 +24340,10 @@ index 4c1cf5798209297e1e8a634b63770e917a84a63c..48b8fa3dea0244f9a0f4e0b8850b17a6
this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit
this.entity = entity;
diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java
-index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e0622d0c485 100644
+index f7c2c03749d6be25bf33afd61e1da120770b3432..64da6726634fc223c0e6dcab4d83a6c8997ff196 100644
--- a/src/main/java/net/minecraft/server/level/DistanceManager.java
+++ b/src/main/java/net/minecraft/server/level/DistanceManager.java
-@@ -36,64 +36,58 @@ import net.minecraft.world.level.ChunkPos;
+@@ -34,58 +34,56 @@ import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk;
import org.slf4j.Logger;
@@ -24322,10 +24359,8 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
- private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8);
- private final TickingTracker tickingTicketsTracker = new TickingTracker();
- private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(32);
-- final Set<ChunkHolder> chunksToUpdateFutures = Sets.newHashSet();
-- final ChunkTaskPriorityQueueSorter ticketThrottler;
-- final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> ticketThrottlerInput;
-- final ProcessorHandle<ChunkTaskPriorityQueueSorter.Release> ticketThrottlerReleaser;
+- final Set<ChunkHolder> chunksToUpdateFutures = new ReferenceOpenHashSet();
+- final ThrottlingChunkTaskDispatcher ticketDispatcher;
- final LongSet ticketsToRelease = new LongOpenHashSet();
- final Executor mainThreadExecutor;
+ // Paper - rewrite chunk system
@@ -24336,13 +24371,9 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
+ // Paper - rewrite chunk system
protected DistanceManager(Executor workerExecutor, Executor mainThreadExecutor) {
- Objects.requireNonNull(mainThreadExecutor);
- ProcessorHandle<Runnable> mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute);
- ChunkTaskPriorityQueueSorter chunktaskqueuesorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(mailbox), workerExecutor, 4);
+ TaskScheduler<Runnable> taskscheduler = TaskScheduler.wrapExecutor("player ticket throttler", mainThreadExecutor);
-- this.ticketThrottler = chunktaskqueuesorter;
-- this.ticketThrottlerInput = chunktaskqueuesorter.getProcessor(mailbox, true);
-- this.ticketThrottlerReleaser = chunktaskqueuesorter.getReleaseProcessor(mailbox);
+- this.ticketDispatcher = new ThrottlingChunkTaskDispatcher(taskscheduler, workerExecutor, 4);
- this.mainThreadExecutor = mainThreadExecutor;
+ // Paper - rewrite chunk system
}
@@ -24405,7 +24436,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
}
-@@ -110,91 +104,15 @@ public abstract class DistanceManager {
+@@ -102,105 +100,15 @@ public abstract class DistanceManager {
protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k);
public boolean runAllUpdates(ChunkMap chunkLoadingManager) {
@@ -24420,17 +24451,31 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
- }
-
- if (!this.chunksToUpdateFutures.isEmpty()) {
+- Iterator iterator = this.chunksToUpdateFutures.iterator();
+-
+- ChunkHolder playerchunk;
+-
- // CraftBukkit start - SPIGOT-7780: Call chunk unload events before updateHighestAllowedStatus
-- this.chunksToUpdateFutures.forEach((playerchunk) -> {
+- while (iterator.hasNext()) {
+- playerchunk = (ChunkHolder) iterator.next();
- playerchunk.callEventIfUnloading(chunkLoadingManager);
-- });
+- }
+-
+- iterator = this.chunksToUpdateFutures.iterator();
- // CraftBukkit end
-- this.chunksToUpdateFutures.forEach((playerchunk) -> {
+-
+- while (iterator.hasNext()) {
+- playerchunk = (ChunkHolder) iterator.next();
- playerchunk.updateHighestAllowedStatus(chunkLoadingManager);
-- });
-- this.chunksToUpdateFutures.forEach((playerchunk) -> {
+- }
+-
+- iterator = this.chunksToUpdateFutures.iterator();
+-
+- while (iterator.hasNext()) {
+- playerchunk = (ChunkHolder) iterator.next();
- playerchunk.updateFutures(chunkLoadingManager, this.mainThreadExecutor);
-- });
+- }
+-
- this.chunksToUpdateFutures.clear();
- return true;
- } else {
@@ -24443,18 +24488,18 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
- if (this.getTickets(j).stream().anyMatch((ticket) -> {
- return ticket.getType() == TicketType.PLAYER;
- })) {
-- ChunkHolder playerchunk = chunkLoadingManager.getUpdatingChunkIfPresent(j);
+- ChunkHolder playerchunk1 = chunkLoadingManager.getUpdatingChunkIfPresent(j);
-
-- if (playerchunk == null) {
+- if (playerchunk1 == null) {
- throw new IllegalStateException();
- }
-
-- CompletableFuture<ChunkResult<LevelChunk>> completablefuture = playerchunk.getEntityTickingChunkFuture();
+- CompletableFuture<ChunkResult<LevelChunk>> completablefuture = playerchunk1.getEntityTickingChunkFuture();
-
- completablefuture.thenAccept((chunkresult) -> {
- this.mainThreadExecutor.execute(() -> {
-- this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> {
-- }, j, false));
+- this.ticketDispatcher.release(j, () -> {
+- }, false);
- });
- });
- }
@@ -24500,7 +24545,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
}
public <T> void addTicket(TicketType<T> type, ChunkPos pos, int level, T argument) {
-@@ -213,13 +131,7 @@ public abstract class DistanceManager {
+@@ -219,13 +127,7 @@ public abstract class DistanceManager {
}
public <T> boolean addRegionTicketAtDistance(TicketType<T> tickettype, ChunkPos chunkcoordintpair, int i, T t0) {
@@ -24515,7 +24560,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
}
public <T> void removeRegionTicket(TicketType<T> type, ChunkPos pos, int radius, T argument) {
-@@ -228,32 +140,21 @@ public abstract class DistanceManager {
+@@ -234,32 +136,21 @@ public abstract class DistanceManager {
}
public <T> boolean removeRegionTicketAtDistance(TicketType<T> tickettype, ChunkPos chunkcoordintpair, int i, T t0) {
@@ -24554,7 +24599,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
}
-@@ -264,9 +165,8 @@ public abstract class DistanceManager {
+@@ -270,9 +161,8 @@ public abstract class DistanceManager {
((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> {
return new ObjectOpenHashSet();
})).add(player);
@@ -24566,7 +24611,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
}
public void removePlayer(SectionPos pos, ServerPlayer player) {
-@@ -278,151 +178,81 @@ public abstract class DistanceManager {
+@@ -284,51 +174,49 @@ public abstract class DistanceManager {
if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully
if (objectset == null || objectset.isEmpty()) { // Paper
this.playersPerChunk.remove(i);
@@ -24633,8 +24678,12 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
+ return this.spawnChunkTracker.hasObjectsNear(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkPos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkPos)); // Paper - chunk tick iteration optimisation
}
+ public LongIterator getSpawnCandidateChunks() {
+@@ -337,47 +225,17 @@ public abstract class DistanceManager {
+ }
+
public String getDebugStatus() {
-- return this.ticketThrottler.getDebugStatus();
+- return this.ticketDispatcher.getDebugStatus();
+ return "No DistanceManager stats available"; // Paper - rewrite chunk system
}
@@ -24680,6 +24729,10 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
+ public LongSet getTickingChunks() {
+@@ -385,59 +243,21 @@ public abstract class DistanceManager {
+ }
+
public void removeTicketsOnClosing() {
- ImmutableSet<TicketType<?>> immutableset = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.FUTURE_AWAIT); // Paper - add additional tickets to preserve
- ObjectIterator<Entry<SortedArraySet<Ticket<?>>>> objectiterator = this.tickets.long2ObjectEntrySet().fastIterator();
@@ -24741,7 +24794,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
private class ChunkTicketTracker extends ChunkTracker {
private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1;
-@@ -468,7 +298,7 @@ public abstract class DistanceManager {
+@@ -483,7 +303,7 @@ public abstract class DistanceManager {
public int runDistanceUpdates(int distance) {
return this.runUpdates(distance);
}
@@ -24750,7 +24803,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
private class FixedPlayerDistanceChunkTracker extends ChunkTracker {
-@@ -548,6 +378,7 @@ public abstract class DistanceManager {
+@@ -563,6 +383,7 @@ public abstract class DistanceManager {
}
}
@@ -24758,7 +24811,7 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
private class PlayerTicketTracker extends DistanceManager.FixedPlayerDistanceChunkTracker {
private int viewDistance = 0;
-@@ -642,5 +473,5 @@ public abstract class DistanceManager {
+@@ -657,5 +478,5 @@ public abstract class DistanceManager {
private boolean haveTicketFor(int distance) {
return distance <= this.viewDistance;
}
@@ -24766,10 +24819,10 @@ index 1e7b440cc2c1bf53210069b38286f67a7b97041b..2d2596f04f5addac38037a14a02c6e06
+ }*/ // Paper - rewrite chunk system
}
diff --git a/src/main/java/net/minecraft/server/level/GenerationChunkHolder.java b/src/main/java/net/minecraft/server/level/GenerationChunkHolder.java
-index 3dc1daa3c6a04d3ff1a2353773b465fc380994a2..3575782f13a7f3c52e64dc5046803305d5c8ce12 100644
+index 65206fdfa5b94eaca139e433b4865c16b16641f3..bf4463bcb5dc439ac5a3fa08dd60845a5fd7489a 100644
--- a/src/main/java/net/minecraft/server/level/GenerationChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/GenerationChunkHolder.java
-@@ -27,249 +27,105 @@ public abstract class GenerationChunkHolder {
+@@ -27,13 +27,7 @@ public abstract class GenerationChunkHolder {
public static final ChunkResult<ChunkAccess> UNLOADED_CHUNK = ChunkResult.error("Unloaded chunk");
public static final CompletableFuture<ChunkResult<ChunkAccess>> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(UNLOADED_CHUNK);
protected final ChunkPos pos;
@@ -24779,10 +24832,12 @@ index 3dc1daa3c6a04d3ff1a2353773b465fc380994a2..3575782f13a7f3c52e64dc5046803305
- private final AtomicReferenceArray<CompletableFuture<ChunkResult<ChunkAccess>>> futures = new AtomicReferenceArray<>(CHUNK_STATUSES.size());
- private final AtomicReference<ChunkGenerationTask> task = new AtomicReference<>();
- private final AtomicInteger generationRefCount = new AtomicInteger();
+- private volatile CompletableFuture<Void> generationSaveSyncFuture = CompletableFuture.completedFuture(null);
+ // Paper - rewrite chunk system
public GenerationChunkHolder(ChunkPos pos) {
this.pos = pos;
+@@ -43,243 +37,96 @@ public abstract class GenerationChunkHolder {
}
public CompletableFuture<ChunkResult<ChunkAccess>> scheduleChunkGenerationTask(ChunkStatus requestedStatus, ChunkMap chunkLoadingManager) {
@@ -24988,24 +25043,29 @@ index 3dc1daa3c6a04d3ff1a2353773b465fc380994a2..3575782f13a7f3c52e64dc5046803305
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
+ protected abstract void addSaveDependency(CompletableFuture<?> savingFuture);
+
public void increaseGenerationRefCount() {
-- this.generationRefCount.incrementAndGet();
+- if (this.generationRefCount.getAndIncrement() == 0) {
+- this.generationSaveSyncFuture = new CompletableFuture<>();
+- this.addSaveDependency(this.generationSaveSyncFuture);
+- }
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
public void decreaseGenerationRefCount() {
+- CompletableFuture<Void> completableFuture = this.generationSaveSyncFuture;
- int i = this.generationRefCount.decrementAndGet();
+- if (i == 0) {
+- completableFuture.complete(null);
+- }
+-
- if (i < 0) {
- throw new IllegalStateException("More releases than claims. Count: " + i);
- }
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
- public int getGenerationRefCount() {
-- return this.generationRefCount.get();
-+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
- }
-
@Nullable
public ChunkAccess getChunkIfPresentUnchecked(ChunkStatus requestedStatus) {
- CompletableFuture<ChunkResult<ChunkAccess>> completableFuture = this.futures.get(requestedStatus.getIndex());
@@ -25050,7 +25110,7 @@ index 3dc1daa3c6a04d3ff1a2353773b465fc380994a2..3575782f13a7f3c52e64dc5046803305
}
public ChunkPos getPos() {
-@@ -277,7 +133,7 @@ public abstract class GenerationChunkHolder {
+@@ -287,7 +134,7 @@ public abstract class GenerationChunkHolder {
}
public FullChunkStatus getFullStatus() {
@@ -25059,7 +25119,7 @@ index 3dc1daa3c6a04d3ff1a2353773b465fc380994a2..3575782f13a7f3c52e64dc5046803305
}
public abstract int getTicketLevel();
-@@ -286,26 +142,15 @@ public abstract class GenerationChunkHolder {
+@@ -296,26 +143,15 @@ public abstract class GenerationChunkHolder {
@VisibleForDebug
public List<Pair<ChunkStatus, CompletableFuture<ChunkResult<ChunkAccess>>>> getAllFutures() {
@@ -25092,19 +25152,19 @@ index 3dc1daa3c6a04d3ff1a2353773b465fc380994a2..3575782f13a7f3c52e64dc5046803305
}
}
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39df8493eb 100644
+index 7e5714fea4cda68b9ae21031c0e0d39061b07e2f..22157cbc4e4bb1e4010116bdf7429815d46bff2e 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -46,7 +46,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
- import net.minecraft.world.level.storage.DimensionDataStorage;
+@@ -52,7 +52,7 @@ import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.LevelStorageSource;
+ import org.slf4j.Logger;
-public class ServerChunkCache extends ChunkSource {
+public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache { // Paper - rewrite chunk system
- public static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
- private static final List<ChunkStatus> CHUNK_STATUSES = ChunkStatus.getStatusList();
-@@ -71,6 +71,62 @@ public class ServerChunkCache extends ChunkSource {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private final DistanceManager distanceManager;
+@@ -78,6 +78,62 @@ public class ServerChunkCache extends ChunkSource {
private final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<net.minecraft.world.level.chunk.LevelChunk> fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>();
long chunkFutureAwaitCounter;
// Paper end
@@ -25167,7 +25227,7 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory) {
this.level = world;
-@@ -97,13 +153,7 @@ public class ServerChunkCache extends ChunkSource {
+@@ -109,13 +165,7 @@ public class ServerChunkCache extends ChunkSource {
}
// CraftBukkit end
// Paper start
@@ -25182,7 +25242,7 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
@Nullable
public ChunkAccess getChunkAtImmediately(int x, int z) {
-@@ -174,63 +224,25 @@ public class ServerChunkCache extends ChunkSource {
+@@ -186,63 +236,25 @@ public class ServerChunkCache extends ChunkSource {
@Nullable
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) {
@@ -25197,18 +25257,18 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
- return ifLoaded;
- }
- // Paper end - Perf: Optimise getChunkAt calls for loaded chunks
-- ProfilerFiller gameprofilerfiller = this.level.getProfiler();
+- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.incrementCounter("getChunk");
- long k = ChunkPos.asLong(x, z);
+-
+- for (int l = 0; l < 4; ++l) {
+- if (k == this.lastChunkPos[l] && leastStatus == this.lastChunkStatus[l]) {
+- ChunkAccess ichunkaccess = this.lastChunk[l];
+ // Paper start - rewrite chunk system
+ if (leastStatus == ChunkStatus.FULL) {
+ final LevelChunk ret = this.fullChunks.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(x, z));
-- for (int l = 0; l < 4; ++l) {
-- if (k == this.lastChunkPos[l] && leastStatus == this.lastChunkStatus[l]) {
-- ChunkAccess ichunkaccess = this.lastChunk[l];
--
- if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime
- return ichunkaccess;
- }
@@ -25256,7 +25316,7 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
}
private void clearCache() {
-@@ -261,56 +273,59 @@ public class ServerChunkCache extends ChunkSource {
+@@ -273,56 +285,59 @@ public class ServerChunkCache extends ChunkSource {
}
private CompletableFuture<ChunkResult<ChunkAccess>> getChunkFutureMainThread(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
@@ -25264,28 +25324,19 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
- long k = chunkcoordintpair.toLong();
- int l = ChunkLevel.byStatus(leastStatus);
- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k);
-+ // Paper start - rewrite chunk system
-+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, chunkX, chunkZ, "Scheduling chunk load off-main");
-
+-
- // CraftBukkit start - don't add new ticket for currently unloading chunk
- boolean currentlyUnloading = false;
- if (playerchunk != null) {
- FullChunkStatus oldChunkState = ChunkLevel.fullStatus(playerchunk.oldTicketLevel);
- FullChunkStatus currentChunkState = ChunkLevel.fullStatus(playerchunk.getTicketLevel());
- currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL));
-+ final int minLevel = ChunkLevel.byStatus(leastStatus);
-+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkX, chunkZ);
-+
-+ final boolean needsFullScheduling = leastStatus == ChunkStatus.FULL && (chunkHolder == null || !chunkHolder.getChunkStatus().isOrAfter(FullChunkStatus.FULL));
-+
-+ if ((chunkHolder == null || chunkHolder.getTicketLevel() > minLevel || needsFullScheduling) && !create) {
-+ return ChunkHolder.UNLOADED_CHUNK_FUTURE;
- }
+- }
- if (create && !currentlyUnloading) {
- // CraftBukkit end
- this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair);
- if (this.chunkAbsent(playerchunk, l)) {
-- ProfilerFiller gameprofilerfiller = this.level.getProfiler();
+- ProfilerFiller gameprofilerfiller = Profiler.get();
-
- gameprofilerfiller.push("chunkLoad");
- this.runDistanceManagerUpdates();
@@ -25293,7 +25344,22 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
- gameprofilerfiller.pop();
- if (this.chunkAbsent(playerchunk, l)) {
- throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("No chunk holder after ticket has been added"));
+- }
+- }
++ // Paper start - rewrite chunk system
++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, chunkX, chunkZ, "Scheduling chunk load off-main");
++
++ final int minLevel = ChunkLevel.byStatus(leastStatus);
++ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkX, chunkZ);
++
++ final boolean needsFullScheduling = leastStatus == ChunkStatus.FULL && (chunkHolder == null || !chunkHolder.getChunkStatus().isOrAfter(FullChunkStatus.FULL));
+
++ if ((chunkHolder == null || chunkHolder.getTicketLevel() > minLevel || needsFullScheduling) && !create) {
++ return ChunkHolder.UNLOADED_CHUNK_FUTURE;
+ }
+
+- return this.chunkAbsent(playerchunk, l) ? GenerationChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.scheduleChunkGenerationTask(leastStatus, this.chunkMap);
+- }
+ final ChunkAccess ifPresent = chunkHolder == null ? null : chunkHolder.getChunkIfPresent(leastStatus);
+ if (needsFullScheduling || ifPresent == null) {
+ // schedule
@@ -25303,13 +25369,9 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
+ ret.complete(ChunkHolder.UNLOADED_CHUNK);
+ } else {
+ ret.complete(ChunkResult.of(chunk));
- }
-- }
-- }
++ }
+ };
-
-- return this.chunkAbsent(playerchunk, l) ? GenerationChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.scheduleChunkGenerationTask(leastStatus, this.chunkMap);
-- }
++
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(
+ chunkX, chunkZ, leastStatus, true,
+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER,
@@ -25352,7 +25414,7 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
}
@Override
-@@ -323,16 +338,7 @@ public class ServerChunkCache extends ChunkSource {
+@@ -335,16 +350,7 @@ public class ServerChunkCache extends ChunkSource {
}
public boolean runDistanceManagerUpdates() { // Paper - public
@@ -25370,13 +25432,17 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
}
// Paper start
-@@ -342,13 +348,14 @@ public class ServerChunkCache extends ChunkSource {
+@@ -354,17 +360,14 @@ public class ServerChunkCache extends ChunkSource {
// Paper end
public boolean isPositionTicking(long pos) {
-- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos);
+- if (!this.level.shouldTickBlocksAt(pos)) {
+- return false;
+- } else {
+- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos);
-
-- return playerchunk == null ? false : (!this.level.shouldTickBlocksAt(pos) ? false : ((ChunkResult) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).isSuccess());
+- return playerchunk == null ? false : ((ChunkResult) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).isSuccess();
+- }
+ // Paper start - rewrite chunk system
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder newChunkHolder = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(pos);
+ return newChunkHolder != null && newChunkHolder.isTickingReady();
@@ -25389,14 +25455,16 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings
this.chunkMap.saveAllChunks(flush);
} // Paper - Timings
-@@ -361,16 +368,12 @@ public class ServerChunkCache extends ChunkSource {
+@@ -377,17 +380,15 @@ public class ServerChunkCache extends ChunkSource {
}
public void close(boolean save) throws IOException {
- if (save) {
- this.save(true);
- }
-- // CraftBukkit end
+ // CraftBukkit end
++ // Paper - rewrite chunk system
+ this.dataStorage.close();
- this.lightEngine.close();
- this.chunkMap.close();
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.close(save, true); // Paper - rewrite chunk system
@@ -25405,114 +25473,18 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
// CraftBukkit start - modelled on below
public void purgeUnload() {
+ if (true) return; // Paper - rewrite chunk system
- this.level.getProfiler().push("purge");
- this.distanceManager.purgeStaleTickets();
- this.runDistanceManagerUpdates();
-@@ -394,6 +397,7 @@ public class ServerChunkCache extends ChunkSource {
- this.level.getProfiler().popPush("chunks");
+ ProfilerFiller gameprofilerfiller = Profiler.get();
+
+ gameprofilerfiller.push("purge");
+@@ -415,6 +416,7 @@ public class ServerChunkCache extends ChunkSource {
+ gameprofilerfiller.popPush("chunks");
if (tickChunks) {
this.level.timings.chunks.startTiming(); // Paper - timings
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getPlayerChunkLoader().tick(); // Paper - rewrite chunk system
this.tickChunks();
this.level.timings.chunks.stopTiming(); // Paper - timings
this.chunkMap.tick();
-@@ -408,6 +412,7 @@ public class ServerChunkCache extends ChunkSource {
- }
-
- private void tickChunks() {
-+ long chunksTicked = 0; // Paper - rewrite chunk system
- long i = this.level.getGameTime();
- long j = i - this.lastInhabitedUpdate;
-
-@@ -417,18 +422,29 @@ public class ServerChunkCache extends ChunkSource {
-
- gameprofilerfiller.push("pollingChunks");
- gameprofilerfiller.push("filteringLoadedChunks");
-- List<ServerChunkCache.ChunkAndHolder> list = Lists.newArrayListWithCapacity(this.chunkMap.size());
-- Iterator iterator = this.chunkMap.getChunks().iterator();
-- if (this.level.getServer().tickRateManager().runsNormally()) this.level.timings.chunkTicks.startTiming(); // Paper
-+ // Paper start - chunk tick iteration optimisations
-+ List<ServerChunkCache.ChunkAndHolder> list;
-+ {
-+ final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.server.level.ServerChunkCache.ChunkAndHolder> tickingChunks =
-+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel) this.level).moonrise$getTickingChunks();
-
-- while (iterator.hasNext()) {
-- ChunkHolder playerchunk = (ChunkHolder) iterator.next();
-- LevelChunk chunk = playerchunk.getTickingChunk();
-+ final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked();
-+ final int size = tickingChunks.size();
-
-- if (chunk != null) {
-- list.add(new ServerChunkCache.ChunkAndHolder(chunk, playerchunk));
-+ if (this.iterationCopy == null || this.iterationCopy.length < size) {
-+ this.iterationCopy = new ServerChunkCache.ChunkAndHolder[raw.length];
- }
-+ System.arraycopy(raw, 0, this.iterationCopy, 0, size);
-+
-+ list = it.unimi.dsi.fastutil.objects.ObjectArrayList.wrap(
-+ this.iterationCopy, size
-+ );
- }
-+ // Paper end - chunk tick iteration optimisations
-+ Iterator iterator = null; // Paper - chunk tick iteration optimisations
-+ if (this.level.getServer().tickRateManager().runsNormally()) this.level.timings.chunkTicks.startTiming(); // Paper
-+
-+ // Paper - chunk tick iteration optimisations
-
- if (this.level.tickRateManager().runsNormally()) {
- gameprofilerfiller.popPush("naturalSpawnCount");
-@@ -460,14 +476,19 @@ public class ServerChunkCache extends ChunkSource {
- LevelChunk chunk1 = chunkproviderserver_a.chunk;
- ChunkPos chunkcoordintpair = chunk1.getPos();
-
-- if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) {
-+ if (true && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { // Paper - rewrite chunk system
- chunk1.incrementInhabitedTime(j);
- if (flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot
- NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
- }
-
-- if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) {
-+ if (true) { // Paper - rewrite chunk system
- this.level.tickChunk(chunk1, l);
-+ // Paper start - rewrite chunk system
-+ if ((++chunksTicked & 7L) == 0L) {
-+ ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks();
-+ }
-+ // Paper end - rewrite chunk system
- }
- }
- }
-@@ -482,22 +503,35 @@ public class ServerChunkCache extends ChunkSource {
- }
-
- gameprofilerfiller.popPush("broadcast");
-- list.forEach((chunkproviderserver_a1) -> {
-- this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
-- chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk);
-- this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
-- });
-+ // Paper start - chunk tick iteration optimisations
-+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
-+ {
-+ final it.unimi.dsi.fastutil.objects.ObjectArrayList<net.minecraft.server.level.ServerChunkCache.ChunkAndHolder> chunks = (it.unimi.dsi.fastutil.objects.ObjectArrayList<net.minecraft.server.level.ServerChunkCache.ChunkAndHolder>)list;
-+ final ServerChunkCache.ChunkAndHolder[] raw = chunks.elements();
-+ final int size = chunks.size();
-+
-+ Objects.checkFromToIndex(0, size, raw.length);
-+ for (int idx = 0; idx < size; ++idx) {
-+ final ServerChunkCache.ChunkAndHolder holder = raw[idx];
-+ raw[idx] = null;
-+
-+ holder.holder().broadcastChanges(holder.chunk());
-+ }
-+ }
-+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
-+ // Paper end - chunk tick iteration optimisations
- gameprofilerfiller.pop();
- gameprofilerfiller.pop();
- }
+@@ -546,11 +548,12 @@ public class ServerChunkCache extends ChunkSource {
}
private void getFullChunk(long pos, Consumer<LevelChunk> chunkConsumer) {
@@ -25529,7 +25501,7 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
}
-@@ -591,6 +625,12 @@ public class ServerChunkCache extends ChunkSource {
+@@ -644,6 +647,12 @@ public class ServerChunkCache extends ChunkSource {
this.chunkMap.setServerViewDistance(watchDistance);
}
@@ -25542,7 +25514,7 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
public void setSimulationDistance(int simulationDistance) {
this.distanceManager.updateSimulationDistance(simulationDistance);
}
-@@ -669,21 +709,19 @@ public class ServerChunkCache extends ChunkSource {
+@@ -735,21 +744,19 @@ public class ServerChunkCache extends ChunkSource {
@Override
// CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
public boolean pollTask() {
@@ -25571,10 +25543,10 @@ index 60f678c26fb5144386d8697ddfd5b6d841563b6f..9ccb3ffc375298fda4dca97803e65e39
}
}
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
-index 1d849ce4e2c85f149af25318b8ffb6dcef6c6788..12d86f27d04bffed8c3844e36b42fbc2f84dacff 100644
+index bc0f1aa61e68d2a8638d89c10bc5c71922d057f9..79c88b315481fe70f037bae834f2b07277cabcda 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
-@@ -97,6 +97,11 @@ public class ServerEntity {
+@@ -101,6 +101,11 @@ public class ServerEntity {
}
public void sendChanges() {
@@ -25587,28 +25559,28 @@ index 1d849ce4e2c85f149af25318b8ffb6dcef6c6788..12d86f27d04bffed8c3844e36b42fbc2
if (!list.equals(this.lastPassengers)) {
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd941126a0b0f4 100644
+index 509a67aff07bcdcad47eb77e923d442349a4f20c..af27a004f618912d6a5f1d2c82c8e7e9fb00a037 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -184,7 +184,7 @@ import org.bukkit.event.weather.LightningStrikeEvent;
+@@ -187,7 +187,7 @@ import org.bukkit.event.weather.LightningStrikeEvent;
import org.bukkit.event.world.TimeSkipEvent;
// CraftBukkit end
--public class ServerLevel extends Level implements WorldGenLevel {
-+public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevelReader { // Paper - rewrite chunk system
+-public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLevel {
++public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevelReader { // Paper - rewrite chunk system
public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0);
public static final IntProvider RAIN_DELAY = UniformInt.of(12000, 180000);
-@@ -200,7 +200,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -203,7 +203,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final PrimaryLevelData serverLevelData; // CraftBukkit - type
private int lastSpawnChunkRadius;
- final EntityTickList entityTickList;
+ final EntityTickList entityTickList = new EntityTickList();
- public final PersistentEntitySectionManager<Entity> entityManager;
+ // Paper - rewrite chunk system
private final GameEventDispatcher gameEventDispatcher;
public boolean noSave;
private final SleepStatus sleepStatus;
-@@ -271,15 +271,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -274,15 +274,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final void loadChunksForMoveAsync(AABB axisalignedbb, ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority priority,
java.util.function.Consumer<List<net.minecraft.world.level.chunk.ChunkAccess>> onLoad) {
@@ -25625,7 +25597,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
int minBlockX = Mth.floor(axisalignedbb.minX - 1.0E-7D) - 3;
int maxBlockX = Mth.floor(axisalignedbb.maxX + 1.0E-7D) + 3;
-@@ -292,30 +284,160 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -295,30 +287,160 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
int minChunkZ = minBlockZ >> 4;
int maxChunkZ = maxBlockZ >> 4;
@@ -25800,7 +25772,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
}
}
-@@ -323,22 +445,46 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -326,22 +448,46 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
for (int cx = minChunkX; cx <= maxChunkX; ++cx) {
for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) {
@@ -25857,7 +25829,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
// Add env and gen to constructor, IWorldDataServer -> WorldDataServer
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey<Level> resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List<CustomSpawner> list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
-@@ -385,14 +531,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -375,14 +521,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
DataFixer datafixer = minecraftserver.getFixerUpper();
EntityPersistentStorage<Entity> entitypersistentstorage = new EntityStorage(new SimpleRegionStorage(new RegionStorageInfo(convertable_conversionsession.getLevelId(), resourcekey, "entities"), convertable_conversionsession.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, DataFixTypes.ENTITY_CHUNK), this, minecraftserver);
@@ -25875,7 +25847,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
return minecraftserver.overworld().getDataStorage();
});
this.chunkSource.getGeneratorState().ensureStructuresGenerated();
-@@ -420,6 +565,19 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -410,6 +555,19 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> {
return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences");
});
@@ -25895,16 +25867,16 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
}
-@@ -553,7 +711,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -542,7 +700,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
gameprofilerfiller.push("checkDespawn");
entity.checkDespawn();
gameprofilerfiller.pop();
-- if (this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) {
-+ if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - rewrite chunk system
+- if (entity instanceof ServerPlayer || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) {
++ if (true) { // Paper - rewrite chunk system
Entity entity1 = entity.getVehicle();
if (entity1 != null) {
-@@ -578,13 +736,16 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -567,13 +725,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
gameprofilerfiller.push("entityManagement");
@@ -25923,7 +25895,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
protected void tickTime() {
-@@ -626,6 +787,63 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -613,6 +774,63 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
});
}
@@ -25987,7 +25959,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
ChunkPos chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
-@@ -675,35 +893,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -662,35 +880,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
gameprofilerfiller.popPush("tickBlocks");
timings.chunkTicksBlocks.startTiming(); // Paper
if (randomTickSpeed > 0) {
@@ -26024,9 +25996,9 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
timings.chunkTicksBlocks.stopTiming(); // Paper
-@@ -976,6 +1166,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -964,6 +1154,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (fluid1.is(fluid)) {
- fluid1.tick(this, pos);
+ fluid1.tick(this, pos, iblockdata);
}
+ // Paper start - rewrite chunk system
+ if ((++this.tickedBlocksOrFluids & 7L) != 0L) {
@@ -26036,7 +26008,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
-@@ -985,6 +1180,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -973,6 +1168,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (iblockdata.is(block)) {
iblockdata.tick(this, pos, this.random);
}
@@ -26048,7 +26020,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
-@@ -1061,6 +1261,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1049,6 +1249,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
public void save(@Nullable ProgressListener progressListener, boolean flush, boolean savingDisabled) {
@@ -26060,7 +26032,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
ServerChunkCache chunkproviderserver = this.getChunkSource();
if (!savingDisabled) {
-@@ -1076,16 +1281,21 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1064,16 +1269,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
timings.worldSaveChunks.startTiming(); // Paper
@@ -26088,7 +26060,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
// CraftBukkit start - moved from MinecraftServer.saveChunks
ServerLevel worldserver1 = this;
-@@ -1218,7 +1428,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1213,7 +1423,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.removePlayerImmediately((ServerPlayer) entity, Entity.RemovalReason.DISCARDED);
}
@@ -26097,7 +26069,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
// CraftBukkit start
-@@ -1249,7 +1459,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1243,7 +1453,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
// CraftBukkit end
@@ -26106,7 +26078,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
}
-@@ -1260,11 +1470,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1254,11 +1464,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
// CraftBukkit end
@@ -26119,7 +26091,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
return false;
} else {
this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit
-@@ -1852,7 +2058,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1891,7 +2097,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
}
@@ -26128,7 +26100,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
bufferedwriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size()));
bufferedwriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count()));
bufferedwriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count()));
-@@ -1901,7 +2107,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1940,7 +2146,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
BufferedWriter bufferedwriter2 = Files.newBufferedWriter(path1);
try {
@@ -26137,7 +26109,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
} catch (Throwable throwable4) {
if (bufferedwriter2 != null) {
try {
-@@ -1922,7 +2128,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1961,7 +2167,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
BufferedWriter bufferedwriter3 = Files.newBufferedWriter(path2);
try {
@@ -26146,7 +26118,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
} catch (Throwable throwable6) {
if (bufferedwriter3 != null) {
try {
-@@ -2064,7 +2270,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2103,7 +2309,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@VisibleForTesting
public String getWatchdogStats() {
@@ -26155,7 +26127,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString();
}), this.blockEntityTickers.size(), ServerLevel.getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType), this.getBlockTicks().count(), this.getFluidTicks().count(), this.gatherChunkSourceStats());
}
-@@ -2094,15 +2300,25 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2133,15 +2339,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public LevelEntityGetter<Entity> getEntities() {
org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
@@ -26184,7 +26156,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
public void startTickingChunk(LevelChunk chunk) {
-@@ -2122,34 +2338,47 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2161,34 +2377,47 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@Override
public void close() throws IOException {
super.close();
@@ -26239,7 +26211,7 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
}
@Override
-@@ -2175,7 +2404,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2234,7 +2463,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
CrashReportCategory crashreportsystemdetails = super.fillReportDetails(report);
crashreportsystemdetails.setDetail("Loaded entity count", () -> {
@@ -26249,10 +26221,10 @@ index 342682178950c8986fb3c86924811089f4de887d..f910e37a8e7cd0358c149d84bafd9411
return crashreportsystemdetails;
}
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 62ec627e80b87a92a2a51ba9fc3626a67636855f..30f53916a9e49165bcfef2bea2c0b50a26f5a8a3 100644
+index 1a7d2ade0e85dd5e6cd6c9202e3277cc2fa43d4a..ba15c34a3ea516d2d946d923551293ac05118926 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -200,7 +200,7 @@ import org.bukkit.event.player.PlayerToggleSneakEvent;
+@@ -218,7 +218,7 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.MainHand;
// CraftBukkit end
@@ -26261,7 +26233,7 @@ index 62ec627e80b87a92a2a51ba9fc3626a67636855f..30f53916a9e49165bcfef2bea2c0b50a
private static final Logger LOGGER = LogUtils.getLogger();
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
-@@ -297,6 +297,36 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
+@@ -324,6 +324,36 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
public @Nullable String clientBrandName = null; // Paper - Brand support
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
@@ -26299,10 +26271,10 @@ index 62ec627e80b87a92a2a51ba9fc3626a67636855f..30f53916a9e49165bcfef2bea2c0b50a
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
this.chatVisibility = ChatVisiblity.FULL;
diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
-index 63fae619e9b4ed49585f88ea7c167b0ee5efd859..cc779de06773451d51f54040fc899e4f45110bc1 100644
+index 39d34f3728ae8d845d1bffc09f3ab8b64eb4d48b..653ba7bb4f4793d7a7cad903e9695ff49666985f 100644
--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java
-@@ -23,15 +23,128 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
+@@ -22,23 +22,135 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
import net.minecraft.world.level.lighting.LevelLightEngine;
import org.slf4j.Logger;
@@ -26310,11 +26282,11 @@ index 63fae619e9b4ed49585f88ea7c167b0ee5efd859..cc779de06773451d51f54040fc899e4f
+public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCloseable, ca.spottedleaf.moonrise.patches.starlight.light.StarLightLightingProvider { // Paper - rewrite chunk system
public static final int DEFAULT_BATCH_SIZE = 1000;
private static final Logger LOGGER = LogUtils.getLogger();
-- private final ProcessorMailbox<Runnable> taskMailbox;
+- private final ConsecutiveExecutor consecutiveExecutor;
- private final ObjectList<Pair<ThreadedLevelLightEngine.TaskType, Runnable>> lightTasks = new ObjectArrayList<>();
+ // Paper - rewrite chunk sytem
private final ChunkMap chunkMap;
-- private final ProcessorHandle<ChunkTaskPriorityQueueSorter.Message<Runnable>> sorterMailbox;
+- private final ChunkTaskDispatcher taskDispatcher;
+ // Paper - rewrite chunk sytem
private final int taskPerBatch = 1000;
- private final AtomicBoolean scheduled = new AtomicBoolean();
@@ -26435,18 +26407,17 @@ index 63fae619e9b4ed49585f88ea7c167b0ee5efd859..cc779de06773451d51f54040fc899e4f
+ // Paper end - rewrite chunk system
public ThreadedLevelLightEngine(
- LightChunkGetter chunkProvider,
-@@ -42,8 +155,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
+ LightChunkGetter chunkProvider, ChunkMap chunkLoadingManager, boolean hasBlockLight, ConsecutiveExecutor processor, ChunkTaskDispatcher executor
) {
super(chunkProvider, true, hasBlockLight);
this.chunkMap = chunkLoadingManager;
-- this.sorterMailbox = executor;
-- this.taskMailbox = processor;
+- this.taskDispatcher = executor;
+- this.consecutiveExecutor = processor;
+ // Paper - rewrite chunk sytem
}
@Override
-@@ -57,164 +169,73 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
+@@ -52,164 +164,73 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl
@Override
public void checkBlock(BlockPos pos) {
@@ -26475,7 +26446,7 @@ index 63fae619e9b4ed49585f88ea7c167b0ee5efd859..cc779de06773451d51f54040fc899e4f
- super.queueSectionData(LightLayer.SKY, SectionPos.of(pos, i), null);
- }
-
-- for (int j = this.levelHeightAccessor.getMinSection(); j < this.levelHeightAccessor.getMaxSection(); j++) {
+- for (int j = this.levelHeightAccessor.getMinSectionY(); j <= this.levelHeightAccessor.getMaxSectionY(); j++) {
- super.updateSectionStatus(SectionPos.of(pos, j), true);
- }
- }, () -> "updateChunkStatus " + pos + " true"));
@@ -26538,12 +26509,12 @@ index 63fae619e9b4ed49585f88ea7c167b0ee5efd859..cc779de06773451d51f54040fc899e4f
}
private void addTask(int x, int z, IntSupplier completedLevelSupplier, ThreadedLevelLightEngine.TaskType stage, Runnable task) {
-- this.sorterMailbox.tell(ChunkTaskPriorityQueueSorter.message(() -> {
+- this.taskDispatcher.submit(() -> {
- this.lightTasks.add(Pair.of(stage, task));
- if (this.lightTasks.size() >= 1000) {
- this.runUpdate();
- }
-- }, ChunkPos.asLong(x, z), completedLevelSupplier));
+- }, ChunkPos.asLong(x, z), completedLevelSupplier);
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system
}
@@ -26593,7 +26564,7 @@ index 63fae619e9b4ed49585f88ea7c167b0ee5efd859..cc779de06773451d51f54040fc899e4f
public void tryScheduleUpdate() {
- if ((!this.lightTasks.isEmpty() || super.hasLightWork()) && this.scheduled.compareAndSet(false, true)) {
-- this.taskMailbox.tell(() -> {
+- this.consecutiveExecutor.schedule(() -> {
- this.runUpdate();
- this.scheduled.set(false);
- });
@@ -26691,7 +26662,7 @@ index eba83b085435150e5954fd5d41dda9ce1d0601ad..daf543b51d8875b374688957ae4bc466
}
}
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
-index b26a4a38144ec1b171db911bbf949b53ed35708f..5a8a33638ceb1d980ffc3e6dd86e7eb11dfd9375 100644
+index 2e72e92762877b28dd908711671e1dfb933de9b0..a1bfd9d9bf992c5516290ca9aabe12ab037faa18 100644
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
@@ -85,6 +85,36 @@ public class WorldGenRegion implements WorldGenLevel {
@@ -26948,19 +26919,19 @@ index 50040c497a819cd1229042ab3cb057d34a32cacc..15c5164d0ef41a978c16ee317fa73e97
+ // Paper end - block counting
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b641c42394 100644
+index 8cdef637f6343119fc77f87e7478ee23e9b8efab..5410a0380c44629f1c9b4f0a8e6017cfc5a31a89 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -167,7 +167,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
+@@ -175,7 +175,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.plugin.PluginManager;
// CraftBukkit end
--public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, CommandSource, ScoreHolder {
-+public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, CommandSource, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
+-public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder {
++public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
-@@ -455,6 +455,97 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -445,6 +445,97 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return this.dimensions.makeBoundingBox(x, y, z);
}
// Paper end
@@ -27058,7 +27029,7 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
public Entity(EntityType<?> type, Level world) {
this.id = Entity.ENTITY_COUNTER.incrementAndGet();
-@@ -1278,41 +1369,82 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -1303,41 +1394,82 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
private Vec3 collide(Vec3 movement) {
@@ -27168,7 +27139,7 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
}
private static float[] collectCandidateStepUpHeights(AABB collisionBox, List<VoxelShape> collisions, float f, float stepHeight) {
-@@ -2628,18 +2760,75 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -2699,18 +2831,75 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public boolean isInWall() {
@@ -27184,13 +27155,13 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
- BlockState iblockdata = this.level().getBlockState(blockposition);
+ final float reducedWith = this.dimensions.width() * 0.8F;
+ final AABB box = AABB.ofSize(this.getEyePosition(), reducedWith, 1.0E-6D, reducedWith);
-+
-+ if (ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isEmpty(box)) {
-+ return false;
-+ }
- return !iblockdata.isAir() && iblockdata.isSuffocating(this.level(), blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level(), blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND);
- });
++ if (ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isEmpty(box)) {
++ return false;
++ }
++
+ final BlockPos.MutableBlockPos tempPos = new BlockPos.MutableBlockPos();
+
+ final int minX = Mth.floor(box.minX);
@@ -27251,7 +27222,7 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
}
public InteractionResult interact(Player player, InteractionHand hand) {
-@@ -4026,14 +4215,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4180,14 +4369,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public Iterable<Entity> getIndirectPassengers() {
@@ -27276,7 +27247,7 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
}
private Iterable<Entity> getIndirectPassengers_old() {
// Paper end - Optimize indirect passenger iteration
-@@ -4398,6 +4590,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4543,6 +4735,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.setPosRaw(x, y, z, false);
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@@ -27292,7 +27263,7 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
if (!checkPosition(this, x, y, z)) {
return;
}
-@@ -4529,6 +4730,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4672,6 +4873,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Override
public final void setRemoved(Entity.RemovalReason entity_removalreason, EntityRemoveEvent.Cause cause) {
@@ -27304,17 +27275,17 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
+ // Paper end - rewrite chunk system
CraftEventFactory.callEntityRemoveEvent(this, cause);
// CraftBukkit end
- final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
-@@ -4540,7 +4747,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+ if (this.removalReason == null) {
+@@ -4682,7 +4889,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stopRiding();
}
- this.getPassengers().forEach(Entity::stopRiding);
+ if (this.removalReason != Entity.RemovalReason.UNLOADED_TO_CHUNK) { this.getPassengers().forEach(Entity::stopRiding); } // Paper - rewrite chunk system
this.levelCallback.onRemove(entity_removalreason);
- // Paper start - Folia schedulers
- if (!(this instanceof ServerPlayer) && entity_removalreason != RemovalReason.CHANGED_DIMENSION && !alreadyRemoved) {
-@@ -4571,7 +4778,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+ this.onRemoval(entity_removalreason);
+ }
+@@ -4698,7 +4905,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Override
public boolean shouldBeSaved() {
@@ -27324,15 +27295,15 @@ index 76e9d34e5219fbae0095cf735b58833c29343573..6fe90b281c95062c0be14650c00b21b6
@Override
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 fb63036d26d2b5370472b741b23bebd71e247463..d7a6eab60bf26916f78f858e224573560e581fef 100644
+index 96bc0ba60195e5e666d47b3a0b943b733986d96a..4cf6cb0abfeb7065c6d9381fb4194371c0cddc35 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
-@@ -38,12 +38,153 @@ import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
+@@ -38,12 +38,130 @@ import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
import net.minecraft.world.level.chunk.storage.SectionStorage;
import net.minecraft.world.level.chunk.storage.SimpleRegionStorage;
--public class PoiManager extends SectionStorage<PoiSection> {
-+public class PoiManager extends SectionStorage<PoiSection> implements ca.spottedleaf.moonrise.patches.chunk_system.level.poi.ChunkSystemPoiManager { // Paper - rewrite chunk system
+-public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> {
++public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> implements ca.spottedleaf.moonrise.patches.chunk_system.level.poi.ChunkSystemPoiManager { // Paper - rewrite chunk system
public static final int MAX_VILLAGE_DISTANCE = 6;
public static final int VILLAGE_SECTION_SIZE = 1;
private final PoiManager.DistanceTracker distanceTracker;
@@ -27454,35 +27425,12 @@ index fb63036d26d2b5370472b741b23bebd71e247463..d7a6eab60bf26916f78f858e22457356
+ this.checkConsistencyWithBlocks(SectionPos.of(chunkX, section, chunkZ), sections[section - minY]);
+ }
+ }
-+
-+ @Override
-+ public final void moonrise$close() throws java.io.IOException {}
-+
-+ @Override
-+ public final net.minecraft.nbt.CompoundTag moonrise$read(final int chunkX, final int chunkZ) throws java.io.IOException {
-+ if (!ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.isRegionFileThread()) {
-+ return ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.loadData(
-+ this.world, chunkX, chunkZ, ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.RegionFileType.POI_DATA,
-+ ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.getIOBlockingPriorityForCurrentThread()
-+ );
-+ }
-+ return this.moonrise$getRegionStorage().read(new ChunkPos(chunkX, chunkZ));
-+ }
-+
-+ @Override
-+ public final void moonrise$write(final int chunkX, final int chunkZ, final net.minecraft.nbt.CompoundTag data) throws java.io.IOException {
-+ if (!ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.isRegionFileThread()) {
-+ ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.scheduleSave(this.world, chunkX, chunkZ, data, ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.RegionFileType.POI_DATA);
-+ return;
-+ }
-+ this.moonrise$getRegionStorage().write(new ChunkPos(chunkX, chunkZ), data);
-+ }
+ // Paper end - rewrite chunk system
+
public PoiManager(
RegionStorageInfo storageKey,
Path directory,
-@@ -62,6 +203,7 @@ public class PoiManager extends SectionStorage<PoiSection> {
+@@ -64,6 +182,7 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> {
world
);
this.distanceTracker = new PoiManager.DistanceTracker();
@@ -27490,7 +27438,7 @@ index fb63036d26d2b5370472b741b23bebd71e247463..d7a6eab60bf26916f78f858e22457356
}
public void add(BlockPos pos, Holder<PoiType> type) {
-@@ -195,8 +337,8 @@ public class PoiManager extends SectionStorage<PoiSection> {
+@@ -197,8 +316,8 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> {
}
public int sectionsToVillage(SectionPos pos) {
@@ -27501,7 +27449,7 @@ index fb63036d26d2b5370472b741b23bebd71e247463..d7a6eab60bf26916f78f858e22457356
}
boolean isVillageCenter(long pos) {
-@@ -210,19 +352,26 @@ public class PoiManager extends SectionStorage<PoiSection> {
+@@ -212,19 +331,26 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> {
@Override
public void tick(BooleanSupplier shouldKeepTicking) {
@@ -27534,7 +27482,7 @@ index fb63036d26d2b5370472b741b23bebd71e247463..d7a6eab60bf26916f78f858e22457356
}
public void checkConsistencyWithBlocks(SectionPos sectionPos, LevelChunkSection chunkSection) {
-@@ -259,7 +408,7 @@ public class PoiManager extends SectionStorage<PoiSection> {
+@@ -263,7 +389,7 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> {
.map(sectionPos -> Pair.of(sectionPos, this.getOrLoad(sectionPos.asLong())))
.filter(pair -> !pair.getSecond().map(PoiSection::isValid).orElse(false))
.map(pair -> pair.getFirst().chunk())
@@ -27544,10 +27492,10 @@ index fb63036d26d2b5370472b741b23bebd71e247463..d7a6eab60bf26916f78f858e22457356
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
-index 971fb29a2c3dc713cb8ab1d2eed054cc16f9c93c..a6c0e89cb645693034f8e90ac2de8f2da457453c 100644
+index b9e0bc8f1e948614d986335de1f3d2df199eea81..f6f0d7c21ee81ff33d4af350c4d39aadfbe140df 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
-@@ -23,7 +23,7 @@ import net.minecraft.core.SectionPos;
+@@ -23,13 +23,27 @@ import net.minecraft.core.SectionPos;
import net.minecraft.util.VisibleForDebug;
import org.slf4j.Logger;
@@ -27556,9 +27504,8 @@ index 971fb29a2c3dc713cb8ab1d2eed054cc16f9c93c..a6c0e89cb645693034f8e90ac2de8f2d
private static final Logger LOGGER = LogUtils.getLogger();
private final Short2ObjectMap<PoiRecord> records = new Short2ObjectOpenHashMap<>();
private final Map<Holder<PoiType>, Set<PoiRecord>> byType = Maps.newHashMap();
-@@ -42,6 +42,20 @@ public class PoiSection {
- .orElseGet(Util.prefix("Failed to read POI section: ", LOGGER::error), () -> new PoiSection(updateListener, false, ImmutableList.of()));
- }
+ private final Runnable setDirty;
+ private boolean isValid;
+ // Paper start - rewrite chunk system
+ private final Optional<PoiSection> noAllocOptional = Optional.of((PoiSection)(Object)this);;
@@ -27578,10 +27525,10 @@ index 971fb29a2c3dc713cb8ab1d2eed054cc16f9c93c..a6c0e89cb645693034f8e90ac2de8f2d
this(updateListener, true, ImmutableList.of());
}
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
-index 2f398750bfee5758ad8b1367b6fc14364e4de776..c292f58ba4b29395484dbbf8591e455f449581d8 100644
+index 2bb2b36f793d25b6e49d1a72bb665cfa9f212730..1362c33ca9ec524372b03c890385888ca6cfe2b0 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
-@@ -359,7 +359,7 @@ public class ArmorStand extends LivingEntity {
+@@ -364,7 +364,7 @@ public class ArmorStand extends LivingEntity {
@Override
protected void pushEntities() {
if (!this.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return; // Paper - Option to prevent armor stands from doing entity lookups
@@ -27604,10 +27551,10 @@ index 3fa2964b979053ecbefc946c7fe76828de86d8f1..28bf0518f7d17099d7e4990defbeda67
public ClipContext(Vec3 start, Vec3 end, ClipContext.Block shapeType, ClipContext.Fluid fluidHandling, Entity entity) {
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
-index bd20bea7f76a7307f1698fb2dfef37125032d166..141b748abe80402731cdaf14a3d36aa7cef4f4bd 100644
+index e185a33b5b1f8e8e0a0e666b24ba3e9186a8a7ff..5d7a6e4b73f032db356e7ec369b150013e940ee6 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
-@@ -18,7 +18,7 @@ import net.minecraft.world.phys.shapes.BooleanOp;
+@@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
@@ -27616,7 +27563,7 @@ index bd20bea7f76a7307f1698fb2dfef37125032d166..141b748abe80402731cdaf14a3d36aa7
List<Entity> getEntities(@Nullable Entity except, AABB box, Predicate<? super Entity> predicate);
<T extends Entity> List<T> getEntities(EntityTypeTest<Entity, T> filter, AABB box, Predicate<? super T> predicate);
-@@ -33,21 +33,44 @@ public interface EntityGetter {
+@@ -30,21 +30,44 @@ public interface EntityGetter {
return this.getEntities(except, box, EntitySelector.NO_SPECTATORS);
}
@@ -27672,7 +27619,7 @@ index bd20bea7f76a7307f1698fb2dfef37125032d166..141b748abe80402731cdaf14a3d36aa7
}
default <T extends Entity> List<T> getEntitiesOfClass(Class<T> entityClass, AABB box) {
-@@ -55,23 +78,41 @@ public interface EntityGetter {
+@@ -52,23 +75,41 @@ public interface EntityGetter {
}
default List<VoxelShape> getEntityCollisions(@Nullable Entity entity, AABB box) {
@@ -27727,503 +27674,11 @@ index bd20bea7f76a7307f1698fb2dfef37125032d166..141b748abe80402731cdaf14a3d36aa7
}
// Paper start - Affects Spawning API
-diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
-index 2109257fde8606abda4f41427f690da3b96c0175..f696afd7e241bf1966a2d505b5d59bff824b43e4 100644
---- a/src/main/java/net/minecraft/world/level/Explosion.java
-+++ b/src/main/java/net/minecraft/world/level/Explosion.java
-@@ -76,6 +76,247 @@ public class Explosion {
- // CraftBukkit end
- public boolean excludeSourceFromDamage = true; // Paper - Allow explosions to damage source
-
-+ // Paper start - optimise collisions
-+ private static final double[] CACHED_RAYS;
-+ static {
-+ final it.unimi.dsi.fastutil.doubles.DoubleArrayList rayCoords = new it.unimi.dsi.fastutil.doubles.DoubleArrayList();
-+
-+ for (int x = 0; x <= 15; ++x) {
-+ for (int y = 0; y <= 15; ++y) {
-+ for (int z = 0; z <= 15; ++z) {
-+ if ((x == 0 || x == 15) || (y == 0 || y == 15) || (z == 0 || z == 15)) {
-+ double xDir = (double)((float)x / 15.0F * 2.0F - 1.0F);
-+ double yDir = (double)((float)y / 15.0F * 2.0F - 1.0F);
-+ double zDir = (double)((float)z / 15.0F * 2.0F - 1.0F);
-+
-+ double mag = Math.sqrt(
-+ xDir * xDir + yDir * yDir + zDir * zDir
-+ );
-+
-+ rayCoords.add((xDir / mag) * (double)0.3F);
-+ rayCoords.add((yDir / mag) * (double)0.3F);
-+ rayCoords.add((zDir / mag) * (double)0.3F);
-+ }
-+ }
-+ }
-+ }
-+
-+ CACHED_RAYS = rayCoords.toDoubleArray();
-+ }
-+
-+ private static final int CHUNK_CACHE_SHIFT = 2;
-+ private static final int CHUNK_CACHE_MASK = (1 << CHUNK_CACHE_SHIFT) - 1;
-+ private static final int CHUNK_CACHE_WIDTH = 1 << CHUNK_CACHE_SHIFT;
-+
-+ private static final int BLOCK_EXPLOSION_CACHE_SHIFT = 3;
-+ private static final int BLOCK_EXPLOSION_CACHE_MASK = (1 << BLOCK_EXPLOSION_CACHE_SHIFT) - 1;
-+ private static final int BLOCK_EXPLOSION_CACHE_WIDTH = 1 << BLOCK_EXPLOSION_CACHE_SHIFT;
-+
-+ // resistance = (res + 0.3F) * 0.3F;
-+ // so for resistance = 0, we need res = -0.3F
-+ private static final Float ZERO_RESISTANCE = Float.valueOf(-0.3f);
-+ private it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache> blockCache = null;
-+ private long[] chunkPosCache = null;
-+ private net.minecraft.world.level.chunk.LevelChunk[] chunkCache = null;
-+ private ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache getOrCacheExplosionBlock(final int x, final int y, final int z,
-+ final long key, final boolean calculateResistance) {
-+ ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache ret = this.blockCache.get(key);
-+ if (ret != null) {
-+ return ret;
-+ }
-+
-+ BlockPos pos = new BlockPos(x, y, z);
-+
-+ if (!this.level.isInWorldBounds(pos)) {
-+ ret = new ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache(key, pos, null, null, 0.0f, true);
-+ } else {
-+ net.minecraft.world.level.chunk.LevelChunk chunk;
-+ long chunkKey = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(x >> 4, z >> 4);
-+ int chunkCacheKey = ((x >> 4) & CHUNK_CACHE_MASK) | (((z >> 4) << CHUNK_CACHE_SHIFT) & (CHUNK_CACHE_MASK << CHUNK_CACHE_SHIFT));
-+ if (this.chunkPosCache[chunkCacheKey] == chunkKey) {
-+ chunk = this.chunkCache[chunkCacheKey];
-+ } else {
-+ this.chunkPosCache[chunkCacheKey] = chunkKey;
-+ this.chunkCache[chunkCacheKey] = chunk = this.level.getChunk(x >> 4, z >> 4);
-+ }
-+
-+ BlockState blockState = ((ca.spottedleaf.moonrise.patches.chunk_getblock.GetBlockChunk)chunk).moonrise$getBlock(x, y, z);
-+ FluidState fluidState = blockState.getFluidState();
-+
-+ Optional<Float> resistance = !calculateResistance ? Optional.empty() : this.damageCalculator.getBlockExplosionResistance((Explosion)(Object)this, this.level, pos, blockState, fluidState);
-+
-+ ret = new ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache(
-+ key, pos, blockState, fluidState,
-+ (resistance.orElse(ZERO_RESISTANCE).floatValue() + 0.3f) * 0.3f,
-+ false
-+ );
-+ }
-+
-+ this.blockCache.put(key, ret);
-+
-+ return ret;
-+ }
-+
-+ private boolean clipsAnything(final Vec3 from, final Vec3 to,
-+ final ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.LazyEntityCollisionContext context,
-+ final ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache[] blockCache,
-+ final BlockPos.MutableBlockPos currPos) {
-+ // assume that context.delegated = false
-+ final double adjX = ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON * (from.x - to.x);
-+ final double adjY = ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON * (from.y - to.y);
-+ final double adjZ = ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON * (from.z - to.z);
-+
-+ if (adjX == 0.0 && adjY == 0.0 && adjZ == 0.0) {
-+ return false;
-+ }
-+
-+ final double toXAdj = to.x - adjX;
-+ final double toYAdj = to.y - adjY;
-+ final double toZAdj = to.z - adjZ;
-+ final double fromXAdj = from.x + adjX;
-+ final double fromYAdj = from.y + adjY;
-+ final double fromZAdj = from.z + adjZ;
-+
-+ int currX = Mth.floor(fromXAdj);
-+ int currY = Mth.floor(fromYAdj);
-+ int currZ = Mth.floor(fromZAdj);
-+
-+ final double diffX = toXAdj - fromXAdj;
-+ final double diffY = toYAdj - fromYAdj;
-+ final double diffZ = toZAdj - fromZAdj;
-+
-+ final double dxDouble = Math.signum(diffX);
-+ final double dyDouble = Math.signum(diffY);
-+ final double dzDouble = Math.signum(diffZ);
-+
-+ final int dx = (int)dxDouble;
-+ final int dy = (int)dyDouble;
-+ final int dz = (int)dzDouble;
-+
-+ final double normalizedDiffX = diffX == 0.0 ? Double.MAX_VALUE : dxDouble / diffX;
-+ final double normalizedDiffY = diffY == 0.0 ? Double.MAX_VALUE : dyDouble / diffY;
-+ final double normalizedDiffZ = diffZ == 0.0 ? Double.MAX_VALUE : dzDouble / diffZ;
-+
-+ double normalizedCurrX = normalizedDiffX * (diffX > 0.0 ? (1.0 - Mth.frac(fromXAdj)) : Mth.frac(fromXAdj));
-+ double normalizedCurrY = normalizedDiffY * (diffY > 0.0 ? (1.0 - Mth.frac(fromYAdj)) : Mth.frac(fromYAdj));
-+ double normalizedCurrZ = normalizedDiffZ * (diffZ > 0.0 ? (1.0 - Mth.frac(fromZAdj)) : Mth.frac(fromZAdj));
-+
-+ for (;;) {
-+ currPos.set(currX, currY, currZ);
-+
-+ // ClipContext.Block.COLLIDER -> BlockBehaviour.BlockStateBase::getCollisionShape
-+ // ClipContext.Fluid.NONE -> ignore fluids
-+
-+ // read block from cache
-+ final long key = BlockPos.asLong(currX, currY, currZ);
-+
-+ final int cacheKey =
-+ (currX & BLOCK_EXPLOSION_CACHE_MASK) |
-+ (currY & BLOCK_EXPLOSION_CACHE_MASK) << (BLOCK_EXPLOSION_CACHE_SHIFT) |
-+ (currZ & BLOCK_EXPLOSION_CACHE_MASK) << (BLOCK_EXPLOSION_CACHE_SHIFT + BLOCK_EXPLOSION_CACHE_SHIFT);
-+ ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache cachedBlock = blockCache[cacheKey];
-+ if (cachedBlock == null || cachedBlock.key != key) {
-+ blockCache[cacheKey] = cachedBlock = this.getOrCacheExplosionBlock(currX, currY, currZ, key, false);
-+ }
-+
-+ final BlockState blockState = cachedBlock.blockState;
-+ if (blockState != null && !((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)blockState).moonrise$emptyCollisionShape()) {
-+ net.minecraft.world.phys.shapes.VoxelShape collision = cachedBlock.cachedCollisionShape;
-+ if (collision == null) {
-+ collision = ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)blockState).moonrise$getConstantCollisionShape();
-+ if (collision == null) {
-+ collision = blockState.getCollisionShape(this.level, currPos, context);
-+ if (!context.isDelegated()) {
-+ // if it was not delegated during this call, assume that for any future ones it will not be delegated
-+ // again, and cache the result
-+ cachedBlock.cachedCollisionShape = collision;
-+ }
-+ } else {
-+ cachedBlock.cachedCollisionShape = collision;
-+ }
-+ }
-+
-+ if (!collision.isEmpty() && collision.clip(from, to, currPos) != null) {
-+ return true;
-+ }
-+ }
-+
-+ if (normalizedCurrX > 1.0 && normalizedCurrY > 1.0 && normalizedCurrZ > 1.0) {
-+ return false;
-+ }
-+
-+ // inc the smallest normalized coordinate
-+
-+ if (normalizedCurrX < normalizedCurrY) {
-+ if (normalizedCurrX < normalizedCurrZ) {
-+ currX += dx;
-+ normalizedCurrX += normalizedDiffX;
-+ } else {
-+ // x < y && x >= z <--> z < y && z <= x
-+ currZ += dz;
-+ normalizedCurrZ += normalizedDiffZ;
-+ }
-+ } else if (normalizedCurrY < normalizedCurrZ) {
-+ // y <= x && y < z
-+ currY += dy;
-+ normalizedCurrY += normalizedDiffY;
-+ } else {
-+ // y <= x && z <= y <--> z <= y && z <= x
-+ currZ += dz;
-+ normalizedCurrZ += normalizedDiffZ;
-+ }
-+ }
-+ }
-+
-+ private float getSeenFraction(final Vec3 source, final Entity target,
-+ final ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache[] blockCache,
-+ final BlockPos.MutableBlockPos blockPos) {
-+ final AABB boundingBox = target.getBoundingBox();
-+ final double diffX = boundingBox.maxX - boundingBox.minX;
-+ final double diffY = boundingBox.maxY - boundingBox.minY;
-+ final double diffZ = boundingBox.maxZ - boundingBox.minZ;
-+
-+ final double incX = 1.0 / (diffX * 2.0 + 1.0);
-+ final double incY = 1.0 / (diffY * 2.0 + 1.0);
-+ final double incZ = 1.0 / (diffZ * 2.0 + 1.0);
-+
-+ if (incX < 0.0 || incY < 0.0 || incZ < 0.0) {
-+ return 0.0f;
-+ }
-+
-+ final double offX = (1.0 - Math.floor(1.0 / incX) * incX) * 0.5 + boundingBox.minX;
-+ final double offY = boundingBox.minY;
-+ final double offZ = (1.0 - Math.floor(1.0 / incZ) * incZ) * 0.5 + boundingBox.minZ;
-+
-+ final ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.LazyEntityCollisionContext context = new ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.LazyEntityCollisionContext(target);
-+
-+ int totalRays = 0;
-+ int missedRays = 0;
-+
-+ for (double dx = 0.0; dx <= 1.0; dx += incX) {
-+ final double fromX = Math.fma(dx, diffX, offX);
-+ for (double dy = 0.0; dy <= 1.0; dy += incY) {
-+ final double fromY = Math.fma(dy, diffY, offY);
-+ for (double dz = 0.0; dz <= 1.0; dz += incZ) {
-+ ++totalRays;
-+
-+ final Vec3 from = new Vec3(
-+ fromX,
-+ fromY,
-+ Math.fma(dz, diffZ, offZ)
-+ );
-+
-+ if (!this.clipsAnything(from, source, context, blockCache, blockPos)) {
-+ ++missedRays;
-+ }
-+ }
-+ }
-+ }
-+
-+ return (float)missedRays / (float)totalRays;
-+ }
-+ // Paper end - optimise collisions
-+
- public static DamageSource getDefaultDamageSource(Level world, @Nullable Entity source) {
- return world.damageSources().explosion(source, Explosion.getIndirectSourceEntityInternal(source));
- }
-@@ -168,68 +409,107 @@ public class Explosion {
- }
- // CraftBukkit end
- this.level.gameEvent(this.source, (Holder) GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z));
-- Set<BlockPos> set = Sets.newHashSet();
-+
-+ // Paper start - collision optimisations
-+ this.blockCache = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>();
-+
-+ this.chunkPosCache = new long[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH];
-+ java.util.Arrays.fill(this.chunkPosCache, ChunkPos.INVALID_CHUNK_POS);
-+
-+ this.chunkCache = new net.minecraft.world.level.chunk.LevelChunk[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH];
-+
-+ final ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache[] blockCache = new ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache[BLOCK_EXPLOSION_CACHE_WIDTH * BLOCK_EXPLOSION_CACHE_WIDTH * BLOCK_EXPLOSION_CACHE_WIDTH];
-+
-+ // use initial cache value that is most likely to be used: the source position
-+ final ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache initialCache;
-+ {
-+ final int blockX = Mth.floor(this.x);
-+ final int blockY = Mth.floor(this.y);
-+ final int blockZ = Mth.floor(this.z);
-+
-+ final long key = BlockPos.asLong(blockX, blockY, blockZ);
-+
-+ initialCache = this.getOrCacheExplosionBlock(blockX, blockY, blockZ, key, true);
-+ }
-+ // Paper end - collision optimisations
-+
- boolean flag = true;
-
- int i;
- int j;
-
-- for (int k = 0; k < 16; ++k) {
-- for (i = 0; i < 16; ++i) {
-- for (j = 0; j < 16; ++j) {
-- if (k == 0 || k == 15 || i == 0 || i == 15 || j == 0 || j == 15) {
-- double d0 = (double) ((float) k / 15.0F * 2.0F - 1.0F);
-- double d1 = (double) ((float) i / 15.0F * 2.0F - 1.0F);
-- double d2 = (double) ((float) j / 15.0F * 2.0F - 1.0F);
-- double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
--
-- d0 /= d3;
-- d1 /= d3;
-- d2 /= d3;
-- float f = this.radius * (0.7F + this.level.random.nextFloat() * 0.6F);
-- double d4 = this.x;
-- double d5 = this.y;
-- double d6 = this.z;
--
-- for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
-- BlockPos blockposition = BlockPos.containing(d4, d5, d6);
-- BlockState iblockdata = this.level.getBlockState(blockposition);
-- if (!iblockdata.isDestroyable()) continue; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
-- FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: Optimize call to getFluid for explosions
--
-- if (!this.level.isInWorldBounds(blockposition)) {
-- break;
-+ // Paper start - collision optimisations
-+ for (int ray = 0, len = CACHED_RAYS.length; ray < len;) {
-+ ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache cachedBlock = initialCache;
-+
-+ double currX = this.x;
-+ double currY = this.y;
-+ double currZ = this.z;
-+
-+ final double incX = CACHED_RAYS[ray];
-+ final double incY = CACHED_RAYS[ray + 1];
-+ final double incZ = CACHED_RAYS[ray + 2];
-+
-+ ray += 3;
-+ float power = this.radius * (0.7F + this.level.random.nextFloat() * 0.6F);
-+ do {
-+ final int blockX = Mth.floor(currX);
-+ final int blockY = Mth.floor(currY);
-+ final int blockZ = Mth.floor(currZ);
-+
-+ final long key = BlockPos.asLong(blockX, blockY, blockZ);
-+
-+ if (cachedBlock.key != key) {
-+ final int cacheKey =
-+ (blockX & BLOCK_EXPLOSION_CACHE_MASK) |
-+ (blockY & BLOCK_EXPLOSION_CACHE_MASK) << (BLOCK_EXPLOSION_CACHE_SHIFT) |
-+ (blockZ & BLOCK_EXPLOSION_CACHE_MASK) << (BLOCK_EXPLOSION_CACHE_SHIFT + BLOCK_EXPLOSION_CACHE_SHIFT);
-+ cachedBlock = blockCache[cacheKey];
-+ if (cachedBlock == null || cachedBlock.key != key) {
-+ blockCache[cacheKey] = cachedBlock = this.getOrCacheExplosionBlock(blockX, blockY, blockZ, key, true);
-+ }
- }
-
-- Optional<Float> optional = this.damageCalculator.getBlockExplosionResistance(this, this.level, blockposition, iblockdata, fluid);
--
-- if (optional.isPresent()) {
-- f -= ((Float) optional.get() + 0.3F) * 0.3F;
-+ if (cachedBlock.outOfWorld) {
-+ break;
- }
--
-- if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f)) {
-- set.add(blockposition);
-- // Paper start - prevent headless pistons from forming
-- if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) {
-- net.minecraft.world.level.block.entity.BlockEntity extension = this.level.getBlockEntity(blockposition);
-- if (extension instanceof net.minecraft.world.level.block.piston.PistonMovingBlockEntity blockEntity && blockEntity.isSourcePiston()) {
-- net.minecraft.core.Direction direction = iblockdata.getValue(net.minecraft.world.level.block.piston.PistonHeadBlock.FACING);
-- set.add(blockposition.relative(direction.getOpposite()));
-+ // Paper end - collision optimisations
-+ BlockState iblockdata = cachedBlock.blockState; // Paper - optimise collisions
-+ // Paper - collision optimisations
-+
-+ // Paper start - collision optimisations
-+ power -= cachedBlock.resistance;
-+
-+ if (power > 0.0f && cachedBlock.shouldExplode == null && iblockdata.isDestroyable()) { // Paper - Protect Bedrock and End Portal/Frames from being destroyed
-+ // note: we expect shouldBlockExplode to be pure with respect to power, as Vanilla currently is.
-+ // basically, it is unused, which allows us to cache the result
-+ final boolean shouldExplode = this.damageCalculator.shouldBlockExplode((Explosion)(Object)this, this.level, cachedBlock.immutablePos, cachedBlock.blockState, power);
-+ cachedBlock.shouldExplode = shouldExplode ? Boolean.TRUE : Boolean.FALSE;
-+ if (shouldExplode) {
-+ if (this.fire || !cachedBlock.blockState.isAir()) {
-+ this.toBlow.add(cachedBlock.immutablePos);
-+ // Paper start - prevent headless pistons from forming
-+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) {
-+ net.minecraft.world.level.block.entity.BlockEntity extension = this.level.getBlockEntity(cachedBlock.immutablePos); // Paper - optimise collisions
-+ if (extension instanceof net.minecraft.world.level.block.piston.PistonMovingBlockEntity blockEntity && blockEntity.isSourcePiston()) {
-+ net.minecraft.core.Direction direction = iblockdata.getValue(net.minecraft.world.level.block.piston.PistonHeadBlock.FACING);
-+ this.toBlow.add(cachedBlock.immutablePos.relative(direction.getOpposite())); // Paper - optimise collisions
-+ }
-+ }
-+ // Paper end - prevent headless pistons from forming
- }
- }
-- // Paper end - prevent headless pistons from forming
- }
-
-- d4 += d0 * 0.30000001192092896D;
-- d5 += d1 * 0.30000001192092896D;
-- d6 += d2 * 0.30000001192092896D;
-- }
-+ power -= 0.22500001F;
-+ currX += incX;
-+ currY += incY;
-+ currZ += incZ;
-+ } while (power > 0.0f);
-+ // Paper end - collision optimisations
- }
-- }
-- }
-- }
-
-- this.toBlow.addAll(set);
-+ // Paper - optimise collisions
- float f2 = this.radius * 2.0F;
-
- i = Mth.floor(this.x - (double) f2 - 1.0D);
-@@ -242,6 +522,10 @@ public class Explosion {
- Vec3 vec3d = new Vec3(this.x, this.y, this.z);
- Iterator iterator = list.iterator();
-
-+ // Paper start - optimise collisions
-+ final BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos();
-+ // Paper end - optimise collisions
-+
- while (iterator.hasNext()) {
- Entity entity = (Entity) iterator.next();
-
-@@ -258,6 +542,7 @@ public class Explosion {
- d8 /= d11;
- d9 /= d11;
- d10 /= d11;
-+ final double seenFraction; // Paper - optimise collisions
- if (this.damageCalculator.shouldDamageEntity(this, entity)) {
- // CraftBukkit start
-
-@@ -273,6 +558,8 @@ public class Explosion {
-
- entity.lastDamageCancelled = false;
-
-+ seenFraction = (double)this.getBlockDensity(vec3d, entity, blockCache, blockPos); // Paper - optimise collisions
-+
- if (entity instanceof EnderDragon) {
- for (EnderDragonPart entityComplexPart : ((EnderDragon) entity).subEntities) {
- // Calculate damage separately for each EntityComplexPart
-@@ -281,16 +568,21 @@ public class Explosion {
- }
- }
- } else {
-- entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity));
-+ // Paper start - optimise collisions
-+ // inline getEntityDamageAmount so that we can avoid double calling getSeenPercent, which is the MOST
-+ // expensive part of this loop!!!!
-+ final double factor = (1.0 - d7) * seenFraction;
-+ entity.hurt(this.damageSource, (float)((factor * factor + factor) / 2.0 * 7.0 * (double)f2 + 1.0));
-+ // Paper end - optimise collisions
- }
-
- if (entity.lastDamageCancelled) { // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Skip entity if damage event was cancelled
- continue;
- }
- // CraftBukkit end
-- }
-+ } else { seenFraction = (double)this.getBlockDensity(vec3d, entity, blockCache, blockPos); } // Paper - optimise collisions
-
-- double d12 = (1.0D - d7) * this.getBlockDensity(vec3d, entity) * (double) this.damageCalculator.getKnockbackMultiplier(entity); // Paper - Optimize explosions
-+ double d12 = (1.0D - d7) * seenFraction * (double) this.damageCalculator.getKnockbackMultiplier(entity); // Paper - Optimize explosions // Paper - optimise collisions
- double d13;
-
- if (entity instanceof LivingEntity) {
-@@ -328,7 +620,11 @@ public class Explosion {
- }
- }
- }
--
-+ // Paper start - optimise collisions
-+ this.blockCache = null;
-+ this.chunkPosCache = null;
-+ this.chunkCache = null;
-+ // Paper end - optimise collisions
- }
-
- public void finalizeExplosion(boolean particles) {
-@@ -545,14 +841,14 @@ public class Explosion {
- private BlockInteraction() {}
- }
- // Paper start - Optimize explosions
-- private float getBlockDensity(Vec3 vec3d, Entity entity) {
-+ private float getBlockDensity(Vec3 vec3d, Entity entity, ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache[] blockCache, BlockPos.MutableBlockPos blockPos) { // Paper - optimise collisions
- if (!this.level.paperConfig().environment.optimizeExplosions) {
-- return getSeenPercent(vec3d, entity);
-+ return this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise collisions
- }
- CacheKey key = new CacheKey(this, entity.getBoundingBox());
- Float blockDensity = this.level.explosionDensityCache.get(key);
- if (blockDensity == null) {
-- blockDensity = getSeenPercent(vec3d, entity);
-+ blockDensity = this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise collisions
- this.level.explosionDensityCache.put(key, blockDensity);
- }
-
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869a618497c 100644
+index d048d0e4b16459b5bad44ebfa3c6a8f336f6762b..332dc7e6bdfb5b3741764d4877185a2e86a982f8 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -81,6 +81,7 @@ import net.minecraft.world.level.storage.LevelData;
+@@ -83,6 +83,7 @@ import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.level.storage.WritableLevelData;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
@@ -28231,7 +27686,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
import net.minecraft.world.scores.Scoreboard;
// CraftBukkit start
-@@ -102,7 +103,7 @@ import org.bukkit.entity.SpawnCategory;
+@@ -104,7 +105,7 @@ import org.bukkit.entity.SpawnCategory;
import org.bukkit.event.block.BlockPhysicsEvent;
// CraftBukkit end
@@ -28240,7 +27695,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
public static final Codec<ResourceKey<Level>> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION);
public static final ResourceKey<Level> OVERWORLD = ResourceKey.create(Registries.DIMENSION, ResourceLocation.withDefaultNamespace("overworld"));
-@@ -199,6 +200,483 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -190,6 +191,483 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public abstract ResourceKey<LevelStem> getTypeKey();
@@ -28721,10 +28176,10 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
+ }
+ // Paper end - optimise random ticking
+
- protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator) { // Paper - create paper world config
+ protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, Holder<DimensionType> holder, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator) { // Paper - create paper world config
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
-@@ -281,6 +759,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -271,6 +749,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
this.timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings
this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime);
this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime);
@@ -28736,7 +28191,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
}
// Paper start - Cancel hit for vanished players
-@@ -549,7 +1032,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -535,7 +1018,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
this.setBlocksDirty(blockposition, iblockdata1, iblockdata2);
}
@@ -28745,7 +28200,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i);
}
-@@ -813,6 +1296,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -800,6 +1283,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Iterator<TickingBlockEntity> iterator = this.blockEntityTickers.iterator();
boolean flag = this.tickRateManager().runsNormally();
@@ -28754,7 +28209,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
int tilesThisCycle = 0;
var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<TickingBlockEntity>(); // Paper - Fix MC-117075; use removeAll
toRemove.add(null); // Paper - Fix MC-117075
-@@ -828,6 +1313,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -815,6 +1300,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Spigot end
} else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) {
tickingblockentity.tick();
@@ -28766,7 +28221,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
}
}
this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075
-@@ -850,12 +1340,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -837,12 +1327,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
// Paper end - Prevent block entity and entity crashes
}
@@ -28788,7 +28243,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
}
// Paper end - Option to prevent armor stands from doing entity lookups
-@@ -966,7 +1464,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -894,7 +1392,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
// Paper end - Perf: Optimize capturedTileEntities lookup
// CraftBukkit end
@@ -28797,24 +28252,22 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
}
public void setBlockEntity(BlockEntity blockEntity) {
-@@ -1056,28 +1554,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
- @Override
- public List<Entity> getEntities(@Nullable Entity except, AABB box, Predicate<? super Entity> predicate) {
- this.getProfiler().incrementCounter("getEntities");
-- List<Entity> list = Lists.newArrayList();
-+ // Paper start - rewrite chunk system
-+ final List<Entity> ret = new java.util.ArrayList<>();
+@@ -986,26 +1484,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ Profiler.get().incrementCounter("getEntities");
+ List<Entity> list = Lists.newArrayList();
- this.getEntities().get(box, (entity1) -> {
- if (entity1 != except && predicate.test(entity1)) {
- list.add(entity1);
- }
-+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)this).moonrise$getEntityLookup().getEntities(except, box, ret, predicate);
++ // Paper start - rewrite chunk system
++ final List<Entity> ret = new java.util.ArrayList<>();
- if (entity1 instanceof EnderDragon) {
- EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity1).getSubEntities();
- int i = aentitycomplexpart.length;
--
++ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)this).moonrise$getEntityLookup().getEntities(except, box, ret, predicate);
+
- for (int j = 0; j < i; ++j) {
- EnderDragonPart entitycomplexpart = aentitycomplexpart[j];
-
@@ -28831,22 +28284,23 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
}
@Override
-@@ -1092,36 +1575,77 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1020,36 +1505,77 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
this.getEntities(filter, box, predicate, result, Integer.MAX_VALUE);
}
- public <T extends Entity> void getEntities(EntityTypeTest<Entity, T> filter, AABB box, Predicate<? super T> predicate, List<? super T> result, int limit) {
-+ // Paper start - rewrite chunk system
-+ public <T extends Entity> void getEntities(final EntityTypeTest<Entity, T> entityTypeTest,
-+ final AABB boundingBox, final Predicate<? super T> predicate,
-+ final List<? super T> into, final int maxCount) {
- this.getProfiler().incrementCounter("getEntities");
+- Profiler.get().incrementCounter("getEntities");
- this.getEntities().get(filter, box, (entity) -> {
- if (predicate.test(entity)) {
- result.add(entity);
- if (result.size() >= limit) {
- return AbortableIterationConsumer.Continuation.ABORT;
- }
++ // Paper start - rewrite chunk system
++ public <T extends Entity> void getEntities(final EntityTypeTest<Entity, T> entityTypeTest,
++ final AABB boundingBox, final Predicate<? super T> predicate,
++ final List<? super T> into, final int maxCount) {
++ this.getProfiler().incrementCounter("getEntities");
+
+ if (entityTypeTest instanceof net.minecraft.world.entity.EntityType<T> byType) {
+ if (maxCount != Integer.MAX_VALUE) {
@@ -28931,7 +28385,7 @@ index 16e721ac80ba21511bdeccfccd055f7700bda61f..7a592a3c5491fc19ab33287e1e60b869
@Nullable
public abstract Entity getEntity(int id);
diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.java
-index a0ae26d6197e1069ca09982b4f8b706c55ae8491..1a4dc4b2561dbaf01246b4fb46266b1ac84008b8 100644
+index 5eb8982678110fabb82a93c5ec67c666b7fde017..ade435de0af4ee3566fa4a490df53cddd2f6531c 100644
--- a/src/main/java/net/minecraft/world/level/LevelReader.java
+++ b/src/main/java/net/minecraft/world/level/LevelReader.java
@@ -22,7 +22,18 @@ import net.minecraft.world.level.dimension.DimensionType;
@@ -28955,20 +28409,20 @@ index a0ae26d6197e1069ca09982b4f8b706c55ae8491..1a4dc4b2561dbaf01246b4fb46266b1a
ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create);
diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java
-index 15f82c9a1ce1fef2e951d1b3c7a65e64b82061ea..90c165c890a2d998e3b0af9b4310e3995ede6f64 100644
+index 8590de51b572c0f73d45aee60313d466e4671da5..b725eea9d3ca81d2ef7802f5d0346d924aa1f808 100644
--- a/src/main/java/net/minecraft/world/level/biome/Biome.java
+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java
-@@ -111,20 +111,7 @@ public final class Biome {
+@@ -112,20 +112,7 @@ public final class Biome {
@Deprecated
- public float getTemperature(BlockPos blockPos) {
+ public float getTemperature(BlockPos blockPos, int seaLevel) {
- long l = blockPos.asLong();
- Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = this.temperatureCache.get();
- float f = long2FloatLinkedOpenHashMap.get(l);
- if (!Float.isNaN(f)) {
- return f;
- } else {
-- float g = this.getHeightAdjustedTemperature(blockPos);
+- float g = this.getHeightAdjustedTemperature(blockPos, seaLevel);
- if (long2FloatLinkedOpenHashMap.size() == 1024) {
- long2FloatLinkedOpenHashMap.removeFirstFloat();
- }
@@ -28976,15 +28430,15 @@ index 15f82c9a1ce1fef2e951d1b3c7a65e64b82061ea..90c165c890a2d998e3b0af9b4310e399
- long2FloatLinkedOpenHashMap.put(l, g);
- return g;
- }
-+ return this.getHeightAdjustedTemperature(blockPos); // Paper - optimise random ticking
++ return this.getHeightAdjustedTemperature(blockPos, seaLevel); // Paper - optimise random ticking
}
public boolean shouldFreeze(LevelReader world, BlockPos blockPos) {
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
-index 3b06c080afebde1d649f05eca0af938ba32931c1..29947de9eb6887f2e61516523ff08d8b581b0f53 100644
+index 4d140bd83ca0e1554afad80ec4fc6186188a79d8..3dd236d39535cfce866eb73673f8d7f1b6dc535c 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
-@@ -279,7 +279,7 @@ public class Block extends BlockBehaviour implements ItemLike {
+@@ -265,7 +265,7 @@ public class Block extends BlockBehaviour implements ItemLike {
}
public static boolean isShapeFullBlock(VoxelShape shape) {
@@ -28994,21 +28448,21 @@ index 3b06c080afebde1d649f05eca0af938ba32931c1..29947de9eb6887f2e61516523ff08d8b
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {}
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 f2036917c5ba9f536087d7ee559704055469730e..d0109633e8bdf109cfc9178963d7b6cf92f8b189 100644
+index 0665ca48fe2f8ab1ce1c0306b11be19b06445f74..a4b4fd83d201fff005c738c84fa5c1bc55d670bd 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
-@@ -763,7 +763,7 @@ public abstract class BlockBehaviour implements FeatureElement {
+@@ -793,7 +793,7 @@ public abstract class BlockBehaviour implements FeatureElement {
boolean test(BlockState state, BlockGetter world, BlockPos pos);
}
- public abstract static class BlockStateBase extends StateHolder<Block, BlockState> {
+ public abstract static class BlockStateBase extends StateHolder<Block, BlockState> implements ca.spottedleaf.moonrise.patches.starlight.blockstate.StarlightAbstractBlockState, ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState { // Paper - rewrite chunk system // Paper - optimise collisions
- private final int lightEmission;
- private final boolean useShapeForLightOcclusion;
-@@ -795,6 +795,76 @@ public abstract class BlockBehaviour implements FeatureElement {
- private FluidState fluidState;
- private boolean isRandomlyTicking;
+ private static final Direction[] DIRECTIONS = Direction.values();
+ private static final VoxelShape[] EMPTY_OCCLUSION_SHAPES = (VoxelShape[]) Util.make(new VoxelShape[BlockBehaviour.BlockStateBase.DIRECTIONS.length], (avoxelshape) -> {
+@@ -837,6 +837,76 @@ public abstract class BlockBehaviour implements FeatureElement {
+ private boolean propagatesSkylightDown;
+ private int lightBlock;
+ // Paper start - rewrite chunk system
+ private int opacityIfCached;
@@ -29083,10 +28537,10 @@ index f2036917c5ba9f536087d7ee559704055469730e..d0109633e8bdf109cfc9178963d7b6cf
protected BlockStateBase(Block block, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<BlockState> codec) {
super(block, propertyMap, codec);
this.fluidState = Fluids.EMPTY.defaultFluidState();
-@@ -859,6 +929,43 @@ public abstract class BlockBehaviour implements FeatureElement {
- this.shapeExceedsCube = this.cache == null || this.cache.largeCollisionShape; // Paper - moved from actual method to here
+@@ -921,6 +991,43 @@ public abstract class BlockBehaviour implements FeatureElement {
- this.legacySolid = this.calculateSolid();
+ this.propagatesSkylightDown = ((Block) this.owner).propagatesSkylightDown(this.asState());
+ this.lightBlock = ((Block) this.owner).getLightBlock(this.asState());
+ // Paper start - rewrite chunk system
+ this.isConditionallyFullOpaque = this.canOcclude & this.useShapeForLightOcclusion;
+ this.opacityIfCached = this.cache == null || this.isConditionallyFullOpaque ? -1 : this.cache.lightBlock;
@@ -29128,19 +28582,19 @@ index f2036917c5ba9f536087d7ee559704055469730e..d0109633e8bdf109cfc9178963d7b6cf
public Block getBlock() {
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
-index db4d95ce98eb1490d5306d1f74b282d27264871a..fba548c4e6d589323ec3ea5f6b269a6fe9faf6a1 100644
+index 37795b9e264c571efe9c718fa9996197dca4ed54..0601f454758cb1447cca2cbff4ef5fd7633fece5 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
-@@ -57,7 +57,7 @@ import net.minecraft.world.ticks.SerializableTickContainer;
+@@ -57,7 +57,7 @@ import net.minecraft.world.ticks.SavedTick;
import net.minecraft.world.ticks.TickContainerAccess;
import org.slf4j.Logger;
--public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiomeSource, LightChunk, StructureAccess {
-+public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiomeSource, LightChunk, StructureAccess, ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk { // Paper - rewrite chunk system
+-public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, LightChunk, StructureAccess {
++public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, LightChunk, StructureAccess, ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk { // Paper - rewrite chunk system
public static final int NO_FILLED_SECTION = -1;
private static final Logger LOGGER = LogUtils.getLogger();
-@@ -77,7 +77,7 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
+@@ -77,7 +77,7 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
@Nullable
protected BlendingData blendingData;
public final Map<Heightmap.Types, Heightmap> heightmaps = Maps.newEnumMap(Heightmap.Types.class);
@@ -29149,7 +28603,7 @@ index db4d95ce98eb1490d5306d1f74b282d27264871a..fba548c4e6d589323ec3ea5f6b269a6f
private final Map<Structure, StructureStart> structureStarts = Maps.newHashMap();
private final Map<Structure, LongSet> structuresRefences = Maps.newHashMap();
protected final Map<BlockPos, CompoundTag> pendingBlockEntities = Maps.newHashMap();
-@@ -90,6 +90,57 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
+@@ -90,6 +90,57 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(ChunkAccess.DATA_TYPE_REGISTRY);
// CraftBukkit end
@@ -29207,7 +28661,7 @@ index db4d95ce98eb1490d5306d1f74b282d27264871a..fba548c4e6d589323ec3ea5f6b269a6f
public ChunkAccess(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor heightLimitView, Registry<Biome> biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] sectionArray, @Nullable BlendingData blendingData) {
this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field lookups
this.chunkPos = pos; this.coordinateKey = ChunkPos.asLong(locX, locZ); // Paper - cache long key
-@@ -99,7 +150,7 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
+@@ -99,7 +150,7 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
this.inhabitedTime = inhabitedTime;
this.postProcessing = new ShortList[heightLimitView.getSectionsCount()];
this.blendingData = blendingData;
@@ -29216,7 +28670,7 @@ index db4d95ce98eb1490d5306d1f74b282d27264871a..fba548c4e6d589323ec3ea5f6b269a6f
if (sectionArray != null) {
if (this.sections.length == sectionArray.length) {
System.arraycopy(sectionArray, 0, this.sections, 0, this.sections.length);
-@@ -111,6 +162,16 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
+@@ -111,6 +162,16 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
ChunkAccess.replaceMissingSections(biomeRegistry, this.sections);
// CraftBukkit start
this.biomeRegistry = biomeRegistry;
@@ -29233,12 +28687,12 @@ index db4d95ce98eb1490d5306d1f74b282d27264871a..fba548c4e6d589323ec3ea5f6b269a6f
}
public final Registry<Biome> biomeRegistry;
// CraftBukkit end
-@@ -442,22 +503,22 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
+@@ -451,22 +512,22 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
@Override
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ) {
- try {
-- int l = QuartPos.fromBlock(this.getMinBuildHeight());
+- int l = QuartPos.fromBlock(this.getMinY());
- int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1;
- int j1 = Mth.clamp(biomeY, l, i1);
- int k1 = this.getSectionIndex(QuartPos.toBlock(j1));
@@ -29271,7 +28725,7 @@ index db4d95ce98eb1490d5306d1f74b282d27264871a..fba548c4e6d589323ec3ea5f6b269a6f
}
// CraftBukkit start
-@@ -514,12 +575,12 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
+@@ -523,12 +584,12 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
}
public void initializeLightSources() {
@@ -29285,21 +28739,21 @@ index db4d95ce98eb1490d5306d1f74b282d27264871a..fba548c4e6d589323ec3ea5f6b269a6f
+ return null; // Paper - rewrite chunk system
}
- public static record TicksToSave(SerializableTickContainer<Block> blocks, SerializableTickContainer<Fluid> fluids) {
+ public static record PackedTicks(List<SavedTick<Block>> blocks, List<SavedTick<Fluid>> fluids) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
-index 29697fad32dad3377eebc82d280ba48d3c1ad516..488938c32a48437721a71d294c77468f00c035b9 100644
+index 906f56d07c26ef3c2dc1a3b62e9349dd91a37742..975abf5948a75c7d0cab8f052af2c4e91bcef2a8 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -119,7 +119,7 @@ public abstract class ChunkGenerator {
- return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("init_biomes", () -> {
+ return CompletableFuture.supplyAsync(() -> {
chunk.fillBiomesFromNoise(this.biomeSource, noiseConfig.sampler());
return chunk;
-- }), Util.backgroundExecutor());
-+ }), Runnable::run); // Paper - rewrite chunk system
+- }, Util.backgroundExecutor().forName("init_biomes"));
++ }, Runnable::run); // Paper - rewrite chunk system
}
- public abstract void applyCarvers(WorldGenRegion chunkRegion, long seed, RandomState noiseConfig, BiomeManager biomeAccess, StructureManager structureAccessor, ChunkAccess chunk, GenerationStep.Carving carverStep);
-@@ -314,7 +314,7 @@ public abstract class ChunkGenerator {
+ public abstract void applyCarvers(WorldGenRegion chunkRegion, long seed, RandomState noiseConfig, BiomeManager biomeAccess, StructureManager structureAccessor, ChunkAccess chunk);
+@@ -311,7 +311,7 @@ public abstract class ChunkGenerator {
return Pair.of(placement.getLocatePos(pos), holder);
}
@@ -29363,10 +28817,10 @@ index dcc0acd259920463a4464213b9a5e793603852f9..ef4161884574d3d137e12591d983dc95
public BlockState getBlockState(BlockPos pos) {
return Blocks.VOID_AIR.defaultBlockState();
diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
-index 365074be989aa4a178114fd5e9810f1a68640196..4af698930712389881601069a921f054c07935f2 100644
+index 7cce66d4c6efe6fd3cc22a6acf72878c964c61ae..30ee3df2278d0d9bd7478b49eda5fff27b8a504c 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java
-@@ -31,7 +31,7 @@ import net.minecraft.world.level.material.FluidState;
+@@ -30,7 +30,7 @@ import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.ticks.BlackholeTickAccess;
import net.minecraft.world.ticks.TickContainerAccess;
@@ -29375,7 +28829,7 @@ index 365074be989aa4a178114fd5e9810f1a68640196..4af698930712389881601069a921f054
private final LevelChunk wrapped;
private final boolean allowWrites;
-@@ -47,6 +47,48 @@ public class ImposterProtoChunk extends ProtoChunk {
+@@ -46,6 +46,48 @@ public class ImposterProtoChunk extends ProtoChunk {
this.allowWrites = propagateToWrapped;
}
@@ -29425,10 +28879,10 @@ index 365074be989aa4a178114fd5e9810f1a68640196..4af698930712389881601069a921f054
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
-index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc901648a4a1 100644
+index 7181acfafad91aa5f6ab7ce663d9be4a1b65b02a..a61294befc2f855fcecb2336a2d5444ce60e0a3a 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
-@@ -53,7 +53,7 @@ import net.minecraft.world.ticks.LevelChunkTicks;
+@@ -54,7 +54,7 @@ import net.minecraft.world.ticks.LevelChunkTicks;
import net.minecraft.world.ticks.TickContainerAccess;
import org.slf4j.Logger;
@@ -29437,7 +28891,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
static final Logger LOGGER = LogUtils.getLogger();
private static final TickingBlockEntity NULL_TICKER = new TickingBlockEntity() {
-@@ -109,6 +109,14 @@ public class LevelChunk extends ChunkAccess {
+@@ -113,6 +113,14 @@ public class LevelChunk extends ChunkAccess {
this.postLoad = entityLoader;
this.blockTicks = blockTickScheduler;
this.fluidTicks = fluidTickScheduler;
@@ -29452,7 +28906,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
}
// CraftBukkit start
-@@ -119,6 +127,39 @@ public class LevelChunk extends ChunkAccess {
+@@ -123,6 +131,39 @@ public class LevelChunk extends ChunkAccess {
// Paper start
boolean loadedTicketLevel;
// Paper end
@@ -29492,14 +28946,14 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
public LevelChunk(ServerLevel world, ProtoChunk protoChunk, @Nullable LevelChunk.PostLoadProcessor entityLoader) {
this(world, protoChunk.getPos(), protoChunk.getUpgradeData(), protoChunk.unpackBlockTicks(), protoChunk.unpackFluidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), entityLoader, protoChunk.getBlendingData());
-@@ -148,13 +189,19 @@ public class LevelChunk extends ChunkAccess {
+@@ -152,13 +193,19 @@ public class LevelChunk extends ChunkAccess {
}
}
- this.skyLightSources = protoChunk.skyLightSources;
+ // Paper - rewrite chunk system
this.setLightCorrect(protoChunk.isLightCorrect());
- this.unsaved = true;
+ this.markUnsaved();
this.needsDecoration = true; // CraftBukkit
// CraftBukkit start
this.persistentDataContainer = protoChunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading.
@@ -29512,9 +28966,9 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
+ // Paper end - rewrite chunk system
}
- @Override
-@@ -337,7 +384,7 @@ public class LevelChunk extends ChunkAccess {
- ProfilerFiller gameprofilerfiller = this.level.getProfiler();
+ public void setUnsavedListener(LevelChunk.UnsavedListener unsavedListener) {
+@@ -361,7 +408,7 @@ public class LevelChunk extends ChunkAccess {
+ ProfilerFiller gameprofilerfiller = Profiler.get();
gameprofilerfiller.push("updateSkyLightSources");
- this.skyLightSources.update(this, j, i, l);
@@ -29522,7 +28976,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
gameprofilerfiller.popPush("queueCheckLight");
this.level.getChunkSource().getLightEngine().checkBlock(blockposition);
gameprofilerfiller.pop();
-@@ -602,11 +649,12 @@ public class LevelChunk extends ChunkAccess {
+@@ -627,11 +674,12 @@ public class LevelChunk extends ChunkAccess {
// CraftBukkit start
public void loadCallback() {
@@ -29536,7 +28990,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
if (server != null) {
/*
* If it's a new world, the first few chunks are generated inside
-@@ -615,6 +663,7 @@ public class LevelChunk extends ChunkAccess {
+@@ -640,6 +688,7 @@ public class LevelChunk extends ChunkAccess {
*/
org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration));
@@ -29544,7 +28998,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
if (this.needsDecoration) {
try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper
-@@ -643,13 +692,15 @@ public class LevelChunk extends ChunkAccess {
+@@ -668,13 +717,15 @@ public class LevelChunk extends ChunkAccess {
}
public void unloadCallback() {
@@ -29562,7 +29016,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
// Paper start
this.loadedTicketLevel = false;
// Paper end
-@@ -657,8 +708,27 @@ public class LevelChunk extends ChunkAccess {
+@@ -682,8 +733,27 @@ public class LevelChunk extends ChunkAccess {
@Override
public boolean isUnsaved() {
@@ -29591,7 +29045,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
// CraftBukkit end
public boolean isEmpty() {
-@@ -764,6 +834,7 @@ public class LevelChunk extends ChunkAccess {
+@@ -791,6 +861,7 @@ public class LevelChunk extends ChunkAccess {
this.pendingBlockEntities.clear();
this.upgradeData.upgrade(this);
@@ -29600,7 +29054,7 @@ index 21946a93b6a2a3c79d15af1d6e7eabc537ba0125..d94e24cfc56c195a47665c212f8fcc90
@Nullable
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
-index 90d1c3e23e753c29660f7d993b3c90ac022941c3..d7b8d984122ba6b6ef5a0be6e012a8828a1af22d 100644
+index 52f44f14bbda60fe771c351e01e6ff470d7371e6..161211124f3f8390530af7ab21f3a0f1025209c5 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -13,7 +13,7 @@ import net.minecraft.world.level.block.Blocks;
@@ -29612,9 +29066,9 @@ index 90d1c3e23e753c29660f7d993b3c90ac022941c3..d7b8d984122ba6b6ef5a0be6e012a882
public static final int SECTION_WIDTH = 16;
public static final int SECTION_HEIGHT = 16;
-@@ -26,6 +26,28 @@ public class LevelChunkSection {
- // CraftBukkit start - read/write
- private PalettedContainer<Holder<Biome>> biomes;
+@@ -25,6 +25,28 @@ public class LevelChunkSection {
+ public final PalettedContainer<BlockState> states;
+ private PalettedContainer<Holder<Biome>> biomes; // CraftBukkit - read/write
+ // Paper start - block counting
+ private static final it.unimi.dsi.fastutil.ints.IntArrayList FULL_LIST = new it.unimi.dsi.fastutil.ints.IntArrayList(16*16*16);
@@ -29638,10 +29092,10 @@ index 90d1c3e23e753c29660f7d993b3c90ac022941c3..d7b8d984122ba6b6ef5a0be6e012a882
+ }
+ // Paper end - block counting
+
- public LevelChunkSection(PalettedContainer<BlockState> datapaletteblock, PalettedContainer<Holder<Biome>> palettedcontainerro) {
- // CraftBukkit end
- this.states = datapaletteblock;
-@@ -92,6 +114,22 @@ public class LevelChunkSection {
+ private LevelChunkSection(LevelChunkSection section) {
+ this.nonEmptyBlockCount = section.nonEmptyBlockCount;
+ this.tickingBlockCount = section.tickingBlockCount;
+@@ -98,6 +120,22 @@ public class LevelChunkSection {
++this.tickingFluidCount;
}
@@ -29664,7 +29118,7 @@ index 90d1c3e23e753c29660f7d993b3c90ac022941c3..d7b8d984122ba6b6ef5a0be6e012a882
return iblockdata1;
}
-@@ -112,40 +150,65 @@ public class LevelChunkSection {
+@@ -118,40 +156,65 @@ public class LevelChunkSection {
}
public void recalcBlockCounts() {
@@ -29751,7 +29205,7 @@ index 90d1c3e23e753c29660f7d993b3c90ac022941c3..d7b8d984122ba6b6ef5a0be6e012a882
}
public PalettedContainer<BlockState> getStates() {
-@@ -163,6 +226,7 @@ public class LevelChunkSection {
+@@ -169,6 +232,7 @@ public class LevelChunkSection {
datapaletteblock.read(buf);
this.biomes = datapaletteblock;
@@ -29760,7 +29214,7 @@ index 90d1c3e23e753c29660f7d993b3c90ac022941c3..d7b8d984122ba6b6ef5a0be6e012a882
public void readBiomes(FriendlyByteBuf buf) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
-index 2fa0097a9374a89177e4f1068d1bfed30b8ff122..339cac6b34b9f2f53852cfcee821bec9e0286c50 100644
+index 112d1259dd37743076ff6c67ffd711d084ba8698..b46c58c952e183bd74854c3eb70d64979af70f18 100644
--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
@@ -28,7 +28,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -29772,7 +29226,7 @@ index 2fa0097a9374a89177e4f1068d1bfed30b8ff122..339cac6b34b9f2f53852cfcee821bec9
private final PalettedContainer.Strategy strategy;
// private final ThreadingDetector threadingDetector = new ThreadingDetector("PalettedContainer"); // Paper - unused
-@@ -155,7 +155,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+@@ -161,7 +161,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
return this.get(this.strategy.getIndex(x, y, z));
}
@@ -29782,13 +29236,13 @@ index 2fa0097a9374a89177e4f1068d1bfed30b8ff122..339cac6b34b9f2f53852cfcee821bec9
return data.palette.valueFor(data.storage.get(index));
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
-index 7f302405a88766c2112539d24d3dd2e513f94985..207dc31afcf5ca5a59ab27ee263aa10f94a79559 100644
+index 5321109ca638036572df9a7e17eafcef2b4f5112..5304254587372465c8ce821d7aa38b39a979f46b 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java
-@@ -143,7 +143,7 @@ public class ProtoChunk extends ChunkAccess {
+@@ -145,7 +145,7 @@ public class ProtoChunk extends ChunkAccess {
}
- if (LightEngine.hasDifferentLightProperties(this, pos, blockState, state)) {
+ if (LightEngine.hasDifferentLightProperties(blockState, state)) {
- this.skyLightSources.update(this, m, j, o);
+ // Paper - rewrite chunk system
this.lightEngine.checkBlock(pos);
@@ -29808,7 +29262,7 @@ index b1058bf0dcda544a074f4d3772d7899b94f98927..b7bf82f6b6023bd628d3e7ea84d2d675
.step(ChunkStatus.FULL, builder -> builder.setTask(ChunkStatusTasks::full))
.build();
diff --git a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatus.java
-index 0baa4adf2a4401f9c955352f27e6f99957d1dff4..3723c07183e7b894cccf4d01bedf1d0d832c1910 100644
+index 4f84ff9cdb3303251e035a12ce9d8b9a0b58f46e..d80b7d555e02d1d4b82945373d383eaedbf4b976 100644
--- a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatus.java
+++ b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatus.java
@@ -11,7 +11,7 @@ import net.minecraft.resources.ResourceLocation;
@@ -29890,11 +29344,11 @@ index 0baa4adf2a4401f9c955352f27e6f99957d1dff4..3723c07183e7b894cccf4d01bedf1d0d
this.chunkType = chunkType;
this.heightmapsAfter = heightMapTypes;
diff --git a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java
-index ae16cf5c803caae636860dd9b1a83abe479ca5a4..b993c4b2595e2879b25753c2e34530f3622c18fa 100644
+index aff4c3d63a97d5bbde004a616f7e14fca59b5ab9..d8dbaecc3c8ef59b0116f0ed4b1c06369b805e1d 100644
--- a/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java
+++ b/src/main/java/net/minecraft/world/level/chunk/status/ChunkStatusTasks.java
-@@ -154,7 +154,7 @@ public class ChunkStatusTasks {
- chunk1 = ((ImposterProtoChunk) protochunk).getWrapped();
+@@ -152,7 +152,7 @@ public class ChunkStatusTasks {
+ chunk1 = protochunkextension.getWrapped();
} else {
chunk1 = new LevelChunk(worldserver, protochunk, ($) -> { // Paper - decompile fix
- ChunkStatusTasks.postLoadProtoChunk(worldserver, protochunk.getEntities());
@@ -29902,16 +29356,16 @@ index ae16cf5c803caae636860dd9b1a83abe479ca5a4..b993c4b2595e2879b25753c2e34530f3
});
generationchunkholder.replaceProtoChunk(new ImposterProtoChunk(chunk1, false));
}
-@@ -175,7 +175,7 @@ public class ChunkStatusTasks {
- });
+@@ -168,7 +168,7 @@ public class ChunkStatusTasks {
+ }, context.mainThreadExecutor());
}
-- private static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities) {
-+ public static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities, ChunkPos pos) { // Paper - public, add ChunkPos param
+- public static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities) { // Paper - public
++ public static void postLoadProtoChunk(ServerLevel world, List<CompoundTag> entities, ChunkPos pos) { // Paper - public // Paper - rewrite chunk system - add ChunkPos param
if (!entities.isEmpty()) {
// CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities
- world.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(entities, world).filter((entity) -> {
-@@ -191,7 +191,7 @@ public class ChunkStatusTasks {
+ world.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(entities, world, EntitySpawnReason.LOAD).filter((entity) -> {
+@@ -180,7 +180,7 @@ public class ChunkStatusTasks {
}
checkDupeUUID(world, entity); // Paper - duplicate uuid resolving
return !needsRemoval;
@@ -30035,128 +29489,8 @@ index f6e08a8334633ff1532616d051bed46b702d0091..4e56398a6fb8b97199f4c74ebebc1055
public static class Builder {
private final ChunkStatus status;
@Nullable
-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 d42585bccb03f8ee1be5e37cfbe8520af4cc5454..cb5196f0ff7b9a59927c60b9d24c987a150e69f1 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
-@@ -165,7 +165,7 @@ public class ChunkSerializer {
- achunksection[k] = chunksection;
- SectionPos sectionposition = SectionPos.of(chunkPos, b0);
-
-- poiStorage.checkConsistencyWithBlocks(sectionposition, chunksection);
-+ // Paper - rewrite chunk system - moved to final load stage
- }
-
- boolean flag3 = nbttagcompound1.contains("BlockLight", 7);
-@@ -287,6 +287,8 @@ public class ChunkSerializer {
- }
- }
-
-+ ca.spottedleaf.moonrise.patches.starlight.util.SaveUtil.loadLightHook(world, chunkPos, nbt, (ChunkAccess)object1); // Paper - rewrite chunk system - note: it's ok to pass the raw value instead of wrapped
-+
- if (chunktype == ChunkType.LEVELCHUNK) {
- return new ImposterProtoChunk((LevelChunk) object1, false);
- } else {
-@@ -341,14 +343,44 @@ public class ChunkSerializer {
- }
- // CraftBukkit end
-
-+ // Paper start - async chunk saving
-+ // must be called sync
-+ public static ca.spottedleaf.moonrise.patches.chunk_system.async_save.AsyncChunkSaveData getAsyncSaveData(ServerLevel world, ChunkAccess chunk) {
-+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(world, chunk.locX, chunk.locZ, "Preparing async chunk save data");
-+
-+ final CompoundTag tickLists = new CompoundTag();
-+ ChunkSerializer.saveTicks(world, tickLists, chunk.getTicksForSerialization());
-+
-+ ListTag blockEntitiesSerialized = new ListTag();
-+ for (final BlockPos blockPos : chunk.getBlockEntitiesPos()) {
-+ final CompoundTag blockEntityNbt = chunk.getBlockEntityNbtForSaving(blockPos, world.registryAccess());
-+ if (blockEntityNbt != null) {
-+ blockEntitiesSerialized.add(blockEntityNbt);
-+ }
-+ }
-+
-+ return new ca.spottedleaf.moonrise.patches.chunk_system.async_save.AsyncChunkSaveData(
-+ tickLists.get(BLOCK_TICKS_TAG),
-+ tickLists.get(FLUID_TICKS_TAG),
-+ blockEntitiesSerialized,
-+ world.getGameTime()
-+ );
-+ }
-+ // Paper end - async chunk saving
-+
- public static CompoundTag write(ServerLevel world, ChunkAccess chunk) {
-+ // Paper start - async chunk saving
-+ return saveChunk(world, chunk, null);
-+ }
-+ public static CompoundTag saveChunk(ServerLevel world, ChunkAccess chunk, ca.spottedleaf.moonrise.patches.chunk_system.async_save.AsyncChunkSaveData asyncsavedata) {
-+ // Paper end - async chunk saving
- ChunkPos chunkcoordintpair = chunk.getPos();
- CompoundTag nbttagcompound = NbtUtils.addCurrentDataVersion(new CompoundTag());
-
- nbttagcompound.putInt("xPos", chunkcoordintpair.x);
- 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 saving
- nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime());
- nbttagcompound.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(chunk.getPersistedStatus()).toString());
- BlendingData blendingdata = chunk.getBlendingData();
-@@ -424,8 +456,17 @@ public class ChunkSerializer {
- nbttagcompound.putBoolean("isLightOn", true);
- }
-
-- ListTag nbttaglist1 = new ListTag();
-- Iterator iterator = chunk.getBlockEntitiesPos().iterator();
-+ // Paper start - async chunk saving
-+ ListTag nbttaglist1;
-+ Iterator<BlockPos> iterator;
-+ if (asyncsavedata != null) {
-+ nbttaglist1 = asyncsavedata.blockEntities();
-+ iterator = java.util.Collections.emptyIterator();
-+ } else {
-+ nbttaglist1 = new ListTag();
-+ iterator = chunk.getBlockEntitiesPos().iterator();
-+ }
-+ // Paper end - async chunk saving
-
- CompoundTag nbttagcompound2;
-
-@@ -461,7 +502,14 @@ public class ChunkSerializer {
- nbttagcompound.put("CarvingMasks", nbttagcompound2);
- }
-
-+ // Paper start
-+ if (asyncsavedata != null) {
-+ nbttagcompound.put(BLOCK_TICKS_TAG, asyncsavedata.blockTickList());
-+ nbttagcompound.put(FLUID_TICKS_TAG, asyncsavedata.fluidTickList());
-+ } else {
- ChunkSerializer.saveTicks(world, nbttagcompound, chunk.getTicksForSerialization());
-+ }
-+ // Paper end
- nbttagcompound.put("PostProcessing", ChunkSerializer.packOffsets(chunk.getPostProcessing()));
- CompoundTag nbttagcompound3 = new CompoundTag();
- Iterator iterator1 = chunk.getHeightmaps().iterator();
-@@ -481,6 +529,7 @@ public class ChunkSerializer {
- nbttagcompound.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound());
- }
- // CraftBukkit end
-+ ca.spottedleaf.moonrise.patches.starlight.util.SaveUtil.saveLightHook(world, chunk, nbttagcompound); // Paper - rewrite chunk system
- return nbttagcompound;
- }
-
-@@ -506,7 +555,7 @@ public class ChunkSerializer {
-
- return nbttaglist == null && nbttaglist1 == null ? null : (chunk) -> {
- if (nbttaglist != null) {
-- world.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(nbttaglist, world));
-+ world.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(nbttaglist, world), chunk.getPos()); // Paper - rewrite chunk system
- }
-
- if (nbttaglist1 != null) {
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 f0f5e9bb5ac65250f0a151f9f90b58468335a8c2..0cdc224656a2baa09b7dfbb249b6a96320ac43e0 100644
+index 092f7b6bba4e1291f76c2c09155f33803e93eb04..82b4638d3c5ec11cdb857dc2defd2113caff7965 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
@@ -28,21 +28,31 @@ import net.minecraft.world.level.dimension.LevelStem;
@@ -30219,12 +29553,12 @@ index f0f5e9bb5ac65250f0a151f9f90b58468335a8c2..0cdc224656a2baa09b7dfbb249b6a963
+ // Paper end - rewrite chunk system
}
- public CompletableFuture<Void> write(ChunkPos chunkPos, CompoundTag nbt) {
-@@ -181,29 +199,54 @@ public class ChunkStorage implements AutoCloseable {
- }
- // Paper end - guard against serializing mismatching coordinates
+ public CompletableFuture<Void> write(ChunkPos chunkPos, Supplier<CompoundTag> nbtSupplier) {
+@@ -185,29 +203,54 @@ public class ChunkStorage implements AutoCloseable {
+ };
+ // Paper end - guard against possible chunk pos desync
this.handleLegacyStructureIndex(chunkPos);
-- return this.worker.store(chunkPos, nbt);
+- return this.worker.store(chunkPos, guardedPosCheck); // Paper - guard against possible chunk pos desync
+ // Paper start - rewrite chunk system
+ try {
+ this.storage.write(chunkPos, nbt);
@@ -30282,10 +29616,10 @@ index f0f5e9bb5ac65250f0a151f9f90b58468335a8c2..0cdc224656a2baa09b7dfbb249b6a963
}
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java
-index 36b8a9ac385e43f3212aca1b1f5bd7115bd00431..503ac0374e0c9f9993ad37bb8bd8cf1570d3615a 100644
+index a0cbccd2cf1ac785745d86c42b6f58fb8bad7ffa..16ca1c8672e5f0a27f8a30498c754a81cdec5191 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java
-@@ -70,12 +70,12 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
+@@ -71,12 +71,12 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
}
}
@@ -30301,16 +29635,16 @@ index 36b8a9ac385e43f3212aca1b1f5bd7115bd00431..503ac0374e0c9f9993ad37bb8bd8cf15
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java
-index 053504cc6c98be3b70bd1722e279d861694e015d..316bf111fe94ce7a71af71cd32c94fcf528d4365 100644
+index cb823d342e41b5861adfc847a313c265fb702a4c..2b1ea97199d5976e5ff4bd049c1e6c8b9b8a4177 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java
-@@ -32,7 +32,7 @@ public class IOWorker implements ChunkScanAccess, AutoCloseable {
+@@ -30,7 +30,7 @@ public class IOWorker implements ChunkScanAccess, AutoCloseable {
private static final Logger LOGGER = LogUtils.getLogger();
private final AtomicBoolean shutdownRequested = new AtomicBoolean();
- private final ProcessorMailbox<StrictQueue.IntRunnable> mailbox;
+ private final PriorityConsecutiveExecutor consecutiveExecutor;
- private final RegionFileStorage storage;
+ public final RegionFileStorage storage; // Paper - public
- private final Map<ChunkPos, IOWorker.PendingStore> pendingWrites = Maps.newLinkedHashMap();
+ private final SequencedMap<ChunkPos, IOWorker.PendingStore> pendingWrites = new LinkedHashMap<>();
private final Long2ObjectLinkedOpenHashMap<CompletableFuture<BitSet>> regionCacheForBlender = new Long2ObjectLinkedOpenHashMap<>();
private static final int REGION_CACHE_SIZE = 1024;
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
@@ -30538,25 +29872,25 @@ index 4c1212c6ef48594e766fa9e35a6e15916602d587..18054304e08c8a6346c0135a0e6a68e7
}
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 092773bd39d77a0dbe22db97c11aecb4a297111c..c7ed3eb80f6e8b918434153093644776866aa220 100644
+index 93972352cd4881dccba9b90ccc8dcced3563e340..c3beb7fcad46a917d2b61bd0a0e98e5106056728 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
-@@ -31,10 +31,10 @@ import net.minecraft.world.level.ChunkPos;
+@@ -40,10 +40,10 @@ import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelHeightAccessor;
import org.slf4j.Logger;
--public class SectionStorage<R> implements AutoCloseable {
-+public abstract class SectionStorage<R> implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.level.storage.ChunkSystemSectionStorage { // Paper - rewrite chunk system
- private static final Logger LOGGER = LogUtils.getLogger();
+-public class SectionStorage<R, P> implements AutoCloseable {
++public class SectionStorage<R, P> implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.level.storage.ChunkSystemSectionStorage { // Paper - rewrite chunk system
+ static final Logger LOGGER = LogUtils.getLogger();
private static final String SECTIONS_TAG = "Sections";
- private final SimpleRegionStorage simpleRegionStorage;
+ // Paper - rewrite chunk system
private final Long2ObjectMap<Optional<R>> storage = new Long2ObjectOpenHashMap<>();
- private final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet();
- private final Function<Runnable, Codec<R>> codec;
-@@ -43,6 +43,15 @@ public class SectionStorage<R> implements AutoCloseable {
- private final ChunkIOErrorReporter errorReporter;
- protected final LevelHeightAccessor levelHeightAccessor;
+ private final LongLinkedOpenHashSet dirtyChunks = new LongLinkedOpenHashSet();
+ private final Codec<P> codec;
+@@ -57,6 +57,18 @@ public class SectionStorage<R, P> implements AutoCloseable {
+ private final Long2ObjectMap<CompletableFuture<Optional<SectionStorage.PackedChunk<P>>>> pendingLoads = new Long2ObjectOpenHashMap<>();
+ private final Object loadLock = new Object();
+ // Paper start - rewrite chunk system
+ private final RegionFileStorage regionStorage;
@@ -30565,19 +29899,24 @@ index 092773bd39d77a0dbe22db97c11aecb4a297111c..c7ed3eb80f6e8b918434153093644776
+ public final RegionFileStorage moonrise$getRegionStorage() {
+ return this.regionStorage;
+ }
++
++ @Override
++ public void moonrise$close() throws IOException {}
+ // Paper end - rewrite chunk system
+
public SectionStorage(
SimpleRegionStorage storageAccess,
- Function<Runnable, Codec<R>> codecFactory,
-@@ -51,12 +60,13 @@ public class SectionStorage<R> implements AutoCloseable {
+ Codec<P> codec,
+@@ -67,7 +79,7 @@ public class SectionStorage<R, P> implements AutoCloseable {
ChunkIOErrorReporter errorHandler,
LevelHeightAccessor world
) {
- this.simpleRegionStorage = storageAccess;
+ // Paper - rewrite chunk system
- this.codec = codecFactory;
- this.factory = factory;
+ this.codec = codec;
+ this.packer = serializer;
+ this.unpacker = deserializer;
+@@ -75,6 +87,7 @@ public class SectionStorage<R, P> implements AutoCloseable {
this.registryAccess = registryManager;
this.errorReporter = errorHandler;
this.levelHeightAccessor = world;
@@ -30585,51 +29924,47 @@ index 092773bd39d77a0dbe22db97c11aecb4a297111c..c7ed3eb80f6e8b918434153093644776
}
protected void tick(BooleanSupplier shouldKeepTicking) {
-@@ -121,44 +131,17 @@ public class SectionStorage<R> implements AutoCloseable {
- }
-
- private CompletableFuture<Optional<CompoundTag>> tryRead(ChunkPos pos) {
-- return this.simpleRegionStorage.read(pos).exceptionally(throwable -> {
-- if (throwable instanceof IOException iOException) {
-- LOGGER.error("Error reading chunk {} data from disk", pos, iOException);
-- this.errorReporter.reportChunkLoadFailure(iOException, this.simpleRegionStorage.storageInfo(), pos);
-- return Optional.empty();
-- } else {
-- throw new CompletionException(throwable);
-- }
-- });
-+ // Paper start - rewrite chunk system
-+ try {
-+ return CompletableFuture.completedFuture(Optional.ofNullable(this.moonrise$read(pos.x, pos.z)));
-+ } catch (final Throwable thr) {
-+ return CompletableFuture.failedFuture(thr);
-+ }
-+ // Paper end - rewrite chunk system
+@@ -188,60 +201,15 @@ public class SectionStorage<R, P> implements AutoCloseable {
+ }
+
+ private CompletableFuture<Optional<SectionStorage.PackedChunk<P>>> tryRead(ChunkPos chunkPos) {
+- RegistryOps<Tag> registryOps = this.registryAccess.createSerializationContext(NbtOps.INSTANCE);
+- return this.simpleRegionStorage
+- .read(chunkPos)
+- .thenApplyAsync(
+- chunkNbt -> chunkNbt.map(
+- nbt -> SectionStorage.PackedChunk.parse(this.codec, registryOps, nbt, this.simpleRegionStorage, this.levelHeightAccessor)
+- ),
+- Util.backgroundExecutor().forName("parseSection")
+- )
+- .exceptionally(throwable -> {
+- if (throwable instanceof IOException iOException) {
+- LOGGER.error("Error reading chunk {} data from disk", chunkPos, iOException);
+- this.errorReporter.reportChunkLoadFailure(iOException, this.simpleRegionStorage.storageInfo(), chunkPos);
+- return Optional.empty();
+- } else {
+- throw new CompletionException(throwable);
+- }
+- });
++ throw new IllegalStateException("Only chunk system can write state, offending class:" + this.getClass().getName()); // Paper - rewrite chunk system
}
- private void readColumn(ChunkPos pos, RegistryOps<Tag> ops, @Nullable CompoundTag nbt) {
-- if (nbt == null) {
-- for (int i = this.levelHeightAccessor.getMinSection(); i < this.levelHeightAccessor.getMaxSection(); i++) {
-- this.storage.put(getKey(pos, i), Optional.empty());
+ private void unpackChunk(ChunkPos chunkPos, @Nullable SectionStorage.PackedChunk<P> result) {
+- if (result == null) {
+- for (int i = this.levelHeightAccessor.getMinSectionY(); i <= this.levelHeightAccessor.getMaxSectionY(); i++) {
+- this.storage.put(getKey(chunkPos, i), Optional.empty());
- }
- } else {
-- Dynamic<Tag> dynamic = new Dynamic<>(ops, nbt);
-- int j = getVersion(dynamic);
-- int k = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
-- boolean bl = j != k;
-- Dynamic<Tag> dynamic2 = this.simpleRegionStorage.upgradeChunkTag(dynamic, j);
-- OptionalDynamic<Tag> optionalDynamic = dynamic2.get("Sections");
--
-- for (int l = this.levelHeightAccessor.getMinSection(); l < this.levelHeightAccessor.getMaxSection(); l++) {
-- long m = getKey(pos, l);
-- Optional<R> optional = optionalDynamic.get(Integer.toString(l))
-- .result()
-- .flatMap(dynamicx -> this.codec.apply(() -> this.setDirty(m)).parse(dynamicx).resultOrPartial(LOGGER::error));
-- this.storage.put(m, optional);
-- optional.ifPresent(sections -> {
-- this.onSectionLoad(m);
+- boolean bl = result.versionChanged();
+-
+- for (int j = this.levelHeightAccessor.getMinSectionY(); j <= this.levelHeightAccessor.getMaxSectionY(); j++) {
+- long l = getKey(chunkPos, j);
+- Optional<R> optional = Optional.ofNullable(result.sectionsByY.get(j)).map(section -> this.unpacker.apply((P)section, () -> this.setDirty(l)));
+- this.storage.put(l, optional);
+- optional.ifPresent(object -> {
+- this.onSectionLoad(l);
- if (bl) {
-- this.setDirty(m);
+- this.setDirty(l);
- }
- });
- }
@@ -30637,26 +29972,23 @@ index 092773bd39d77a0dbe22db97c11aecb4a297111c..c7ed3eb80f6e8b918434153093644776
+ throw new IllegalStateException("Only chunk system can load in state, offending class:" + this.getClass().getName()); // Paper - rewrite chunk system
}
- private void writeColumn(ChunkPos pos) {
-@@ -166,10 +149,13 @@ public class SectionStorage<R> implements AutoCloseable {
- Dynamic<Tag> dynamic = this.writeColumn(pos, registryOps);
- Tag tag = dynamic.getValue();
- if (tag instanceof CompoundTag) {
+ private void writeChunk(ChunkPos pos) {
+- RegistryOps<Tag> registryOps = this.registryAccess.createSerializationContext(NbtOps.INSTANCE);
+- Dynamic<Tag> dynamic = this.writeChunk(pos, registryOps);
+- Tag tag = dynamic.getValue();
+- if (tag instanceof CompoundTag) {
- this.simpleRegionStorage.write(pos, (CompoundTag)tag).exceptionally(throwable -> {
- this.errorReporter.reportChunkSaveFailure(throwable, this.simpleRegionStorage.storageInfo(), pos);
- return null;
- });
-+ // Paper start - rewrite chunk system
-+ try {
-+ this.moonrise$write(pos.x, pos.z, (net.minecraft.nbt.CompoundTag)tag);
-+ } catch (final IOException ex) {
-+ LOGGER.error("Error writing poi chunk data to disk for chunk " + pos, ex);
-+ }
-+ // Paper end - rewrite chunk system
- } else {
- LOGGER.error("Expected compound tag, got {}", tag);
- }
-@@ -209,7 +195,7 @@ public class SectionStorage<R> implements AutoCloseable {
+- } else {
+- LOGGER.error("Expected compound tag, got {}", tag);
+- }
++ throw new IllegalStateException("Only chunk system can write state, offending class:" + this.getClass().getName()); // Paper - rewrite chunk system
+ }
+
+ private <T> Dynamic<T> writeChunk(ChunkPos chunkPos, DynamicOps<T> ops) {
+@@ -277,7 +245,7 @@ public class SectionStorage<R, P> implements AutoCloseable {
protected void onSectionLoad(long pos) {
}
@@ -30664,17 +29996,18 @@ index 092773bd39d77a0dbe22db97c11aecb4a297111c..c7ed3eb80f6e8b918434153093644776
+ public void setDirty(long pos) { // Paper - public
Optional<R> optional = this.storage.get(pos);
if (optional != null && !optional.isEmpty()) {
- this.dirty.add(pos);
-@@ -236,6 +222,6 @@ public class SectionStorage<R> implements AutoCloseable {
+ this.dirtyChunks.add(ChunkPos.asLong(SectionPos.x(pos), SectionPos.z(pos)));
+@@ -298,7 +266,7 @@ public class SectionStorage<R, P> implements AutoCloseable {
@Override
public void close() throws IOException {
- this.simpleRegionStorage.close();
+ this.moonrise$close(); // Paper - rewrite chunk system
}
- }
+
+ static record PackedChunk<T>(Int2ObjectMap<T> sectionsByY, boolean versionChanged) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
-index e0e843f4f69013379ed70cb63d9b4f72163b828b..aafb05c5e63903f5790a6bcb862c8d79588be5a6 100644
+index 578d270d5b7efb9ac8f5dde539170f6021e2b786..c5085ebf4e801837010f3750c5e89576bb0c27a5 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
@@ -14,7 +14,7 @@ import net.minecraft.util.datafix.DataFixTypes;
@@ -30759,15 +30092,15 @@ index 74a285b8b018a9c94ccea519f1ce8b9e2ef3cb64..d8b4196adf955f8d414688dc451caac2
}
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
-index fb0be805c86e311927f55e8f090592465195384e..996899cb18e6c29665b9de7a1cc97c9a4187924b 100644
+index 44e64d716eee71492f9a8d813934bb96463ece45..d52fcb82fdeab5b2e95b97a876c6e6701f569013 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -86,7 +86,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
- return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("init_biomes", () -> {
+ return CompletableFuture.supplyAsync(() -> {
this.doCreateBiomes(blender, noiseConfig, structureAccessor, chunk);
return chunk;
-- }), Util.backgroundExecutor());
-+ }), Runnable::run); // Paper - rewrite chunk system
+- }, Util.backgroundExecutor().forName("init_biomes"));
++ }, Runnable::run); // Paper - rewrite chunk system
}
private void doCreateBiomes(Blender blender, RandomState noiseConfig, StructureManager structureAccessor, ChunkAccess chunk) {
@@ -30775,13 +30108,13 @@ index fb0be805c86e311927f55e8f090592465195384e..996899cb18e6c29665b9de7a1cc97c9a
}
return ichunkaccess1;
-- }), Util.backgroundExecutor());
-+ }), Runnable::run); // Paper - rewrite chunk system
+- }, Util.backgroundExecutor().forName("wgen_fill_noise"));
++ }, Runnable::run); // Paper - rewrite chunk system
}
private ChunkAccess doFill(Blender blender, StructureManager structureAccessor, RandomState noiseConfig, ChunkAccess chunk, int minimumCellY, int cellHeight) {
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
-index c6181e14d85d454506534f9bbe856156c0d4a062..3694c5d2d522216cd2e6e91e502a56a08595ca84 100644
+index c3586281c9594769593a6027ea0a78f7c76c0262..decdb275e83fa6244aa3a24458872b42c49d04ed 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java
@@ -47,8 +47,13 @@ public class StructureCheck {
@@ -30855,16 +30188,17 @@ index c6181e14d85d454506534f9bbe856156c0d4a062..3694c5d2d522216cd2e6e91e502a56a0
referencesByStructure.computeInt(structure, (feature, references) -> references == null ? 1 : references + 1);
return referencesByStructure;
diff --git a/src/main/java/net/minecraft/world/level/lighting/LevelLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/LevelLightEngine.java
-index 82e4fad11121167445df97060fb717fa86191297..b3e2bb9245be1bb2f587117b0f6016cba18e217f 100644
+index 8d90e783967280025d711c709facbcc87f611f8a..987e3397503cd07d3a2f172cede341297bc58dba 100644
--- a/src/main/java/net/minecraft/world/level/lighting/LevelLightEngine.java
+++ b/src/main/java/net/minecraft/world/level/lighting/LevelLightEngine.java
-@@ -9,145 +9,103 @@ import net.minecraft.world.level.LightLayer;
+@@ -9,151 +9,111 @@ import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.LightChunkGetter;
-public class LevelLightEngine implements LightEventListener {
-+public class LevelLightEngine implements LightEventListener, ca.spottedleaf.moonrise.patches.starlight.light.StarLightLightingProvider {
++public class LevelLightEngine implements LightEventListener, ca.spottedleaf.moonrise.patches.starlight.light.StarLightLightingProvider { // Paper - rewrite chunk system
public static final int LIGHT_SECTION_PADDING = 1;
+ public static final LevelLightEngine EMPTY = new LevelLightEngine();
protected final LevelHeightAccessor levelHeightAccessor;
- @Nullable
- private final LightEngine<?, ?> blockEngine;
@@ -30908,6 +30242,15 @@ index 82e4fad11121167445df97060fb717fa86191297..b3e2bb9245be1bb2f587117b0f6016cb
+ // Paper end - rewrite chunk system
}
+ private LevelLightEngine() {
+ this.levelHeightAccessor = LevelHeightAccessor.create(0, 0);
+- this.blockEngine = null;
+- this.skyEngine = null;
++ // Paper start - rewrite chunk system
++ this.lightEngine = new ca.spottedleaf.moonrise.patches.starlight.light.StarLightInterface(null, false, false, (LevelLightEngine)(Object)this);
++ // Paper end - rewrite chunk system
+ }
+
@Override
public void checkBlock(BlockPos pos) {
- if (this.blockEngine != null) {
@@ -31043,19 +30386,18 @@ index 82e4fad11121167445df97060fb717fa86191297..b3e2bb9245be1bb2f587117b0f6016cb
+ return this.lightEngine.getRawBrightness(pos, ambientDarkness); // Paper - rewrite chunk system
}
- public boolean lightOnInSection(SectionPos sectionPos) {
-- long l = sectionPos.asLong();
+ public boolean lightOnInColumn(long sectionPos) {
- return this.blockEngine == null
-- || this.blockEngine.storage.lightOnInSection(l) && (this.skyEngine == null || this.skyEngine.storage.lightOnInSection(l));
+- || this.blockEngine.storage.lightOnInColumn(sectionPos) && (this.skyEngine == null || this.skyEngine.storage.lightOnInColumn(sectionPos));
+ throw new UnsupportedOperationException(); // Paper - rewrite chunk system // Paper - not implemented on server
}
public int getLightSectionCount() {
diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java
-index c8f7c43134e7c51ce8af5b3c1a28c11db67715a2..29123f3a2f211c08d1a9ccf62ca9bc9822f90111 100644
+index 5dc2674b537f4a61b2e21a21bdb2e8dc090d3a3c..6cf6d4ec7b9e43c7b2b4c0e2fb080964ff588130 100644
--- a/src/main/java/net/minecraft/world/phys/AABB.java
+++ b/src/main/java/net/minecraft/world/phys/AABB.java
-@@ -326,7 +326,7 @@ public class AABB {
+@@ -331,7 +331,7 @@ public class AABB {
}
@Nullable
@@ -31063,7 +30405,7 @@ index c8f7c43134e7c51ce8af5b3c1a28c11db67715a2..29123f3a2f211c08d1a9ccf62ca9bc98
+ public static Direction getDirection( // Paper - optimise collisions - public
AABB box, Vec3 intersectingVector, double[] traceDistanceResult, @Nullable Direction approachDirection, double deltaX, double deltaY, double deltaZ
) {
- if (deltaX > 1.0E-7) {
+ return getDirection(
diff --git a/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
index 4fee67f7214b464b9e09862778e3ef187fcb8b72..31a54af04ab072a433d6df9fe37beb12243fea80 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
@@ -31360,7 +30702,7 @@ index 7ec02a7849437a18860aa0df7d9ddd71b2447d4c..5e45e49ab09344cb95736f4124b1c6e0
public OffsetDoubleList(DoubleList oldList, double offset) {
this.delegate = oldList;
diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
-index 0fdd2cdd8d215ca1523eda8ad7316cdd5f41a6b5..7ede56f77af1d40e10fde2e660d5794e4b37dc5d 100644
+index 5a0b0b47da3d796c391ac15eb573af25a1dfcd32..672a2038c6d8b31090403766460c6149a75adf8b 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
@@ -16,9 +16,15 @@ public final class Shapes {
@@ -31451,7 +30793,10 @@ index 0fdd2cdd8d215ca1523eda8ad7316cdd5f41a6b5..7ede56f77af1d40e10fde2e660d5794e
- DoubleArrayList.wrap(new double[]{minX, maxX}),
- DoubleArrayList.wrap(new double[]{minY, maxY}),
- DoubleArrayList.wrap(new double[]{minZ, maxZ})
-- );
++ minX == 0.0 && maxX == 1.0 ? ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minX, maxX }),
++ minY == 0.0 && maxY == 1.0 ? ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minY, maxY }),
++ minZ == 0.0 && maxZ == 1.0 ? ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minZ, maxZ })
+ );
- } else if (i == 0 && j == 0 && k == 0) {
- return block();
- } else {
@@ -31468,10 +30813,7 @@ index 0fdd2cdd8d215ca1523eda8ad7316cdd5f41a6b5..7ede56f77af1d40e10fde2e660d5794e
- (int)Math.round(maxX * (double)l),
- (int)Math.round(maxY * (double)m),
- (int)Math.round(maxZ * (double)n)
-+ minX == 0.0 && maxX == 1.0 ? ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minX, maxX }),
-+ minY == 0.0 && maxY == 1.0 ? ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minY, maxY }),
-+ minZ == 0.0 && maxZ == 1.0 ? ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minZ, maxZ })
- );
+- );
- return new CubeVoxelShape(bitSetDiscreteVoxelShape);
}
} else {
@@ -31602,7 +30944,7 @@ index 0fdd2cdd8d215ca1523eda8ad7316cdd5f41a6b5..7ede56f77af1d40e10fde2e660d5794e
}
private static boolean joinIsNotEmpty(
-@@ -219,70 +226,120 @@ public final class Shapes {
+@@ -219,51 +226,116 @@ public final class Shapes {
return maxDist;
}
@@ -31646,35 +30988,34 @@ index 0fdd2cdd8d215ca1523eda8ad7316cdd5f41a6b5..7ede56f77af1d40e10fde2e660d5794e
+ // Paper end - optimise collisions
}
- public static VoxelShape getFaceShape(VoxelShape shape, Direction direction) {
-- if (shape == block()) {
-- return block();
-- } else {
+- public static boolean mergedFaceOccludes(VoxelShape one, VoxelShape two, Direction direction) {
+- if (one != block() && two != block()) {
- Direction.Axis axis = direction.getAxis();
-- boolean bl;
-- int i;
-- if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
-- bl = DoubleMath.fuzzyEquals(shape.max(axis), 1.0, 1.0E-7);
-- i = shape.shape.getSize(axis) - 1;
-- } else {
-- bl = DoubleMath.fuzzyEquals(shape.min(axis), 0.0, 1.0E-7);
-- i = 0;
+- Direction.AxisDirection axisDirection = direction.getAxisDirection();
+- VoxelShape voxelShape = axisDirection == Direction.AxisDirection.POSITIVE ? one : two;
+- VoxelShape voxelShape2 = axisDirection == Direction.AxisDirection.POSITIVE ? two : one;
+- if (!DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0, 1.0E-7)) {
+- voxelShape = empty();
- }
-+ return ((ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape)shape).moonrise$getFaceShapeClamped(direction); // Paper - optimise collisions
-+ }
-
-- return (VoxelShape)(!bl ? empty() : new SliceShape(shape, axis, i));
-- }
+ // Paper start - optimise collisions
+ private static boolean mergedMayOccludeBlock(final VoxelShape shape1, final VoxelShape shape2) {
+ // if the combined bounds of the two shapes cannot occlude, then neither can the merged
+ final AABB bounds1 = shape1.bounds();
+ final AABB bounds2 = shape2.bounds();
-+
+
+- if (!DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0, 1.0E-7)) {
+- voxelShape2 = empty();
+- }
+ final double minX = Math.min(bounds1.minX, bounds2.minX);
+ final double minY = Math.min(bounds1.minY, bounds2.minY);
+ final double minZ = Math.min(bounds1.minZ, bounds2.minZ);
-+
+
+- return !joinIsNotEmpty(
+- block(),
+- joinUnoptimized(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), BooleanOp.OR),
+- BooleanOp.ONLY_FIRST
+- );
+- } else {
+ final double maxX = Math.max(bounds1.maxX, bounds2.maxX);
+ final double maxY = Math.max(bounds1.maxY, bounds2.maxY);
+ final double maxZ = Math.max(bounds1.maxZ, bounds2.maxZ);
@@ -31682,38 +31023,20 @@ index 0fdd2cdd8d215ca1523eda8ad7316cdd5f41a6b5..7ede56f77af1d40e10fde2e660d5794e
+ return (minX <= ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON && maxX >= (1 - ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)) &&
+ (minY <= ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON && maxY >= (1 - ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)) &&
+ (minZ <= ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON && maxZ >= (1 - ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON));
- }
++ }
+ // Paper end - optimise collisions
-
-- public static boolean mergedFaceOccludes(VoxelShape one, VoxelShape two, Direction direction) {
-- if (one != block() && two != block()) {
-- Direction.Axis axis = direction.getAxis();
-- Direction.AxisDirection axisDirection = direction.getAxisDirection();
-- VoxelShape voxelShape = axisDirection == Direction.AxisDirection.POSITIVE ? one : two;
-- VoxelShape voxelShape2 = axisDirection == Direction.AxisDirection.POSITIVE ? two : one;
-- if (!DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0, 1.0E-7)) {
-- voxelShape = empty();
-- }
++
+ // Paper start - optimise collisions
+ public static boolean mergedFaceOccludes(final VoxelShape first, final VoxelShape second, final Direction direction) {
+ // see if any of the shapes on their own occludes, only if cached
+ if (((ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape)first).moonrise$occludesFullBlockIfCached() || ((ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape)second).moonrise$occludesFullBlockIfCached()) {
+ return true;
+ }
-
-- if (!DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0, 1.0E-7)) {
-- voxelShape2 = empty();
-- }
++
+ if (first.isEmpty() & second.isEmpty()) {
+ return false;
+ }
-
-- return !joinIsNotEmpty(
-- block(),
-- joinUnoptimized(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), BooleanOp.OR),
-- BooleanOp.ONLY_FIRST
-- );
-- } else {
++
+ // we optimise getOpposite, so we can use it
+ // secondly, use our cache to retrieve sliced shape
+ final VoxelShape newFirst = ((ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape)first).moonrise$getFaceShapeClamped(direction);
@@ -31785,7 +31108,7 @@ index b07f1c58e00d232e7c83e6df3499e4b677645609..b88c71f27996d24d29048e06a69a0046
private static DiscreteVoxelShape makeSlice(DiscreteVoxelShape voxelSet, Direction.Axis axis, int sliceWidth) {
diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
-index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe8e23a1a4 100644
+index bcb79462c8b3309ae8701cba4753b27a9d22eb2e..d850a7de74150a04622da71d9614320f3d5d69e8 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
@@ -15,38 +15,505 @@ import net.minecraft.world.phys.AABB;
@@ -32311,7 +31634,7 @@ index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe
}
public VoxelShape singleEncompassing() {
-@@ -69,28 +536,95 @@ public abstract class VoxelShape {
+@@ -69,7 +536,7 @@ public abstract class VoxelShape {
public abstract DoubleList getCoords(Direction.Axis axis);
public boolean isEmpty() {
@@ -32319,6 +31642,10 @@ index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe
+ return this.isEmpty; // Paper - optimise collisions
}
+ public VoxelShape move(Vec3 vec3d) {
+@@ -77,24 +544,91 @@ public abstract class VoxelShape {
+ }
+
public VoxelShape move(double x, double y, double z) {
- return (VoxelShape)(this.isEmpty()
- ? Shapes.empty()
@@ -32423,7 +31750,7 @@ index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe
}
public void forAllEdges(Shapes.DoubleLineConsumer consumer) {
-@@ -127,9 +661,24 @@ public abstract class VoxelShape {
+@@ -131,9 +665,24 @@ public abstract class VoxelShape {
}
public List<AABB> toAabbs() {
@@ -32451,7 +31778,7 @@ index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe
}
public double min(Direction.Axis axis, double from, double to) {
-@@ -155,42 +704,63 @@ public abstract class VoxelShape {
+@@ -159,42 +708,63 @@ public abstract class VoxelShape {
}
@Nullable
@@ -32473,7 +31800,7 @@ index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe
- this.findIndex(Direction.Axis.Y, vec32.y - (double)pos.getY()),
- this.findIndex(Direction.Axis.Z, vec32.z - (double)pos.getZ())
- )
-- ? new BlockHitResult(vec32, Direction.getNearest(vec3.x, vec3.y, vec3.z).getOpposite(), pos, true)
+- ? new BlockHitResult(vec32, Direction.getApproximateNearest(vec3.x, vec3.y, vec3.z).getOpposite(), pos, true)
- : AABB.clip(this.toAabbs(), start, end, pos);
+ }
+
@@ -32544,8 +31871,8 @@ index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe
}
public VoxelShape getFaceShape(Direction facing) {
-@@ -226,8 +796,29 @@ public abstract class VoxelShape {
- }
+@@ -249,9 +819,30 @@ public abstract class VoxelShape {
+ && DoubleMath.fuzzyEquals(doubleList.getDouble(1), 1.0, 1.0E-7);
}
- public double collide(Direction.Axis axis, AABB box, double maxDist) {
@@ -32560,27 +31887,28 @@ index d440003ca4403511a964f61bcf67ac2cd75c5359..11824d39e72fa003b3a56aa9b8d679fe
+ }
+ switch (axis) {
+ case X: {
-+ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.collideX((VoxelShape)(Object)this, source, source_move);
++ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.collideX((VoxelShape) (Object) this, source, source_move);
+ }
+ case Y: {
-+ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.collideY((VoxelShape)(Object)this, source, source_move);
++ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.collideY((VoxelShape) (Object) this, source, source_move);
+ }
+ case Z: {
-+ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.collideZ((VoxelShape)(Object)this, source, source_move);
++ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.collideZ((VoxelShape) (Object) this, source, source_move);
+ }
+ default: {
+ throw new RuntimeException("Unknown axis: " + axis);
+ }
+ }
-+ // Paper end - optimise collisions
}
++ // Paper end - optimise collisions
protected double collideX(AxisCycle axisCycle, AABB box, double maxDist) {
+ if (this.isEmpty()) {
diff --git a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java
-index 47c2b2da9799690291396effb9e1b06d71efc6fd..c42c0d1e4da30aa15f32d4ca524aeabd26fc50cf 100644
+index 26620c06d26a2c0eb957fbadc6ac3d7a309bff46..3858c83c58e78435a6e29de84c33faa2f26d593d 100644
--- a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java
+++ b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java
-@@ -18,7 +18,7 @@ import net.minecraft.core.BlockPos;
+@@ -17,7 +17,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.nbt.ListTag;
import net.minecraft.world.level.ChunkPos;
@@ -32589,7 +31917,7 @@ index 47c2b2da9799690291396effb9e1b06d71efc6fd..c42c0d1e4da30aa15f32d4ca524aeabd
private final Queue<ScheduledTick<T>> tickQueue = new PriorityQueue<>(ScheduledTick.DRAIN_ORDER);
@Nullable
private List<SavedTick<T>> pendingTicks;
-@@ -26,6 +26,30 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
+@@ -25,6 +25,30 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
@Nullable
private BiConsumer<LevelChunkTicks<T>, ScheduledTick<T>> onTickAdded;
@@ -32620,7 +31948,7 @@ index 47c2b2da9799690291396effb9e1b06d71efc6fd..c42c0d1e4da30aa15f32d4ca524aeabd
public LevelChunkTicks() {
}
-@@ -50,7 +74,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
+@@ -49,7 +73,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
public ScheduledTick<T> poll() {
ScheduledTick<T> scheduledTick = this.tickQueue.poll();
if (scheduledTick != null) {
@@ -32629,7 +31957,7 @@ index 47c2b2da9799690291396effb9e1b06d71efc6fd..c42c0d1e4da30aa15f32d4ca524aeabd
}
return scheduledTick;
-@@ -59,7 +83,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
+@@ -58,7 +82,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
@Override
public void schedule(ScheduledTick<T> orderedTick) {
if (this.ticksPerPosition.add(orderedTick)) {
@@ -32638,7 +31966,7 @@ index 47c2b2da9799690291396effb9e1b06d71efc6fd..c42c0d1e4da30aa15f32d4ca524aeabd
}
}
-@@ -81,7 +105,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
+@@ -80,7 +104,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
while (iterator.hasNext()) {
ScheduledTick<T> scheduledTick = iterator.next();
if (predicate.test(scheduledTick)) {
@@ -32647,15 +31975,15 @@ index 47c2b2da9799690291396effb9e1b06d71efc6fd..c42c0d1e4da30aa15f32d4ca524aeabd
this.ticksPerPosition.remove(scheduledTick);
}
}
-@@ -98,6 +122,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
+@@ -110,6 +134,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
+ }
- @Override
- public ListTag save(long l, Function<T, String> function) {
-+ this.lastSaved = l; // Paper - rewrite chunk system
+ public ListTag save(long time, Function<T, String> typeToNameFunction) {
++ this.lastSaved = time; // Paper - rewrite chunk system
ListTag listTag = new ListTag();
- if (this.pendingTicks != null) {
- for (SavedTick<T> savedTick : this.pendingTicks) {
-@@ -114,6 +139,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
+
+ for (SavedTick<T> savedTick : this.pack(time)) {
+@@ -121,6 +146,7 @@ public class LevelChunkTicks<T> implements SerializableTickContainer<T>, TickCon
public void unpack(long time) {
if (this.pendingTicks != null) {
@@ -32664,7 +31992,7 @@ index 47c2b2da9799690291396effb9e1b06d71efc6fd..c42c0d1e4da30aa15f32d4ca524aeabd
for (SavedTick<T> savedTick : this.pendingTicks) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
-index 69c7fe5bf5b914276a9f7a0e57ce668e569d91f9..33322b57b4c6922f4daad0f584733f0f24083911 100644
+index 887a17a0833064eb5701222e5fb6f5ccf9511588..ca1dd58229b7e39dffdd7a69c296dc5f652aa5e6 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -82,6 +82,12 @@ public class CraftChunk implements Chunk {
@@ -32706,7 +32034,7 @@ index 69c7fe5bf5b914276a9f7a0e57ce668e569d91f9..33322b57b4c6922f4daad0f584733f0f
- entityManager.ensureChunkQueuedForLoad(pair); // Start entity loading
-
- // SPIGOT-6772: Use entity mailbox and re-schedule entities if they get unloaded
-- ProcessorMailbox<Runnable> mailbox = ((EntityStorage) entityManager.permanentStorage).entityDeserializerQueue;
+- ConsecutiveExecutor mailbox = ((EntityStorage) entityManager.permanentStorage).entityDeserializerQueue;
- BooleanSupplier supplier = () -> {
- // only execute inbox if our entities are not present
- if (entityManager.areEntitiesLoaded(pair)) {
@@ -32744,10 +32072,10 @@ index 69c7fe5bf5b914276a9f7a0e57ce668e569d91f9..33322b57b4c6922f4daad0f584733f0f
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-index 35d1dcabb182b0a31727e5ddefe33955c804603b..0bad47a4d45e9ca399de98edd0956efb90d21062 100644
+index f85e8ec660bf588f694aa96e6e2ade478a9696b7..625f45b50654732231c835df867f9d84897dd211 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-@@ -1430,7 +1430,7 @@ public final class CraftServer implements Server {
+@@ -1356,7 +1356,7 @@ public final class CraftServer implements Server {
// Paper - Put world into worldlist before initing the world; move up
this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal);
@@ -32756,7 +32084,7 @@ index 35d1dcabb182b0a31727e5ddefe33955c804603b..0bad47a4d45e9ca399de98edd0956efb
this.pluginManager.callEvent(new WorldLoadEvent(internal.getWorld()));
return internal.getWorld();
-@@ -1475,7 +1475,7 @@ public final class CraftServer implements Server {
+@@ -1401,7 +1401,7 @@ public final class CraftServer implements Server {
}
handle.getChunkSource().close(save);
@@ -32765,7 +32093,7 @@ index 35d1dcabb182b0a31727e5ddefe33955c804603b..0bad47a4d45e9ca399de98edd0956efb
handle.convertable.close();
} catch (Exception ex) {
this.getLogger().log(Level.SEVERE, null, ex);
-@@ -2511,7 +2511,7 @@ public final class CraftServer implements Server {
+@@ -2368,7 +2368,7 @@ public final class CraftServer implements Server {
@Override
public boolean isPrimaryThread() {
@@ -32775,10 +32103,10 @@ index 35d1dcabb182b0a31727e5ddefe33955c804603b..0bad47a4d45e9ca399de98edd0956efb
// Paper start - Adventure
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-index 3e5d381c0f2cfaf46292db0819d4996edf6e8564..5ff343759cc0c5046a9d45e8f74d4e6ec63f0f91 100644
+index 03cef3e33de1cf2a1ad4c7a5ba9a65ee3b69ee52..570c129cac344d22da903c84e95e37fcc03703e9 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
-@@ -461,10 +461,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+@@ -458,10 +458,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z));
if (playerChunk == null) return false;
@@ -32796,7 +32124,7 @@ index 3e5d381c0f2cfaf46292db0819d4996edf6e8564..5ff343759cc0c5046a9d45e8f74d4e6e
ClientboundLevelChunkWithLightPacket refreshPacket = new ClientboundLevelChunkWithLightPacket(chunk, this.world.getLightEngine(), null, null);
for (ServerPlayer player : playersInRange) {
-@@ -472,8 +476,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+@@ -469,8 +473,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
player.connection.send(refreshPacket);
}
@@ -32806,7 +32134,7 @@ index 3e5d381c0f2cfaf46292db0819d4996edf6e8564..5ff343759cc0c5046a9d45e8f74d4e6e
return true;
}
-@@ -577,20 +580,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+@@ -574,20 +577,8 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public Collection<Plugin> getPluginChunkTickets(int x, int z) {
DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager;
@@ -32828,7 +32156,7 @@ index 3e5d381c0f2cfaf46292db0819d4996edf6e8564..5ff343759cc0c5046a9d45e8f74d4e6e
}
@Override
-@@ -598,7 +589,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+@@ -595,7 +586,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
Map<Plugin, ImmutableList.Builder<Chunk>> ret = new HashMap<>();
DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager;
@@ -32837,7 +32165,7 @@ index 3e5d381c0f2cfaf46292db0819d4996edf6e8564..5ff343759cc0c5046a9d45e8f74d4e6e
long chunkKey = chunkTickets.getLongKey();
SortedArraySet<Ticket<?>> tickets = chunkTickets.getValue();
-@@ -1297,12 +1288,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+@@ -1278,12 +1269,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public int getViewDistance() {
@@ -32852,7 +32180,7 @@ index 3e5d381c0f2cfaf46292db0819d4996edf6e8564..5ff343759cc0c5046a9d45e8f74d4e6e
}
public BlockMetadataStore getBlockMetadata() {
-@@ -2440,17 +2431,20 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+@@ -2416,17 +2407,20 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public void setSimulationDistance(final int simulationDistance) {
@@ -32877,10 +32205,10 @@ index 3e5d381c0f2cfaf46292db0819d4996edf6e8564..5ff343759cc0c5046a9d45e8f74d4e6e
// Paper start - implement pointers
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
-index 5f12c91ea598b4b133bf41532a9864645ebf6cea..e02fa642f11809607e30e22b51c65373edd70842 100644
+index cdc53abb5572fa57b4ec98a694c5583ad0982a05..e59572f05b69b8302b69de8cbcfbc889f67634b5 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
-@@ -3496,7 +3496,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+@@ -3402,7 +3402,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setViewDistance(final int viewDistance) {
@@ -32891,7 +32219,7 @@ index 5f12c91ea598b4b133bf41532a9864645ebf6cea..e02fa642f11809607e30e22b51c65373
}
@Override
-@@ -3506,7 +3508,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+@@ -3412,7 +3414,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setSimulationDistance(final int simulationDistance) {
@@ -32902,7 +32230,7 @@ index 5f12c91ea598b4b133bf41532a9864645ebf6cea..e02fa642f11809607e30e22b51c65373
}
@Override
-@@ -3516,6 +3520,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+@@ -3422,6 +3426,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void setSendViewDistance(final int viewDistance) {
@@ -32913,10 +32241,10 @@ index 5f12c91ea598b4b133bf41532a9864645ebf6cea..e02fa642f11809607e30e22b51c65373
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
-index 5717c0e1d6df07a4613356dc78d970d2101c68d7..cab7ca4218e5903b6a5e518af55457b9a1b5111c 100644
+index 625562a38bc78feae3ae4b50b9afefbd05ff767a..e34060c21755c61228ba91e468b7c92fc4c4cf0c 100644
--- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java
-@@ -263,7 +263,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
+@@ -262,7 +262,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
return ichunkaccess1;
};
@@ -32926,10 +32254,10 @@ index 5717c0e1d6df07a4613356dc78d970d2101c68d7..cab7ca4218e5903b6a5e518af55457b9
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
-index fceed3d08ee6f4c171685986bb19d2be592eedc6..bf18f9ad7dec2b09ebfcb5ec6566f2556e842f22 100644
+index e444662ee4d9405eeea7caa41b9cd6b36586d840..504ab4b545e084c962ebd5f26d9336adc16030fb 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
-@@ -829,5 +829,12 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel {
+@@ -808,6 +808,13 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel {
public ChunkAccess getChunkIfLoadedImmediately(final int x, final int z) {
return this.handle.getChunkIfLoadedImmediately(x, z);
}
@@ -32942,6 +32270,7 @@ index fceed3d08ee6f4c171685986bb19d2be592eedc6..bf18f9ad7dec2b09ebfcb5ec6566f255
+ // Paper end - rewrite chunk system
// Paper end
}
+
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
index ef2598760458833021ef1bee92137f42c9fe591f..1f23e775eba1c34e01145bd91b0ce26fed6ca9de 100644
--- a/src/main/java/org/spigotmc/AsyncCatcher.java
diff --git a/patches/server/1072-fixup-Optimize-BlockPosition-helper-methods.patch b/patches/server/0827-fixup-Optimize-BlockPosition-helper-methods.patch
index f68e9eae92..5a70b45e95 100644
--- a/patches/server/1072-fixup-Optimize-BlockPosition-helper-methods.patch
+++ b/patches/server/0827-fixup-Optimize-BlockPosition-helper-methods.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] fixup! Optimize BlockPosition helper methods
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
-index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..7362d471f9c1858e0dd7832e1ff59e3e51d7f249 100644
+index 0d51fb4be8b49e3b57c3c55aff6bcf13d5c78ddd..a1d54d978d34d75475f92dfb806113586e7e449c 100644
--- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/src/main/java/net/minecraft/core/BlockPos.java
-@@ -161,7 +161,7 @@ public class BlockPos extends Vec3i {
+@@ -162,7 +162,7 @@ public class BlockPos extends Vec3i {
@Override
public BlockPos above(int distance) {
@@ -17,7 +17,7 @@ index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..7362d471f9c1858e0dd7832e1ff59e3e
}
@Override
-@@ -171,7 +171,7 @@ public class BlockPos extends Vec3i {
+@@ -172,7 +172,7 @@ public class BlockPos extends Vec3i {
@Override
public BlockPos below(int i) {
@@ -26,7 +26,7 @@ index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..7362d471f9c1858e0dd7832e1ff59e3e
}
@Override
-@@ -181,7 +181,7 @@ public class BlockPos extends Vec3i {
+@@ -182,7 +182,7 @@ public class BlockPos extends Vec3i {
@Override
public BlockPos north(int distance) {
@@ -35,7 +35,7 @@ index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..7362d471f9c1858e0dd7832e1ff59e3e
}
@Override
-@@ -191,7 +191,7 @@ public class BlockPos extends Vec3i {
+@@ -192,7 +192,7 @@ public class BlockPos extends Vec3i {
@Override
public BlockPos south(int distance) {
@@ -44,7 +44,7 @@ index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..7362d471f9c1858e0dd7832e1ff59e3e
}
@Override
-@@ -201,7 +201,7 @@ public class BlockPos extends Vec3i {
+@@ -202,7 +202,7 @@ public class BlockPos extends Vec3i {
@Override
public BlockPos west(int distance) {
@@ -53,7 +53,7 @@ index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..7362d471f9c1858e0dd7832e1ff59e3e
}
@Override
-@@ -211,7 +211,7 @@ public class BlockPos extends Vec3i {
+@@ -212,7 +212,7 @@ public class BlockPos extends Vec3i {
@Override
public BlockPos east(int distance) {
diff --git a/patches/server/1073-fixup-Moonrise-optimisation-patches.patch b/patches/server/0828-fixup-Moonrise-optimisation-patches.patch
index 031f4c876b..e2197234c7 100644
--- a/patches/server/1073-fixup-Moonrise-optimisation-patches.patch
+++ b/patches/server/0828-fixup-Moonrise-optimisation-patches.patch
@@ -361,37 +361,35 @@ index 0000000000000000000000000000000000000000..b5335a2a8cb5dc7637c7112c8f719338
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java
-index 5fca5dc7cdfa976bcc58dfcf0d14abb78a931475..cee2c8efbe280e20c63e2d66464dc835cd328e4a 100644
+index 49160a30b8e19e5c5ada811fbcae2a05959524f3..44bb25554634af2ec0b2e9b3d9231304d5dff034 100644
--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java
+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/ChunkSystemConverters.java
-@@ -1,5 +1,6 @@
+@@ -1,10 +1,11 @@
package ca.spottedleaf.moonrise.patches.chunk_system;
+import ca.spottedleaf.moonrise.common.PlatformHooks;
import net.minecraft.SharedConstants;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
-@@ -25,21 +26,13 @@ public final class ChunkSystemConverters {
+ import net.minecraft.server.level.ServerLevel;
+-import net.minecraft.util.datafix.DataFixTypes;
++import net.minecraft.util.datafix.fixes.References;
+
+ public final class ChunkSystemConverters {
+
+@@ -25,13 +26,13 @@ public final class ChunkSystemConverters {
public static CompoundTag convertPoiCompoundTag(final CompoundTag data, final ServerLevel world) {
final int dataVersion = getDataVersion(data, DEFAULT_POI_DATA_VERSION);
-- // Paper start - dataconverter
-- return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
-- ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.POI_CHUNK, data, dataVersion, getCurrentVersion()
-- );
-- // Paper end - dataconverter
-+ return PlatformHooks.get().convertNBT(DataFixTypes.POI_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
+- return DataFixTypes.POI_CHUNK.update(world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
++ return PlatformHooks.get().convertNBT(References.POI_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
}
public static CompoundTag convertEntityChunkCompoundTag(final CompoundTag data, final ServerLevel world) {
final int dataVersion = getDataVersion(data, DEFAULT_ENTITY_CHUNK_DATA_VERSION);
-- // Paper start - dataconverter
-- return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(
-- ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY_CHUNK, data, dataVersion, getCurrentVersion()
-- );
-- // Paper end - dataconverter
-+ return PlatformHooks.get().convertNBT(DataFixTypes.ENTITY_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
+- return DataFixTypes.ENTITY_CHUNK.update(world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
++ return PlatformHooks.get().convertNBT(References.ENTITY_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
}
private ChunkSystemConverters() {}
@@ -3839,7 +3837,7 @@ index 883fe6401f1b9711fa544d18a815b4d638f580df..aacd543f03b35908011d0c2891e978cc
+
}
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
-index 5c7f2471a0b15ac2e714527296ad2aa7291999eb..40dc7569c32b100d4eebbde9024ded2acbb2fb20 100644
+index 997b05167c19472acb98edac32d4548cc65efa8e..5ed6599d1f9a2edf8c904f3602b06d26d857600c 100644
--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
@@ -1,6 +1,8 @@
@@ -3898,27 +3896,16 @@ index 5c7f2471a0b15ac2e714527296ad2aa7291999eb..40dc7569c32b100d4eebbde9024ded2a
}
// Paper start - rewrite chunk system
-@@ -100,18 +104,7 @@ public final class ChunkEntitySlices {
+@@ -100,7 +104,7 @@ public final class ChunkEntitySlices {
}
final ListTag entitiesTag = new ListTag();
-- final java.util.Map<net.minecraft.world.entity.EntityType<?>, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
- for (final Entity entity : entities) {
-- // Paper start - Entity load/save limit per chunk
-- final EntityType<?> entityType = entity.getType();
-- final int saveLimit = world.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
-- if (saveLimit > -1) {
-- if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
-- continue;
-- }
-- savedEntityCounts.merge(entityType, 1, Integer::sum);
-- }
-- // Paper end - Entity load/save limit per chunk
+ for (final Entity entity : PlatformHooks.get().modifySavedEntities(world, chunkPos.x, chunkPos.z, entities)) {
CompoundTag compoundTag = new CompoundTag();
if (entity.save(compoundTag)) {
entitiesTag.add(compoundTag);
-@@ -158,12 +151,12 @@ public final class ChunkEntitySlices {
+@@ -147,12 +151,12 @@ public final class ChunkEntitySlices {
continue;
}
if (entity.shouldBeSaved()) {
@@ -3933,7 +3920,7 @@ index 5c7f2471a0b15ac2e714527296ad2aa7291999eb..40dc7569c32b100d4eebbde9024ded2a
}
}
}
-@@ -172,33 +165,6 @@ public final class ChunkEntitySlices {
+@@ -161,34 +165,7 @@ public final class ChunkEntitySlices {
return this.entities.size() != 0;
}
@@ -3964,10 +3951,12 @@ index 5c7f2471a0b15ac2e714527296ad2aa7291999eb..40dc7569c32b100d4eebbde9024ded2a
- }
- // Paper end
-
- private List<Entity> getAllEntities() {
+- private List<Entity> getAllEntities() {
++ public List<Entity> getAllEntities() {
final int len = this.entities.size();
if (len == 0) {
-@@ -262,6 +228,7 @@ public final class ChunkEntitySlices {
+ return new ArrayList<>();
+@@ -251,6 +228,7 @@ public final class ChunkEntitySlices {
return false;
}
((ChunkSystemEntity)entity).moonrise$setChunkStatus(this.status);
@@ -3975,7 +3964,7 @@ index 5c7f2471a0b15ac2e714527296ad2aa7291999eb..40dc7569c32b100d4eebbde9024ded2a
final int sectionIndex = chunkSection - this.minSection;
this.allEntities.addEntity(entity, sectionIndex);
-@@ -295,6 +262,7 @@ public final class ChunkEntitySlices {
+@@ -284,6 +262,7 @@ public final class ChunkEntitySlices {
return false;
}
((ChunkSystemEntity)entity).moonrise$setChunkStatus(null);
@@ -4287,7 +4276,7 @@ index fd35e4db0c8fec8f86b8743bcc2b15ed2e7433f1..bbf9d6c1c9525d97160806819a57be03
// completely empty, no point in storing this
continue;
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/storage/ChunkSystemSectionStorage.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/storage/ChunkSystemSectionStorage.java
-index 3f5edb756beb9c31b6f591a24b778d6ac2b0bf51..23bd741dc0bfd48b8064a2b498d71cfa8f8145b2 100644
+index fb87d7ece6ebccfd0ffd2f1a609b45a0d2461d9e..524752744e37a2db0e3ea089468bdf497129bfef 100644
--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/storage/ChunkSystemSectionStorage.java
+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/storage/ChunkSystemSectionStorage.java
@@ -1,12 +1,8 @@
@@ -4304,7 +4293,7 @@ index 3f5edb756beb9c31b6f591a24b778d6ac2b0bf51..23bd741dc0bfd48b8064a2b498d71cfa
public interface ChunkSystemSectionStorage {
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
-index a608f57ebca98eda88ad749d0aad021678be54f9..b2fa9883aefb07f64bb5db7e0052218d2ad09aba 100644
+index 852d75a73dae7448cbe1e2f5e164b235efa8a969..b2fa9883aefb07f64bb5db7e0052218d2ad09aba 100644
--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
@@ -1,7 +1,8 @@
@@ -4425,16 +4414,16 @@ index a608f57ebca98eda88ad749d0aad021678be54f9..b2fa9883aefb07f64bb5db7e0052218d
// send view distances
this.player.connection.send(this.updateClientChunkRadius(sendViewDistance));
this.player.connection.send(this.updateClientSimulationDistance(tickViewDistance));
-@@ -1079,8 +1078,7 @@ public final class RegionizedPlayerChunkLoader {
+@@ -1078,5 +1077,9 @@ public final class RegionizedPlayerChunkLoader {
+
// now all tickets should be removed, which is all of our external state
}
-
-- // For external checks
-- public it.unimi.dsi.fastutil.longs.LongOpenHashSet getSentChunksRaw() {
++
+ public LongOpenHashSet getSentChunksRaw() {
- return this.sentChunks;
- }
++ return this.sentChunks;
++ }
}
+ }
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..f98df65eaed2abedc66f3a49790e0cfb65354ed9 100644
--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
@@ -6173,7 +6162,7 @@ index e0b26ccb63596748b80fc6a5e47e373ba811ba8b..5f4b99d8c5453f8ad2e600a57ea4e7da
\ No newline at end of file
+}
diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java
-index fbdf721e8b4cfe6cef4ee60c53c680cbfc858d88..98382575eb6cd48aa163264e4935c812db1f1aff 100644
+index fbdf721e8b4cfe6cef4ee60c53c680cbfc858d88..6ab353b0d2465c3680bb3c8d0852ba0f65c00fd2 100644
--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java
+++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java
@@ -1,7 +1,9 @@
@@ -6210,7 +6199,7 @@ index fbdf721e8b4cfe6cef4ee60c53c680cbfc858d88..98382575eb6cd48aa163264e4935c812
final ProtoChunk protoChunk = (ProtoChunk)this.fromChunk;
chunk = new LevelChunk(this.world, protoChunk, (final LevelChunk unused) -> {
- ChunkStatusTasks.postLoadProtoChunk(world, protoChunk.getEntities(), protoChunk.getPos()); // Paper - pass chunk pos
-+ ChunkStatusTasks.postLoadProtoChunk(world, protoChunk.getEntities());
++ PlatformHooks.get().postLoadProtoChunk(world, protoChunk);
});
this.chunkHolder.replaceProtoChunk(new ImposterProtoChunk(chunk, false));
}
@@ -9985,10 +9974,10 @@ index 57692a503e147a00ac4e1586cd78e12b71a80d3f..689ce367164e79e0426eeecb81dbbc52
public static void saveLightHook(final Level world, final ChunkAccess chunk, final CompoundTag nbt) {
try {
diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
-index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..8371ce4e3df5ef8e39acd6e005209337cc76b451 100644
+index 9bd509915b391e9d382fe47798e2c345b6e59a9a..65c7e7a1b1a5472ee03149bb4ccd9f7d0229069b 100644
--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
+++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
-@@ -243,6 +243,7 @@ public class GlobalConfiguration extends ConfigurationPart {
+@@ -242,6 +242,7 @@ public class GlobalConfiguration extends ConfigurationPart {
@PostProcess
private void postProcess() {
@@ -9997,12 +9986,12 @@ index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..8371ce4e3df5ef8e39acd6e005209337
}
}
diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java
-index f22d22ebcedcc9c20225677844c86a1ad27c4211..ee1d39b6196c0f87ba473a15d3377e858922696c 100644
+index 71e04e5c1bc0722abf8ca2e0738bd60b6d7ae21c..8e0dfaf02343d74ce786e4fc647bc4c1d73c0014 100644
--- a/src/main/java/net/minecraft/core/MappedRegistry.java
+++ b/src/main/java/net/minecraft/core/MappedRegistry.java
-@@ -78,6 +78,19 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
- };
- private final Object tagAdditionLock = new Object();
+@@ -50,6 +50,19 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
+ return this.getTags();
+ }
+ // Paper start - fluid method optimisations
+ private void injectFluidRegister(
@@ -10020,22 +10009,22 @@ index f22d22ebcedcc9c20225677844c86a1ad27c4211..ee1d39b6196c0f87ba473a15d3377e85
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
this(key, lifecycle, false);
}
-@@ -145,6 +158,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
- this.toId.put(value, i);
- this.registrationInfos.put(key, info);
- this.registryLifecycle = this.registryLifecycle.add(info.lifecycle());
-+ this.injectFluidRegister(key, value); // Paper - fluid method optimisations
- return reference;
+@@ -114,6 +127,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
+ this.toId.put(value, i);
+ this.registrationInfos.put(key, info);
+ this.registryLifecycle = this.registryLifecycle.add(info.lifecycle());
++ this.injectFluidRegister(key, value); // Paper - fluid method optimisations
+ return reference;
+ }
}
-
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 696d075ca2883f3c37e35f983c4d020e5db89d16..25047b8536bc7e7a91ac0dfb82ad77099af6f125 100644
+index 7c388e230c4a88edf6212dd8990e8238d3265ebf..8a66012b7f2396031840c8c718f49f8aab716ee0 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1106,7 +1106,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+ }
// Spigot end
- // Paper end - Improved watchdog support; move final shutdown items here
- ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.deinit(); // Paper - rewrite chunk system
+ // Paper start - rewrite chunk system
+ LOGGER.info("Waiting for I/O tasks to complete...");
@@ -10045,27 +10034,27 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..25047b8536bc7e7a91ac0dfb82ad7709
+ ca.spottedleaf.moonrise.common.util.MoonriseCommon.haltExecutors();
+ }
+ // Paper end - rewrite chunk system
- // Paper start - move final shutdown items here
- Util.shutdownExecutors();
- try {
+ }
+
+ 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 4db96543e2072e47040bb25a9d97ea6a69c4a43d..2b082a644332569f0bcc84011430366150ef504d 100644
+index 8e2c0def0d158bdacfa0d455be82db24cc4bdf64..3b5b6799b6e7832d7cc7d73afb5f2ca04fee6060 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
-@@ -245,7 +245,7 @@ public class ChunkHolder extends GenerationChunkHolder implements ca.spottedleaf
-
- if (ichunkaccess != null) {
- ichunkaccess.setUnsaved(true);
+@@ -252,7 +252,7 @@ public class ChunkHolder extends GenerationChunkHolder implements ca.spottedleaf
+ return false;
+ } else {
+ ichunkaccess.markUnsaved();
- LevelChunk chunk = this.getChunkToSend(); // Paper - rewrite chunk system
+ LevelChunk chunk = this.playersSentChunkTo.size() == 0 ? null : this.getChunkToSend(); // Paper - rewrite chunk system
- if (chunk != null) {
- int j = this.lightEngine.getMinLightSection();
+ if (chunk == null) {
+ return false;
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index af8cb316ac169aa8d98a88765b85bb013b9ba961..38de8d8ed2efa3476d4e906bdc4b5944430bd1b7 100644
+index 60adb0caf3d6f03a57fc55303852070107f1736e..64b9738584fe2efd1ce4a3d7e2c75e091adc2504 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -916,7 +916,6 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -910,7 +910,6 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper start - optimise entity tracker
private void newTrackerTick() {
@@ -10073,7 +10062,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..38de8d8ed2efa3476d4e906bdc4b5944
final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup entityLookup = (ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup)((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getEntityLookup();;
final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.world.entity.Entity> trackerEntities = entityLookup.trackerEntities;
-@@ -927,21 +926,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -921,21 +920,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (tracker == null) {
continue;
}
@@ -10099,7 +10088,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..38de8d8ed2efa3476d4e906bdc4b5944
}
}
// Paper end - optimise entity tracker
-@@ -1178,6 +1167,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1172,6 +1161,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.removePlayer(player);
}
}
@@ -10111,7 +10100,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..38de8d8ed2efa3476d4e906bdc4b5944
// Paper end - optimise entity tracker
public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
-@@ -1283,20 +1277,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1262,20 +1256,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
private int getEffectiveRange() {
@@ -10147,10 +10136,10 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..38de8d8ed2efa3476d4e906bdc4b5944
public void updatePlayers(List<ServerPlayer> players) {
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-index dcb5651d1d9b10b40430fb2f713beedf68336704..b380509cc942a054ea176216210ba69f5b517ae9 100644
+index 22157cbc4e4bb1e4010116bdf7429815d46bff2e..23a13bfd23514cde6dcf8d59ba3b43d84f266aad 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -92,7 +92,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
+@@ -99,7 +99,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler chunkTaskScheduler = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler();
final CompletableFuture<ChunkAccess> completable = new CompletableFuture<>();
chunkTaskScheduler.scheduleChunkLoad(
@@ -10159,7 +10148,7 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b380509cc942a054ea176216210ba69f
completable::complete
);
-@@ -123,6 +123,15 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
+@@ -130,6 +130,15 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
return ifPresent;
}
@@ -10175,7 +10164,7 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b380509cc942a054ea176216210ba69f
return load ? this.syncLoad(chunkX, chunkZ, toStatus) : null;
}
// Paper end - rewrite chunk system
-@@ -242,7 +251,24 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
+@@ -254,7 +263,24 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@Nullable
@Override
public LevelChunk getChunkNow(int chunkX, int chunkZ) {
@@ -10201,7 +10190,7 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b380509cc942a054ea176216210ba69f
}
private void clearCache() {
-@@ -299,7 +325,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
+@@ -311,7 +337,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(
chunkX, chunkZ, leastStatus, true,
@@ -10210,7 +10199,7 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b380509cc942a054ea176216210ba69f
complete
);
-@@ -556,7 +582,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
+@@ -549,7 +575,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private void getFullChunk(long pos, Consumer<LevelChunk> chunkConsumer) {
// Paper start - rewrite chunk system
@@ -10221,10 +10210,10 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b380509cc942a054ea176216210ba69f
chunkConsumer.accept(fullChunk);
}
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index f9abf63e12ea930275121b470e4e4906cff0fc12..55e81892b928a02e240aaa31dd501b0aacef8dbe 100644
+index af27a004f618912d6a5f1d2c82c8e7e9fb00a037..c7523387f0e9bbfe952abd237a936c8319f10200 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -799,11 +799,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -775,11 +775,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
// Paper start - optimise random ticking
@@ -10240,7 +10229,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..55e81892b928a02e240aaa31dd501b0a
final ChunkPos cpos = chunk.getPos();
final int offsetX = cpos.x << 4;
-@@ -813,39 +815,32 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -789,39 +791,32 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
final int offsetY = (sectionIndex + minSection) << 4;
final LevelChunkSection section = sections[sectionIndex];
final net.minecraft.world.level.chunk.PalettedContainer<net.minecraft.world.level.block.state.BlockState> states = section.states;
@@ -10289,7 +10278,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..55e81892b928a02e240aaa31dd501b0a
}
}
}
-@@ -856,6 +851,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -832,6 +827,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper end - optimise random ticking
public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
@@ -10297,8 +10286,8 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..55e81892b928a02e240aaa31dd501b0a
ChunkPos chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
int j = chunkcoordintpair.getMinBlockX();
-@@ -863,7 +859,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
- ProfilerFiller gameprofilerfiller = this.getProfiler();
+@@ -839,7 +835,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
+ ProfilerFiller gameprofilerfiller = Profiler.get();
gameprofilerfiller.push("thunder");
- if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder
@@ -10306,7 +10295,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..55e81892b928a02e240aaa31dd501b0a
BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15));
if (this.isRainingAt(blockposition)) {
-@@ -895,7 +891,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf.
+@@ -871,7 +867,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow
for (int l = 0; l < randomTickSpeed; ++l) {
@@ -10316,10 +10305,10 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..55e81892b928a02e240aaa31dd501b0a
}
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
-index 5e2c4969e77c669acbb4a13c07033cb267c3d586..f1371f3b9ea0cda0cf146d876828a6823632463c 100644
+index 4fe3024e26b56c2d796acf703a1bc200ff309f09..7529b3d90e65036c7bf869af30475932d547b3ab 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
-@@ -1475,7 +1475,7 @@ public abstract class PlayerList {
+@@ -1407,7 +1407,7 @@ public abstract class PlayerList {
public void setViewDistance(int viewDistance) {
this.viewDistance = viewDistance;
@@ -10616,10 +10605,10 @@ index 15c5164d0ef41a978c16ee317fa73e97f2480207..1f9c436a632e4f110be61cf76fcfc3b7
return ret;
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355e8d839ef 100644
+index 5410a0380c44629f1c9b4f0a8e6017cfc5a31a89..a3b0363fbc207ed9edc8a4d6619b6fff9389a9c7 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -461,6 +461,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -448,6 +448,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper start - rewrite chunk system
private final boolean isHardColliding = this.moonrise$isHardCollidingUncached();
private net.minecraft.server.level.FullChunkStatus chunkStatus;
@@ -10627,7 +10616,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
private int sectionX = Integer.MIN_VALUE;
private int sectionY = Integer.MIN_VALUE;
private int sectionZ = Integer.MIN_VALUE;
-@@ -481,6 +482,16 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -468,6 +469,16 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.chunkStatus = status;
}
@@ -10644,7 +10633,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
@Override
public final int moonrise$getSectionX() {
return this.sectionX;
-@@ -529,6 +540,54 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -516,6 +527,54 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return this.getIndirectPassengersStream().anyMatch((entity) -> entity instanceof Player);
}
// Paper end - rewrite chunk system
@@ -10699,7 +10688,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
// Paper start - optimise entity tracker
private net.minecraft.server.level.ChunkMap.TrackedEntity trackedEntity;
-@@ -1465,73 +1524,67 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -1402,73 +1461,67 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return movement;
}
@@ -10818,7 +10807,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
// Paper end - optimise collisions
}
-@@ -2853,64 +2906,99 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -2836,64 +2889,99 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return false;
}
@@ -10935,11 +10924,11 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
+ if (collisionShape.isEmpty()) {
+ continue;
+ }
++
++ final AABB toCollide = boundingBox.move(-(double)blockX, -(double)blockY, -(double)blockZ);
- if (ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.voxelShapeIntersectNoEmpty(collisionShape, toCollide)) {
- return true;
-+ final AABB toCollide = boundingBox.move(-(double)blockX, -(double)blockY, -(double)blockZ);
-+
+ final AABB singleAABB = ((ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape)collisionShape).moonrise$getSingleAABBRepresentation();
+ if (singleAABB != null) {
+ if (ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.voxelShapeIntersect(singleAABB, toCollide)) {
@@ -10959,7 +10948,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
}
}
}
-@@ -4451,82 +4539,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+@@ -4508,82 +4596,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return Mth.lerp(delta, this.yRotO, this.yRot);
}
@@ -10982,32 +10971,36 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
- Vec3 vec3d = Vec3.ZERO;
- int k1 = 0;
- BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
-+ }
-
+-
- for (int l1 = i; l1 < j; ++l1) {
- for (int i2 = k; i2 < l; ++i2) {
- for (int j2 = i1; j2 < j1; ++j2) {
- blockposition_mutableblockposition.set(l1, i2, j2);
- FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition);
-+ final AABB boundingBox = this.getBoundingBox().deflate(1.0E-3);
-
+-
- if (fluid.is(tag)) {
- double d2 = (double) ((float) i2 + fluid.getHeight(this.level(), blockposition_mutableblockposition));
-+ final Level world = this.level;
-+ final int minSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(world);
-
+-
- if (d2 >= axisalignedbb.minY) {
- flag1 = true;
- d1 = Math.max(d2 - axisalignedbb.minY, d1);
- if (flag) {
- Vec3 vec3d1 = fluid.getFlow(this.level(), blockposition_mutableblockposition);
-+ final int minBlockX = Mth.floor(boundingBox.minX);
-+ final int minBlockY = Math.max((minSection << 4), Mth.floor(boundingBox.minY));
-+ final int minBlockZ = Mth.floor(boundingBox.minZ);
-
+-
- if (d1 < 0.4D) {
- vec3d1 = vec3d1.scale(d1);
- }
++ }
++
++ final AABB boundingBox = this.getBoundingBox().deflate(1.0E-3);
++
++ final Level world = this.level;
++ final int minSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(world);
++
++ final int minBlockX = Mth.floor(boundingBox.minX);
++ final int minBlockY = Math.max((minSection << 4), Mth.floor(boundingBox.minY));
++ final int minBlockZ = Mth.floor(boundingBox.minZ);
++
+ // note: bounds are exclusive in Vanilla, so we subtract 1 - our loop expects bounds to be inclusive
+ final int maxBlockX = Mth.ceil(boundingBox.maxX) - 1;
+ final int maxBlockY = Math.min((ca.spottedleaf.moonrise.common.util.WorldUtil.getMaxSection(world) << 4) | 15, Mth.ceil(boundingBox.maxY) - 1);
@@ -11015,9 +11008,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
+
+ final boolean isPushable = this.isPushedByFluid();
+ final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
-
-- vec3d = vec3d.add(vec3d1);
-- ++k1;
++
+ Vec3 pushVector = Vec3.ZERO;
+ double totalPushes = 0.0;
+ double maxHeightDiff = 0.0;
@@ -11037,7 +11028,9 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
+ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) {
+ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) {
+ final net.minecraft.world.level.chunk.LevelChunkSection[] sections = chunkSource.getChunk(currChunkX, currChunkZ, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, false).getSections();
-+
+
+- vec3d = vec3d.add(vec3d1);
+- ++k1;
+ // bound y
+ for (int currChunkY = minChunkY; currChunkY <= maxChunkY; ++currChunkY) {
+ final int sectionIdx = currChunkY - minSection;
@@ -11066,10 +11059,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
+
+ if (fluidState.isEmpty() || !fluidState.is(fluid)) {
+ continue;
- }
-- // CraftBukkit start - store last lava contact location
-- if (tag == FluidTags.LAVA) {
-- this.lastLavaContact = blockposition_mutableblockposition.immutable();
++ }
+
+ mutablePos.set(currX | (currChunkX << 4), currY | (currChunkY << 4), currZ | (currChunkZ << 4));
+
@@ -11085,7 +11075,10 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
+
+ if (!isPushable) {
+ continue;
-+ }
+ }
+- // CraftBukkit start - store last lava contact location
+- if (tag == FluidTags.LAVA) {
+- this.lastLavaContact = blockposition_mutableblockposition.immutable();
+
+ ++totalPushes;
+
@@ -11151,10 +11144,10 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..379456dd5c18ca627b9cf6a473fd0355
public boolean touchingUnloadedChunk() {
AABB axisalignedbb = this.getBoundingBox().inflate(1.0D);
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 a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..42642b49a4ed6d06f52e4076dfb745b32a964a34 100644
+index 4cf6cb0abfeb7065c6d9381fb4194371c0cddc35..5930a430983061afddf20e3208ff2462ca1b78cd 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
-@@ -73,8 +73,7 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
+@@ -73,8 +73,7 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> im
ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, chunkX, chunkZ, "Accessing poi chunk off-main");
@@ -11164,7 +11157,7 @@ index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..42642b49a4ed6d06f52e4076dfb745b3
return ret == null ? Optional.empty() : ret.getSectionForVanilla(chunkY);
}
-@@ -128,9 +127,13 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
+@@ -128,9 +127,13 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> im
public final void moonrise$onUnload(final long coordinate) { // Paper - rewrite chunk system
final int chunkX = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(coordinate);
final int chunkZ = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(coordinate);
@@ -11180,7 +11173,7 @@ index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..42642b49a4ed6d06f52e4076dfb745b3
this.updateDistanceTracking(sectionPos);
}
}
-@@ -139,8 +142,12 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
+@@ -139,8 +142,12 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> im
public final void moonrise$loadInPoiChunk(final ca.spottedleaf.moonrise.patches.chunk_system.level.poi.PoiChunk poiChunk) {
final int chunkX = poiChunk.chunkX;
final int chunkZ = poiChunk.chunkZ;
@@ -11194,35 +11187,7 @@ index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..42642b49a4ed6d06f52e4076dfb745b3
final PoiSection section = poiChunk.getSection(sectionY);
if (section != null && !((ca.spottedleaf.moonrise.patches.chunk_system.level.poi.ChunkSystemPoiSection)section).moonrise$isEmpty()) {
this.onSectionLoad(SectionPos.asLong(chunkX, sectionY, chunkZ));
-@@ -166,22 +173,15 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
-
- @Override
- public final net.minecraft.nbt.CompoundTag moonrise$read(final int chunkX, final int chunkZ) throws java.io.IOException {
-- if (!ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.isRegionFileThread()) {
-- return ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.loadData(
-- this.world, chunkX, chunkZ, ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.RegionFileType.POI_DATA,
-- ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.getIOBlockingPriorityForCurrentThread()
-- );
-- }
-- return this.moonrise$getRegionStorage().read(new ChunkPos(chunkX, chunkZ));
-+ return ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.loadData(
-+ this.world, chunkX, chunkZ, ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionFileType.POI_DATA,
-+ ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.getIOBlockingPriorityForCurrentThread()
-+ );
- }
-
- @Override
- public final void moonrise$write(final int chunkX, final int chunkZ, final net.minecraft.nbt.CompoundTag data) throws java.io.IOException {
-- if (!ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.isRegionFileThread()) {
-- ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.scheduleSave(this.world, chunkX, chunkZ, data, ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread.RegionFileType.POI_DATA);
-- return;
-- }
-- this.moonrise$getRegionStorage().write(new ChunkPos(chunkX, chunkZ), data);
-+ ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.scheduleSave(this.world, chunkX, chunkZ, data, ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionFileType.POI_DATA);
- }
- // Paper end - rewrite chunk system
-
-@@ -359,8 +359,10 @@ public class PoiManager extends SectionStorage<PoiSection> implements ca.spotted
+@@ -316,8 +323,10 @@ public class PoiManager extends SectionStorage<PoiSection, PoiSection.Packed> im
}
public int sectionsToVillage(SectionPos pos) {
@@ -11236,11 +11201,11 @@ index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..42642b49a4ed6d06f52e4076dfb745b3
boolean isVillageCenter(long pos) {
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
-index 11e895d837794d79a76303b912092096bd7d07a8..f1458b0153f6a93875f2e439759324985fa13556 100644
+index f6f0d7c21ee81ff33d4af350c4d39aadfbe140df..712cbfc100e8aaf612d1d651dae64f57f892a768 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
-@@ -43,7 +43,7 @@ public class PoiSection implements ca.spottedleaf.moonrise.patches.chunk_system.
- }
+@@ -31,7 +31,7 @@ public class PoiSection implements ca.spottedleaf.moonrise.patches.chunk_system.
+ private boolean isValid;
// Paper start - rewrite chunk system
- private final Optional<PoiSection> noAllocOptional = Optional.of((PoiSection)(Object)this);;
@@ -11249,10 +11214,10 @@ index 11e895d837794d79a76303b912092096bd7d07a8..f1458b0153f6a93875f2e43975932498
@Override
public final boolean moonrise$isEmpty() {
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced43549b35d20 100644
+index 332dc7e6bdfb5b3741764d4877185a2e86a982f8..40fe47c7c145587ac81f0f15c237ed72ea9c094d 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -280,26 +280,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -264,26 +264,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
}
// Paper end - rewrite chunk system
// Paper start - optimise collisions
@@ -11280,7 +11245,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
final AABB boundingBox = entity.getBoundingBox();
if (ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isEmpty(boundingBox)) {
return false;
-@@ -329,7 +316,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -313,7 +300,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
final Vec3 to = clipContext.getTo();
final Vec3 from = clipContext.getFrom();
@@ -11289,7 +11254,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
}
private static final FluidState AIR_FLUIDSTATE = Fluids.EMPTY.defaultFluidState();
-@@ -383,7 +370,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -367,7 +354,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
int lastChunkY = Integer.MIN_VALUE;
int lastChunkZ = Integer.MIN_VALUE;
@@ -11298,7 +11263,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
for (;;) {
currPos.set(currX, currY, currZ);
-@@ -466,7 +453,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -450,7 +437,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
* @author Spottedleaf
*/
@Override
@@ -11307,7 +11272,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
// can only do this in this class, as not everything that implements BlockGetter can retrieve chunks
return fastClip(clipContext.getFrom(), clipContext.getTo(), (Level)(Object)this, clipContext);
}
-@@ -476,7 +463,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -460,7 +447,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
* @author Spottedleaf
*/
@Override
@@ -11316,7 +11281,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.getCollisionsForBlocksOrWorldBorder((Level)(Object)this, entity, box, null, null,
ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_CHECK_ONLY,
(final BlockState state, final BlockPos pos) -> {
-@@ -502,8 +489,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -486,8 +473,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
* @author Spottedleaf
*/
@Override
@@ -11327,7 +11292,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
if (boundsShape.isEmpty()) {
return java.util.Optional.empty();
}
-@@ -562,103 +549,139 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -546,103 +533,139 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
* @author Spottedleaf
*/
@Override
@@ -11387,12 +11352,12 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
- lastChunk = (LevelChunk)chunkSource.getChunk(newChunkX, newChunkZ, ChunkStatus.FULL, false);
- }
+ final ChunkSource chunkSource = this.getChunkSource();
-+
+
+- if (lastChunk == null) {
+ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) {
+ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) {
+ final ChunkAccess chunk = chunkSource.getChunk(currChunkX, currChunkZ, ChunkStatus.FULL, false);
-
-- if (lastChunk == null) {
++
+ if (chunk == null) {
continue;
}
@@ -11537,7 +11502,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
}
}
}
-@@ -667,6 +690,74 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -651,6 +674,74 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
return java.util.Optional.ofNullable(selected);
}
// Paper end - optimise collisions
@@ -11612,10 +11577,10 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
// Paper start - optimise random ticking
@Override
public abstract Holder<Biome> getUncachedNoiseBiome(final int x, final int y, final int z);
-@@ -685,6 +776,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+@@ -669,6 +760,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
// Paper end - optimise random ticking
- protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray
+ protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, Holder<DimensionType> holder, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator) { // Paper - create paper world config
+ // Paper start - getblock optimisations - cache world height/sections
+ final DimensionType dimType = holder.value();
+ this.minY = dimType.minY();
@@ -11628,6 +11593,24 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..41ecc30c1e38bf84655464d539ced435
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
this.generator = gen;
+@@ -1573,7 +1673,16 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
+ if (slices == null) {
+ return new org.bukkit.entity.Entity[0];
+ }
+- return slices.getChunkEntities();
++
++ List<org.bukkit.entity.Entity> ret = new java.util.ArrayList<>();
++ for (Entity entity : slices.getAllEntities()) {
++ org.bukkit.entity.Entity bukkit = entity.getBukkitEntity();
++ if (bukkit != null && bukkit.isValid()) {
++ ret.add(bukkit);
++ }
++ }
++
++ return ret.toArray(new org.bukkit.entity.Entity[0]);
+ }
+ // Paper end - rewrite chunk system
+
diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java
index 01352cc83b25eb0e30b7e0ff521fc7c1b3d5155b..90f8360f547ce709fd13ee34f8e67d8bfa94b498 100644
--- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java
@@ -11643,11 +11626,11 @@ index 01352cc83b25eb0e30b7e0ff521fc7c1b3d5155b..90f8360f547ce709fd13ee34f8e67d8b
public interface NoiseBiomeSource {
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 d0109633e8bdf109cfc9178963d7b6cf92f8b189..ad9c85c19146970371106050ec009a96075769c1 100644
+index a4b4fd83d201fff005c738c84fa5c1bc55d670bd..8631655a181735df53f8a02c9eb98f0cc13f55bb 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
-@@ -796,18 +796,12 @@ public abstract class BlockBehaviour implements FeatureElement {
- private boolean isRandomlyTicking;
+@@ -838,18 +838,12 @@ public abstract class BlockBehaviour implements FeatureElement {
+ private int lightBlock;
// Paper start - rewrite chunk system
- private int opacityIfCached;
@@ -11665,7 +11648,7 @@ index d0109633e8bdf109cfc9178963d7b6cf92f8b189..ad9c85c19146970371106050ec009a96
// Paper end - rewrite chunk system
// Paper start - optimise collisions
private static final int RANDOM_OFFSET = 704237939;
-@@ -817,16 +811,22 @@ public abstract class BlockBehaviour implements FeatureElement {
+@@ -859,16 +853,22 @@ public abstract class BlockBehaviour implements FeatureElement {
private final int id2 = it.unimi.dsi.fastutil.HashCommon.murmurHash3(it.unimi.dsi.fastutil.HashCommon.murmurHash3(ID_GENERATOR.getAndIncrement() + RANDOM_OFFSET) + RANDOM_OFFSET);
private boolean occludesFullBlock;
private boolean emptyCollisionShape;
@@ -11690,7 +11673,7 @@ index d0109633e8bdf109cfc9178963d7b6cf92f8b189..ad9c85c19146970371106050ec009a96
}
@Override
-@@ -844,6 +844,11 @@ public abstract class BlockBehaviour implements FeatureElement {
+@@ -886,6 +886,11 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.emptyCollisionShape;
}
@@ -11702,7 +11685,7 @@ index d0109633e8bdf109cfc9178963d7b6cf92f8b189..ad9c85c19146970371106050ec009a96
@Override
public final int moonrise$uniqueId1() {
return this.id1;
-@@ -855,14 +860,9 @@ public abstract class BlockBehaviour implements FeatureElement {
+@@ -897,14 +902,9 @@ public abstract class BlockBehaviour implements FeatureElement {
}
@Override
@@ -11718,8 +11701,8 @@ index d0109633e8bdf109cfc9178963d7b6cf92f8b189..ad9c85c19146970371106050ec009a96
// Paper end - optimise collisions
protected BlockStateBase(Block block, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<BlockState> codec) {
-@@ -931,39 +931,37 @@ public abstract class BlockBehaviour implements FeatureElement {
- this.legacySolid = this.calculateSolid();
+@@ -993,39 +993,37 @@ public abstract class BlockBehaviour implements FeatureElement {
+ this.lightBlock = ((Block) this.owner).getLightBlock(this.asState());
// Paper start - rewrite chunk system
this.isConditionallyFullOpaque = this.canOcclude & this.useShapeForLightOcclusion;
- this.opacityIfCached = this.cache == null || this.isConditionallyFullOpaque ? -1 : this.cache.lightBlock;
@@ -11773,10 +11756,10 @@ index d0109633e8bdf109cfc9178963d7b6cf92f8b189..ad9c85c19146970371106050ec009a96
// Paper end - optimise collisions
}
diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..97a7860b66be418399912307f8e68db9b4edf121 100644
+index 422b364764e0df16ca250b4939d7b226e69c0840..2df28ffc731bd77e0d7af3541cfd3741aa5af83b 100644
--- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-@@ -17,7 +17,7 @@ import java.util.stream.Collectors;
+@@ -15,7 +15,7 @@ import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.state.properties.Property;
@@ -11785,13 +11768,13 @@ index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..97a7860b66be418399912307f8e68db9
public static final String NAME_TAG = "Name";
public static final String PROPERTIES_TAG = "Properties";
public static final Function<Entry<Property<?>, Comparable<?>>, String> PROPERTY_ENTRY_TO_STRING_FUNCTION = new Function<Entry<Property<?>, Comparable<?>>, String>() {
-@@ -36,14 +36,28 @@ public abstract class StateHolder<O, S> {
+@@ -34,14 +34,28 @@ public abstract class StateHolder<O, S> {
}
};
protected final O owner;
- private final Reference2ObjectArrayMap<Property<?>, Comparable<?>> values;
-+ private Reference2ObjectArrayMap<Property<?>, Comparable<?>> values; // Paper - optimise blockstate property access - remove final
- private Table<Property<?>, Comparable<?>, S> neighbours;
++ private Reference2ObjectArrayMap<Property<?>, Comparable<?>> values; // Paper - optimise blockstate property access - remove final
+ private Map<Property<?>, S[]> neighbours;
protected final MapCodec<S> propertiesCodec;
+ // Paper start - optimise blockstate property access
@@ -11815,7 +11798,7 @@ index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..97a7860b66be418399912307f8e68db9
}
public <T extends Comparable<T>> S cycle(Property<T> property) {
-@@ -80,20 +94,21 @@ public abstract class StateHolder<O, S> {
+@@ -67,20 +81,21 @@ public abstract class StateHolder<O, S> {
}
public Collection<Property<?>> getProperties() {
@@ -11844,22 +11827,21 @@ index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..97a7860b66be418399912307f8e68db9
}
public <T extends Comparable<T>> Optional<T> getOptionalValue(Property<T> property) {
-@@ -102,36 +117,52 @@ public abstract class StateHolder<O, S> {
+@@ -93,22 +108,30 @@ public abstract class StateHolder<O, S> {
+
+ @Nullable
+ public <T extends Comparable<T>> T getNullableValue(Property<T> property) {
+- Comparable<?> comparable = this.values.get(property);
+- return comparable == null ? null : property.getValueClass().cast(comparable);
++ return property == null ? null : this.optimisedTable.get(this.tableIndex, property); // Paper - optimise blockstate property access
}
public <T extends Comparable<T>, V extends T> S setValue(Property<T> property, V value) {
- Comparable<?> comparable = this.values.get(property);
- if (comparable == null) {
- throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.owner);
-- } else if (comparable.equals(value)) {
-- return (S)this;
- } else {
-- S object = this.neighbours.get(property, value);
-- if (object == null) {
-- throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on " + this.owner + ", it is not an allowed value");
-- } else {
-- return object;
-- }
+- return this.setValueInternal(property, value, comparable);
+ // Paper start - optimise blockstate property access
+ final S ret = this.optimisedTable.set(this.tableIndex, property, value);
+ if (ret != null) {
@@ -11871,19 +11853,11 @@ index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..97a7860b66be418399912307f8e68db9
public <T extends Comparable<T>, V extends T> S trySetValue(Property<T> property, V value) {
- Comparable<?> comparable = this.values.get(property);
-- if (comparable != null && !comparable.equals(value)) {
-- S object = this.neighbours.get(property, value);
-- if (object == null) {
-- throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on " + this.owner + ", it is not an allowed value");
-- } else {
-- return object;
-- }
-- } else {
-- return (S)this;
+- return (S)(comparable == null ? this : this.setValueInternal(property, value, comparable));
+ // Paper start - optimise blockstate property access
+ if (property == null) {
+ return (S)(StateHolder<O, S>)(Object)this;
- }
++ }
+ final S ret = this.optimisedTable.trySet(this.tableIndex, property, value, (S)(StateHolder<O, S>)(Object)this);
+ if (ret != null) {
+ return ret;
@@ -11892,34 +11866,45 @@ index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..97a7860b66be418399912307f8e68db9
+ // Paper end - optimise blockstate property access
}
+ private <T extends Comparable<T>, V extends T> S setValueInternal(Property<T> property, V newValue, Comparable<?> oldValue) {
+@@ -125,18 +148,27 @@ public abstract class StateHolder<O, S> {
+ }
+
public void populateNeighbours(Map<Map<Property<?>, Comparable<?>>, S> states) {
+- if (this.neighbours != null) {
+- throw new IllegalStateException();
+- } else {
+- Map<Property<?>, S[]> map = new Reference2ObjectArrayMap<>(this.values.size());
+ // Paper start - optimise blockstate property access
+ final Map<Map<Property<?>, Comparable<?>>, S> map = states;
-+ if (true) {
-+ if (this.optimisedTable.isLoaded()) {
-+ return;
-+ }
-+ this.optimisedTable.loadInTable(map);
-+
-+ // de-duplicate the tables
-+ for (final Map.Entry<Map<Property<?>, Comparable<?>>, S> entry : map.entrySet()) {
-+ final S value = entry.getValue();
-+ ((StateHolder<O, S>)value).optimisedTable = this.optimisedTable;
-+ }
-+
-+ // remove values arrays
-+ for (final Map.Entry<Map<Property<?>, Comparable<?>>, S> entry : map.entrySet()) {
-+ final S value = entry.getValue();
-+ ((StateHolder<O, S>)value).values = null;
-+ }
-+
++ if (this.optimisedTable.isLoaded()) {
+ return;
+ }
-+ // Paper end - optimise blockstate property access
- if (this.neighbours != null) {
- throw new IllegalStateException();
- } else {
-@@ -158,7 +189,11 @@ public abstract class StateHolder<O, S> {
++ this.optimisedTable.loadInTable(map);
+
+- for (Entry<Property<?>, Comparable<?>> entry : this.values.entrySet()) {
+- Property<?> property = entry.getKey();
+- map.put(property, property.getPossibleValues().stream().map(value -> states.get(this.makeNeighbourValues(property, value))).toArray());
+- }
++ // de-duplicate the tables
++ for (final Map.Entry<Map<Property<?>, Comparable<?>>, S> entry : map.entrySet()) {
++ final S value = entry.getValue();
++ ((StateHolder<O, S>)value).optimisedTable = this.optimisedTable;
++ }
+
+- this.neighbours = map;
++ // remove values arrays
++ for (final Map.Entry<Map<Property<?>, Comparable<?>>, S> entry : map.entrySet()) {
++ final S value = entry.getValue();
++ ((StateHolder<O, S>)value).values = null;
+ }
++
++ return;
++ // Paper end optimise blockstate property access
+ }
+
+ private Map<Property<?>, Comparable<?>> makeNeighbourValues(Property<?> property, Comparable<?> value) {
+@@ -146,7 +178,11 @@ public abstract class StateHolder<O, S> {
}
public Map<Property<?>, Comparable<?>> getValues() {
@@ -11933,16 +11918,18 @@ index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..97a7860b66be418399912307f8e68db9
protected static <O, S extends StateHolder<O, S>> Codec<S> codec(Codec<O> codec, Function<O, S> ownerToStateFunction) {
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-index b63116b333b6e06494091a82588acfb639bddb71..054a2569b5b103835facef1e34867c60884e5c29 100644
+index ea76aa490358e9e1d13350ba0ea246ec2c423894..98058505d36baf74008da08339afc196713b14a7 100644
--- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-@@ -4,11 +4,21 @@ import com.google.common.collect.ImmutableSet;
- import java.util.Collection;
+@@ -3,13 +3,23 @@ package net.minecraft.world.level.block.state.properties;
+ import java.util.List;
import java.util.Optional;
--public class BooleanProperty extends Property<Boolean> {
-+public class BooleanProperty extends Property<Boolean> implements ca.spottedleaf.moonrise.patches.blockstate_propertyaccess.PropertyAccess<Boolean> { // Paper - optimise blockstate property access
- private final ImmutableSet<Boolean> values = ImmutableSet.of(true, false);
+-public final class BooleanProperty extends Property<Boolean> {
++public final class BooleanProperty extends Property<Boolean> implements ca.spottedleaf.moonrise.patches.blockstate_propertyaccess.PropertyAccess<Boolean> { // Paper - optimise blockstate property access
+ private static final List<Boolean> VALUES = List.of(true, false);
+ private static final int TRUE_INDEX = 0;
+ private static final int FALSE_INDEX = 1;
+ // Paper start - optimise blockstate property access
+ private static final Boolean[] BY_ID = new Boolean[]{ Boolean.FALSE, Boolean.TRUE };
@@ -11953,24 +11940,25 @@ index b63116b333b6e06494091a82588acfb639bddb71..054a2569b5b103835facef1e34867c60
+ }
+ // Paper end - optimise blockstate property access
+
- protected BooleanProperty(String name) {
+ private BooleanProperty(String name) {
super(name, Boolean.class);
+ this.moonrise$setById(BY_ID); // Paper - optimise blockstate property access
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-index 3097298fe356df98967cf4bdeaaede69dfe8a441..c23cb4ac167799e61ab9a4e1f43a5722d596332e 100644
+index 85a197232be9377c0313ec00e8f935551e2c60e0..30b2fce9e47ffcc3de1542b1d0f073f5640127a7 100644
--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-@@ -11,10 +11,38 @@ import java.util.function.Predicate;
+@@ -10,11 +10,39 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import net.minecraft.util.StringRepresentable;
--public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Property<T> {
-+public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Property<T> implements ca.spottedleaf.moonrise.patches.blockstate_propertyaccess.PropertyAccess<T> { // Paper - optimise blockstate property access
- private final ImmutableSet<T> values;
- private final Map<String, T> names = Maps.newHashMap();
+-public final class EnumProperty<T extends Enum<T> & StringRepresentable> extends Property<T> {
++public final class EnumProperty<T extends Enum<T> & StringRepresentable> extends Property<T> implements ca.spottedleaf.moonrise.patches.blockstate_propertyaccess.PropertyAccess<T> { // Paper - optimise blockstate property access
+ private final List<T> values;
+ private final Map<String, T> names;
+ private final int[] ordinalToIndex;
+ // Paper start - optimise blockstate property access
+ private int[] idLookupTable;
@@ -11982,7 +11970,7 @@ index 3097298fe356df98967cf4bdeaaede69dfe8a441..c23cb4ac167799e61ab9a4e1f43a5722
+ }
+
+ private void init() {
-+ final Collection<T> values = this.getPossibleValues();
++ final java.util.Collection<T> values = this.getPossibleValues();
+ final Class<T> clazz = this.getValueClass();
+
+ int id = 0;
@@ -12000,28 +11988,28 @@ index 3097298fe356df98967cf4bdeaaede69dfe8a441..c23cb4ac167799e61ab9a4e1f43a5722
+ }
+ // Paper end - optimise blockstate property access
+
- protected EnumProperty(String name, Class<T> type, Collection<T> values) {
+ private EnumProperty(String name, Class<T> type, List<T> values) {
super(name, type);
- this.values = ImmutableSet.copyOf(values);
-@@ -27,6 +55,7 @@ public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Prope
+ if (values.isEmpty()) {
+@@ -37,6 +65,7 @@ public final class EnumProperty<T extends Enum<T> & StringRepresentable> extends
- this.names.put(string, enum_);
+ this.names = builder.buildOrThrow();
}
+ this.init(); // Paper - optimise blockstate property access
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-index 3a850321a4bcc68058483b5fd53e829c425a68af..4a21ec538d7410159bb26b9bf3701605b5ef317f 100644
+index 55a87592a99105dbf57b26fb6ccba695295fce24..986365acc9983331a7982ea2e1eac2b0efe1506d 100644
--- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-@@ -6,11 +6,33 @@ import java.util.Collection;
+@@ -5,11 +5,33 @@ import java.util.List;
import java.util.Optional;
- import java.util.Set;
+ import java.util.stream.IntStream;
--public class IntegerProperty extends Property<Integer> {
-+public class IntegerProperty extends Property<Integer> implements ca.spottedleaf.moonrise.patches.blockstate_propertyaccess.PropertyAccess<Integer> { // Paper - optimise blockstate property access
- private final ImmutableSet<Integer> values;
+-public final class IntegerProperty extends Property<Integer> {
++public final class IntegerProperty extends Property<Integer> implements ca.spottedleaf.moonrise.patches.blockstate_propertyaccess.PropertyAccess<Integer> { // Paper - optimise blockstate property access
+ private final IntImmutableList values;
public final int min;
public final int max;
@@ -12047,19 +12035,19 @@ index 3a850321a4bcc68058483b5fd53e829c425a68af..4a21ec538d7410159bb26b9bf3701605
+ }
+ // Paper end - optimise blockstate property access
+
- protected IntegerProperty(String name, int min, int max) {
+ private IntegerProperty(String name, int min, int max) {
super(name, Integer.class);
if (min < 0) {
-@@ -28,6 +50,7 @@ public class IntegerProperty extends Property<Integer> {
-
- this.values = ImmutableSet.copyOf(set);
+@@ -21,6 +43,7 @@ public final class IntegerProperty extends Property<Integer> {
+ this.max = max;
+ this.values = IntImmutableList.toList(IntStream.range(min, max + 1));
}
+ this.init(); // Paper - optimise blockstate property access
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
-index 9055f15af0cae55effa6942913a9d7edf3857e07..e63a7541f43e5c8f92f348c4e49756b33698c668 100644
+index fcf04c5c58ff35d38c5bf0df562ae2f8dc98a0ee..0b116160924300a9d62ad5948bfaf276f0386e4d 100644
--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
@@ -10,7 +10,7 @@ import java.util.stream.Stream;
@@ -12111,7 +12099,7 @@ index 9055f15af0cae55effa6942913a9d7edf3857e07..e63a7541f43e5c8f92f348c4e49756b3
public Property.Value<T> value(T value) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java b/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java
-index c5e1040c239874dcf20b79472bf690ee7f0a9e5f..0f403e0c257b1304be2ede89b8529676dbe8c32b 100644
+index 98dbeaf8bde15940e5b5d5d1f13fd4bb32f0a10d..7beea075b5a7ef738a4ac0558b99f4c5708f2c4a 100644
--- a/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java
+++ b/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java
@@ -8,12 +8,19 @@ import net.minecraft.network.FriendlyByteBuf;
@@ -12136,10 +12124,10 @@ index c5e1040c239874dcf20b79472bf690ee7f0a9e5f..0f403e0c257b1304be2ede89b8529676
this(idList, bits, listener);
entries.forEach(this.values::add);
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
-index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..170df85f42410f4766b04e73fc3a95e6dc4a3b8a 100644
+index a61294befc2f855fcecb2336a2d5444ce60e0a3a..a0e51681731dc7b487d5b14ae0d44a881bd5cb09 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
-@@ -53,7 +53,7 @@ import net.minecraft.world.ticks.LevelChunkTicks;
+@@ -54,7 +54,7 @@ import net.minecraft.world.ticks.LevelChunkTicks;
import net.minecraft.world.ticks.TickContainerAccess;
import org.slf4j.Logger;
@@ -12148,12 +12136,30 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..170df85f42410f4766b04e73fc3a95e6
static final Logger LOGGER = LogUtils.getLogger();
private static final TickingBlockEntity NULL_TICKER = new TickingBlockEntity() {
+@@ -688,7 +688,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
+ */
+ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
+ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration));
+- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(this.locX, this.locZ).getEntityChunk().callEntitiesLoadEvent(); // Paper - rewrite chunk system
++ org.bukkit.craftbukkit.event.CraftEventFactory.callEntitiesLoadEvent(this.level, this.chunkPos, ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(this.locX, this.locZ).getEntityChunk().getAllEntities()); // Paper - rewrite chunk system
+
+ if (this.needsDecoration) {
+ try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper
+@@ -719,7 +719,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
+ public void unloadCallback() {
+ if (!this.loadedTicketLevel) { LOGGER.error("Double calling chunk unload!", new Throwable()); } // Paper
+ org.bukkit.Server server = this.level.getCraftServer();
+- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(this.locX, this.locZ).getEntityChunk().callEntitiesUnloadEvent(); // Paper - rewrite chunk system
++ org.bukkit.craftbukkit.event.CraftEventFactory.callEntitiesUnloadEvent(this.level, this.chunkPos, ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(this.locX, this.locZ).getEntityChunk().getAllEntities()); // Paper - rewrite chunk system
+ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
+ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(bukkitChunk, true); // Paper - rewrite chunk system - force save to true so that mustNotSave is correctly set below
+ server.getPluginManager().callEvent(unloadEvent);
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
-index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323269e1a74 100644
+index 161211124f3f8390530af7ab21f3a0f1025209c5..4167ed830382c6a76bb281e9d753919925c6bd00 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
-@@ -27,15 +27,17 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
- private PalettedContainer<Holder<Biome>> biomes;
+@@ -26,15 +26,17 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+ private PalettedContainer<Holder<Biome>> biomes; // CraftBukkit - read/write
// Paper start - block counting
- private static final it.unimi.dsi.fastutil.ints.IntArrayList FULL_LIST = new it.unimi.dsi.fastutil.ints.IntArrayList(16*16*16);
@@ -12174,7 +12180,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
@Override
public final int moonrise$getSpecialCollidingBlocks() {
-@@ -43,7 +45,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -42,7 +44,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
}
@Override
@@ -12183,7 +12189,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
return this.tickingBlocks;
}
// Paper end - block counting
-@@ -83,6 +85,45 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -86,6 +88,45 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
return this.setBlockState(x, y, z, state, true);
}
@@ -12229,7 +12235,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
public BlockState setBlockState(int x, int y, int z, BlockState state, boolean lock) {
BlockState iblockdata1;
-@@ -102,7 +143,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -105,7 +146,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
}
}
@@ -12238,7 +12244,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
--this.tickingFluidCount;
}
-@@ -113,25 +154,11 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -116,25 +157,11 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
}
}
@@ -12266,7 +12272,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
return iblockdata1;
}
-@@ -167,7 +194,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -170,7 +197,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
final int paletteSize = palette.getSize();
final net.minecraft.util.BitStorage storage = data.storage();
@@ -12275,7 +12281,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
if (paletteSize == 1) {
counts = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(1);
counts.put(0, FULL_LIST);
-@@ -175,10 +202,10 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -178,10 +205,10 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
counts = ((ca.spottedleaf.moonrise.patches.block_counting.BlockCountingBitStorage)storage).moonrise$countEntries();
}
@@ -12289,7 +12295,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
final int paletteCount = coordinates.size();
final BlockState state = palette.valueFor(paletteIdx);
-@@ -188,25 +215,30 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -191,25 +218,30 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
}
if (ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isSpecialCollidingBlock(state)) {
@@ -12327,7 +12333,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
}
}
}
-@@ -229,7 +261,11 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
+@@ -232,7 +264,11 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
datapaletteblock.read(buf);
this.biomes = datapaletteblock;
@@ -12341,7 +12347,7 @@ index c3b1caa352b988ec44fa2b2eb0536517711f5460..df1b3f3ae48f66137484e0eb3f4c7323
public void readBiomes(FriendlyByteBuf buf) {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LinearPalette.java b/src/main/java/net/minecraft/world/level/chunk/LinearPalette.java
-index f4c3f2a49b8d023b8ef67529eba30cf31467d8bf..716eb6f406db4b81b8854de0ea693a72f9ca9d13 100644
+index bc4d9452bbeb05a691fd285603e49491f41d3ad2..f8d9892970c9092f7cc84434d4fbf34354ce1195 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LinearPalette.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LinearPalette.java
@@ -7,13 +7,20 @@ import net.minecraft.network.FriendlyByteBuf;
@@ -12367,7 +12373,7 @@ index f4c3f2a49b8d023b8ef67529eba30cf31467d8bf..716eb6f406db4b81b8854de0ea693a72
this.registry = idList;
this.values = (T[])(new Object[1 << bits]);
diff --git a/src/main/java/net/minecraft/world/level/chunk/Palette.java b/src/main/java/net/minecraft/world/level/chunk/Palette.java
-index e379f39cc6e03723a5323d8392b4c10bfde65115..882284fe7beeb56a8b35ac6153ff41e84ebad27e 100644
+index b8922e4a13df535cdc5701e893a6e460b33ff90d..100807f8b8337f56f49cdb818ccc75be2f08ecd1 100644
--- a/src/main/java/net/minecraft/world/level/chunk/Palette.java
+++ b/src/main/java/net/minecraft/world/level/chunk/Palette.java
@@ -5,7 +5,7 @@ import java.util.function.Predicate;
@@ -12380,11 +12386,11 @@ index e379f39cc6e03723a5323d8392b4c10bfde65115..882284fe7beeb56a8b35ac6153ff41e8
boolean maybeHas(Predicate<T> predicate);
diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
-index 13d3c877b006a4975e7370713e3919c661e7890f..955862559b8c751b82082a5c0e02031324bf4805 100644
+index b46c58c952e183bd74854c3eb70d64979af70f18..533167eaa8bd39006fb1c7e193c81359973da9af 100644
--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
-@@ -41,6 +41,33 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
- // this.threadingDetector.checkAndUnlock(); // Paper - disable this
+@@ -71,6 +71,33 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+ );
}
+ // Paper start - optimise palette reads
@@ -12414,26 +12420,25 @@ index 13d3c877b006a4975e7370713e3919c661e7890f..955862559b8c751b82082a5c0e020313
+ }
+ // Paper end - optimise palette reads
+
- // Paper start - Anti-Xray - Add preset values
- @Deprecated @io.papermc.paper.annotation.DoNotUse public static <T> Codec<PalettedContainer<T>> codecRW(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy paletteProvider, T defaultValue) { return PalettedContainer.codecRW(idList, entryCodec, paletteProvider, defaultValue, null); }
- public static <T> Codec<PalettedContainer<T>> codecRW(IdMap<T> idList, Codec<T> entryCodec, PalettedContainer.Strategy paletteProvider, T defaultValue, T @org.jetbrains.annotations.Nullable [] presetValues) {
-@@ -113,6 +140,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
- }
- }
- // Paper end
+ public PalettedContainer(
+ IdMap<T> idList,
+ PalettedContainer.Strategy paletteProvider,
+@@ -81,12 +108,14 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+ this.registry = idList;
+ this.strategy = paletteProvider;
+ this.data = new PalettedContainer.Data<>(dataProvider, storage, dataProvider.factory().create(dataProvider.bits(), idList, this, paletteEntries));
+ this.updateData(this.data); // Paper - optimise palette reads
}
- // Paper start - Anti-Xray - Add preset values
-@@ -122,6 +150,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+ private PalettedContainer(IdMap<T> idList, PalettedContainer.Strategy paletteProvider, PalettedContainer.Data<T> data) {
this.registry = idList;
this.strategy = paletteProvider;
this.data = data;
+ this.updateData(this.data); // Paper - optimise palette reads
}
- // Paper start - Anti-Xray - Add preset values
-@@ -133,6 +162,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+ private PalettedContainer(PalettedContainer<T> container) {
+@@ -100,6 +129,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
this.registry = idList;
this.data = this.createOrReuseData(null, 0);
this.data.palette.idFor(object);
@@ -12441,15 +12446,15 @@ index 13d3c877b006a4975e7370713e3919c661e7890f..955862559b8c751b82082a5c0e020313
}
private PalettedContainer.Data<T> createOrReuseData(@Nullable PalettedContainer.Data<T> previousData, int bits) {
-@@ -158,6 +188,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+@@ -115,6 +145,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
PalettedContainer.Data<T> data2 = this.createOrReuseData(data, newBits);
data2.copyFrom(data.palette, data.storage);
this.data = data2;
+ this.updateData(this.data); // Paper - optimise palette reads
- this.addPresetValues();
- return object == null ? -1 : data2.palette.idFor(object);
- // Paper end
-@@ -191,9 +222,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+ return data2.palette.idFor(object);
+ }
+
+@@ -136,9 +167,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
}
private synchronized T getAndSet(int index, T value) { // Paper - synchronize
@@ -12465,7 +12470,7 @@ index 13d3c877b006a4975e7370713e3919c661e7890f..955862559b8c751b82082a5c0e020313
}
public void set(int x, int y, int z, T value) {
-@@ -217,8 +251,10 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+@@ -162,8 +196,10 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
}
public T get(int index) { // Paper - public
@@ -12478,15 +12483,15 @@ index 13d3c877b006a4975e7370713e3919c661e7890f..955862559b8c751b82082a5c0e020313
}
@Override
-@@ -238,6 +274,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+@@ -183,6 +219,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
data.palette.read(buf);
buf.readLongArray(data.storage.getRaw());
this.data = data;
+ this.updateData(this.data); // Paper - optimise palette reads
- this.addPresetValues(); // Paper - Anti-Xray - Add preset values (inefficient, but this isn't used by the server)
} finally {
this.release();
-@@ -386,7 +423,44 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
+ }
+@@ -323,7 +360,44 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
void accept(T object, int count);
}
@@ -12533,7 +12538,7 @@ index 13d3c877b006a4975e7370713e3919c661e7890f..955862559b8c751b82082a5c0e020313
for (int i = 0; i < storage.getSize(); i++) {
T object = palette.valueFor(storage.get(i));
diff --git a/src/main/java/net/minecraft/world/level/chunk/SingleValuePalette.java b/src/main/java/net/minecraft/world/level/chunk/SingleValuePalette.java
-index 24b608cfcd6f39db02e682e5d8162dc4ad9fd6d6..3a06392a327f26d78c28fdcce39f74b130c4d906 100644
+index a45e6410600afc5464e5d29932c193786ce0a6fb..a1ba68c95c2cdebdc0d7782cce7895529918073c 100644
--- a/src/main/java/net/minecraft/world/level/chunk/SingleValuePalette.java
+++ b/src/main/java/net/minecraft/world/level/chunk/SingleValuePalette.java
@@ -8,12 +8,24 @@ import net.minecraft.network.FriendlyByteBuf;
@@ -12587,10 +12592,10 @@ index 24b608cfcd6f39db02e682e5d8162dc4ad9fd6d6..3a06392a327f26d78c28fdcce39f74b1
@Override
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 1e0439cf3f4008fa430acb90b45f5bc4cdd6d7f2..e46bdcbf3514eaa6f4990a797a63c5041a142807 100644
+index f1237f6fd6414900ffbad0caee31aa83310eeef4..8071ce70d66909bb4bda45792bf329a939d6f918 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
-@@ -28,7 +28,7 @@ import net.minecraft.nbt.NbtIo; // Paper
+@@ -25,7 +25,7 @@ import net.minecraft.util.profiling.jfr.JvmProfiler;
import net.minecraft.world.level.ChunkPos;
import org.slf4j.Logger;
@@ -12599,13 +12604,13 @@ index 1e0439cf3f4008fa430acb90b45f5bc4cdd6d7f2..e46bdcbf3514eaa6f4990a797a63c504
private static final Logger LOGGER = LogUtils.getLogger();
private static final int SECTOR_BYTES = 4096;
-@@ -51,6 +51,20 @@ public class RegionFile implements AutoCloseable {
- private final IntBuffer timestamps;
+@@ -49,6 +49,21 @@ public class RegionFile implements AutoCloseable {
@VisibleForTesting
protected final RegionBitmap usedSectors;
+
+ // Paper start - rewrite chunk system
+ @Override
-+ public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(final CompoundTag data, final ChunkPos pos) throws IOException {
++ public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(final net.minecraft.nbt.CompoundTag data, final ChunkPos pos) throws IOException {
+ final RegionFile.ChunkBuffer buffer = ((RegionFile)(Object)this).new ChunkBuffer(pos);
+ ((ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemChunkBuffer)buffer).moonrise$setWriteOnClose(false);
+
@@ -12617,10 +12622,11 @@ index 1e0439cf3f4008fa430acb90b45f5bc4cdd6d7f2..e46bdcbf3514eaa6f4990a797a63c504
+ );
+ }
+ // Paper end - rewrite chunk system
- // Paper start - Attempt to recalculate regionfile header if it is corrupt
- private static long roundToSectors(long bytes) {
- long sectors = bytes >>> 12; // 4096 = 2^12
-@@ -682,6 +696,16 @@ public class RegionFile implements AutoCloseable {
++
+ public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException {
+ this(storageKey, directory, path, RegionFileVersion.getSelected(), dsync);
+ }
+@@ -220,6 +235,16 @@ public class RegionFile implements AutoCloseable {
@Nullable
private DataInputStream createExternalChunkInputStream(ChunkPos pos, byte flags) throws IOException {
@@ -12637,10 +12643,10 @@ index 1e0439cf3f4008fa430acb90b45f5bc4cdd6d7f2..e46bdcbf3514eaa6f4990a797a63c504
Path path = this.getExternalChunkPath(pos);
if (!Files.isRegularFile(path, new LinkOption[0])) {
-@@ -978,10 +1002,29 @@ public class RegionFile implements AutoCloseable {
-
+@@ -443,10 +468,29 @@ public class RegionFile implements AutoCloseable {
}
- // Paper end
+
+ public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails
- private class ChunkBuffer extends ByteArrayOutputStream {
+ private class ChunkBuffer extends ByteArrayOutputStream implements ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemChunkBuffer { // Paper - rewrite chunk system
@@ -12668,7 +12674,7 @@ index 1e0439cf3f4008fa430acb90b45f5bc4cdd6d7f2..e46bdcbf3514eaa6f4990a797a63c504
public ChunkBuffer(final ChunkPos chunkcoordintpair) {
super(8096);
super.write(0);
-@@ -1015,7 +1058,7 @@ public class RegionFile implements AutoCloseable {
+@@ -480,7 +524,7 @@ public class RegionFile implements AutoCloseable {
JvmProfiler.INSTANCE.onRegionFileWrite(RegionFile.this.info, this.pos, RegionFile.this.version, i);
bytebuffer.putInt(0, i);
@@ -12678,7 +12684,7 @@ index 1e0439cf3f4008fa430acb90b45f5bc4cdd6d7f2..e46bdcbf3514eaa6f4990a797a63c504
}
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 40689256711cc94a806ca1da346f4f62eda31526..b0ace4c7f25425a58c0707e7a7992446164bef88 100644
+index 18054304e08c8a6346c0135a0e6a68e77fe5c37c..9dbc9e2f9d5aab71720bb81803efe76e2f361f04 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -28,8 +28,8 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -12788,10 +12794,10 @@ index 40689256711cc94a806ca1da346f4f62eda31526..b0ace4c7f25425a58c0707e7a7992446
+ }
+ }
// Paper end - rewrite chunk system
- // Paper start - recalculate region file headers
- private final boolean isChunkData;
-@@ -143,6 +234,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
- this.isChunkData = isChunkDataFolder(this.folder); // Paper - recalculate region file headers
+
+ protected RegionFileStorage(RegionStorageInfo storageKey, Path directory, boolean dsync) { // Paper - protected
+@@ -112,6 +203,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
+ this.info = storageKey;
}
+ // Paper start - rewrite chunk system
@@ -12804,7 +12810,7 @@ index 40689256711cc94a806ca1da346f4f62eda31526..b0ace4c7f25425a58c0707e7a7992446
// Paper start - rewrite chunk system
if (existingOnly) {
diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
-index 1c0712295695727ee9c4d430d4157b8e17cbd71f..7b8e5be1648ef8741aadabd6cbdcf991012c3ce2 100644
+index 261e5994d13f8bc30490b86691c80c0a21e7640a..f4fbcbb8ff6d2677af1a02a0801a323c06dce9b1 100644
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
@@ -55,6 +55,48 @@ public abstract class FlowingFluid extends Fluid {
@@ -12856,12 +12862,12 @@ index 1c0712295695727ee9c4d430d4157b8e17cbd71f..7b8e5be1648ef8741aadabd6cbdcf991
public FlowingFluid() {}
@Override
-@@ -239,53 +281,70 @@ public abstract class FlowingFluid extends Fluid {
+@@ -246,65 +288,70 @@ public abstract class FlowingFluid extends Fluid {
}
}
-- private boolean canPassThroughWall(Direction face, BlockGetter world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState) {
-- Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap;
+- private static boolean canPassThroughWall(Direction face, BlockGetter world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState) {
+- VoxelShape voxelshape = fromState.getCollisionShape(world, fromPos);
+ // Paper start - fluid method optimisations
+ private static boolean canPassThroughWall(final Direction direction, final BlockGetter level,
+ final BlockPos fromPos, final BlockState fromState,
@@ -12871,56 +12877,71 @@ index 1c0712295695727ee9c4d430d4157b8e17cbd71f..7b8e5be1648ef8741aadabd6cbdcf991
+ return true;
+ }
-- if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) {
-- object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get();
-- } else {
-- object2bytelinkedopenhashmap = null;
+- if (voxelshape == Shapes.block()) {
+ if (((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)fromState).moonrise$occludesFullBlock() | ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)toState).moonrise$occludesFullBlock()) {
+ // don't even try to cache simple cases
-+ return false;
- }
+ return false;
+- } else {
+- VoxelShape voxelshape1 = state.getCollisionShape(world, pos);
+-
+- if (voxelshape1 == Shapes.block()) {
+- return false;
+- } else if (voxelshape1 == Shapes.empty() && voxelshape == Shapes.empty()) {
+- return true;
+- } else {
+- Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap;
+-
+- if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) {
+- object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get();
+- } else {
+- object2bytelinkedopenhashmap = null;
+- }
++ }
-- Block.BlockStatePairKey block_a;
+- FlowingFluid.BlockStatePairKey fluidtypeflowing_a;
+ final ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey[] cache = ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)fromState).moonrise$hasCache() & ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)toState).moonrise$hasCache() ?
+ COLLISION_OCCLUSION_CACHE.get() : null;
-- if (object2bytelinkedopenhashmap != null) {
-- block_a = new Block.BlockStatePairKey(state, fromState, face);
-- byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a);
+- if (object2bytelinkedopenhashmap != null) {
+- fluidtypeflowing_a = new FlowingFluid.BlockStatePairKey(state, fromState, face);
+- byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(fluidtypeflowing_a);
+ final int keyIndex
+ = (((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)fromState).moonrise$uniqueId1() ^ ((ca.spottedleaf.moonrise.patches.collisions.block.CollisionBlockState)toState).moonrise$uniqueId2() ^ ((ca.spottedleaf.moonrise.patches.collisions.util.CollisionDirection)(Object)direction).moonrise$uniqueId())
+ & (COLLISION_OCCLUSION_CACHE_SIZE - 1);
-- if (b0 != 127) {
-- return b0 != 0;
+- if (b0 != 127) {
+- return b0 != 0;
+- }
+- } else {
+- fluidtypeflowing_a = null;
+- }
+-
+- boolean flag = !Shapes.mergedFaceOccludes(voxelshape1, voxelshape, face);
+ if (cache != null) {
+ final ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey cached = cache[keyIndex];
+ if (cached != null && cached.first() == fromState && cached.second() == toState && cached.direction() == direction) {
+ return cached.result();
- }
-- } else {
-- block_a = null;
- }
++ }
++ }
-- VoxelShape voxelshape = state.getCollisionShape(world, pos);
-- VoxelShape voxelshape1 = fromState.getCollisionShape(world, fromPos);
-- boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, face);
+- if (object2bytelinkedopenhashmap != null) {
+- if (object2bytelinkedopenhashmap.size() == 200) {
+- object2bytelinkedopenhashmap.removeLastByte();
+- }
+ final VoxelShape shape1 = fromState.getCollisionShape(level, fromPos);
+ final VoxelShape shape2 = toState.getCollisionShape(level, toPos);
-- if (object2bytelinkedopenhashmap != null) {
-- if (object2bytelinkedopenhashmap.size() == 200) {
-- object2bytelinkedopenhashmap.removeLastByte();
-- }
+- object2bytelinkedopenhashmap.putAndMoveToFirst(fluidtypeflowing_a, (byte) (flag ? 1 : 0));
+- }
+ final boolean result = !Shapes.mergedFaceOccludes(shape1, shape2, direction);
-- object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0));
+- return flag;
+- }
+ if (cache != null) {
+ // we can afford to replace in-use keys more often due to the excessive caching the collision patch does in mergedFaceOccludes
+ cache[keyIndex] = new ca.spottedleaf.moonrise.patches.collisions.util.FluidOcclusionCacheKey(fromState, toState, direction, result);
}
-
-- return flag;
++
+ return result;
}
+ // Paper end - fluid method optimisations
@@ -12951,12 +12972,12 @@ index 1c0712295695727ee9c4d430d4157b8e17cbd71f..7b8e5be1648ef8741aadabd6cbdcf991
+ // Paper end - fluid method optimisations
}
- protected abstract boolean canConvertToSource(Level world);
+ protected abstract boolean canConvertToSource(ServerLevel world);
diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java
-index 14bb12d2a0066e8b020f2e0e670a7a5c74633623..8ceeb053a391d1a53083eb0680cf34c453afcba2 100644
+index 87adfe152abd1b8b4d547034576883c5d1cdf134..2d50d72bf026d0cf9c546a3c6fc1859379bfd805 100644
--- a/src/main/java/net/minecraft/world/level/material/FluidState.java
+++ b/src/main/java/net/minecraft/world/level/material/FluidState.java
-@@ -21,12 +21,30 @@ import net.minecraft.world.level.block.state.properties.Property;
+@@ -22,12 +22,30 @@ import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
@@ -12988,7 +13009,7 @@ index 14bb12d2a0066e8b020f2e0e670a7a5c74633623..8ceeb053a391d1a53083eb0680cf34c4
public FluidState(Fluid fluid, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<FluidState> codec) {
super(fluid, propertyMap, codec);
this.isEmpty = fluid.isEmpty(); // Paper - Perf: moved from isEmpty()
-@@ -37,11 +55,11 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
+@@ -38,11 +56,11 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public boolean isSource() {
@@ -13002,7 +13023,7 @@ index 14bb12d2a0066e8b020f2e0e670a7a5c74633623..8ceeb053a391d1a53083eb0680cf34c4
}
public boolean isEmpty() {
-@@ -53,11 +71,11 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
+@@ -54,11 +72,11 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public float getOwnHeight() {
@@ -13016,7 +13037,7 @@ index 14bb12d2a0066e8b020f2e0e670a7a5c74633623..8ceeb053a391d1a53083eb0680cf34c4
}
public boolean shouldRenderBackwardUpFace(BlockGetter world, BlockPos pos) {
-@@ -83,7 +101,7 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
+@@ -84,7 +102,7 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public boolean isRandomlyTicking() {
@@ -13024,8 +13045,8 @@ index 14bb12d2a0066e8b020f2e0e670a7a5c74633623..8ceeb053a391d1a53083eb0680cf34c4
+ return this.isRandomlyTicking; // Paper - fluid method optimisations
}
- public void randomTick(Level world, BlockPos pos, RandomSource random) {
-@@ -95,7 +113,12 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
+ public void randomTick(ServerLevel world, BlockPos pos, RandomSource random) {
+@@ -96,7 +114,12 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public BlockState createLegacyBlock() {
@@ -13053,7 +13074,7 @@ index 1d36f8dcffd22cf844448d3d8351fb8718cf5227..fbe0c4b0fdbb992b7002f6afe1e74d63
final int minFullX = discreteVoxelShape.firstFull(Direction.Axis.X);
final int minFullY = discreteVoxelShape.firstFull(Direction.Axis.Y);
diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
-index c348171c150bf69d24303d0862e45ab78baddcab..4c8185fbc560a5c5304729e5827ae7762933ec36 100644
+index 672a2038c6d8b31090403766460c6149a75adf8b..513bed7f11aee667c87046db4cf912b80e8f3638 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
@@ -180,13 +180,13 @@ public final class Shapes {
@@ -13072,32 +13093,8 @@ index c348171c150bf69d24303d0862e45ab78baddcab..4c8185fbc560a5c5304729e5827ae776
// Paper end - optimise collisions
}
-@@ -255,7 +255,22 @@ public final class Shapes {
- }
-
- public static VoxelShape getFaceShape(VoxelShape shape, Direction direction) {
-- return ((ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape)shape).moonrise$getFaceShapeClamped(direction); // Paper - optimise collisions
-+ if (shape == block()) {
-+ return block();
-+ } else {
-+ Direction.Axis axis = direction.getAxis();
-+ boolean bl;
-+ int i;
-+ if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
-+ bl = DoubleMath.fuzzyEquals(shape.max(axis), 1.0, 1.0E-7);
-+ i = shape.shape.getSize(axis) - 1;
-+ } else {
-+ bl = DoubleMath.fuzzyEquals(shape.min(axis), 0.0, 1.0E-7);
-+ i = 0;
-+ }
-+
-+ return (VoxelShape)(!bl ? empty() : new SliceShape(shape, axis, i));
-+ }
- }
-
- // Paper start - optimise collisions
diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
-index 11824d39e72fa003b3a56aa9b8d679fe8e23a1a4..c207e54dc52e67ba91dac5c6ce1391a77f597bcd 100644
+index d850a7de74150a04622da71d9614320f3d5d69e8..3f8e7e29c3e52211a29e6f0a32890f6b53bfd9a8 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java
@@ -162,13 +162,13 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
@@ -13238,7 +13235,7 @@ index 11824d39e72fa003b3a56aa9b8d679fe8e23a1a4..c207e54dc52e67ba91dac5c6ce1391a7
}
public abstract DoubleList getCoords(Direction.Axis axis);
-@@ -547,9 +565,9 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
+@@ -551,9 +569,9 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
final ArrayVoxelShape ret = new ArrayVoxelShape(
this.shape,
@@ -13251,7 +13248,7 @@ index 11824d39e72fa003b3a56aa9b8d679fe8e23a1a4..c207e54dc52e67ba91dac5c6ce1391a7
);
final ca.spottedleaf.moonrise.patches.collisions.shape.CachedToAABBs cachedToAABBs = this.cachedToAABBs;
-@@ -574,6 +592,11 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
+@@ -578,6 +596,11 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
final List<AABB> aabbs = this.toAabbs();
@@ -13263,7 +13260,7 @@ index 11824d39e72fa003b3a56aa9b8d679fe8e23a1a4..c207e54dc52e67ba91dac5c6ce1391a7
if (aabbs.size() == 1) {
final AABB singleAABB = aabbs.get(0);
final VoxelShape ret = Shapes.create(singleAABB);
-@@ -700,7 +723,32 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
+@@ -704,7 +727,32 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
}
protected int findIndex(Direction.Axis axis, double coord) {
@@ -13297,7 +13294,7 @@ index 11824d39e72fa003b3a56aa9b8d679fe8e23a1a4..c207e54dc52e67ba91dac5c6ce1391a7
}
@Nullable
-@@ -723,13 +771,13 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
+@@ -727,13 +775,13 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
final AABB singleAABB = this.singleAABBRepresentation;
if (singleAABB != null) {
if (singleAABB.contains(fromBehindOffsetX, fromBehindOffsetY, fromBehindOffsetZ)) {
@@ -13313,20 +13310,23 @@ index 11824d39e72fa003b3a56aa9b8d679fe8e23a1a4..c207e54dc52e67ba91dac5c6ce1391a7
}
return AABB.clip(((VoxelShape)(Object)this).toAabbs(), from, to, offset);
-@@ -783,17 +831,23 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
+@@ -786,20 +834,24 @@ public abstract class VoxelShape implements ca.spottedleaf.moonrise.patches.coll
+ }
}
- private VoxelShape calculateFace(Direction direction) {
-- Direction.Axis axis = direction.getAxis();
-- DoubleList doubleList = this.getCoords(axis);
-- if (doubleList.size() == 2
-- && DoubleMath.fuzzyEquals(doubleList.getDouble(0), 0.0, 1.0E-7)
-- && DoubleMath.fuzzyEquals(doubleList.getDouble(1), 1.0, 1.0E-7)) {
+- private VoxelShape calculateFace(Direction facing) {
+- Direction.Axis axis = facing.getAxis();
+- if (this.isCubeLikeAlong(axis)) {
- return this;
- } else {
-- Direction.AxisDirection axisDirection = direction.getAxisDirection();
+- Direction.AxisDirection axisDirection = facing.getAxisDirection();
- int i = this.findIndex(axis, axisDirection == Direction.AxisDirection.POSITIVE ? 0.9999999 : 1.0E-7);
-- return new SliceShape(this, axis, i);
+- SliceShape sliceShape = new SliceShape(this, axis, i);
+- if (sliceShape.isEmpty()) {
+- return Shapes.empty();
+- } else {
+- return (VoxelShape)(sliceShape.isCubeLike() ? Shapes.block() : sliceShape);
++ private VoxelShape calculateFace(Direction direction) {
+ // Paper start - optimise collisions
+ final Direction.Axis axis = direction.getAxis();
+ switch (axis) {
@@ -13341,9 +13341,9 @@ index 11824d39e72fa003b3a56aa9b8d679fe8e23a1a4..c207e54dc52e67ba91dac5c6ce1391a7
+ }
+ default: {
+ throw new IllegalStateException("Unknown axis: " + axis);
-+ }
+ }
}
+ // Paper end - optimise collisions
}
- // Paper start - optimise collisions
+ protected boolean isCubeLike() {
diff --git a/patches/server/1071-Revert-Custom-table-implementation-for-blockstate-st.patch b/patches/server/1071-Revert-Custom-table-implementation-for-blockstate-st.patch
deleted file mode 100644
index fa362b310f..0000000000
--- a/patches/server/1071-Revert-Custom-table-implementation-for-blockstate-st.patch
+++ /dev/null
@@ -1,345 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Spottedleaf <[email protected]>
-Date: Mon, 21 Oct 2024 12:52:44 -0700
-Subject: [PATCH] Revert "Custom table implementation for blockstate state
- lookups"
-
-This reverts commit 14a7e6521ba0ce6dc8ebf98a1ccce59a5ec6a194.
-
-TODO Replace via deleting the patch
-
-diff --git a/src/main/java/io/papermc/paper/util/table/ZeroCollidingReferenceStateTable.java b/src/main/java/io/papermc/paper/util/table/ZeroCollidingReferenceStateTable.java
-deleted file mode 100644
-index 57d0cd3ad6f972e986c72a57f1a6e36003f190c2..0000000000000000000000000000000000000000
---- a/src/main/java/io/papermc/paper/util/table/ZeroCollidingReferenceStateTable.java
-+++ /dev/null
-@@ -1,160 +0,0 @@
--package io.papermc.paper.util.table;
--
--import com.google.common.collect.Table;
--import net.minecraft.world.level.block.state.StateHolder;
--import net.minecraft.world.level.block.state.properties.Property;
--import java.util.Collection;
--import java.util.HashSet;
--import java.util.Map;
--import java.util.Set;
--
--public final class ZeroCollidingReferenceStateTable {
--
-- // upper 32 bits: starting index
-- // lower 32 bits: bitset for contained ids
-- protected final long[] this_index_table;
-- protected final Comparable<?>[] this_table;
-- protected final StateHolder<?, ?> this_state;
--
-- protected long[] index_table;
-- protected StateHolder<?, ?>[][] value_table;
--
-- public ZeroCollidingReferenceStateTable(final StateHolder<?, ?> state, final Map<Property<?>, Comparable<?>> this_map) {
-- this.this_state = state;
-- this.this_index_table = this.create_table(this_map.keySet());
--
-- int max_id = -1;
-- for (final Property<?> property : this_map.keySet()) {
-- final int id = lookup_vindex(property, this.this_index_table);
-- if (id > max_id) {
-- max_id = id;
-- }
-- }
--
-- this.this_table = new Comparable[max_id + 1];
-- for (final Map.Entry<Property<?>, Comparable<?>> entry : this_map.entrySet()) {
-- this.this_table[lookup_vindex(entry.getKey(), this.this_index_table)] = entry.getValue();
-- }
-- }
--
-- public void loadInTable(final Table<Property<?>, Comparable<?>, StateHolder<?, ?>> table,
-- final Map<Property<?>, Comparable<?>> this_map) {
-- final Set<Property<?>> combined = new HashSet<>(table.rowKeySet());
-- combined.addAll(this_map.keySet());
--
-- this.index_table = this.create_table(combined);
--
-- int max_id = -1;
-- for (final Property<?> property : combined) {
-- final int id = lookup_vindex(property, this.index_table);
-- if (id > max_id) {
-- max_id = id;
-- }
-- }
--
-- this.value_table = new StateHolder[max_id + 1][];
--
-- final Map<Property<?>, Map<Comparable<?>, StateHolder<?, ?>>> map = table.rowMap();
-- for (final Property<?> property : map.keySet()) {
-- final Map<Comparable<?>, StateHolder<?, ?>> propertyMap = map.get(property);
--
-- final int id = lookup_vindex(property, this.index_table);
-- final StateHolder<?, ?>[] states = this.value_table[id] = new StateHolder[property.getPossibleValues().size()];
--
-- for (final Map.Entry<Comparable<?>, StateHolder<?, ?>> entry : propertyMap.entrySet()) {
-- if (entry.getValue() == null) {
-- // TODO what
-- continue;
-- }
--
-- states[((Property)property).getIdFor(entry.getKey())] = entry.getValue();
-- }
-- }
--
--
-- for (final Map.Entry<Property<?>, Comparable<?>> entry : this_map.entrySet()) {
-- final Property<?> property = entry.getKey();
-- final int index = lookup_vindex(property, this.index_table);
--
-- if (this.value_table[index] == null) {
-- this.value_table[index] = new StateHolder[property.getPossibleValues().size()];
-- }
--
-- this.value_table[index][((Property)property).getIdFor(entry.getValue())] = this.this_state;
-- }
-- }
--
--
-- protected long[] create_table(final Collection<Property<?>> collection) {
-- int max_id = -1;
-- for (final Property<?> property : collection) {
-- final int id = property.getId();
-- if (id > max_id) {
-- max_id = id;
-- }
-- }
--
-- final long[] ret = new long[((max_id + 1) + 31) >>> 5]; // ceil((max_id + 1) / 32)
--
-- for (final Property<?> property : collection) {
-- final int id = property.getId();
--
-- ret[id >>> 5] |= (1L << (id & 31));
-- }
--
-- int total = 0;
-- for (int i = 1, len = ret.length; i < len; ++i) {
-- ret[i] |= (long)(total += Long.bitCount(ret[i - 1] & 0xFFFFFFFFL)) << 32;
-- }
--
-- return ret;
-- }
--
-- public Comparable<?> get(final Property<?> state) {
-- final Comparable<?>[] table = this.this_table;
-- final int index = lookup_vindex(state, this.this_index_table);
--
-- if (index < 0 || index >= table.length) {
-- return null;
-- }
-- return table[index];
-- }
--
-- public StateHolder<?, ?> get(final Property<?> property, final Comparable<?> with) {
-- final int withId = ((Property)property).getIdFor(with);
-- if (withId < 0) {
-- return null;
-- }
--
-- final int index = lookup_vindex(property, this.index_table);
-- final StateHolder<?, ?>[][] table = this.value_table;
-- if (index < 0 || index >= table.length) {
-- return null;
-- }
--
-- final StateHolder<?, ?>[] values = table[index];
--
-- if (withId >= values.length) {
-- return null;
-- }
--
-- return values[withId];
-- }
--
-- protected static int lookup_vindex(final Property<?> property, final long[] index_table) {
-- final int id = property.getId();
-- final long bitset_mask = (1L << (id & 31));
-- final long lower_mask = bitset_mask - 1;
-- final int index = id >>> 5;
-- if (index >= index_table.length) {
-- return -1;
-- }
-- final long index_value = index_table[index];
-- final long contains_check = ((index_value & bitset_mask) - 1) >> (Long.SIZE - 1); // -1L if doesn't contain
--
-- // index = total bits set in lower table values (upper 32 bits of index_value) plus total bits set in lower indices below id
-- // contains_check is 0 if the bitset had id set, else it's -1: so index is unaffected if contains_check == 0,
-- // otherwise it comes out as -1.
-- return (int)(((index_value >>> 32) + Long.bitCount(index_value & lower_mask)) | contains_check);
-- }
--}
-diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-index 45744d86e9582a93a0cec26009deea091080fbbe..daedcfd867ed6171fb61bdcbded417a11c8a5b0f 100644
---- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-@@ -39,13 +39,11 @@ public abstract class StateHolder<O, S> {
- private final Reference2ObjectArrayMap<Property<?>, Comparable<?>> values;
- private Table<Property<?>, Comparable<?>, S> neighbours;
- protected final MapCodec<S> propertiesCodec;
-- protected final io.papermc.paper.util.table.ZeroCollidingReferenceStateTable optimisedTable; // Paper - optimise state lookup
-
- protected StateHolder(O owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<S> codec) {
- this.owner = owner;
- this.values = propertyMap;
- this.propertiesCodec = codec;
-- this.optimisedTable = new io.papermc.paper.util.table.ZeroCollidingReferenceStateTable(this, propertyMap); // Paper - optimise state lookup
- }
-
- public <T extends Comparable<T>> S cycle(Property<T> property) {
-@@ -86,11 +84,11 @@ public abstract class StateHolder<O, S> {
- }
-
- public <T extends Comparable<T>> boolean hasProperty(Property<T> property) {
-- return this.optimisedTable.get(property) != null; // Paper - optimise state lookup
-+ return this.values.containsKey(property);
- }
-
- public <T extends Comparable<T>> T getValue(Property<T> property) {
-- Comparable<?> comparable = this.optimisedTable.get(property); // Paper - optimise state lookup
-+ Comparable<?> comparable = this.values.get(property);
- if (comparable == null) {
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
- } else {
-@@ -99,18 +97,24 @@ public abstract class StateHolder<O, S> {
- }
-
- public <T extends Comparable<T>> Optional<T> getOptionalValue(Property<T> property) {
-- Comparable<?> comparable = this.optimisedTable.get(property); // Paper - optimise state lookup
-+ Comparable<?> comparable = this.values.get(property);
- return comparable == null ? Optional.empty() : Optional.of(property.getValueClass().cast(comparable));
- }
-
- public <T extends Comparable<T>, V extends T> S setValue(Property<T> property, V value) {
-- // Paper start - optimise state lookup
-- final S ret = (S)this.optimisedTable.get(property, value);
-- if (ret == null) {
-- throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on " + this.owner + ", it is not an allowed value");
-+ Comparable<?> comparable = this.values.get(property);
-+ if (comparable == null) {
-+ throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.owner);
-+ } else if (comparable.equals(value)) {
-+ return (S)this;
-+ } else {
-+ S object = this.neighbours.get(property, value);
-+ if (object == null) {
-+ throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on " + this.owner + ", it is not an allowed value");
-+ } else {
-+ return object;
-+ }
- }
-- return ret;
-- // Paper end - optimise state lookup
- }
-
- public <T extends Comparable<T>, V extends T> S trySetValue(Property<T> property, V value) {
-@@ -143,7 +147,7 @@ public abstract class StateHolder<O, S> {
- }
- }
-
-- this.neighbours = (Table<Property<?>, Comparable<?>, S>)(table.isEmpty() ? table : ArrayTable.create(table)); this.optimisedTable.loadInTable((Table)this.neighbours, this.values); // Paper - optimise state lookup
-+ this.neighbours = (Table<Property<?>, Comparable<?>, S>)(table.isEmpty() ? table : ArrayTable.create(table));
- }
- }
-
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-index ff5fd91257c4554c523682009efe1db83f53fd5b..b63116b333b6e06494091a82588acfb639bddb71 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-@@ -7,13 +7,6 @@ import java.util.Optional;
- public class BooleanProperty extends Property<Boolean> {
- private final ImmutableSet<Boolean> values = ImmutableSet.of(true, false);
-
-- // Paper start - optimise iblockdata state lookup
-- @Override
-- public final int getIdFor(final Boolean value) {
-- return value.booleanValue() ? 1 : 0;
-- }
-- // Paper end - optimise iblockdata state lookup
--
- protected BooleanProperty(String name) {
- super(name, Boolean.class);
- }
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-index 498c5abe0a9d024d77029719c621c1c8485791f3..3097298fe356df98967cf4bdeaaede69dfe8a441 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-@@ -15,15 +15,6 @@ public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Prope
- private final ImmutableSet<T> values;
- private final Map<String, T> names = Maps.newHashMap();
-
-- // Paper start - optimise iblockdata state lookup
-- private int[] idLookupTable;
--
-- @Override
-- public final int getIdFor(final T value) {
-- return this.idLookupTable[value.ordinal()];
-- }
-- // Paper end - optimise iblockdata state lookup
--
- protected EnumProperty(String name, Class<T> type, Collection<T> values) {
- super(name, type);
- this.values = ImmutableSet.copyOf(values);
-@@ -36,14 +27,6 @@ public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Prope
-
- this.names.put(string, enum_);
- }
-- // Paper start - optimise BlockState lookup
-- int id = 0;
-- this.idLookupTable = new int[type.getEnumConstants().length];
-- java.util.Arrays.fill(this.idLookupTable, -1);
-- for (final T value : this.getPossibleValues()) {
-- this.idLookupTable[value.ordinal()] = id++;
-- }
-- // Paper end - optimise BlockState lookup
- }
-
- @Override
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-index 977504f2641d0133a572b0d5de85d058609343bb..3a850321a4bcc68058483b5fd53e829c425a68af 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-@@ -11,16 +11,6 @@ public class IntegerProperty extends Property<Integer> {
- public final int min;
- public final int max;
-
-- // Paper start - optimise iblockdata state lookup
-- @Override
-- public final int getIdFor(final Integer value) {
-- final int val = value.intValue();
-- final int ret = val - this.min;
--
-- return ret | ((this.max - ret) >> 31);
-- }
-- // Paper end - optimise iblockdata state lookup
--
- protected IntegerProperty(String name, int min, int max) {
- super(name, Integer.class);
- if (min < 0) {
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
-index b9493e3762410aca8e683c32b5aef187c0bee082..9055f15af0cae55effa6942913a9d7edf3857e07 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
-@@ -24,17 +24,6 @@ public abstract class Property<T extends Comparable<T>> {
- );
- private final Codec<Property.Value<T>> valueCodec = this.codec.xmap(this::value, Property.Value::value);
-
-- // Paper start - optimise iblockdata state lookup
-- private static final java.util.concurrent.atomic.AtomicInteger ID_GENERATOR = new java.util.concurrent.atomic.AtomicInteger();
-- private final int id = ID_GENERATOR.getAndIncrement();
--
-- public final int getId() {
-- return this.id;
-- }
--
-- public abstract int getIdFor(final T value);
-- // Paper end - optimise state lookup
--
- protected Property(String name, Class<T> type) {
- this.clazz = type;
- this.name = name;
diff --git a/patches/unapplied/server/1005-Custom-table-implementation-for-blockstate-state-loo.patch b/patches/unapplied/server/1005-Custom-table-implementation-for-blockstate-state-loo.patch
deleted file mode 100644
index 96d90abea3..0000000000
--- a/patches/unapplied/server/1005-Custom-table-implementation-for-blockstate-state-loo.patch
+++ /dev/null
@@ -1,343 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Spottedleaf <[email protected]>
-Date: Thu, 11 Mar 2021 20:05:44 -0800
-Subject: [PATCH] Custom table implementation for blockstate state lookups
-
-Testing some redstone intensive machines showed to bring about a 10%
-improvement.
-
-diff --git a/src/main/java/io/papermc/paper/util/table/ZeroCollidingReferenceStateTable.java b/src/main/java/io/papermc/paper/util/table/ZeroCollidingReferenceStateTable.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..57d0cd3ad6f972e986c72a57f1a6e36003f190c2
---- /dev/null
-+++ b/src/main/java/io/papermc/paper/util/table/ZeroCollidingReferenceStateTable.java
-@@ -0,0 +1,160 @@
-+package io.papermc.paper.util.table;
-+
-+import com.google.common.collect.Table;
-+import net.minecraft.world.level.block.state.StateHolder;
-+import net.minecraft.world.level.block.state.properties.Property;
-+import java.util.Collection;
-+import java.util.HashSet;
-+import java.util.Map;
-+import java.util.Set;
-+
-+public final class ZeroCollidingReferenceStateTable {
-+
-+ // upper 32 bits: starting index
-+ // lower 32 bits: bitset for contained ids
-+ protected final long[] this_index_table;
-+ protected final Comparable<?>[] this_table;
-+ protected final StateHolder<?, ?> this_state;
-+
-+ protected long[] index_table;
-+ protected StateHolder<?, ?>[][] value_table;
-+
-+ public ZeroCollidingReferenceStateTable(final StateHolder<?, ?> state, final Map<Property<?>, Comparable<?>> this_map) {
-+ this.this_state = state;
-+ this.this_index_table = this.create_table(this_map.keySet());
-+
-+ int max_id = -1;
-+ for (final Property<?> property : this_map.keySet()) {
-+ final int id = lookup_vindex(property, this.this_index_table);
-+ if (id > max_id) {
-+ max_id = id;
-+ }
-+ }
-+
-+ this.this_table = new Comparable[max_id + 1];
-+ for (final Map.Entry<Property<?>, Comparable<?>> entry : this_map.entrySet()) {
-+ this.this_table[lookup_vindex(entry.getKey(), this.this_index_table)] = entry.getValue();
-+ }
-+ }
-+
-+ public void loadInTable(final Table<Property<?>, Comparable<?>, StateHolder<?, ?>> table,
-+ final Map<Property<?>, Comparable<?>> this_map) {
-+ final Set<Property<?>> combined = new HashSet<>(table.rowKeySet());
-+ combined.addAll(this_map.keySet());
-+
-+ this.index_table = this.create_table(combined);
-+
-+ int max_id = -1;
-+ for (final Property<?> property : combined) {
-+ final int id = lookup_vindex(property, this.index_table);
-+ if (id > max_id) {
-+ max_id = id;
-+ }
-+ }
-+
-+ this.value_table = new StateHolder[max_id + 1][];
-+
-+ final Map<Property<?>, Map<Comparable<?>, StateHolder<?, ?>>> map = table.rowMap();
-+ for (final Property<?> property : map.keySet()) {
-+ final Map<Comparable<?>, StateHolder<?, ?>> propertyMap = map.get(property);
-+
-+ final int id = lookup_vindex(property, this.index_table);
-+ final StateHolder<?, ?>[] states = this.value_table[id] = new StateHolder[property.getPossibleValues().size()];
-+
-+ for (final Map.Entry<Comparable<?>, StateHolder<?, ?>> entry : propertyMap.entrySet()) {
-+ if (entry.getValue() == null) {
-+ // TODO what
-+ continue;
-+ }
-+
-+ states[((Property)property).getIdFor(entry.getKey())] = entry.getValue();
-+ }
-+ }
-+
-+
-+ for (final Map.Entry<Property<?>, Comparable<?>> entry : this_map.entrySet()) {
-+ final Property<?> property = entry.getKey();
-+ final int index = lookup_vindex(property, this.index_table);
-+
-+ if (this.value_table[index] == null) {
-+ this.value_table[index] = new StateHolder[property.getPossibleValues().size()];
-+ }
-+
-+ this.value_table[index][((Property)property).getIdFor(entry.getValue())] = this.this_state;
-+ }
-+ }
-+
-+
-+ protected long[] create_table(final Collection<Property<?>> collection) {
-+ int max_id = -1;
-+ for (final Property<?> property : collection) {
-+ final int id = property.getId();
-+ if (id > max_id) {
-+ max_id = id;
-+ }
-+ }
-+
-+ final long[] ret = new long[((max_id + 1) + 31) >>> 5]; // ceil((max_id + 1) / 32)
-+
-+ for (final Property<?> property : collection) {
-+ final int id = property.getId();
-+
-+ ret[id >>> 5] |= (1L << (id & 31));
-+ }
-+
-+ int total = 0;
-+ for (int i = 1, len = ret.length; i < len; ++i) {
-+ ret[i] |= (long)(total += Long.bitCount(ret[i - 1] & 0xFFFFFFFFL)) << 32;
-+ }
-+
-+ return ret;
-+ }
-+
-+ public Comparable<?> get(final Property<?> state) {
-+ final Comparable<?>[] table = this.this_table;
-+ final int index = lookup_vindex(state, this.this_index_table);
-+
-+ if (index < 0 || index >= table.length) {
-+ return null;
-+ }
-+ return table[index];
-+ }
-+
-+ public StateHolder<?, ?> get(final Property<?> property, final Comparable<?> with) {
-+ final int withId = ((Property)property).getIdFor(with);
-+ if (withId < 0) {
-+ return null;
-+ }
-+
-+ final int index = lookup_vindex(property, this.index_table);
-+ final StateHolder<?, ?>[][] table = this.value_table;
-+ if (index < 0 || index >= table.length) {
-+ return null;
-+ }
-+
-+ final StateHolder<?, ?>[] values = table[index];
-+
-+ if (withId >= values.length) {
-+ return null;
-+ }
-+
-+ return values[withId];
-+ }
-+
-+ protected static int lookup_vindex(final Property<?> property, final long[] index_table) {
-+ final int id = property.getId();
-+ final long bitset_mask = (1L << (id & 31));
-+ final long lower_mask = bitset_mask - 1;
-+ final int index = id >>> 5;
-+ if (index >= index_table.length) {
-+ return -1;
-+ }
-+ final long index_value = index_table[index];
-+ final long contains_check = ((index_value & bitset_mask) - 1) >> (Long.SIZE - 1); // -1L if doesn't contain
-+
-+ // index = total bits set in lower table values (upper 32 bits of index_value) plus total bits set in lower indices below id
-+ // contains_check is 0 if the bitset had id set, else it's -1: so index is unaffected if contains_check == 0,
-+ // otherwise it comes out as -1.
-+ return (int)(((index_value >>> 32) + Long.bitCount(index_value & lower_mask)) | contains_check);
-+ }
-+}
-diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-index daedcfd867ed6171fb61bdcbded417a11c8a5b0f..45744d86e9582a93a0cec26009deea091080fbbe 100644
---- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
-@@ -39,11 +39,13 @@ public abstract class StateHolder<O, S> {
- private final Reference2ObjectArrayMap<Property<?>, Comparable<?>> values;
- private Table<Property<?>, Comparable<?>, S> neighbours;
- protected final MapCodec<S> propertiesCodec;
-+ protected final io.papermc.paper.util.table.ZeroCollidingReferenceStateTable optimisedTable; // Paper - optimise state lookup
-
- protected StateHolder(O owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<S> codec) {
- this.owner = owner;
- this.values = propertyMap;
- this.propertiesCodec = codec;
-+ this.optimisedTable = new io.papermc.paper.util.table.ZeroCollidingReferenceStateTable(this, propertyMap); // Paper - optimise state lookup
- }
-
- public <T extends Comparable<T>> S cycle(Property<T> property) {
-@@ -84,11 +86,11 @@ public abstract class StateHolder<O, S> {
- }
-
- public <T extends Comparable<T>> boolean hasProperty(Property<T> property) {
-- return this.values.containsKey(property);
-+ return this.optimisedTable.get(property) != null; // Paper - optimise state lookup
- }
-
- public <T extends Comparable<T>> T getValue(Property<T> property) {
-- Comparable<?> comparable = this.values.get(property);
-+ Comparable<?> comparable = this.optimisedTable.get(property); // Paper - optimise state lookup
- if (comparable == null) {
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
- } else {
-@@ -97,24 +99,18 @@ public abstract class StateHolder<O, S> {
- }
-
- public <T extends Comparable<T>> Optional<T> getOptionalValue(Property<T> property) {
-- Comparable<?> comparable = this.values.get(property);
-+ Comparable<?> comparable = this.optimisedTable.get(property); // Paper - optimise state lookup
- return comparable == null ? Optional.empty() : Optional.of(property.getValueClass().cast(comparable));
- }
-
- public <T extends Comparable<T>, V extends T> S setValue(Property<T> property, V value) {
-- Comparable<?> comparable = this.values.get(property);
-- if (comparable == null) {
-- throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + this.owner);
-- } else if (comparable.equals(value)) {
-- return (S)this;
-- } else {
-- S object = this.neighbours.get(property, value);
-- if (object == null) {
-- throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on " + this.owner + ", it is not an allowed value");
-- } else {
-- return object;
-- }
-+ // Paper start - optimise state lookup
-+ final S ret = (S)this.optimisedTable.get(property, value);
-+ if (ret == null) {
-+ throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on " + this.owner + ", it is not an allowed value");
- }
-+ return ret;
-+ // Paper end - optimise state lookup
- }
-
- public <T extends Comparable<T>, V extends T> S trySetValue(Property<T> property, V value) {
-@@ -147,7 +143,7 @@ public abstract class StateHolder<O, S> {
- }
- }
-
-- this.neighbours = (Table<Property<?>, Comparable<?>, S>)(table.isEmpty() ? table : ArrayTable.create(table));
-+ this.neighbours = (Table<Property<?>, Comparable<?>, S>)(table.isEmpty() ? table : ArrayTable.create(table)); this.optimisedTable.loadInTable((Table)this.neighbours, this.values); // Paper - optimise state lookup
- }
- }
-
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-index b63116b333b6e06494091a82588acfb639bddb71..ff5fd91257c4554c523682009efe1db83f53fd5b 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java
-@@ -7,6 +7,13 @@ import java.util.Optional;
- public class BooleanProperty extends Property<Boolean> {
- private final ImmutableSet<Boolean> values = ImmutableSet.of(true, false);
-
-+ // Paper start - optimise iblockdata state lookup
-+ @Override
-+ public final int getIdFor(final Boolean value) {
-+ return value.booleanValue() ? 1 : 0;
-+ }
-+ // Paper end - optimise iblockdata state lookup
-+
- protected BooleanProperty(String name) {
- super(name, Boolean.class);
- }
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-index 3097298fe356df98967cf4bdeaaede69dfe8a441..498c5abe0a9d024d77029719c621c1c8485791f3 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java
-@@ -15,6 +15,15 @@ public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Prope
- private final ImmutableSet<T> values;
- private final Map<String, T> names = Maps.newHashMap();
-
-+ // Paper start - optimise iblockdata state lookup
-+ private int[] idLookupTable;
-+
-+ @Override
-+ public final int getIdFor(final T value) {
-+ return this.idLookupTable[value.ordinal()];
-+ }
-+ // Paper end - optimise iblockdata state lookup
-+
- protected EnumProperty(String name, Class<T> type, Collection<T> values) {
- super(name, type);
- this.values = ImmutableSet.copyOf(values);
-@@ -27,6 +36,14 @@ public class EnumProperty<T extends Enum<T> & StringRepresentable> extends Prope
-
- this.names.put(string, enum_);
- }
-+ // Paper start - optimise BlockState lookup
-+ int id = 0;
-+ this.idLookupTable = new int[type.getEnumConstants().length];
-+ java.util.Arrays.fill(this.idLookupTable, -1);
-+ for (final T value : this.getPossibleValues()) {
-+ this.idLookupTable[value.ordinal()] = id++;
-+ }
-+ // Paper end - optimise BlockState lookup
- }
-
- @Override
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-index 3a850321a4bcc68058483b5fd53e829c425a68af..977504f2641d0133a572b0d5de85d058609343bb 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java
-@@ -11,6 +11,16 @@ public class IntegerProperty extends Property<Integer> {
- public final int min;
- public final int max;
-
-+ // Paper start - optimise iblockdata state lookup
-+ @Override
-+ public final int getIdFor(final Integer value) {
-+ final int val = value.intValue();
-+ final int ret = val - this.min;
-+
-+ return ret | ((this.max - ret) >> 31);
-+ }
-+ // Paper end - optimise iblockdata state lookup
-+
- protected IntegerProperty(String name, int min, int max) {
- super(name, Integer.class);
- if (min < 0) {
-diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
-index 9055f15af0cae55effa6942913a9d7edf3857e07..b9493e3762410aca8e683c32b5aef187c0bee082 100644
---- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
-+++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java
-@@ -24,6 +24,17 @@ public abstract class Property<T extends Comparable<T>> {
- );
- private final Codec<Property.Value<T>> valueCodec = this.codec.xmap(this::value, Property.Value::value);
-
-+ // Paper start - optimise iblockdata state lookup
-+ private static final java.util.concurrent.atomic.AtomicInteger ID_GENERATOR = new java.util.concurrent.atomic.AtomicInteger();
-+ private final int id = ID_GENERATOR.getAndIncrement();
-+
-+ public final int getId() {
-+ return this.id;
-+ }
-+
-+ public abstract int getIdFor(final T value);
-+ // Paper end - optimise state lookup
-+
- protected Property(String name, Class<T> type) {
- this.clazz = type;
- this.name = name;