mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2026-01-04 15:41:40 +00:00
[ci skip] cleanup (14/14)
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Taiyou06 <kaandindar21@gmail.com>
|
||||||
|
Date: Sun, 16 Feb 2025 01:13:04 +0100
|
||||||
|
Subject: [PATCH] Use ensureCapacity to pre-populate the size of ticking chunks
|
||||||
|
list output
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
index 6735f9e23c8972b7cf1438a2f3b49d780c1ff78c..c80464d333bd37a9b8bc7cea2291c8c72e6f9bd6 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||||
|
@@ -585,7 +585,11 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
|
final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked();
|
||||||
|
final int size = tickingChunks.size();
|
||||||
|
|
||||||
|
- final ChunkMap chunkMap = this.chunkMap;
|
||||||
|
+ // Leaf start - Use ensureCapacity to pre-populate the size of ticking chunks list output
|
||||||
|
+ if (output instanceof ArrayList<LevelChunk> arrayList) {
|
||||||
|
+ arrayList.ensureCapacity(size);
|
||||||
|
+ }
|
||||||
|
+ // Leaf end - Use ensureCapacity to pre-populate the size of ticking chunks list output
|
||||||
|
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
final ServerChunkCache.ChunkAndHolder chunkAndHolder = raw[i];
|
||||||
@@ -1,22 +1,16 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
From: Taiyou06 <kaandindar21@gmail.com>
|
From: Taiyou06 <kaandindar21@gmail.com>
|
||||||
Date: Sun, 16 Feb 2025 01:13:04 +0100
|
Date: Sun, 16 Feb 2025 01:13:04 +0100
|
||||||
Subject: [PATCH] ensureCapacity with collectTickingChunks
|
Subject: [PATCH] Directly use the pre-filtered ticking chunks list as the
|
||||||
|
output
|
||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||||
index 6735f9e23c8972b7cf1438a2f3b49d780c1ff78c..a3afd10ef6bdc7439cb92af97f7336d6331e26a0 100644
|
index c80464d333bd37a9b8bc7cea2291c8c72e6f9bd6..b1f1b596a597d559aa672a3cb46a03917ad746af 100644
|
||||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||||
@@ -585,17 +585,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
@@ -592,14 +592,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||||
final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked();
|
// Leaf end - Use ensureCapacity to pre-populate the size of ticking chunks list output
|
||||||
final int size = tickingChunks.size();
|
|
||||||
|
|
||||||
- final ChunkMap chunkMap = this.chunkMap;
|
|
||||||
+ // Directly add all pre-filtered ticking chunks to output
|
|
||||||
+ if (output instanceof ArrayList<LevelChunk> arrayList) {
|
|
||||||
+ arrayList.ensureCapacity(size);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
- final ServerChunkCache.ChunkAndHolder chunkAndHolder = raw[i];
|
- final ServerChunkCache.ChunkAndHolder chunkAndHolder = raw[i];
|
||||||
@@ -27,7 +21,7 @@ index 6735f9e23c8972b7cf1438a2f3b49d780c1ff78c..a3afd10ef6bdc7439cb92af97f7336d6
|
|||||||
- }
|
- }
|
||||||
-
|
-
|
||||||
- output.add(levelChunk);
|
- output.add(levelChunk);
|
||||||
+ output.add(raw[i].chunk());
|
+ output.add(raw[i].chunk()); // Leaf - Directly use the pre-filtered ticking chunks list as the output
|
||||||
}
|
}
|
||||||
// Paper end - chunk tick iteration optimisation
|
// Paper end - chunk tick iteration optimisation
|
||||||
}
|
}
|
||||||
@@ -5,10 +5,10 @@ Subject: [PATCH] Some Optimizations on SerializableChunkData
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||||
index 6b6aaeca14178b5b709e20ae13552d42217f15c0..c10ed10dd843bfa12be3f80a244cda94f8c56807 100644
|
index 6b6aaeca14178b5b709e20ae13552d42217f15c0..c0939c311c554a4660b80725294663bab7915733 100644
|
||||||
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||||
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||||
@@ -502,14 +502,14 @@ public record SerializableChunkData(
|
@@ -502,14 +502,16 @@ public record SerializableChunkData(
|
||||||
throw new IllegalArgumentException("Chunk can't be serialized: " + chunk);
|
throw new IllegalArgumentException("Chunk can't be serialized: " + chunk);
|
||||||
} else {
|
} else {
|
||||||
ChunkPos pos = chunk.getPos();
|
ChunkPos pos = chunk.getPos();
|
||||||
@@ -20,18 +20,20 @@ index 6b6aaeca14178b5b709e20ae13552d42217f15c0..c10ed10dd843bfa12be3f80a244cda94
|
|||||||
final int minLightSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinLightSection(level);
|
final int minLightSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinLightSection(level);
|
||||||
final int maxLightSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMaxLightSection(level);
|
final int maxLightSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMaxLightSection(level);
|
||||||
final int minBlockSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(level);
|
final int minBlockSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(level);
|
||||||
|
+ // Leaf start - Some Optimizations on SerializableChunkData
|
||||||
+ // Pre-allocate with correct capacity to avoid resizing
|
+ // Pre-allocate with correct capacity to avoid resizing
|
||||||
+ final int expectedSectionCount = maxLightSection - minLightSection + 1;
|
+ final int expectedSectionCount = maxLightSection - minLightSection + 1;
|
||||||
+ List<SerializableChunkData.SectionData> list = new ArrayList<>(expectedSectionCount);
|
+ List<SerializableChunkData.SectionData> list = new ArrayList<>(expectedSectionCount);
|
||||||
|
+ // Leaf end - Some Optimizations on SerializableChunkData
|
||||||
|
|
||||||
final LevelChunkSection[] chunkSections = chunk.getSections();
|
final LevelChunkSection[] chunkSections = chunk.getSections();
|
||||||
final ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray[] blockNibbles = ((ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk)chunk).starlight$getBlockNibbles();
|
final ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray[] blockNibbles = ((ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk)chunk).starlight$getBlockNibbles();
|
||||||
@@ -541,10 +541,11 @@ public record SerializableChunkData(
|
@@ -541,10 +543,11 @@ public record SerializableChunkData(
|
||||||
((ca.spottedleaf.moonrise.patches.starlight.storage.StarlightSectionData)(Object)sectionData).starlight$setSkyLightState(skyNibble.state);
|
((ca.spottedleaf.moonrise.patches.starlight.storage.StarlightSectionData)(Object)sectionData).starlight$setSkyLightState(skyNibble.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
- sectionsList.add(sectionData);
|
- sectionsList.add(sectionData);
|
||||||
+ list.add(sectionData);
|
+ list.add(sectionData); // Leaf - Some Optimizations on SerializableChunkData
|
||||||
}
|
}
|
||||||
// Paper end - starlight
|
// Paper end - starlight
|
||||||
|
|
||||||
@@ -39,11 +41,12 @@ index 6b6aaeca14178b5b709e20ae13552d42217f15c0..c10ed10dd843bfa12be3f80a244cda94
|
|||||||
List<CompoundTag> list1 = new ArrayList<>(chunk.getBlockEntitiesPos().size());
|
List<CompoundTag> list1 = new ArrayList<>(chunk.getBlockEntitiesPos().size());
|
||||||
|
|
||||||
for (BlockPos blockPos : chunk.getBlockEntitiesPos()) {
|
for (BlockPos blockPos : chunk.getBlockEntitiesPos()) {
|
||||||
@@ -554,7 +555,14 @@ public record SerializableChunkData(
|
@@ -554,7 +557,16 @@ public record SerializableChunkData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- List<CompoundTag> list2 = new ArrayList<>();
|
- List<CompoundTag> list2 = new ArrayList<>();
|
||||||
|
+ // Leaf start - Some Optimizations on SerializableChunkData
|
||||||
+ // For entities, use an initial estimated capacity if it's a ProtoChunk
|
+ // For entities, use an initial estimated capacity if it's a ProtoChunk
|
||||||
+ int entityEstimate = 64; // Reasonable default size
|
+ int entityEstimate = 64; // Reasonable default size
|
||||||
+ if (chunk.getPersistedStatus().getChunkType() == ChunkType.PROTOCHUNK) {
|
+ if (chunk.getPersistedStatus().getChunkType() == ChunkType.PROTOCHUNK) {
|
||||||
@@ -51,16 +54,17 @@ index 6b6aaeca14178b5b709e20ae13552d42217f15c0..c10ed10dd843bfa12be3f80a244cda94
|
|||||||
+ entityEstimate = Math.max(16, protoChunk.getEntities().size());
|
+ entityEstimate = Math.max(16, protoChunk.getEntities().size());
|
||||||
+ }
|
+ }
|
||||||
+ List<CompoundTag> list2 = new ArrayList<>(entityEstimate);
|
+ List<CompoundTag> list2 = new ArrayList<>(entityEstimate);
|
||||||
|
+ // Leaf end - Some Optimizations on SerializableChunkData
|
||||||
+
|
+
|
||||||
long[] longs = null;
|
long[] longs = null;
|
||||||
if (chunk.getPersistedStatus().getChunkType() == ChunkType.PROTOCHUNK) {
|
if (chunk.getPersistedStatus().getChunkType() == ChunkType.PROTOCHUNK) {
|
||||||
ProtoChunk protoChunk = (ProtoChunk)chunk;
|
ProtoChunk protoChunk = (ProtoChunk)chunk;
|
||||||
@@ -570,14 +578,16 @@ public record SerializableChunkData(
|
@@ -570,14 +582,18 @@ public record SerializableChunkData(
|
||||||
for (Entry<Heightmap.Types, Heightmap> entry : chunk.getHeightmaps()) {
|
for (Entry<Heightmap.Types, Heightmap> entry : chunk.getHeightmaps()) {
|
||||||
if (chunk.getPersistedStatus().heightmapsAfter().contains(entry.getKey())) {
|
if (chunk.getPersistedStatus().heightmapsAfter().contains(entry.getKey())) {
|
||||||
long[] rawData = entry.getValue().getRawData();
|
long[] rawData = entry.getValue().getRawData();
|
||||||
- map.put(entry.getKey(), (long[])rawData.clone());
|
- map.put(entry.getKey(), (long[])rawData.clone());
|
||||||
+ map.put(entry.getKey(), Arrays.copyOf(rawData, rawData.length));
|
+ map.put(entry.getKey(), Arrays.copyOf(rawData, rawData.length)); // Leaf - Some Optimizations on SerializableChunkData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,11 +72,13 @@ index 6b6aaeca14178b5b709e20ae13552d42217f15c0..c10ed10dd843bfa12be3f80a244cda94
|
|||||||
- ShortList[] lists = Arrays.stream(chunk.getPostProcessing())
|
- ShortList[] lists = Arrays.stream(chunk.getPostProcessing())
|
||||||
- .map(list3 -> list3 != null ? new ShortArrayList(list3) : null)
|
- .map(list3 -> list3 != null ? new ShortArrayList(list3) : null)
|
||||||
- .toArray(ShortList[]::new);
|
- .toArray(ShortList[]::new);
|
||||||
|
+ // Leaf start - Some Optimizations on SerializableChunkData
|
||||||
+ ShortList[] postProcessing = chunk.getPostProcessing();
|
+ ShortList[] postProcessing = chunk.getPostProcessing();
|
||||||
+ ShortList[] lists = new ShortList[postProcessing.length];
|
+ ShortList[] lists = new ShortList[postProcessing.length];
|
||||||
+ for (int i = 0; i < postProcessing.length; i++) {
|
+ for (int i = 0; i < postProcessing.length; i++) {
|
||||||
+ lists[i] = postProcessing[i] != null ? new ShortArrayList(postProcessing[i]) : null;
|
+ lists[i] = postProcessing[i] != null ? new ShortArrayList(postProcessing[i]) : null;
|
||||||
+ }
|
+ }
|
||||||
|
+ // Leaf end - Some Optimizations on SerializableChunkData
|
||||||
CompoundTag compoundTag = packStructureData(
|
CompoundTag compoundTag = packStructureData(
|
||||||
StructurePieceSerializationContext.fromLevel(level), pos, chunk.getAllStarts(), chunk.getAllReferences()
|
StructurePieceSerializationContext.fromLevel(level), pos, chunk.getAllStarts(), chunk.getAllReferences()
|
||||||
);
|
);
|
||||||
@@ -5,10 +5,10 @@ Subject: [PATCH] Rework ChunkHolderManager
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
||||||
index be820c6093dd2ae7642b9bee11edf65e3a8d7242..29872fa10ec833ff9391fc09df034204f092f8a6 100644
|
index be820c6093dd2ae7642b9bee11edf65e3a8d7242..d6a30d6735d24f24a8108b6a5d15725587bb662a 100644
|
||||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
||||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
|
||||||
@@ -736,24 +736,19 @@ public final class ChunkHolderManager {
|
@@ -736,24 +736,20 @@ public final class ChunkHolderManager {
|
||||||
|
|
||||||
final int sectionShift = ((ChunkSystemServerLevel)this.world).moonrise$getRegionChunkShift();
|
final int sectionShift = ((ChunkSystemServerLevel)this.world).moonrise$getRegionChunkShift();
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ index be820c6093dd2ae7642b9bee11edf65e3a8d7242..29872fa10ec833ff9391fc09df034204
|
|||||||
- return removeDelay <= 0L;
|
- return removeDelay <= 0L;
|
||||||
- };
|
- };
|
||||||
-
|
-
|
||||||
|
+ // Leaf start - Rework ChunkHolderManager
|
||||||
+ // Collect sections to process first to avoid concurrent modification issues
|
+ // Collect sections to process first to avoid concurrent modification issues
|
||||||
+ List<Long> sectionKeys = new ArrayList<>();
|
+ List<Long> sectionKeys = new ArrayList<>();
|
||||||
for (final PrimitiveIterator.OfLong iterator = this.sectionToChunkToExpireCount.keyIterator(); iterator.hasNext();) {
|
for (final PrimitiveIterator.OfLong iterator = this.sectionToChunkToExpireCount.keyIterator(); iterator.hasNext();) {
|
||||||
@@ -40,7 +41,7 @@ index be820c6093dd2ae7642b9bee11edf65e3a8d7242..29872fa10ec833ff9391fc09df034204
|
|||||||
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(
|
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(
|
||||||
CoordinateUtils.getChunkX(sectionKey) << sectionShift,
|
CoordinateUtils.getChunkX(sectionKey) << sectionShift,
|
||||||
CoordinateUtils.getChunkZ(sectionKey) << sectionShift
|
CoordinateUtils.getChunkZ(sectionKey) << sectionShift
|
||||||
@@ -761,45 +756,66 @@ public final class ChunkHolderManager {
|
@@ -761,11 +757,15 @@ public final class ChunkHolderManager {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Long2IntOpenHashMap chunkToExpireCount = this.sectionToChunkToExpireCount.get(sectionKey);
|
final Long2IntOpenHashMap chunkToExpireCount = this.sectionToChunkToExpireCount.get(sectionKey);
|
||||||
@@ -57,8 +58,8 @@ index be820c6093dd2ae7642b9bee11edf65e3a8d7242..29872fa10ec833ff9391fc09df034204
|
|||||||
+ // Process each chunk in this section
|
+ // Process each chunk in this section
|
||||||
for (final Iterator<Long2IntMap.Entry> iterator1 = chunkToExpireCount.long2IntEntrySet().fastIterator(); iterator1.hasNext();) {
|
for (final Iterator<Long2IntMap.Entry> iterator1 = chunkToExpireCount.long2IntEntrySet().fastIterator(); iterator1.hasNext();) {
|
||||||
final Long2IntMap.Entry entry = iterator1.next();
|
final Long2IntMap.Entry entry = iterator1.next();
|
||||||
-
|
|
||||||
final long chunkKey = entry.getLongKey();
|
@@ -773,33 +773,51 @@ public final class ChunkHolderManager {
|
||||||
final int expireCount = entry.getIntValue();
|
final int expireCount = entry.getIntValue();
|
||||||
|
|
||||||
final SortedArraySet<Ticket<?>> tickets = this.tickets.get(chunkKey);
|
final SortedArraySet<Ticket<?>> tickets = this.tickets.get(chunkKey);
|
||||||
@@ -123,3 +124,11 @@ index be820c6093dd2ae7642b9bee11edf65e3a8d7242..29872fa10ec833ff9391fc09df034204
|
|||||||
if (chunkToExpireCount.isEmpty()) {
|
if (chunkToExpireCount.isEmpty()) {
|
||||||
this.sectionToChunkToExpireCount.remove(sectionKey);
|
this.sectionToChunkToExpireCount.remove(sectionKey);
|
||||||
}
|
}
|
||||||
|
@@ -807,6 +825,7 @@ public final class ChunkHolderManager {
|
||||||
|
this.ticketLockArea.unlock(ticketLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ // Leaf end - Rework ChunkHolderManager
|
||||||
|
|
||||||
|
this.processTicketUpdates();
|
||||||
|
}
|
||||||
@@ -5,59 +5,51 @@ Subject: [PATCH] Optimize chunkUnload
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
|
diff --git a/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
|
||||||
index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..75893974d198b946bdc07b01b4c68ff999df5028 100644
|
index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..bed3a64388bb43e47c2ba4e67f7dde5b990d9578 100644
|
||||||
--- a/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
|
--- a/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
|
||||||
+++ b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
|
+++ b/ca/spottedleaf/moonrise/patches/starlight/light/SWMRNibbleArray.java
|
||||||
@@ -3,6 +3,8 @@ package ca.spottedleaf.moonrise.patches.starlight.light;
|
@@ -22,12 +22,24 @@ public final class SWMRNibbleArray {
|
||||||
import net.minecraft.world.level.chunk.DataLayer;
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.Arrays;
|
|
||||||
+import java.util.Map;
|
|
||||||
+import java.util.WeakHashMap;
|
|
||||||
|
|
||||||
// SWMR -> Single Writer Multi Reader Nibble Array
|
|
||||||
public final class SWMRNibbleArray {
|
|
||||||
@@ -22,21 +24,35 @@ public final class SWMRNibbleArray {
|
|
||||||
protected static final int INIT_STATE_INIT = 2; // initialised
|
protected static final int INIT_STATE_INIT = 2; // initialised
|
||||||
protected static final int INIT_STATE_HIDDEN = 3; // initialised, but conversion to Vanilla data should be treated as if NULL
|
protected static final int INIT_STATE_HIDDEN = 3; // initialised, but conversion to Vanilla data should be treated as if NULL
|
||||||
|
|
||||||
|
+ // Leaf start - Optimize chunkUnload
|
||||||
+ private volatile boolean cachedIsAllZero = false;
|
+ private volatile boolean cachedIsAllZero = false;
|
||||||
+ private boolean cachedIsAllZeroValid = false;
|
+ private boolean cachedIsAllZeroValid = false;
|
||||||
+
|
+
|
||||||
+ private static final ThreadLocal<SaveState[]> SAVE_STATE_CACHE =
|
+ private static final ThreadLocal<SaveState[]> SAVE_STATE_CACHE = ThreadLocal.withInitial(() -> new SaveState[4]);
|
||||||
+ ThreadLocal.withInitial(() -> new SaveState[4]);
|
|
||||||
+
|
+
|
||||||
public static final int ARRAY_SIZE = 16 * 16 * 16 / (8/4); // blocks / bytes per block
|
public static final int ARRAY_SIZE = 16 * 16 * 16 / (8/4); // blocks / bytes per block
|
||||||
// this allows us to maintain only 1 byte array when we're not updating
|
// this allows us to maintain only 1 byte array when we're not updating
|
||||||
- static final ThreadLocal<ArrayDeque<byte[]>> WORKING_BYTES_POOL = ThreadLocal.withInitial(ArrayDeque::new);
|
- static final ThreadLocal<ArrayDeque<byte[]>> WORKING_BYTES_POOL = ThreadLocal.withInitial(ArrayDeque::new);
|
||||||
+ static final ThreadLocal<ArrayDeque<byte[]>> WORKING_BYTES_POOL = new ThreadLocal<ArrayDeque<byte[]>>() {
|
+ static final ThreadLocal<ArrayDeque<byte[]>> WORKING_BYTES_POOL = ThreadLocal.withInitial(() -> {
|
||||||
+ @Override
|
+ return new ArrayDeque<>(8); // Limit pool size to avoid memory leaks
|
||||||
+ protected ArrayDeque<byte[]> initialValue() {
|
+ });
|
||||||
+ return new ArrayDeque<byte[]>(8); // Limit pool size to avoid memory leaks
|
+ // Leaf end - Optimize chunkUnload
|
||||||
+ }
|
|
||||||
+ };
|
|
||||||
|
|
||||||
private static byte[] allocateBytes() {
|
private static byte[] allocateBytes() {
|
||||||
- final byte[] inPool = WORKING_BYTES_POOL.get().pollFirst();
|
- final byte[] inPool = WORKING_BYTES_POOL.get().pollFirst();
|
||||||
|
+ // Leaf start - Optimize chunkUnload
|
||||||
+ final ArrayDeque<byte[]> queue = WORKING_BYTES_POOL.get();
|
+ final ArrayDeque<byte[]> queue = WORKING_BYTES_POOL.get();
|
||||||
+ final byte[] inPool = queue.pollFirst();
|
+ final byte[] inPool = queue.pollFirst();
|
||||||
|
+ // Leaf end - Optimize chunkUnload
|
||||||
if (inPool != null) {
|
if (inPool != null) {
|
||||||
return inPool;
|
return inPool;
|
||||||
}
|
}
|
||||||
-
|
@@ -36,7 +48,12 @@ public final class SWMRNibbleArray {
|
||||||
return new byte[ARRAY_SIZE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void freeBytes(final byte[] bytes) {
|
private static void freeBytes(final byte[] bytes) {
|
||||||
- WORKING_BYTES_POOL.get().addFirst(bytes);
|
- WORKING_BYTES_POOL.get().addFirst(bytes);
|
||||||
|
+ // Leaf start - Optimize chunkUnload
|
||||||
+ final ArrayDeque<byte[]> queue = WORKING_BYTES_POOL.get();
|
+ final ArrayDeque<byte[]> queue = WORKING_BYTES_POOL.get();
|
||||||
+ if (queue.size() < 8) { // Limit pool size to prevent memory leaks
|
+ if (queue.size() < 8) { // Limit pool size to prevent memory leaks
|
||||||
+ queue.addFirst(bytes);
|
+ queue.addFirst(bytes);
|
||||||
+ }
|
+ }
|
||||||
|
+ // Leaf end - Optimize chunkUnload
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SWMRNibbleArray fromVanilla(final DataLayer nibble) {
|
public static SWMRNibbleArray fromVanilla(final DataLayer nibble) {
|
||||||
@@ -131,15 +147,44 @@ public final class SWMRNibbleArray {
|
@@ -131,15 +148,44 @@ public final class SWMRNibbleArray {
|
||||||
public SaveState getSaveState() {
|
public SaveState getSaveState() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
final int state = this.stateVisible;
|
final int state = this.stateVisible;
|
||||||
@@ -65,9 +57,9 @@ index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..75893974d198b946bdc07b01b4c68ff9
|
|||||||
if (state == INIT_STATE_NULL) {
|
if (state == INIT_STATE_NULL) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
+
|
|
||||||
if (state == INIT_STATE_UNINIT) {
|
if (state == INIT_STATE_UNINIT) {
|
||||||
- return new SaveState(null, state);
|
- return new SaveState(null, state);
|
||||||
|
+ // Leaf start - Optimize chunkUnload
|
||||||
+ // Use array-based cache instead of WeakHashMap
|
+ // Use array-based cache instead of WeakHashMap
|
||||||
+ SaveState[] cache = SAVE_STATE_CACHE.get();
|
+ SaveState[] cache = SAVE_STATE_CACHE.get();
|
||||||
+ SaveState cachedState = cache[INIT_STATE_UNINIT];
|
+ SaveState cachedState = cache[INIT_STATE_UNINIT];
|
||||||
@@ -89,7 +81,6 @@ index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..75893974d198b946bdc07b01b4c68ff9
|
|||||||
+ cachedIsAllZeroValid = true;
|
+ cachedIsAllZeroValid = true;
|
||||||
}
|
}
|
||||||
- final boolean zero = isAllZero(data);
|
- final boolean zero = isAllZero(data);
|
||||||
+
|
|
||||||
if (zero) {
|
if (zero) {
|
||||||
+ // Use array-based cache instead of WeakHashMap
|
+ // Use array-based cache instead of WeakHashMap
|
||||||
+ SaveState[] cache = SAVE_STATE_CACHE.get();
|
+ SaveState[] cache = SAVE_STATE_CACHE.get();
|
||||||
@@ -102,10 +93,11 @@ index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..75893974d198b946bdc07b01b4c68ff9
|
|||||||
+ }
|
+ }
|
||||||
+ return cachedState;
|
+ return cachedState;
|
||||||
+ }
|
+ }
|
||||||
|
+ // Leaf end - Optimize chunkUnload
|
||||||
return state == INIT_STATE_INIT ? new SaveState(null, INIT_STATE_UNINIT) : null;
|
return state == INIT_STATE_INIT ? new SaveState(null, INIT_STATE_UNINIT) : null;
|
||||||
} else {
|
} else {
|
||||||
return new SaveState(data.clone(), state);
|
return new SaveState(data.clone(), state);
|
||||||
@@ -148,14 +193,23 @@ public final class SWMRNibbleArray {
|
@@ -148,17 +194,28 @@ public final class SWMRNibbleArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean isAllZero(final byte[] data) {
|
protected static boolean isAllZero(final byte[] data) {
|
||||||
@@ -114,14 +106,15 @@ index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..75893974d198b946bdc07b01b4c68ff9
|
|||||||
-
|
-
|
||||||
- for (int k = 1; k < (1 << 4); ++k) {
|
- for (int k = 1; k < (1 << 4); ++k) {
|
||||||
- whole |= data[(i << 4) | k];
|
- whole |= data[(i << 4) | k];
|
||||||
+ // check in 8-byte chunks
|
+ // Leaf start - Optimize chunkUnload
|
||||||
|
+ // Check in 8-byte chunks
|
||||||
+ final int longLength = ARRAY_SIZE >>> 3;
|
+ final int longLength = ARRAY_SIZE >>> 3;
|
||||||
+ for (int i = 0; i < longLength; i++) {
|
+ for (int i = 0; i < longLength; i++) {
|
||||||
+ long value = 0;
|
+ long value = 0;
|
||||||
+ final int baseIndex = i << 3;
|
+ final int baseIndex = i << 3;
|
||||||
+ // Combine 8 bytes into a long
|
+ // Combine 8 bytes into a long
|
||||||
+ for (int j = 0; j < 8; j++) {
|
+ for (int j = 0; j < 8; j++) {
|
||||||
+ value |= ((long)(data[baseIndex + j] & 0xFF)) << (j << 3);
|
+ value |= ((long) (data[baseIndex + j] & 0xFF)) << (j << 3);
|
||||||
+ }
|
+ }
|
||||||
+ if (value != 0) {
|
+ if (value != 0) {
|
||||||
+ return false;
|
+ return false;
|
||||||
@@ -135,50 +128,45 @@ index 4ca68a903e67606fc4ef0bfa9862a73797121c8b..75893974d198b946bdc07b01b4c68ff9
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,6 +217,10 @@ public final class SWMRNibbleArray {
|
+ // Leaf end - Optimize chunkUnload
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -349,6 +406,7 @@ public final class SWMRNibbleArray {
|
||||||
+ private void invalidateCache() {
|
|
||||||
+ this.cachedIsAllZeroValid = false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
// operation type: updating on src, updating on other
|
|
||||||
public void extrudeLower(final SWMRNibbleArray other) {
|
|
||||||
if (other.stateUpdating == INIT_STATE_NULL) {
|
|
||||||
@@ -349,6 +407,7 @@ public final class SWMRNibbleArray {
|
|
||||||
}
|
}
|
||||||
this.updatingDirty = false;
|
this.updatingDirty = false;
|
||||||
this.stateVisible = this.stateUpdating;
|
this.stateVisible = this.stateUpdating;
|
||||||
+ this.cachedIsAllZeroValid = false; // Invalidate cache on update
|
+ this.cachedIsAllZeroValid = false; // Leaf - Optimize chunkUnload - Invalidate cache on update
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -424,7 +483,14 @@ public final class SWMRNibbleArray {
|
@@ -424,7 +482,16 @@ public final class SWMRNibbleArray {
|
||||||
final int shift = (index & 1) << 2;
|
final int shift = (index & 1) << 2;
|
||||||
final int i = index >>> 1;
|
final int i = index >>> 1;
|
||||||
|
|
||||||
- this.storageUpdating[i] = (byte)((this.storageUpdating[i] & (0xF0 >>> shift)) | (value << shift));
|
- this.storageUpdating[i] = (byte)((this.storageUpdating[i] & (0xF0 >>> shift)) | (value << shift));
|
||||||
|
+ // Leaf start - Optimize chunkUnload
|
||||||
+ byte oldValue = this.storageUpdating[i];
|
+ byte oldValue = this.storageUpdating[i];
|
||||||
+ byte newValue = (byte)((oldValue & (0xF0 >>> shift)) | (value << shift));
|
+ byte newValue = (byte)((oldValue & (0xF0 >>> shift)) | (value << shift));
|
||||||
+
|
+
|
||||||
+ // Only invalidate cache if the value actually changes
|
+ // Only invalidate cache if the value actually changes
|
||||||
+ if (oldValue != newValue) {
|
+ if (oldValue != newValue) {
|
||||||
+ this.storageUpdating[i] = newValue;
|
+ this.storageUpdating[i] = newValue;
|
||||||
+ this.invalidateCache();
|
+ this.cachedIsAllZeroValid = false;
|
||||||
+ }
|
+ }
|
||||||
|
+ // Leaf end - Optimize chunkUnload
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class SaveState {
|
public static final class SaveState {
|
||||||
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||||
index b8ac6a9ba7b56ccd034757f7d135d272b8e69e90..f6c33a7ca59d00c8967034402be00767a66b6948 100644
|
index b8ac6a9ba7b56ccd034757f7d135d272b8e69e90..dc158e981199b507531af810ff9ced3ca717e39e 100644
|
||||||
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
|
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||||
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||||
@@ -24,6 +24,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
@@ -24,6 +24,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
||||||
private boolean isRandomlyTickingBlocksStatus; // Leaf - Cache random tick block status
|
private boolean isRandomlyTickingBlocksStatus; // Leaf - Cache random tick block status
|
||||||
public final PalettedContainer<BlockState> states;
|
public final PalettedContainer<BlockState> states;
|
||||||
private PalettedContainer<Holder<Biome>> biomes; // CraftBukkit - read/write
|
private PalettedContainer<Holder<Biome>> biomes; // CraftBukkit - read/write
|
||||||
+ private boolean modified = false;
|
+ private boolean modified = false; // Leaf - Optimize chunkUnload
|
||||||
|
|
||||||
// Paper start - block counting
|
// Paper start - block counting
|
||||||
private static final it.unimi.dsi.fastutil.shorts.ShortArrayList FULL_LIST = new it.unimi.dsi.fastutil.shorts.ShortArrayList(16*16*16);
|
private static final it.unimi.dsi.fastutil.shorts.ShortArrayList FULL_LIST = new it.unimi.dsi.fastutil.shorts.ShortArrayList(16*16*16);
|
||||||
@@ -186,14 +174,15 @@ index b8ac6a9ba7b56ccd034757f7d135d272b8e69e90..f6c33a7ca59d00c8967034402be00767
|
|||||||
// Paper end - block counting
|
// Paper end - block counting
|
||||||
|
|
||||||
public BlockState setBlockState(int x, int y, int z, BlockState state, boolean useLocks) {
|
public BlockState setBlockState(int x, int y, int z, BlockState state, boolean useLocks) {
|
||||||
+ this.modified = true;
|
+ this.modified = true; // Leaf - Optimize chunkUnload
|
||||||
BlockState blockState;
|
BlockState blockState;
|
||||||
if (useLocks) {
|
if (useLocks) {
|
||||||
blockState = this.states.getAndSet(x, y, z, state);
|
blockState = this.states.getAndSet(x, y, z, state);
|
||||||
@@ -328,7 +330,29 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
@@ -328,7 +330,32 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
||||||
this.biomes = palettedContainer;
|
this.biomes = palettedContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ // Leaf start - Optimize chunkUnload
|
||||||
+ private LevelChunkSection(short nonEmptyBlockCount, short tickingBlockCount, short tickingFluidCount,
|
+ private LevelChunkSection(short nonEmptyBlockCount, short tickingBlockCount, short tickingFluidCount,
|
||||||
+ PalettedContainer<BlockState> states, PalettedContainer<Holder<Biome>> biomes) {
|
+ PalettedContainer<BlockState> states, PalettedContainer<Holder<Biome>> biomes) {
|
||||||
+ this.nonEmptyBlockCount = nonEmptyBlockCount;
|
+ this.nonEmptyBlockCount = nonEmptyBlockCount;
|
||||||
@@ -201,10 +190,12 @@ index b8ac6a9ba7b56ccd034757f7d135d272b8e69e90..f6c33a7ca59d00c8967034402be00767
|
|||||||
+ this.tickingFluidCount = tickingFluidCount;
|
+ this.tickingFluidCount = tickingFluidCount;
|
||||||
+ this.states = states;
|
+ this.states = states;
|
||||||
+ this.biomes = biomes;
|
+ this.biomes = biomes;
|
||||||
+ this.isRandomlyTickingBlocksStatus = this.tickingBlockCount > 0;
|
+ this.isRandomlyTickingBlocksStatus = this.tickingBlockCount > 0; // Leaf - Cache random tick block status
|
||||||
+ }
|
+ }
|
||||||
|
+ // Leaf end - Optimize chunkUnload
|
||||||
+
|
+
|
||||||
public LevelChunkSection copy() {
|
public LevelChunkSection copy() {
|
||||||
|
+ // Leaf - Optimize chunkUnload
|
||||||
+ // If the section hasn't been modified and no random ticking blocks/fluids,
|
+ // If the section hasn't been modified and no random ticking blocks/fluids,
|
||||||
+ // return a lightweight copy that shares palette data
|
+ // return a lightweight copy that shares palette data
|
||||||
+ if (!this.modified && this.tickingBlockCount == 0 && this.tickingFluidCount == 0) {
|
+ if (!this.modified && this.tickingBlockCount == 0 && this.tickingFluidCount == 0) {
|
||||||
@@ -216,7 +207,7 @@ index b8ac6a9ba7b56ccd034757f7d135d272b8e69e90..f6c33a7ca59d00c8967034402be00767
|
|||||||
+ this.biomes // Share reference instead of copying
|
+ this.biomes // Share reference instead of copying
|
||||||
+ );
|
+ );
|
||||||
+ }
|
+ }
|
||||||
|
+ // Leaf end - Optimize chunkUnload
|
||||||
return new LevelChunkSection(this);
|
return new LevelChunkSection(this);
|
||||||
}
|
}
|
||||||
+
|
|
||||||
}
|
}
|
||||||
@@ -1,44 +1,18 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
From: Taiyou06 <kaandindar21@gmail.com>
|
From: Taiyou06 <kaandindar21@gmail.com>
|
||||||
Date: Sun, 2 Mar 2025 21:23:20 +0100
|
Date: Sun, 2 Mar 2025 21:23:20 +0100
|
||||||
Subject: [PATCH] Async ChunkSend
|
Subject: [PATCH] Async chunk sending
|
||||||
|
|
||||||
|
|
||||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||||
index a35e9fae8f8da0c42f0616c4f78dc396492673aa..4e2e9cbd46c12f5d11dca0ecc0d41078918d52a9 100644
|
index a35e9fae8f8da0c42f0616c4f78dc396492673aa..af49117695c0785033b984ff91550e2fccbbc5e6 100644
|
||||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||||
@@ -22,15 +22,13 @@ import it.unimi.dsi.fastutil.longs.LongComparator;
|
@@ -411,19 +411,91 @@ public final class RegionizedPlayerChunkLoader {
|
||||||
import it.unimi.dsi.fastutil.longs.LongHeapPriorityQueue;
|
|
||||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
|
||||||
import net.minecraft.network.protocol.Packet;
|
|
||||||
-import net.minecraft.network.protocol.game.ClientboundForgetLevelChunkPacket;
|
|
||||||
-import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket;
|
|
||||||
-import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket;
|
|
||||||
-import net.minecraft.network.protocol.game.ClientboundSetSimulationDistancePacket;
|
|
||||||
+import net.minecraft.network.protocol.game.*;
|
|
||||||
import net.minecraft.server.level.ChunkTrackingView;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
|
||||||
import net.minecraft.server.level.TicketType;
|
|
||||||
import net.minecraft.server.network.PlayerChunkSender;
|
|
||||||
+import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
|
||||||
import net.minecraft.world.level.ChunkPos;
|
|
||||||
import net.minecraft.world.level.GameRules;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
|
||||||
@@ -43,6 +41,8 @@ import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
+import static org.dreeam.leaf.config.LeafConfig.LOGGER;
|
|
||||||
+
|
|
||||||
public final class RegionizedPlayerChunkLoader {
|
|
||||||
|
|
||||||
public static final TicketType<Long> PLAYER_TICKET = TicketType.create("chunk_system:player_ticket", Long::compareTo);
|
|
||||||
@@ -411,18 +411,84 @@ public final class RegionizedPlayerChunkLoader {
|
|
||||||
this.delayedTicketOps.addLast(op);
|
this.delayedTicketOps.addLast(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ // Leaf start - Async chunk sending
|
||||||
+ /**
|
+ /**
|
||||||
+ * Sends a chunk to the player.
|
+ * Sends a chunk to the player.
|
||||||
+ * If async chunk sending is enabled, this will prepare and send the chunk packet asynchronously.
|
+ * If async chunk sending is enabled, this will prepare and send the chunk packet asynchronously.
|
||||||
@@ -49,7 +23,8 @@ index a35e9fae8f8da0c42f0616c4f78dc396492673aa..4e2e9cbd46c12f5d11dca0ecc0d41078
|
|||||||
- ((ChunkSystemChunkHolder)((ChunkSystemServerLevel)this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
|
- ((ChunkSystemChunkHolder)((ChunkSystemServerLevel)this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
|
||||||
- .getChunkHolder(chunkX, chunkZ).vanillaChunkHolder).moonrise$addReceivedChunk(this.player);
|
- .getChunkHolder(chunkX, chunkZ).vanillaChunkHolder).moonrise$addReceivedChunk(this.player);
|
||||||
+ final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
|
+ final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
|
||||||
+
|
|
||||||
|
- final LevelChunk chunk = ((ChunkSystemLevel)this.world).moonrise$getFullChunkIfLoaded(chunkX, chunkZ);
|
||||||
+ if (!this.sentChunks.add(chunkKey)) {
|
+ if (!this.sentChunks.add(chunkKey)) {
|
||||||
+ // Already in our sent list - silently return instead of throwing an exception
|
+ // Already in our sent list - silently return instead of throwing an exception
|
||||||
+ return;
|
+ return;
|
||||||
@@ -62,13 +37,12 @@ index a35e9fae8f8da0c42f0616c4f78dc396492673aa..4e2e9cbd46c12f5d11dca0ecc0d41078
|
|||||||
+ this.sentChunks.remove(chunkKey);
|
+ this.sentChunks.remove(chunkKey);
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
- final LevelChunk chunk = ((ChunkSystemLevel)this.world).moonrise$getFullChunkIfLoaded(chunkX, chunkZ);
|
|
||||||
+ // Try to mark the chunk as received by this player
|
+ // Try to mark the chunk as received by this player
|
||||||
+ try {
|
+ try {
|
||||||
+ // This part needs to remain on the main thread as it affects shared state
|
+ // This part needs to remain on the main thread as it affects shared state
|
||||||
+ ((ChunkSystemChunkHolder) ((ChunkSystemServerLevel) this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
|
+ ((ChunkSystemServerLevel) this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
|
||||||
+ .getChunkHolder(chunkX, chunkZ).vanillaChunkHolder).moonrise$addReceivedChunk(this.player);
|
+ .getChunkHolder(chunkX, chunkZ).vanillaChunkHolder.moonrise$addReceivedChunk(this.player);
|
||||||
|
|
||||||
+ // Call onChunkWatch on the main thread as it might affect server state
|
+ // Call onChunkWatch on the main thread as it might affect server state
|
||||||
PlatformHooks.get().onChunkWatch(this.world, chunk, this.player);
|
PlatformHooks.get().onChunkWatch(this.world, chunk, this.player);
|
||||||
@@ -86,22 +60,26 @@ index a35e9fae8f8da0c42f0616c4f78dc396492673aa..4e2e9cbd46c12f5d11dca0ecc0d41078
|
|||||||
+ // Async implementation
|
+ // Async implementation
|
||||||
+ net.minecraft.Util.backgroundExecutor().execute(() -> {
|
+ net.minecraft.Util.backgroundExecutor().execute(() -> {
|
||||||
+ try {
|
+ try {
|
||||||
+ final ServerGamePacketListenerImpl connection = this.player.connection;
|
+ final net.minecraft.server.network.ServerGamePacketListenerImpl connection = this.player.connection;
|
||||||
+ final ServerLevel serverLevel = this.world;
|
+ final ServerLevel serverLevel = this.world;
|
||||||
|
+
|
||||||
+ // Create the packet with anti-xray control flag
|
+ // Create the packet with anti-xray control flag
|
||||||
+ final ClientboundLevelChunkWithLightPacket packet = new ClientboundLevelChunkWithLightPacket(
|
+ final net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket packet = new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||||
+ chunk, serverLevel.getLightEngine(), null, null,
|
+ chunk, serverLevel.getLightEngine(), null, null,
|
||||||
+ serverLevel.chunkPacketBlockController.shouldModify(this.player, chunk)
|
+ serverLevel.chunkPacketBlockController.shouldModify(this.player, chunk)
|
||||||
+ );
|
+ );
|
||||||
|
+
|
||||||
+ // Let the main thread handle the anti-xray processing
|
+ // Let the main thread handle the anti-xray processing
|
||||||
+ serverLevel.getServer().execute(() -> {
|
+ serverLevel.getServer().execute(() -> {
|
||||||
+ if (this.removed || !this.sentChunks.contains(chunkKey)) {
|
+ if (this.removed || !this.sentChunks.contains(chunkKey)) {
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
+ // This will trigger anti-xray processing and mark the packet as ready when done
|
+ // This will trigger anti-xray processing and mark the packet as ready when done
|
||||||
+ // The packet automatically handles readiness
|
+ // The packet automatically handles readiness
|
||||||
+ // Send the packet (which will be held until ready by the network layer)
|
+ // Send the packet (which will be held until ready by the network layer)
|
||||||
+ connection.send(packet);
|
+ connection.send(packet);
|
||||||
|
+
|
||||||
+ // Fire events and send POI packets
|
+ // Fire events and send POI packets
|
||||||
+ if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
+ if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||||
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(
|
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(
|
||||||
@@ -110,11 +88,11 @@ index a35e9fae8f8da0c42f0616c4f78dc396492673aa..4e2e9cbd46c12f5d11dca0ecc0d41078
|
|||||||
+ ).callEvent();
|
+ ).callEvent();
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ ChunkPos pos = chunk.getPos();
|
+ net.minecraft.network.protocol.game.DebugPackets.sendPoiPacketsForChunk(serverLevel, chunk.getPos());
|
||||||
+ DebugPackets.sendPoiPacketsForChunk(serverLevel, pos);
|
|
||||||
+ });
|
+ });
|
||||||
+ } catch (Exception e) {
|
+ } catch (Exception e) {
|
||||||
+ LOGGER.error("Failed to send chunk asynchronously", e);
|
+ org.dreeam.leaf.async.AsyncChunkSending.LOGGER.error("Failed to send chunk asynchronously!", e);
|
||||||
|
+
|
||||||
+ if (!this.removed) {
|
+ if (!this.removed) {
|
||||||
+ this.sentChunks.remove(chunkKey);
|
+ this.sentChunks.remove(chunkKey);
|
||||||
+ }
|
+ }
|
||||||
@@ -124,5 +102,7 @@ index a35e9fae8f8da0c42f0616c4f78dc396492673aa..4e2e9cbd46c12f5d11dca0ecc0d41078
|
|||||||
+ PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk);
|
+ PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk);
|
||||||
+ }
|
+ }
|
||||||
}
|
}
|
||||||
|
+ // Leaf end - Async chunk sending
|
||||||
|
|
||||||
private void sendUnloadChunk(final int chunkX, final int chunkZ) {
|
private void sendUnloadChunk(final int chunkX, final int chunkZ) {
|
||||||
|
if (!this.sentChunks.remove(CoordinateUtils.getChunkKey(chunkX, chunkZ))) {
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.dreeam.leaf.async;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
public class AsyncChunkSending {
|
||||||
|
|
||||||
|
public static final Logger LOGGER = LogManager.getLogger(AsyncChunkSending.class.getSimpleName());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user