diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 7c07a430f..3cc7ccda7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -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()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 803147f3a..1adde1b62 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -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 LEVEL_CHUNK_WITH_LIGHT = (user, event, packet) -> { + public static final BiConsumer 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 container = mcSection.blockStateContainer(); + Palette 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 container = mcSection.blockStateContainer(); + Palette 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 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 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 skyUpdates = buf.readByteArrayList(2048); + List 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 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); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/packet/BlockEntityData.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/packet/BlockEntityData.java new file mode 100644 index 000000000..3b57e24b6 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/packet/BlockEntityData.java @@ -0,0 +1,5 @@ +package net.momirealms.craftengine.core.world.chunk.packet; + +import net.momirealms.sparrow.nbt.Tag; + +public record BlockEntityData(int packedXZ, short y, int type, Tag tag) {} diff --git a/gradle.properties b/gradle.properties index b1b3587c7..008212c9c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -50,7 +50,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.15 -nms_helper_version=0.61.9 +nms_helper_version=0.62 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23 amazon_awssdk_eventstream_version=1.0.1