From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 9 Aug 2025 14:52:44 +0900 Subject: [PATCH] thread unsafe chunk map diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java index f1e1e96a425ae0186164b3ae6caca226fdd7e12e..68f31c3f2003afe1096b8eeb26a2d2a64af2a85a 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java @@ -78,6 +78,7 @@ public final class ChunkHolderManager { final ChunkUnloadQueue unloadQueue; private final ConcurrentLong2ReferenceChainedHashTable chunkHolders = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(16384, 0.25f); + public final org.dreeam.leaf.world.ChunkCache chunkHoldersNoSync; // Leaf - thread unsafe chunk map private final ServerLevel world; private final ChunkTaskScheduler taskScheduler; private long currentTick; @@ -112,6 +113,7 @@ public final class ChunkHolderManager { this.taskScheduler = taskScheduler; this.ticketLockArea = new ReentrantAreaLock(taskScheduler.getChunkSystemLockShift()); this.unloadQueue = new ChunkUnloadQueue(((ChunkSystemServerLevel)world).moonrise$getRegionChunkShift()); + this.chunkHoldersNoSync = new org.dreeam.leaf.world.ChunkCache<>(world.getChunkSource().mainThread); // Leaf - thread unsafe chunk map } public boolean processTicketUpdates(final int chunkX, final int chunkZ) { @@ -374,6 +376,7 @@ public final class ChunkHolderManager { if (current == null) { // must create current = ChunkHolderManager.this.createChunkHolder(key); + ChunkHolderManager.this.chunkHoldersNoSync.put(key, current); // Leaf - thread unsafe chunk map ChunkHolderManager.this.chunkHolders.put(key, current); current.updateTicketLevel(newLevel); } else { @@ -923,11 +926,24 @@ public final class ChunkHolderManager { } public NewChunkHolder getChunkHolder(final int chunkX, final int chunkZ) { - return this.chunkHolders.get(CoordinateUtils.getChunkKey(chunkX, chunkZ)); + // Leaf start - thread unsafe chunk map + final long position = CoordinateUtils.getChunkKey(chunkX, chunkZ); + if (this.chunkHoldersNoSync.isSameThread()) { + return this.chunkHoldersNoSync.get(position); + } else { + return this.chunkHolders.get(position); + } + // Leaf end - thread unsafe chunk map } public NewChunkHolder getChunkHolder(final long position) { - return this.chunkHolders.get(position); + // Leaf start - thread unsafe chunk map + if (this.chunkHoldersNoSync.isSameThread()) { + return this.chunkHoldersNoSync.get(position); + } else { + return this.chunkHolders.get(position); + } + // Leaf end - thread unsafe chunk map } public void raisePriority(final int x, final int z, final Priority priority) { @@ -986,6 +1002,7 @@ public final class ChunkHolderManager { } current = this.createChunkHolder(position); + this.chunkHoldersNoSync.put(position, current); // Leaf - thread unsafe chunk map this.chunkHolders.put(position, current); @@ -1158,7 +1175,11 @@ public final class ChunkHolderManager { holder.onUnload(); this.autoSaveQueue.remove(holder); PlatformHooks.get().onChunkHolderDelete(this.world, holder.vanillaChunkHolder); - this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ)); + // Leaf start - thread unsafe chunk map + long position = CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ); + this.chunkHoldersNoSync.remove(position); + this.chunkHolders.remove(position); + // Leaf end - thread unsafe chunk map } // note: never call while inside the chunk system, this will absolutely break everything diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java index 540a1af9f4e0cf69ff987105a34d92a35e669fb0..c7af60b6d1920d8784ec3ff0e6791dcd0708a259 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -1768,6 +1768,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + serverLevel.getChunkSource().fullChunksNonSync.setThread(); // Leaf - thread unsafe chunk map + serverLevel.moonrise$getChunkTaskScheduler().chunkHolderManager.chunkHoldersNoSync.setThread(); // Leaf - thread unsafe chunk map ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread currentThread = (ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread) Thread.currentThread(); currentThread.currentTickingServerLevel = serverLevel; @@ -1786,7 +1788,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>(); + public final org.dreeam.leaf.world.ChunkCache fullChunksNonSync; // Leaf - thread unsafe chunk map public int getFullChunksCount() { return this.fullChunks.size(); } @@ -87,16 +88,27 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override public final void moonrise$setFullChunk(final int chunkX, final int chunkZ, final LevelChunk chunk) { final long key = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ); + // Leaf start - thread unsafe chunk map if (chunk == null) { + this.fullChunksNonSync.remove(key); this.fullChunks.remove(key); } else { + this.fullChunksNonSync.put(key,chunk); this.fullChunks.put(key, chunk); } + // Leaf end - thread unsafe chunk map } @Override public final LevelChunk moonrise$getFullChunkIfLoaded(final int chunkX, final int chunkZ) { - return this.fullChunks.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ)); + // Leaf start - thread unsafe chunk map + long key = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ); + if (this.fullChunksNonSync.isSameThread()) { + return this.fullChunksNonSync.get(key); + } else { + return this.fullChunks.get(key); + } + // Leaf end - thread unsafe chunk map } private ChunkAccess syncLoad(final int chunkX, final int chunkZ, final ChunkStatus toStatus) { @@ -204,6 +216,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(level); this.mainThread = Thread.currentThread(); Path path = levelStorageAccess.getDimensionPath(level.dimension()).resolve("data"); + this.fullChunksNonSync = new org.dreeam.leaf.world.ChunkCache<>(mainThread); // Leaf - thread unsafe chunk map try { FileUtil.createDirectoriesSafe(path); @@ -283,7 +296,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Nullable public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { - return this.fullChunks.get(ChunkPos.asLong(x, z)); + // Leaf start - thread unsafe chunk map + long key = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(x, z); + if (this.fullChunksNonSync.isSameThread()) { + return this.fullChunksNonSync.get(key); + } else { + return this.fullChunks.get(key); + } + // Leaf end - thread unsafe chunk map } // Paper end @@ -318,7 +338,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon public ChunkAccess getChunk(int x, int z, ChunkStatus chunkStatus, boolean requireChunk) { // Paper start - rewrite chunk system if (chunkStatus == ChunkStatus.FULL) { - final LevelChunk ret = this.fullChunks.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(x, z)); + long key = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(x, z); // Leaf - thread unsafe chunk map + final LevelChunk ret = this.fullChunksNonSync.isSameThread() ? this.fullChunksNonSync.get(key) : this.fullChunks.get(key); // Leaf - thread unsafe chunk map if (ret != null) { return ret; @@ -335,7 +356,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override public LevelChunk getChunkNow(int chunkX, int chunkZ) { // Paper start - rewrite chunk system - final LevelChunk ret = this.fullChunks.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ)); + long key = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ); // Leaf - thread unsafe chunk map + final LevelChunk ret = this.fullChunksNonSync.isSameThread() ? this.fullChunksNonSync.get(key) : this.fullChunks.get(key); // Leaf - thread unsafe chunk map if (!ca.spottedleaf.moonrise.common.PlatformHooks.get().hasCurrentlyLoadingChunk()) { return ret; } diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java index 28e2c4f211de1a3a9d95342965699917db613782..e900060907ce7612b251bdf6d526ef83ea968a7a 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -1065,6 +1065,18 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl // Paper end - Perf: make sure loaded chunks get the inlined variant of this function } + // Leaf start - thread unsafe chunk map + @Nullable + public final LevelChunk getChunkAtIfLoadedUnchecked(int x, int z) { + return ((ServerLevel) this).chunkSource.fullChunksNonSync.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(x, z)); + } + + @Nullable + public final BlockState getBlockStateIfLoadedUnchecked(int x, int y, int z) { + LevelChunk chunk = ((ServerLevel) this).chunkSource.fullChunksNonSync.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(x >> 4, z >> 4)); + return chunk == null ? null : chunk.getBlockStateFinal(x, y, z); + } + // Leaf end - thread unsafe chunk map // Paper start - if loaded @Nullable @Override