9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-30 20:39:10 +00:00

Merge pull request #139 from jhqwqmc/dev

feat(network): 重构 LevelChunkWithLight 包处理逻辑
This commit is contained in:
XiaoMoMi
2025-04-26 15:54:38 +08:00
committed by GitHub
4 changed files with 152 additions and 16 deletions

View File

@@ -129,7 +129,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
}
private void registerPacketHandlers() {
registerNMSPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, Reflections.clazz$ClientboundLevelChunkWithLightPacket);
registerNMSPacketConsumer(PacketConsumers.PLAYER_INFO_UPDATE, Reflections.clazz$ClientboundPlayerInfoUpdatePacket);
registerNMSPacketConsumer(PacketConsumers.PLAYER_ACTION, Reflections.clazz$ServerboundPlayerActionPacket);
registerNMSPacketConsumer(PacketConsumers.SWING_HAND, Reflections.clazz$ServerboundSwingPacket);
@@ -152,6 +151,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
registerNMSPacketConsumer(PacketConsumers.HANDSHAKE_C2S, Reflections.clazz$ClientIntentionPacket);
registerNMSPacketConsumer(PacketConsumers.LOGIN_ACKNOWLEDGED, Reflections.clazz$ServerboundLoginAcknowledgedPacket);
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, Reflections.clazz$ServerboundResourcePackPacket);
registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
registerByteBufPacketConsumer(VersionHelper.isVersionNewerThan1_21_3() ? PacketConsumers.LEVEL_PARTICLE_1_21_3 : (VersionHelper.isVersionNewerThan1_20_5() ? PacketConsumers.LEVEL_PARTICLE_1_20_5 : PacketConsumers.LEVEL_PARTICLE_1_20), this.packetIds.clientboundLevelParticlesPacket());

View File

