9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-19 15:09:25 +00:00
Files
Leaf/leaf-server/minecraft-patches/features/0127-Rewrite-ClientboundLightUpdatePacketData.patch
2025-06-13 18:11:40 +09:00

241 lines
10 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Taiyou06 <kaandindar21@gmail.com>
Date: Mon, 24 Feb 2025 21:33:24 +0100
Subject: [PATCH] Rewrite ClientboundLightUpdatePacketData
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On writing operations:
At 256 sections with 0.75 fill ratio: 18x faster (333.489 μs → 18.606 μs)
At 256 sections with 0.5 fill ratio: 13.5x faster (147.804 μs → 10.962 μs)
diff --git a/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java b/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java
index a0b54f3a3d11e0f0f1cb806406a870ba36da8f07..234280499fe1bc495bcdd4c3e144d1f99b7e6975 100644
--- a/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java
@@ -16,30 +16,113 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
public class ClientboundLightUpdatePacketData {
private static final StreamCodec<ByteBuf, byte[]> DATA_LAYER_STREAM_CODEC = ByteBufCodecs.byteArray(2048);
+
+ // Leaf start - Rewrite ClientboundLightUpdatePacketData
+ // Static constants to avoid allocations
+ private static final byte[][] EMPTY_ARRAY = new byte[0][];
+
+ // Pre-sized arrays to avoid dynamic resizing
+ private static final ThreadLocal<byte[][]> SKY_BUFFER = ThreadLocal.withInitial(() -> new byte[256][]);
+ private static final ThreadLocal<byte[][]> BLOCK_BUFFER = ThreadLocal.withInitial(() -> new byte[256][]);
+
+ // Pre-cached BitSets with fixed size
private final BitSet skyYMask;
private final BitSet blockYMask;
private final BitSet emptySkyYMask;
private final BitSet emptyBlockYMask;
- private final List<byte[]> skyUpdates;
- private final List<byte[]> blockUpdates;
+
+ // Fixed arrays with exact counts
+ private final byte[][] skyUpdates;
+ private final byte[][] blockUpdates;
+ private final int skyUpdateCount;
+ private final int blockUpdateCount;
+ // Leaf end - Rewrite ClientboundLightUpdatePacketData
public ClientboundLightUpdatePacketData(ChunkPos chunkPos, LevelLightEngine lightEngine, @Nullable BitSet skyLight, @Nullable BitSet blockLight) {
- this.skyYMask = new BitSet();
- this.blockYMask = new BitSet();
- this.emptySkyYMask = new BitSet();
- this.emptyBlockYMask = new BitSet();
- this.skyUpdates = Lists.newArrayList();
- this.blockUpdates = Lists.newArrayList();
-
- for (int i = 0; i < lightEngine.getLightSectionCount(); i++) {
+ // Leaf start - Rewrite ClientboundLightUpdatePacketData
+ int sectionCount = lightEngine.getLightSectionCount();
+
+ // Round up to nearest long boundary (64 bits) to prevent BitSet expansion
+ int longWords = (sectionCount + 63) >>> 6;
+ int bitSetSize = longWords << 6;
+
+ // Pre-size all BitSets to exact size needed
+ this.skyYMask = new BitSet(bitSetSize);
+ this.blockYMask = new BitSet(bitSetSize);
+ this.emptySkyYMask = new BitSet(bitSetSize);
+ this.emptyBlockYMask = new BitSet(bitSetSize);
+
+ // Get buffer arrays from thread local storage to avoid allocations
+ byte[][] skyBuffer = SKY_BUFFER.get();
+ byte[][] blockBuffer = BLOCK_BUFFER.get();
+
+ // Process all sections in a single pass
+ int skyCount = 0;
+ int blockCount = 0;
+ int minLightSection = lightEngine.getMinLightSection();
+
+ // Cache layer listeners to avoid repeated method calls
+ var skyLayerListener = lightEngine.getLayerListener(LightLayer.SKY);
+ var blockLayerListener = lightEngine.getLayerListener(LightLayer.BLOCK);
+
+ // Single pass through all sections
+ for (int i = 0; i < sectionCount; i++) {
+ int sectionY = minLightSection + i;
+ SectionPos sectionPos = SectionPos.of(chunkPos.x, sectionY, chunkPos.z);
+
+ // Process sky light
if (skyLight == null || skyLight.get(i)) {
- this.prepareSectionData(chunkPos, lightEngine, LightLayer.SKY, i, this.skyYMask, this.emptySkyYMask, this.skyUpdates);
+ DataLayer skyData = skyLayerListener.getDataLayerData(sectionPos);
+ if (skyData != null) {
+ if (skyData.isEmpty()) {
+ emptySkyYMask.set(i);
+ } else {
+ skyYMask.set(i);
+ // Store in buffer temporarily - only clone at the end
+ skyBuffer[skyCount++] = skyData.getData();
+ }
+ }
}
+ // Process block light
if (blockLight == null || blockLight.get(i)) {
- this.prepareSectionData(chunkPos, lightEngine, LightLayer.BLOCK, i, this.blockYMask, this.emptyBlockYMask, this.blockUpdates);
+ DataLayer blockData = blockLayerListener.getDataLayerData(sectionPos);
+ if (blockData != null) {
+ if (blockData.isEmpty()) {
+ emptyBlockYMask.set(i);
+ } else {
+ blockYMask.set(i);
+ // Store in buffer temporarily - only clone at the end
+ blockBuffer[blockCount++] = blockData.getData();
+ }
+ }
+ }
+ }
+
+ // Create final arrays with exact sizes
+ if (skyCount > 0) {
+ this.skyUpdates = new byte[skyCount][];
+ // Clone only at the end to minimize work
+ for (int i = 0; i < skyCount; i++) {
+ this.skyUpdates[i] = skyBuffer[i].clone();
+ }
+ } else {
+ this.skyUpdates = EMPTY_ARRAY;
+ }
+
+ if (blockCount > 0) {
+ this.blockUpdates = new byte[blockCount][];
+ // Clone only at the end to minimize work
+ for (int i = 0; i < blockCount; i++) {
+ this.blockUpdates[i] = blockBuffer[i].clone();
}
+ } else {
+ this.blockUpdates = EMPTY_ARRAY;
}
+
+ this.skyUpdateCount = skyCount;
+ this.blockUpdateCount = blockCount;
+ // Leaf end - Rewrite ClientboundLightUpdatePacketData
}
public ClientboundLightUpdatePacketData(FriendlyByteBuf buffer, int x, int z) {
@@ -47,8 +130,30 @@ public class ClientboundLightUpdatePacketData {
this.blockYMask = buffer.readBitSet();
this.emptySkyYMask = buffer.readBitSet();
this.emptyBlockYMask = buffer.readBitSet();
- this.skyUpdates = buffer.readList(DATA_LAYER_STREAM_CODEC);
- this.blockUpdates = buffer.readList(DATA_LAYER_STREAM_CODEC);
+
+ // Leaf start - Rewrite ClientboundLightUpdatePacketData
+ // Read lists directly as arrays to avoid intermediate collections
+ List<byte[]> skyList = buffer.readList(DATA_LAYER_STREAM_CODEC);
+ List<byte[]> blockList = buffer.readList(DATA_LAYER_STREAM_CODEC);
+
+ int skySize = skyList.size();
+ int blockSize = blockList.size();
+
+ if (skySize > 0) {
+ this.skyUpdates = skyList.toArray(new byte[skySize][]);
+ } else {
+ this.skyUpdates = EMPTY_ARRAY;
+ }
+
+ if (blockSize > 0) {
+ this.blockUpdates = blockList.toArray(new byte[blockSize][]);
+ } else {
+ this.blockUpdates = EMPTY_ARRAY;
+ }
+
+ this.skyUpdateCount = skySize;
+ this.blockUpdateCount = blockSize;
+ // Leaf end - Rewrite ClientboundLightUpdatePacketData
}
public void write(FriendlyByteBuf buffer) {
@@ -56,25 +161,33 @@ public class ClientboundLightUpdatePacketData {
buffer.writeBitSet(this.blockYMask);
buffer.writeBitSet(this.emptySkyYMask);
buffer.writeBitSet(this.emptyBlockYMask);
- buffer.writeCollection(this.skyUpdates, DATA_LAYER_STREAM_CODEC);
- buffer.writeCollection(this.blockUpdates, DATA_LAYER_STREAM_CODEC);
- }
- private void prepareSectionData(
- ChunkPos chunkPos, LevelLightEngine levelLightEngine, LightLayer lightLayer, int index, BitSet skyLight, BitSet blockLight, List<byte[]> updates
- ) {
- DataLayer dataLayerData = levelLightEngine.getLayerListener(lightLayer)
- .getDataLayerData(SectionPos.of(chunkPos, levelLightEngine.getMinLightSection() + index));
- if (dataLayerData != null) {
- if (dataLayerData.isEmpty()) {
- blockLight.set(index);
- } else {
- skyLight.set(index);
- updates.add(dataLayerData.copy().getData());
+ // Leaf start - Rewrite ClientboundLightUpdatePacketData
+ // Avoid creating unnecessary objects when writing
+ if (this.skyUpdateCount > 0) {
+ // Use direct array access for efficiency
+ buffer.writeVarInt(this.skyUpdateCount);
+ for (int i = 0; i < this.skyUpdateCount; i++) {
+ DATA_LAYER_STREAM_CODEC.encode(buffer, this.skyUpdates[i]);
}
+ } else {
+ buffer.writeVarInt(0);
}
+
+ if (this.blockUpdateCount > 0) {
+ // Use direct array access for efficiency
+ buffer.writeVarInt(this.blockUpdateCount);
+ for (int i = 0; i < this.blockUpdateCount; i++) {
+ DATA_LAYER_STREAM_CODEC.encode(buffer, this.blockUpdates[i]);
+ }
+ } else {
+ buffer.writeVarInt(0);
+ }
+ // Leaf end - Rewrite ClientboundLightUpdatePacketData
}
+ // Getter methods
+
public BitSet getSkyYMask() {
return this.skyYMask;
}
@@ -84,7 +197,7 @@ public class ClientboundLightUpdatePacketData {
}
public List<byte[]> getSkyUpdates() {
- return this.skyUpdates;
+ return this.skyUpdateCount > 0 ? java.util.Arrays.asList(this.skyUpdates) : List.of(); // Leaf - Rewrite ClientboundLightUpdatePacketData
}
public BitSet getBlockYMask() {
@@ -96,6 +209,6 @@ public class ClientboundLightUpdatePacketData {
}
public List<byte[]> getBlockUpdates() {
- return this.blockUpdates;
+ return this.blockUpdateCount > 0 ? java.util.Arrays.asList(this.blockUpdates) : List.of(); // Leaf - Rewrite ClientboundLightUpdatePacketData
}
}