diff options
author | Spottedleaf <[email protected]> | 2024-10-24 08:18:20 -0700 |
---|---|---|
committer | Spottedleaf <[email protected]> | 2024-10-25 11:25:09 -0700 |
commit | ecf4d9715e235c8d26202404c66642ca7e90aa68 (patch) | |
tree | ee52ec90cec283475af937df40e7b142e6965d2b | |
parent | 47258a71184e0b3c919e2f224cf2aca985722ddf (diff) | |
download | Paper-ecf4d9715e235c8d26202404c66642ca7e90aa68.tar.gz Paper-ecf4d9715e235c8d26202404c66642ca7e90aa68.zip |
Begin fixing issues
See diff in the update text file
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; |