From 4da72b140fd6eabcab8d88b62fe6eae779cc22f0 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 26 Apr 2025 16:36:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8C=BA=E5=9D=97=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../bukkit/api/CraftEngineBlocks.java | 10 +-- .../bukkit/api/CraftEngineFurniture.java | 13 +++ .../plugin/network/PacketConsumers.java | 80 ++----------------- 4 files changed, 27 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 9888e2c5b..f0b0d8a09 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Given the extensive and intricate nature of plugin configurations, a modular tem The plugin enables model inheritance and texture overrides through configuration, while supporting [all item models](https://misode.github.io/assets/item/) from version 1.21.4 onward. It incorporates a version migration system that automatically downgrades 1.21.4+ item models to legacy formats with maximum backward compatibility. ### Breaking Changes You Have to Know & Possible Incompatibility with Other Plugins -- CraftEngine injects into PalettedContainer to ensure efficient storage and synchronization of plugin block data. This may cause conflicts with some other plugins that modify the palette. When analyzing server performance using Spark, palette operation overhead will be attributed to the CraftEngine plugin in the profiling results.. +- CraftEngine injects into PalettedContainer to ensure efficient storage and synchronization of plugin block data. This may cause conflicts with some other plugins that modify the palette. When analyzing server performance using Spark, palette operation overhead will be attributed to the CraftEngine plugin in the profiling results. - CraftEngine injects into FurnaceBlockEntity to modify its recipe fetching logic. - CraftEngine uses real server-side blocks, any plugin relying on Bukkit's Material class will fail to correctly identify custom block types. The proper approach is to use alternatives like BlockState#getBlock (mojmap) instead of the Material class. - CraftEngine implements 0-tick collision entities by extending certain Minecraft entities, ensuring hard collision works correctly on the server side (e.g., making a pig stand on a chair). However, some anti-cheat plugins do not check entity AABB (Axis-Aligned Bounding Box) properly when detecting player movement, which may lead to false flags. diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java index 00fad28bf..7b8467ea5 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java @@ -124,7 +124,7 @@ public final class CraftEngineBlocks { } /** - * Removes a block from the world if it's a custom one + * Removes a block from the world if it's custom * * @param block block to remove * @return success or not @@ -136,7 +136,7 @@ public final class CraftEngineBlocks { } /** - * Removes a block from the world if it's a custom one + * Removes a block from the world if it's custom * * @param block block to remove * @param applyPhysics whether to apply physics @@ -150,7 +150,7 @@ public final class CraftEngineBlocks { } /** - * Removes a block from the world if it's a custom one + * Removes a block from the world if it's custom * * @param block block to remove * @param player player who breaks the block @@ -193,7 +193,7 @@ public final class CraftEngineBlocks { } /** - * Checks if a block is a custom one + * Checks if a block is custom * * @param block block * @return is custom block or not @@ -236,7 +236,7 @@ public final class CraftEngineBlocks { * @return bukkit block data */ @NotNull - public static BlockData createBukkitBlockData(@NotNull ImmutableBlockState blockState) { + public static BlockData getBukkitBlockData(@NotNull ImmutableBlockState blockState) { return BlockStateUtils.fromBlockData(blockState.customBlockState().handle()); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java index a187386ab..4abf9bbab 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java @@ -2,6 +2,8 @@ package net.momirealms.craftengine.bukkit.api; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; +import net.momirealms.craftengine.bukkit.nms.CollisionEntity; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.bukkit.world.BukkitWorld; @@ -122,6 +124,17 @@ public final class CraftEngineFurniture { return furnitureId != null; } + /** + * Check if an entity is a collision entity + * + * @param entity entity to check + * @return is collision entity or not + */ + public static boolean isCollisionEntity(@NotNull Entity entity) { + Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(entity); + return nmsEntity instanceof CollisionEntity; + } + /** * Check if an entity is a seat * 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 1adde1b62..afd444347 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 @@ -43,6 +43,7 @@ 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.NBT; import net.momirealms.sparrow.nbt.Tag; import org.bukkit.*; import org.bukkit.block.Block; @@ -97,77 +98,11 @@ public class PacketConsumers { 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(); + + boolean named = !VersionHelper.isVersionNewerThan1_20_2(); // ClientboundLevelChunkPacketData int heightmapsCount = 0; Map heightmapsMap = new HashMap<>(); @@ -180,8 +115,9 @@ public class PacketConsumers { heightmapsMap.put(key, value); } } else { - heightmaps = buf.readNbt(false); + heightmaps = buf.readNbt(named); } + int varInt = buf.readVarInt(); byte[] buffer = new byte[varInt]; buf.readBytes(buffer); @@ -191,7 +127,7 @@ public class PacketConsumers { byte packedXZ = buf.readByte(); short y = buf.readShort(); int type = buf.readVarInt(); - Tag tag = buf.readNbt(false); + Tag tag = buf.readNbt(named); BlockEntityData blockEntityData = new BlockEntityData(packedXZ, y, type, tag); blockEntitiesData.add(blockEntityData); } @@ -269,7 +205,7 @@ public class PacketConsumers { buf.writeLongArray(entry.getValue()); } } else { - buf.writeNbt(heightmaps, false); + buf.writeNbt(heightmaps, named); } buf.writeVarInt(buffer.length); buf.writeBytes(buffer); @@ -278,7 +214,7 @@ public class PacketConsumers { buf.writeByte(blockEntityData.packedXZ()); buf.writeShort(blockEntityData.y()); buf.writeVarInt(blockEntityData.type()); - buf.writeNbt(blockEntityData.tag(), false); + buf.writeNbt(blockEntityData.tag(), named); } buf.writeBitSet(skyYMask); buf.writeBitSet(blockYMask);