mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
215 lines
12 KiB
Diff
215 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: hayanesuru <hayanesuru@outlook.jp>
|
|
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<NewChunkHolder> chunkHolders = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(16384, 0.25f);
|
|
+ public final org.dreeam.leaf.world.ChunkCache<NewChunkHolder> 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<TickTa
|
|
serverLevelTickingSemaphore.acquire();
|
|
tasks.add(
|
|
serverLevel.tickExecutor.submit(() -> {
|
|
+ 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<TickTa
|
|
}
|
|
|
|
while (!tasks.isEmpty()) {
|
|
- tasks.pop().get();
|
|
+ ServerLevel serverLevel = tasks.pop().get(); // Leaf - thread unsafe chunk map
|
|
+ serverLevel.getChunkSource().fullChunksNonSync.setThread(); // Leaf - thread unsafe chunk map
|
|
+ serverLevel.moonrise$getChunkTaskScheduler().chunkHolderManager.chunkHoldersNoSync.setThread(); // Leaf - thread unsafe chunk map
|
|
}
|
|
} catch (java.lang.InterruptedException | java.util.concurrent.ExecutionException e) {
|
|
throw new RuntimeException(e); // Propagate exception
|
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
|
index bd4c98e9ec41a2bd608e2e2245c503be3171ceee..f6bcd33400ccfc146f508ffd7f8b673439eb5211 100644
|
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -77,6 +77,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
private volatile NaturalSpawner.SpawnState lastSpawnState; // Leaf - optimize mob spawning
|
|
// Paper start
|
|
public final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<net.minecraft.world.level.chunk.LevelChunk> fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>();
|
|
+ public final org.dreeam.leaf.world.ChunkCache<LevelChunk> 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<Entity>, 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
|