@@ -40,6 +40,7 @@ import net.momirealms.craftengine.core.world.EntityHitResult;
import net.momirealms.craftengine.core.world.WorldEvents;
import net.momirealms.craftengine.core.world.chunk.Palette;
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
import net.momirealms.craftengine.core.world.chunk.packet.BlockEntityData;
import net.momirealms.craftengine.core.world.chunk.packet.MCSection;
import net.momirealms.craftengine.core.world.collision.AABB;
import net.momirealms.sparrow.nbt.Tag;
@@ -92,15 +93,119 @@ public class PacketConsumers {
return mappingsMOD[stateId];
}
// TODO Use bytebuffer?
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> LEVEL_CHUNK_WITH_LIGHT = (user, event, packet) -> {
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> LEVEL_CHUNK_WITH_LIGHT = (user, event) -> {
try {
BukkitServerPlayer player = (BukkitServerPlayer) user;
FriendlyByteBuf buf = event.getBuffer();
// 我不明白为什么1.20~1.20.1会出问题貌似是readNbt的问题
if (!VersionHelper.isVersionNewerThan1_20_2()) {
Object packet = FastNMS.INSTANCE.constructor$ClientboundLevelChunkWithLightPacket(buf);
if (user.clientModEnabled()) {
Object chunkData = FastNMS.INSTANCE.field$ClientboundLevelChunkWithLightPacket$chunkData(packet);
byte[] buffer = FastNMS.INSTANCE.field$ClientboundLevelChunkPacketData$buffer(chunkData);
ByteBuf byteBuf = Unpooled.copiedBuffer(buffer);
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
try {
MCSection mcSection = new MCSection(BLOCK_LIST, BIOME_LIST);
mcSection.readPacket(friendlyByteBuf);
PalettedContainer<Integer> container = mcSection.blockStateContainer();
Palette<Integer> palette = container.data().palette();
if (palette.canRemap()) {
palette.remap(PacketConsumers::remapMOD);
} else {
for (int j = 0; j < 4096; j++) {
int state = container.get(j);
int newState = remapMOD(state);
if (newState != state) {
container.set(j, newState);
}
}
}
mcSection.writePacket(newBuf);
} catch (Exception e) {
break;
}
}
Reflections.field$ClientboundLevelChunkPacketData$buffer.set(chunkData, newBuf.array());
} else {
Object chunkData = FastNMS.INSTANCE.field$ClientboundLevelChunkWithLightPacket$chunkData(packet);
byte[] buffer = FastNMS.INSTANCE.field$ClientboundLevelChunkPacketData$buffer(chunkData);
ByteBuf byteBuf = Unpooled.copiedBuffer(buffer);
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
try {
MCSection mcSection = new MCSection(BLOCK_LIST, BIOME_LIST);
mcSection.readPacket(friendlyByteBuf);
PalettedContainer<Integer> container = mcSection.blockStateContainer();
Palette<Integer> palette = container.data().palette();
if (palette.canRemap()) {
palette.remap(PacketConsumers::remap);
} else {
for (int j = 0; j < 4096; j++) {
int state = container.get(j);
int newState = remap(state);
if (newState != state) {
container.set(j, newState);
}
}
}
mcSection.writePacket(newBuf);
} catch (Exception e) {
break;
}
}
Reflections.field$ClientboundLevelChunkPacketData$buffer.set(chunkData, newBuf.array());
}
buf.clear();
buf.writeVarInt(event.packetID());
FastNMS.INSTANCE.method$ClientboundLevelChunkWithLightPacket$write(packet, buf);
event.setChanged(true);
return;
}
// 这里是正片
int chunkX = buf.readInt();
int chunkZ = buf.readInt();
// ClientboundLevelChunkPacketData
int heightmapsCount = 0;
Map<Integer, long[]> heightmapsMap = new HashMap<>();
Tag heightmaps = null;
if (VersionHelper.isVersionNewerThan1_21_5()) {
heightmapsCount = buf.readVarInt();
for (int i = 0; i < heightmapsCount; i++) {
int key = buf.readVarInt();
long[] value = buf.readLongArray();
heightmapsMap.put(key, value);
}
} else {
heightmaps = buf.readNbt(false);
}
int varInt = buf.readVarInt();
byte[] buffer = new byte[varInt];
buf.readBytes(buffer);
int blockEntitiesDataCount = buf.readVarInt();
List<BlockEntityData> blockEntitiesData = new ArrayList<>();
for (int i = 0; i < blockEntitiesDataCount; i++) {
byte packedXZ = buf.readByte();
short y = buf.readShort();
int type = buf.readVarInt();
Tag tag = buf.readNbt(false);
BlockEntityData blockEntityData = new BlockEntityData(packedXZ, y, type, tag);
blockEntitiesData.add(blockEntityData);
}
// ClientboundLightUpdatePacketData
BitSet skyYMask = buf.readBitSet();
BitSet blockYMask = buf.readBitSet();
BitSet emptySkyYMask = buf.readBitSet();
BitSet emptyBlockYMask = buf.readBitSet();
List<byte[]> skyUpdates = buf.readByteArrayList(2048);
List<byte[]> blockUpdates = buf.readByteArrayList(2048);
// 开始处理
if (user.clientModEnabled()) {
BukkitServerPlayer player = (BukkitServerPlayer) user;
Object chunkData = FastNMS.INSTANCE.field$ClientboundLevelChunkWithLightPacket$chunkData(packet);
byte[] buffer = (byte[]) Reflections.field$ClientboundLevelChunkPacketData$buffer.get(chunkData);
ByteBuf buf = Unpooled.copiedBuffer(buffer);
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
ByteBuf byteBuf = Unpooled.copiedBuffer(buffer);
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
try {
@@ -124,13 +229,10 @@ public class PacketConsumers {
break;
}
}
Reflections.field$ClientboundLevelChunkPacketData$buffer.set(chunkData, newBuf.array());
buffer = newBuf.array();
} else {
BukkitServerPlayer player = (BukkitServerPlayer) user;
Object chunkData = FastNMS.INSTANCE.field$ClientboundLevelChunkWithLightPacket$chunkData(packet);
byte[] buffer = (byte[]) Reflections.field$ClientboundLevelChunkPacketData$buffer.get(chunkData);
ByteBuf buf = Unpooled.copiedBuffer(buffer);
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
ByteBuf byteBuf = Unpooled.copiedBuffer(buffer);
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer());
for (int i = 0, count = player.clientSideSectionCount(); i < count; i++) {
try {
@@ -154,8 +256,37 @@ public class PacketConsumers {
break;
}
}
Reflections.field$ClientboundLevelChunkPacketData$buffer.set(chunkData, newBuf.array());
buffer = newBuf.array();
}
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeInt(chunkX);
buf.writeInt(chunkZ);
if (VersionHelper.isVersionNewerThan1_21_5()) {
buf.writeVarInt(heightmapsCount);
for (Map.Entry<Integer, long[]> entry : heightmapsMap.entrySet()) {
buf.writeVarInt(entry.getKey());
buf.writeLongArray(entry.getValue());
}
} else {
buf.writeNbt(heightmaps, false);
}
buf.writeVarInt(buffer.length);
buf.writeBytes(buffer);
buf.writeVarInt(blockEntitiesDataCount);
for (BlockEntityData blockEntityData : blockEntitiesData) {
buf.writeByte(blockEntityData.packedXZ());
buf.writeShort(blockEntityData.y());
buf.writeVarInt(blockEntityData.type());
buf.writeNbt(blockEntityData.tag(), false);
}
buf.writeBitSet(skyYMask);
buf.writeBitSet(blockYMask);
buf.writeBitSet(emptySkyYMask);
buf.writeBitSet(emptyBlockYMask);
buf.writeByteArrayList(skyUpdates);
buf.writeByteArrayList(blockUpdates);
event.setChanged(true);
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundLevelChunkWithLightPacket", e);
}