mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-21 07:49:18 +00:00
376 lines
24 KiB
Diff
376 lines
24 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
|
Date: Sat, 1 Feb 2025 00:33:03 +0300
|
|
Subject: [PATCH] Chunk System optimization
|
|
|
|
|
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
|
index f81cc357618c70f2fcf0bc24b0b25be566ffffcc..a2062d976ca45b1360476051f23ff126ff812d4e 100644
|
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
|
@@ -301,7 +301,7 @@ public final class RegionizedPlayerChunkLoader {
|
|
return false;
|
|
}
|
|
|
|
- public void tick() {
|
|
+ public synchronized void tick() { // DivineMC - Chunk System optimization - synchronized
|
|
TickThread.ensureTickThread("Cannot tick player chunk loader async");
|
|
long currTime = System.nanoTime();
|
|
for (final ServerPlayer player : new java.util.ArrayList<>(this.world.players())) {
|
|
@@ -362,7 +362,7 @@ public final class RegionizedPlayerChunkLoader {
|
|
GENERATED_TICKET_LEVEL,
|
|
TICK_TICKET_LEVEL
|
|
};
|
|
- private final Long2ByteOpenHashMap chunkTicketStage = new Long2ByteOpenHashMap();
|
|
+ private final it.unimi.dsi.fastutil.longs.Long2ByteMap chunkTicketStage = it.unimi.dsi.fastutil.longs.Long2ByteMaps.synchronize(new Long2ByteOpenHashMap()); // DivineMC - Chunk System optimization
|
|
{
|
|
this.chunkTicketStage.defaultReturnValue(CHUNK_TICKET_STAGE_NONE);
|
|
}
|
|
@@ -492,7 +492,7 @@ public final class RegionizedPlayerChunkLoader {
|
|
}
|
|
|
|
@Override
|
|
- protected void removeCallback(final PlayerChunkLoaderData parameter, final int chunkX, final int chunkZ) {
|
|
+ protected synchronized void removeCallback(final PlayerChunkLoaderData parameter, final int chunkX, final int chunkZ) { // DivineMC - Chunk System optimization - synchronized
|
|
final long chunk = CoordinateUtils.getChunkKey(chunkX, chunkZ);
|
|
// note: by the time this is called, the tick cleanup should have ran - so, if the chunk is at
|
|
// the tick stage it was deemed in range for loading. Thus, we need to move it to generated
|
|
@@ -626,7 +626,7 @@ public final class RegionizedPlayerChunkLoader {
|
|
return Math.max(Math.abs(dx), Math.abs(dz)) <= this.lastTickDistance;
|
|
}
|
|
|
|
- private boolean areNeighboursGenerated(final int chunkX, final int chunkZ, final int radius) {
|
|
+ private synchronized boolean areNeighboursGenerated(final int chunkX, final int chunkZ, final int radius) { // DivineMC - Chunk System optimization - synchronized
|
|
for (int dz = -radius; dz <= radius; ++dz) {
|
|
for (int dx = -radius; dx <= radius; ++dx) {
|
|
if ((dx | dz) == 0) {
|
|
@@ -645,19 +645,11 @@ public final class RegionizedPlayerChunkLoader {
|
|
return true;
|
|
}
|
|
|
|
- void updateQueues(final long time) {
|
|
+ synchronized void updateQueues(final long time) { // DivineMC - Chunk System optimization - synchronized
|
|
TickThread.ensureTickThread(this.player, "Cannot tick player chunk loader async");
|
|
if (this.removed) {
|
|
throw new IllegalStateException("Ticking removed player chunk loader");
|
|
}
|
|
- // update rate limits
|
|
- final double loadRate = this.getMaxChunkLoadRate();
|
|
- final double genRate = this.getMaxChunkGenRate();
|
|
- final double sendRate = this.getMaxChunkSendRate();
|
|
-
|
|
- this.chunkLoadTicketLimiter.tickAllocation(time, loadRate, loadRate);
|
|
- this.chunkGenerateTicketLimiter.tickAllocation(time, genRate, genRate);
|
|
- this.chunkSendLimiter.tickAllocation(time, sendRate, sendRate);
|
|
|
|
// try to progress chunk loads
|
|
while (!this.loadingQueue.isEmpty()) {
|
|
@@ -684,8 +676,7 @@ public final class RegionizedPlayerChunkLoader {
|
|
}
|
|
|
|
// try to push more chunk loads
|
|
- final long maxLoads = Math.max(0L, Math.min(MAX_RATE, Math.min(this.loadQueue.size(), this.getMaxChunkLoads())));
|
|
- final int maxLoadsThisTick = (int)this.chunkLoadTicketLimiter.takeAllocation(time, loadRate, maxLoads);
|
|
+ final int maxLoadsThisTick = this.loadQueue.size(); // DivineMC - Chunk System optimization
|
|
if (maxLoadsThisTick > 0) {
|
|
final LongArrayList chunks = new LongArrayList(maxLoadsThisTick);
|
|
for (int i = 0; i < maxLoadsThisTick; ++i) {
|
|
@@ -760,9 +751,7 @@ public final class RegionizedPlayerChunkLoader {
|
|
}
|
|
|
|
// try to push more chunk generations
|
|
- final long maxGens = Math.max(0L, Math.min(MAX_RATE, Math.min(this.genQueue.size(), this.getMaxChunkGenerates())));
|
|
- // preview the allocations, as we may not actually utilise all of them
|
|
- final long maxGensThisTick = this.chunkGenerateTicketLimiter.previewAllocation(time, genRate, maxGens);
|
|
+ final long maxGensThisTick = this.genQueue.size(); // DivineMC - Chunk System optimization
|
|
long ratedGensThisTick = 0L;
|
|
while (!this.genQueue.isEmpty()) {
|
|
final long chunkKey = this.genQueue.firstLong();
|
|
@@ -792,8 +781,6 @@ public final class RegionizedPlayerChunkLoader {
|
|
);
|
|
this.generatingQueue.enqueue(chunkKey);
|
|
}
|
|
- // take the allocations we actually used
|
|
- this.chunkGenerateTicketLimiter.takeAllocation(time, genRate, ratedGensThisTick);
|
|
|
|
// try to pull ticking chunks
|
|
while (!this.tickingQueue.isEmpty()) {
|
|
@@ -823,10 +810,10 @@ public final class RegionizedPlayerChunkLoader {
|
|
}
|
|
|
|
// try to pull sending chunks
|
|
- final long maxSends = Math.max(0L, Math.min(MAX_RATE, Integer.MAX_VALUE)); // note: no logic to track concurrent sends
|
|
- final int maxSendsThisTick = Math.min((int)this.chunkSendLimiter.takeAllocation(time, sendRate, maxSends), this.sendQueue.size());
|
|
+ final int maxSendsThisTick = this.sendQueue.size(); // DivineMC - Chunk System optimization
|
|
// we do not return sends that we took from the allocation back because we want to limit the max send rate, not target it
|
|
for (int i = 0; i < maxSendsThisTick; ++i) {
|
|
+ if (this.sendQueue.isEmpty()) break; // DivineMC - Chunk System optimization
|
|
final long pendingSend = this.sendQueue.firstLong();
|
|
final int pendingSendX = CoordinateUtils.getChunkX(pendingSend);
|
|
final int pendingSendZ = CoordinateUtils.getChunkZ(pendingSend);
|
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
|
index 0c99bffa769d53562a10d23c4a9b37dc59c7f478..08c7e25c736fc7a1587bcb2a490845f63001ac8d 100644
|
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
|
@@ -145,7 +145,7 @@ public final class ChunkHolderManager {
|
|
|
|
public List<ChunkHolder> getOldChunkHolders() {
|
|
final List<ChunkHolder> ret = new ArrayList<>(this.chunkHolders.size() + 1);
|
|
- for (final Iterator<NewChunkHolder> iterator = this.chunkHolders.valueIterator(); iterator.hasNext();) {
|
|
+ for (final Iterator<NewChunkHolder> iterator = this.chunkHolders.values().iterator(); iterator.hasNext();) { // DivineMC - Chunk System optimization
|
|
ret.add(iterator.next().vanillaChunkHolder);
|
|
}
|
|
return ret;
|
|
@@ -153,7 +153,7 @@ public final class ChunkHolderManager {
|
|
|
|
public List<NewChunkHolder> getChunkHolders() {
|
|
final List<NewChunkHolder> ret = new ArrayList<>(this.chunkHolders.size() + 1);
|
|
- for (final Iterator<NewChunkHolder> iterator = this.chunkHolders.valueIterator(); iterator.hasNext();) {
|
|
+ for (final Iterator<NewChunkHolder> iterator = this.chunkHolders.values().iterator(); iterator.hasNext();) { // DivineMC - Chunk System optimization
|
|
ret.add(iterator.next());
|
|
}
|
|
return ret;
|
|
@@ -168,7 +168,7 @@ public final class ChunkHolderManager {
|
|
return new Iterable<ChunkHolder>() {
|
|
@Override
|
|
public Iterator<ChunkHolder> iterator() {
|
|
- final Iterator<NewChunkHolder> iterator = ChunkHolderManager.this.chunkHolders.valueIterator();
|
|
+ final Iterator<NewChunkHolder> iterator = ChunkHolderManager.this.chunkHolders.values().iterator(); // DivineMC - Chunk System optimization
|
|
return new Iterator<ChunkHolder>() {
|
|
@Override
|
|
public boolean hasNext() {
|
|
@@ -1208,6 +1208,27 @@ public final class ChunkHolderManager {
|
|
}
|
|
}
|
|
|
|
+ // DivineMC start - Chunk System optimization
|
|
+ public final org.agrona.collections.Object2ObjectHashMap<Long, NewChunkHolder> blockTickingChunkHolders = new org.agrona.collections.Object2ObjectHashMap<>(16384, 0.25f);
|
|
+ public final org.agrona.collections.Object2ObjectHashMap<Long, NewChunkHolder> entityTickingChunkHolders = new org.agrona.collections.Object2ObjectHashMap<>(16384, 0.25f);
|
|
+
|
|
+ public void markBlockTicking(NewChunkHolder newChunkHolder) {
|
|
+ this.blockTickingChunkHolders.put(newChunkHolder.getCachedLongPos(), newChunkHolder);
|
|
+ }
|
|
+
|
|
+ public void markNonBlockTickingIfPossible(NewChunkHolder newChunkHolder) {
|
|
+ this.blockTickingChunkHolders.remove(newChunkHolder.getCachedLongPos());
|
|
+ }
|
|
+
|
|
+ public void markEntityTicking(NewChunkHolder newChunkHolder) {
|
|
+ this.entityTickingChunkHolders.put(newChunkHolder.getCachedLongPos(), newChunkHolder);
|
|
+ }
|
|
+
|
|
+ public void markNonEntityTickingIfPossible(NewChunkHolder newChunkHolder) {
|
|
+ this.entityTickingChunkHolders.remove(newChunkHolder.getCachedLongPos());
|
|
+ }
|
|
+ // DivineMC end - Chunk System optimization
|
|
+
|
|
public enum TicketOperationType {
|
|
ADD, REMOVE, ADD_IF_REMOVED, ADD_AND_REMOVE
|
|
}
|
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
|
|
index e4a5fa25ed368fc4662c30934da2963ef446d782..84354d8e2d391ae9e912c782f9a64b426aeb6c3a 100644
|
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
|
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java
|
|
@@ -644,11 +644,19 @@ public final class NewChunkHolder {
|
|
}
|
|
|
|
public final ChunkHolder vanillaChunkHolder;
|
|
+ // DivineMC start - Chunk System optimization
|
|
+ private final long cachedLongPos;
|
|
+
|
|
+ public long getCachedLongPos() {
|
|
+ return cachedLongPos;
|
|
+ }
|
|
+ // DivineMC end - Chunk System optimization
|
|
|
|
public NewChunkHolder(final ServerLevel world, final int chunkX, final int chunkZ, final ChunkTaskScheduler scheduler) {
|
|
this.world = world;
|
|
this.chunkX = chunkX;
|
|
this.chunkZ = chunkZ;
|
|
+ this.cachedLongPos = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(this.chunkX, this.chunkZ); // DivineMC - Chunk System optimization
|
|
this.scheduler = scheduler;
|
|
this.vanillaChunkHolder = new ChunkHolder(
|
|
new ChunkPos(chunkX, chunkZ), ChunkHolderManager.MAX_TICKET_LEVEL, world,
|
|
@@ -1214,6 +1222,19 @@ public final class NewChunkHolder {
|
|
|
|
private void updateCurrentState(final FullChunkStatus to) {
|
|
this.currentFullChunkStatus = to;
|
|
+ // DivineMC start - Chunk System optimization
|
|
+ if (to.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
|
|
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markBlockTicking(this);
|
|
+ } else {
|
|
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markNonBlockTickingIfPossible(this);
|
|
+ }
|
|
+
|
|
+ if (to.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
|
|
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markEntityTicking(this);
|
|
+ } else {
|
|
+ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.markNonEntityTickingIfPossible(this);
|
|
+ }
|
|
+ // DivineMC end - Chunk System optimization
|
|
}
|
|
|
|
// only to be called on the main thread, no locks need to be held
|
|
diff --git a/net/minecraft/server/level/DistanceManager.java b/net/minecraft/server/level/DistanceManager.java
|
|
index 5eab6179ce3913cb4e4d424f910ba423faf21c85..189205fbeed7673398fa6f7706864d3723467811 100644
|
|
--- a/net/minecraft/server/level/DistanceManager.java
|
|
+++ b/net/minecraft/server/level/DistanceManager.java
|
|
@@ -178,14 +178,14 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches
|
|
|
|
public boolean inEntityTickingRange(long chunkPos) {
|
|
// Paper start - rewrite chunk system
|
|
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().getChunkHolder(chunkPos);
|
|
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().entityTickingChunkHolders.get(chunkPos); // DivineMC - Chunk System optimization
|
|
return chunkHolder != null && chunkHolder.isEntityTickingReady();
|
|
// Paper end - rewrite chunk system
|
|
}
|
|
|
|
public boolean inBlockTickingRange(long chunkPos) {
|
|
// Paper start - rewrite chunk system
|
|
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().getChunkHolder(chunkPos);
|
|
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().blockTickingChunkHolders.get(chunkPos); // DivineMC - Chunk System optimization
|
|
return chunkHolder != null && chunkHolder.isTickingReady();
|
|
// Paper end - rewrite chunk system
|
|
}
|
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
|
index 2678bf59d557f085c7265e2f3eb038647723d35e..b30d6968fba2ab4d9cde0ac9d4f1cfc629c65359 100644
|
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -441,7 +441,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
|
|
public boolean isPositionTicking(long chunkPos) {
|
|
// 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(chunkPos);
|
|
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder newChunkHolder = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.blockTickingChunkHolders.get(chunkPos); // DivineMC Chunk System optimization
|
|
return newChunkHolder != null && newChunkHolder.isTickingReady();
|
|
// Paper end - rewrite chunk system
|
|
}
|
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
|
index a3f363d0c86142e03edc7fc6e2ff6ed81de8ed65..57668810e86b1f293c661d01c2486a3da7256c1e 100644
|
|
--- a/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
|
@@ -857,7 +857,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
@Override
|
|
public boolean shouldTickBlocksAt(long chunkPos) {
|
|
// Paper start - rewrite chunk system
|
|
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder holder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkPos);
|
|
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder holder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.blockTickingChunkHolders.get(chunkPos); // DivineMC - Chunk System optimization
|
|
return holder != null && holder.isTickingReady();
|
|
// Paper end - rewrite chunk system
|
|
}
|
|
@@ -2567,7 +2567,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
|
|
private boolean isPositionTickingWithEntitiesLoaded(long chunkPos) {
|
|
// Paper start - rewrite chunk system
|
|
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkPos);
|
|
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.blockTickingChunkHolders.get(chunkPos); // DivineMC - Chunk System optimization
|
|
// isTicking implies the chunk is loaded, and the chunk is loaded now implies the entities are loaded
|
|
return chunkHolder != null && chunkHolder.isTickingReady();
|
|
// Paper end - rewrite chunk system
|
|
@@ -2582,14 +2582,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
|
|
public boolean isNaturalSpawningAllowed(BlockPos pos) {
|
|
// Paper start - rewrite chunk system
|
|
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(pos));
|
|
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.entityTickingChunkHolders.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(pos)); // DivineMC - Chunk System optimization
|
|
return chunkHolder != null && chunkHolder.isEntityTickingReady();
|
|
// Paper end - rewrite chunk system
|
|
}
|
|
|
|
public boolean isNaturalSpawningAllowed(ChunkPos chunkPos) {
|
|
// Paper start - rewrite chunk system
|
|
- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkPos));
|
|
+ final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.entityTickingChunkHolders.get(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkPos)); // DivineMC - Chunk System optimization
|
|
return chunkHolder != null && chunkHolder.isEntityTickingReady();
|
|
// Paper end - rewrite chunk system
|
|
}
|
|
diff --git a/net/minecraft/world/level/LevelReader.java b/net/minecraft/world/level/LevelReader.java
|
|
index 26c8c1e5598daf3550aef05b12218c47bda6618b..94c824ab1457939c425e1f99929d3222ee2c18a0 100644
|
|
--- a/net/minecraft/world/level/LevelReader.java
|
|
+++ b/net/minecraft/world/level/LevelReader.java
|
|
@@ -70,10 +70,27 @@ public interface LevelReader extends ca.spottedleaf.moonrise.patches.chunk_syste
|
|
|
|
@Override
|
|
default Holder<Biome> getNoiseBiome(int x, int y, int z) {
|
|
- ChunkAccess chunk = this.getChunk(QuartPos.toSection(x), QuartPos.toSection(z), ChunkStatus.BIOMES, false);
|
|
+ ChunkAccess chunk = this.fasterChunkAccess(this, QuartPos.toSection(x), QuartPos.toSection(z), ChunkStatus.BIOMES, false); // DivineMC - Chunk System optimization
|
|
return chunk != null ? chunk.getNoiseBiome(x, y, z) : this.getUncachedNoiseBiome(x, y, z);
|
|
}
|
|
|
|
+ // DivineMC start - Chunk System optimization
|
|
+ private @Nullable ChunkAccess fasterChunkAccess(LevelReader instance, int x, int z, ChunkStatus chunkStatus, boolean create) {
|
|
+ if (!create && instance instanceof net.minecraft.server.level.ServerLevel world) {
|
|
+ final net.minecraft.server.level.ChunkHolder holder = (world.getChunkSource().chunkMap).getVisibleChunkIfPresent(ChunkPos.asLong(x, z));
|
|
+ if (holder != null) {
|
|
+ final java.util.concurrent.CompletableFuture<net.minecraft.server.level.ChunkResult<net.minecraft.world.level.chunk.LevelChunk>> future = holder.getFullChunkFuture();
|
|
+ final net.minecraft.server.level.ChunkResult<net.minecraft.world.level.chunk.LevelChunk> either = future.getNow(null);
|
|
+ if (either != null) {
|
|
+ final net.minecraft.world.level.chunk.LevelChunk chunk = either.orElse(null);
|
|
+ if (chunk != null) return chunk;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return instance.getChunk(x, z, chunkStatus, create);
|
|
+ }
|
|
+ // DivineMC end - Chunk System optimization
|
|
+
|
|
Holder<Biome> getUncachedNoiseBiome(int x, int y, int z);
|
|
|
|
boolean isClientSide();
|
|
diff --git a/net/minecraft/world/level/chunk/storage/IOWorker.java b/net/minecraft/world/level/chunk/storage/IOWorker.java
|
|
index 2199a9e2a0141c646d108f2687a27f1d165453c5..c28c2583b257f92207b822a1fdde8f5b7e480992 100644
|
|
--- a/net/minecraft/world/level/chunk/storage/IOWorker.java
|
|
+++ b/net/minecraft/world/level/chunk/storage/IOWorker.java
|
|
@@ -212,7 +212,38 @@ public class IOWorker implements ChunkScanAccess, AutoCloseable {
|
|
});
|
|
}
|
|
|
|
+ // DivineMC start - Chunk System optimization
|
|
+ private void checkHardLimit() {
|
|
+ if (this.pendingWrites.size() >= org.bxteam.divinemc.DivineConfig.chunkDataCacheLimit) {
|
|
+ LOGGER.warn("Chunk data cache size exceeded hard limit ({} >= {}), forcing writes to disk (you can increase chunkDataCacheLimit in c2me.toml)", this.pendingWrites.size(), org.bxteam.divinemc.DivineConfig.chunkDataCacheLimit);
|
|
+ while (this.pendingWrites.size() >= org.bxteam.divinemc.DivineConfig.chunkDataCacheSoftLimit * 0.75) {
|
|
+ writeResult0();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void writeResult0() {
|
|
+ java.util.Iterator<java.util.Map.Entry<net.minecraft.world.level.ChunkPos, net.minecraft.world.level.chunk.storage.IOWorker.PendingStore>> iterator = this.pendingWrites.entrySet().iterator();
|
|
+ if (iterator.hasNext()) {
|
|
+ java.util.Map.Entry<ChunkPos, IOWorker.PendingStore> entry = iterator.next();
|
|
+ iterator.remove();
|
|
+ this.runStore(entry.getKey(), entry.getValue());
|
|
+ }
|
|
+ }
|
|
+ // DivineMC end - Chunk System optimization
|
|
+
|
|
private void storePendingChunk() {
|
|
+ // DivineMC start - Chunk System optimization
|
|
+ if (!this.pendingWrites.isEmpty()) {
|
|
+ checkHardLimit();
|
|
+ if (this.pendingWrites.size() >= org.bxteam.divinemc.DivineConfig.chunkDataCacheSoftLimit) {
|
|
+ int writeFrequency = Math.min(1, (this.pendingWrites.size() - (int) org.bxteam.divinemc.DivineConfig.chunkDataCacheSoftLimit) / 16);
|
|
+ for (int i = 0; i < writeFrequency; i++) {
|
|
+ writeResult0();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // DivineMC end - Chunk System optimization
|
|
Entry<ChunkPos, IOWorker.PendingStore> entry = this.pendingWrites.pollFirstEntry();
|
|
if (entry != null) {
|
|
this.runStore(entry.getKey(), entry.getValue());
|
|
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
|
index 6ebd1300c2561116b83cb2472ac7939ead36d576..16cd10ab8de69ca3d29c84cf93715645322fd72a 100644
|
|
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
|
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
|
@@ -244,7 +244,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
|
|
|
protected RegionFileStorage(RegionStorageInfo info, Path folder, boolean sync) { // Paper - protected
|
|
this.folder = folder;
|
|
- this.sync = sync;
|
|
+ this.sync = Boolean.parseBoolean(System.getProperty("com.ishland.c2me.chunkio.syncDiskWrites", String.valueOf(sync))); // DivineMC - C2ME: sync disk writes
|
|
this.info = info;
|
|
this.isChunkData = isChunkDataFolder(this.folder); // Paper - recalculate region file headers
|
|
}
|