mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
73ffcb09faoptimize mob spawning333373d204fix async mob spawning data race7c9f88e4f8[ci skip] cleanupbf9486f0f0remove hash lookup in optimize random tick915ac01cd3cleanupb90c1cd527fix playermobcaps commandfd34d9f626cleanup5d663b4d36optimize collectSpawningChunks (#382)
174 lines
12 KiB
Diff
174 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Taiyou06 <kaandindar21@gmail.com>
|
|
Date: Sun, 2 Mar 2025 21:23:20 +0100
|
|
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
|
|
index 32608df3da169159c070f37cb55407f4f6187744..fc3901acdfcdad85fbd435ca21869388a90b2207 100644
|
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
|
@@ -436,7 +436,15 @@ public final class RegionizedPlayerChunkLoader {
|
|
// Note: drop isAlive() check so that chunks properly unload client-side when the player dies
|
|
((ChunkSystemChunkHolder)((ChunkSystemServerLevel)this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
|
|
.getChunkHolder(chunkX, chunkZ).vanillaChunkHolder).moonrise$removeReceivedChunk(this.player);
|
|
- this.player.connection.send(new ClientboundForgetLevelChunkPacket(new ChunkPos(chunkX, chunkZ)));
|
|
+ // Leaf start - Async chunk sending
|
|
+ if (org.dreeam.leaf.config.modules.async.AsyncChunkSend.enabled) {
|
|
+ org.dreeam.leaf.async.chunk.AsyncChunkSend.POOL.execute(
|
|
+ () -> this.player.connection.send(new ClientboundForgetLevelChunkPacket(new ChunkPos(chunkX, chunkZ)))
|
|
+ );
|
|
+ } else {
|
|
+ this.player.connection.send(new ClientboundForgetLevelChunkPacket(new ChunkPos(chunkX, chunkZ)));
|
|
+ }
|
|
+ // Leaf end - Async chunk sending
|
|
// Paper start - PlayerChunkUnloadEvent
|
|
if (io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
|
new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(player.getBukkitEntity().getWorld().getChunkAt(new ChunkPos(chunkX, chunkZ).longKey), player.getBukkitEntity()).callEvent();
|
|
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
|
index 526c117e0d53ad527eb610c79cdc46ec16b18c0c..9e5edbb05900fdaa8b9deed0fc65e9ca31fe6d61 100644
|
|
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
|
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
|
@@ -75,6 +75,45 @@ public class ClientboundLevelChunkPacketData {
|
|
}
|
|
}
|
|
|
|
+ // Leaf start - Async chunk sending
|
|
+ public ClientboundLevelChunkPacketData(LevelChunk levelChunk, io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo, BlockEntity[] blockEntities, Map<Heightmap.Types, long[]> heightmaps) {
|
|
+ this.heightmaps = heightmaps;
|
|
+
|
|
+ if (Thread.currentThread() instanceof org.dreeam.leaf.async.chunk.AsyncChunkSendThread) {
|
|
+ ByteBuf buffer = Unpooled.buffer(calculateChunkSize(levelChunk));
|
|
+ extractChunkData(new FriendlyByteBuf(buffer), levelChunk, chunkPacketInfo);
|
|
+ byte[] array = it.unimi.dsi.fastutil.bytes.ByteArrays.setLength(buffer.array(), buffer.writerIndex());
|
|
+ if (chunkPacketInfo != null) {
|
|
+ chunkPacketInfo.setBuffer(array);
|
|
+ }
|
|
+ this.buffer = array;
|
|
+ } else {
|
|
+ this.buffer = new byte[calculateChunkSize(levelChunk)];
|
|
+ // Paper start - Anti-Xray - Add chunk packet info
|
|
+ if (chunkPacketInfo != null) {
|
|
+ chunkPacketInfo.setBuffer(this.buffer);
|
|
+ }
|
|
+ extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk, chunkPacketInfo);
|
|
+ }
|
|
+
|
|
+ this.blockEntitiesData = Lists.newArrayList();
|
|
+ int totalTileEntities = 0; // Paper - Handle oversized block entities in chunks
|
|
+
|
|
+ for (BlockEntity blockEntity : blockEntities) {
|
|
+ // Paper start - Handle oversized block entities in chunks
|
|
+ if (++totalTileEntities > BLOCK_ENTITY_LIMIT) {
|
|
+ net.minecraft.network.protocol.Packet<ClientGamePacketListener> packet = blockEntity.getUpdatePacket();
|
|
+ if (packet != null) {
|
|
+ this.extraPackets.add(packet);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ // Paper end - Handle oversized block entities in chunks
|
|
+ this.blockEntitiesData.add(ClientboundLevelChunkPacketData.BlockEntityInfo.create(blockEntity));
|
|
+ }
|
|
+ }
|
|
+ // Leaf end - Async chunk sending
|
|
+
|
|
public ClientboundLevelChunkPacketData(RegistryFriendlyByteBuf buffer, int x, int z) {
|
|
this.heightmaps = HEIGHTMAPS_STREAM_CODEC.decode(buffer);
|
|
int varInt = buffer.readVarInt();
|
|
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
|
|
index 8578d1f78ddd1bb75f3230f04bfaa35af9f5f822..d8e938abf5123b092cec80feb6468e3d91ae823e 100644
|
|
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
|
|
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
|
|
@@ -44,6 +44,17 @@ public class ClientboundLevelChunkWithLightPacket implements Packet<ClientGamePa
|
|
this.lightData = new ClientboundLightUpdatePacketData(pos, lightEngine, skyLight, blockLight);
|
|
chunk.getLevel().chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks
|
|
}
|
|
+ // Leaf start - Async chunk sending
|
|
+ public ClientboundLevelChunkWithLightPacket(LevelChunk chunk, LevelLightEngine lightEngine, @Nullable BitSet skyLight, @Nullable BitSet blockLight, boolean modifyBlocks, net.minecraft.world.level.block.entity.BlockEntity[] blockEntities, java.util.Map<net.minecraft.world.level.levelgen.Heightmap.Types, long[]> heightmaps) {
|
|
+ ChunkPos pos = chunk.getPos();
|
|
+ this.x = pos.x;
|
|
+ this.z = pos.z;
|
|
+ io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo = modifyBlocks ? chunk.getLevel().chunkPacketBlockController.getChunkPacketInfo(this, chunk) : null; // Paper - Ant-Xray
|
|
+ this.chunkData = new ClientboundLevelChunkPacketData(chunk, chunkPacketInfo, blockEntities, heightmaps); // Paper - Anti-Xray
|
|
+ this.lightData = new ClientboundLightUpdatePacketData(pos, lightEngine, skyLight, blockLight);
|
|
+ chunk.getLevel().chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks
|
|
+ }
|
|
+ // Leaf end - Async chunk sending
|
|
|
|
private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) {
|
|
this.x = buffer.readInt();
|
|
diff --git a/net/minecraft/server/network/PlayerChunkSender.java b/net/minecraft/server/network/PlayerChunkSender.java
|
|
index 14878690a88fd4de3e2c127086607e6c819c636c..62e1dabd84b80d5e2e4a8fcb308934dce2d8c74b 100644
|
|
--- a/net/minecraft/server/network/PlayerChunkSender.java
|
|
+++ b/net/minecraft/server/network/PlayerChunkSender.java
|
|
@@ -64,13 +64,29 @@ public class PlayerChunkSender {
|
|
if (!list.isEmpty()) {
|
|
ServerGamePacketListenerImpl serverGamePacketListenerImpl = player.connection;
|
|
this.unacknowledgedBatches++;
|
|
- serverGamePacketListenerImpl.send(ClientboundChunkBatchStartPacket.INSTANCE);
|
|
+ // Leaf start - Async chunk sending
|
|
+ if (org.dreeam.leaf.config.modules.async.AsyncChunkSend.enabled) {
|
|
+ org.dreeam.leaf.async.chunk.AsyncChunkSend.POOL.execute(
|
|
+ () -> serverGamePacketListenerImpl.send(ClientboundChunkBatchStartPacket.INSTANCE)
|
|
+ );
|
|
+ } else {
|
|
+ serverGamePacketListenerImpl.send(ClientboundChunkBatchStartPacket.INSTANCE);
|
|
+ }
|
|
+ // Leaf end - Async chunk sending
|
|
|
|
for (LevelChunk levelChunk : list) {
|
|
sendChunk(serverGamePacketListenerImpl, serverLevel, levelChunk);
|
|
}
|
|
|
|
- serverGamePacketListenerImpl.send(new ClientboundChunkBatchFinishedPacket(list.size()));
|
|
+ // Leaf start - Async chunk sending
|
|
+ if (org.dreeam.leaf.config.modules.async.AsyncChunkSend.enabled) {
|
|
+ org.dreeam.leaf.async.chunk.AsyncChunkSend.POOL.execute(
|
|
+ () -> serverGamePacketListenerImpl.send(new ClientboundChunkBatchFinishedPacket(list.size()))
|
|
+ );
|
|
+ } else {
|
|
+ serverGamePacketListenerImpl.send(new ClientboundChunkBatchFinishedPacket(list.size()));
|
|
+ }
|
|
+ // Leaf end - Async chunk sending
|
|
this.batchQuota = this.batchQuota - list.size();
|
|
}
|
|
}
|
|
@@ -81,7 +97,23 @@ public class PlayerChunkSender {
|
|
// Paper start - Anti-Xray
|
|
public static void sendChunk(ServerGamePacketListenerImpl packetListener, ServerLevel level, LevelChunk chunk) {
|
|
final boolean shouldModify = level.chunkPacketBlockController.shouldModify(packetListener.player, chunk);
|
|
- packetListener.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null, shouldModify));
|
|
+ // Leaf start - Async chunk sending
|
|
+ if (org.dreeam.leaf.config.modules.async.AsyncChunkSend.enabled) {
|
|
+ var blockEntities = chunk.blockEntities.values().toArray(new net.minecraft.world.level.block.entity.BlockEntity[0]);
|
|
+ java.util.Map<net.minecraft.world.level.levelgen.Heightmap.Types, long[]> heightmaps = new java.util.concurrent.ConcurrentHashMap<>();
|
|
+
|
|
+ for (var entry : chunk.getHeightmaps()) {
|
|
+ if (entry.getKey().sendToClient()) {
|
|
+ heightmaps.put(entry.getKey(), entry.getValue().getRawData());
|
|
+ }
|
|
+ }
|
|
+ org.dreeam.leaf.async.chunk.AsyncChunkSend.POOL.execute(
|
|
+ () -> packetListener.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null, shouldModify, blockEntities, heightmaps))
|
|
+ );
|
|
+ } else {
|
|
+ packetListener.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null, shouldModify));
|
|
+ }
|
|
+ // Leaf end - Async chunk sending
|
|
// Paper end - Anti-Xray
|
|
// Paper start - PlayerChunkLoadEvent
|
|
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
|
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
|
index 36c033b0ee63dfc273d721fb4b614733e8fdef19..4d06df242ab73411bdefc4770e131b27a6ea668a 100644
|
|
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
|
|
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
|
@@ -18,7 +18,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_
|
|
public static final int SECTION_HEIGHT = 16;
|
|
public static final int SECTION_SIZE = 4096;
|
|
public static final int BIOME_CONTAINER_BITS = 2;
|
|
- short nonEmptyBlockCount; // Paper - package private
|
|
+ volatile short nonEmptyBlockCount; // Paper - package private // Leaf - Async chunk sending - volatile
|
|
private short tickingBlockCount;
|
|
private short tickingFluidCount;
|
|
private boolean isRandomlyTickingBlocksStatus; // Leaf - Cache random tick block status
|