From b834e981c25f76be4499056304b4f5e28991f4d0 Mon Sep 17 00:00:00 2001 From: XiaoMoMi <972454774@qq.com> Date: Sat, 8 Nov 2025 21:40:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20item=20=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/block/BukkitBlockManager.java | 4 + .../BukkitBlockEntityElementConfigs.java | 1 + .../element/ItemBlockEntityElement.java | 65 ++++++++++++++++ .../element/ItemBlockEntityElementConfig.java | 77 +++++++++++++++++++ .../ItemDisplayBlockEntityElement.java | 2 +- .../TextDisplayBlockEntityElement.java | 2 +- .../bukkit/entity/data/ItemEntityData.java | 11 +++ .../plugin/injector/BlockGenerator.java | 8 ++ .../element/BlockEntityElementConfigs.java | 1 + 9 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElement.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemEntityData.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 01d66a69d..10c77c589 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -290,6 +290,10 @@ public final class BukkitBlockManager extends AbstractBlockManager { this.burnOdds.put(nmsBlock, settings.fireSpreadChance()); this.burnableBlocks.add(nmsBlock); } + + Key vanillaBlockId = state.vanillaBlockState().ownerId(); + BlockGenerator.field$CraftEngineBlock$isNoteBlock().set(nmsBlock, vanillaBlockId.equals(BlockKeys.NOTE_BLOCK)); + BlockGenerator.field$CraftEngineBlock$isTripwire().set(nmsBlock, vanillaBlockId.equals(BlockKeys.TRIPWIRE)); } catch (ReflectiveOperationException e) { this.plugin.logger().warn("Failed to apply platform block settings for block state " + state, e); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java index 8553a7c56..ee182e392 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/BukkitBlockEntityElementConfigs.java @@ -7,6 +7,7 @@ public class BukkitBlockEntityElementConfigs extends BlockEntityElementConfigs { static { register(ITEM_DISPLAY, ItemDisplayBlockEntityElementConfig.FACTORY); register(TEXT_DISPLAY, TextDisplayBlockEntityElementConfig.FACTORY); + register(ITEM, ItemBlockEntityElementConfig.FACTORY); } private BukkitBlockEntityElementConfigs() {} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElement.java new file mode 100644 index 000000000..7cf886977 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElement.java @@ -0,0 +1,65 @@ +package net.momirealms.craftengine.bukkit.block.entity.renderer.element; + +import it.unimi.dsi.fastutil.ints.IntList; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.world.BlockPos; +import org.joml.Vector3f; + +import java.util.List; +import java.util.UUID; + +public class ItemBlockEntityElement implements BlockEntityElement { + public final ItemBlockEntityElementConfig config; + public final Object cachedSpawnPacket1; + public final Object cachedSpawnPacket2; + public final Object cachedRidePacket; + public final Object cachedDespawnPacket; + public final Object cachedUpdatePosPacket; + public final int entityId1; + public final int entityId2; + + public ItemBlockEntityElement(ItemBlockEntityElementConfig config, BlockPos pos) { + this(config, pos, CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(), CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(), false); + } + + public ItemBlockEntityElement(ItemBlockEntityElementConfig config, BlockPos pos, int entityId1, int entityId2, boolean posChanged) { + this.config = config; + Vector3f position = config.position(); + this.cachedSpawnPacket1 = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId1, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, + 0, 0, MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 + ); + this.cachedSpawnPacket2 = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId2, UUID.randomUUID(), pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, + 0, 0, MEntityTypes.ITEM, 0, CoreReflections.instance$Vec3$Zero, 0 + ); + this.cachedRidePacket = FastNMS.INSTANCE.constructor$ClientboundSetPassengersPacket(entityId1, entityId2); + this.cachedDespawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(IntList.of(entityId1, entityId2)); + this.entityId1 = entityId1; + this.entityId2 = entityId2; + this.cachedUpdatePosPacket = posChanged ? FastNMS.INSTANCE.constructor$ClientboundEntityPositionSyncPacket(this.entityId1, pos.x() + position.x, pos.y() + position.y, pos.z() + position.z, 0, 0, false) : null; + } + + @Override + public void hide(Player player) { + player.sendPacket(this.cachedDespawnPacket, false); + } + + @Override + public void show(Player player) { + player.sendPackets(List.of(this.cachedSpawnPacket1, this.cachedSpawnPacket2, this.cachedRidePacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId2, this.config.metadataValues(player))), false); + } + + @Override + public void transform(Player player) { + if (this.cachedUpdatePosPacket != null) { + player.sendPackets(List.of(this.cachedUpdatePosPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId2, this.config.metadataValues(player))), false); + } else { + player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId2, this.config.metadataValues(player)), false); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java new file mode 100644 index 000000000..96873d757 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java @@ -0,0 +1,77 @@ +package net.momirealms.craftengine.bukkit.block.entity.renderer.element; + +import net.momirealms.craftengine.bukkit.entity.data.ItemEntityData; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig; +import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.World; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +public class ItemBlockEntityElementConfig implements BlockEntityElementConfig { + public static final Factory FACTORY = new Factory(); + private final Function> lazyMetadataPacket; + private final Function> item; + private final Vector3f position; + + public ItemBlockEntityElementConfig(Function> item, Vector3f position) { + this.item = item; + this.position = position; + this.lazyMetadataPacket = player -> { + List dataValues = new ArrayList<>(); + ItemEntityData.Item.addEntityDataIfNotDefaultValue(item.apply(player).getLiteralObject(), dataValues); + ItemEntityData.NoGravity.addEntityDataIfNotDefaultValue(true, dataValues); + return dataValues; + }; + } + + @Override + public ItemBlockEntityElement create(World world, BlockPos pos) { + return new ItemBlockEntityElement(this, pos); + } + + @Override + public ItemBlockEntityElement create(World world, BlockPos pos, ItemBlockEntityElement previous) { + return new ItemBlockEntityElement(this, pos, previous.entityId1, previous.entityId2, !previous.config.position.equals(this.position)); + } + + @Override + public Class elementClass() { + return ItemBlockEntityElement.class; + } + + public Vector3f position() { + return position; + } + + public Item item(Player player) { + return this.item.apply(player); + } + + public List metadataValues(Player player) { + return this.lazyMetadataPacket.apply(player); + } + + public static class Factory implements BlockEntityElementConfigFactory { + + @SuppressWarnings("unchecked") + @Override + public BlockEntityElementConfig create(Map arguments) { + Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.item_display.missing_item")); + return (BlockEntityElementConfig) new ItemBlockEntityElementConfig( + player -> BukkitItemManager.instance().createWrappedItem(itemId, player), + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position") + ); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java index 4159f41d7..558e56ff9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElement.java @@ -42,7 +42,7 @@ public class ItemDisplayBlockEntityElement implements BlockEntityElement { @Override public void show(Player player) { - player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), true); + player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), false); } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java index de3c7a644..9cefef8eb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElement.java @@ -42,7 +42,7 @@ public class TextDisplayBlockEntityElement implements BlockEntityElement { @Override public void show(Player player) { - player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), true); + player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadataValues(player))), false); } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemEntityData.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemEntityData.java new file mode 100644 index 000000000..a31b2272b --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemEntityData.java @@ -0,0 +1,11 @@ +package net.momirealms.craftengine.bukkit.entity.data; + +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; + +public class ItemEntityData extends BaseEntityData { + public static final ItemEntityData Item = new ItemEntityData<>(ItemEntityData.class, EntityDataValue.Serializers$ITEM_STACK, CoreReflections.instance$ItemStack$EMPTY); + + public ItemEntityData(Class clazz, Object serializer, T defaultValue) { + super(clazz, serializer, defaultValue); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java index 70f1823bb..b757fae76 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java @@ -201,6 +201,14 @@ public final class BlockGenerator { field$CraftEngineBlock$isTripwire = clazz$CraftEngineBlock.getField("isClientSideTripwire"); } + public static Field field$CraftEngineBlock$isNoteBlock() { + return field$CraftEngineBlock$isNoteBlock; + } + + public static Field field$CraftEngineBlock$isTripwire() { + return field$CraftEngineBlock$isTripwire; + } + public static DelegatingBlock generateBlock(Key blockId) throws Throwable { ObjectHolder behaviorHolder = new ObjectHolder<>(EmptyBlockBehavior.INSTANCE); ObjectHolder shapeHolder = new ObjectHolder<>(STONE_SHAPE); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java index 910c56f56..1dabfa3be 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java @@ -13,6 +13,7 @@ import java.util.Optional; public abstract class BlockEntityElementConfigs { public static final Key ITEM_DISPLAY = Key.of("craftengine:item_display"); public static final Key TEXT_DISPLAY = Key.of("craftengine:text_display"); + public static final Key ITEM = Key.of("craftengine:item"); public static void register(Key key, BlockEntityElementConfigFactory type) { ((WritableRegistry) BuiltInRegistries.BLOCK_ENTITY_ELEMENT_TYPE)