From df24a4047dd48a62048feb4d99237720e63598a1 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 5 Dec 2025 01:19:59 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=B8=BA=E6=B2=99=E5=8F=91=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=97=8B=E8=BD=AC=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/SeatBlockBehavior.java | 2 +- .../bukkit/block/entity/SeatBlockEntity.java | 12 ++- .../entity/furniture/BukkitFurniture.java | 91 ++++++++++++++++++- .../furniture/BukkitFurnitureManager.java | 28 ++++-- .../furniture/FurnitureEventListener.java | 59 ++++++++++++ .../item/listener/DebugStickListener.java | 13 ++- .../plugin/network/BukkitNetworkManager.java | 6 ++ .../default/configuration/blocks/sofa.yml | 2 + .../configuration/templates/events.yml | 31 +++++++ .../furniture/AbstractFurnitureManager.java | 2 +- .../core/entity/furniture/Furniture.java | 35 +++++-- .../entity/furniture/FurnitureConfigImpl.java | 3 +- .../craftengine/core/item/ItemKeys.java | 1 + .../core/pack/AbstractPackManager.java | 1 + .../function/CycleBlockPropertyFunction.java | 3 +- 15 files changed, 257 insertions(+), 32 deletions(-) create mode 100644 common-files/src/main/resources/resources/default/configuration/templates/events.yml diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java index e1c68747b..c54f6eb66 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java @@ -33,7 +33,7 @@ public class SeatBlockBehavior extends BukkitBlockBehavior implements EntityBloc @Override public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) { - return new SeatBlockEntity(pos, state, this.seats, this.directionProperty); + return new SeatBlockEntity(pos, state, this.seats); } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java index 5ff7a8812..00352c68c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.block.entity; +import net.momirealms.craftengine.bukkit.block.behavior.SeatBlockBehavior; import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.entity.BlockEntity; @@ -13,14 +14,14 @@ import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.sparrow.nbt.CompoundTag; +import java.util.Optional; + public class SeatBlockEntity extends BlockEntity implements SeatOwner { private final Seat[] seats; - private final Property facing; @SuppressWarnings("unchecked") - public SeatBlockEntity(BlockPos pos, ImmutableBlockState blockState, SeatConfig[] seats, Property directionProperty) { + public SeatBlockEntity(BlockPos pos, ImmutableBlockState blockState, SeatConfig[] seats) { super(BukkitBlockEntityTypes.SEAT, pos, blockState); - this.facing = directionProperty; this.seats = new Seat[seats.length]; for (int i = 0; i < seats.length; i++) { this.seats[i] = new BukkitSeat<>(this, seats[i]); @@ -41,7 +42,10 @@ public class SeatBlockEntity extends BlockEntity implements SeatOwner { public boolean spawnSeat(Player player) { int yRot = 0; - if (this.facing != null) { + Optional behavior = super.blockState.behavior().getAs(SeatBlockBehavior.class); + if (behavior.isEmpty()) return false; + Property facing = behavior.get().directionProperty(); + if (facing != null) { HorizontalDirection direction = super.blockState.get(facing); yRot = switch (direction) { case NORTH -> 0; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java index d7bbe6f9d..e7fe83ce7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java @@ -1,21 +1,34 @@ package net.momirealms.craftengine.bukkit.entity.furniture; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; import net.momirealms.craftengine.bukkit.entity.BukkitEntity; import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.core.entity.furniture.Collider; -import net.momirealms.craftengine.core.entity.furniture.Furniture; -import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig; -import net.momirealms.craftengine.core.entity.furniture.FurnitureDataAccessor; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; +import net.momirealms.craftengine.bukkit.util.LocationUtils; +import net.momirealms.craftengine.core.entity.furniture.*; +import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig; +import net.momirealms.craftengine.core.entity.player.InteractionResult; +import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.QuaternionUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.WorldPosition; +import net.momirealms.craftengine.core.world.collision.AABB; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataType; import org.joml.Quaternionf; import org.joml.Vector3f; import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; public class BukkitFurniture extends Furniture { private final WeakReference metaEntity; @@ -40,6 +53,76 @@ public class BukkitFurniture extends Furniture { } } + @Override + public boolean setVariant(String variantName) { + FurnitureVariant variant = this.config.getVariant(variantName); + if (variant == null) return false; + if (this.currentVariant == variant) return false; + BukkitFurnitureManager.instance().invalidateFurniture(this); + super.clearColliders(); + super.setVariantInternal(variant); + BukkitFurnitureManager.instance().initFurniture(this); + this.addCollidersToWorld(); + this.refresh(); + return true; + } + + @SuppressWarnings("deprecation") + @Override + public CompletableFuture moveTo(WorldPosition position) { + ItemDisplay itemDisplay = this.metaEntity.get(); + if (itemDisplay == null) return CompletableFuture.completedFuture(false); + // 检查新位置是否可用 + List aabbs = new ArrayList<>(); + for (FurnitureHitBoxConfig hitBoxConfig : getCurrentVariant().hitBoxConfigs()) { + hitBoxConfig.prepareForPlacement(position, aabbs::add); + } + if (!aabbs.isEmpty()) { + if (!FastNMS.INSTANCE.checkEntityCollision(position.world.serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) { + return CompletableFuture.completedFuture(false); + } + } + // 准备传送 + CompletableFuture future = new CompletableFuture<>(); + BukkitFurnitureManager.instance().invalidateFurniture(this); + super.clearColliders(); + this.location = LocationUtils.toLocation(position); + Object removePacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(itemDisplay.getEntityId()); }}); + for (Player player : itemDisplay.getTrackedPlayers()) { + BukkitAdaptors.adapt(player).sendPacket(removePacket, false); + } + itemDisplay.teleportAsync(this.location).thenAccept(result -> { + if (result) { + super.setVariantInternal(getCurrentVariant()); + BukkitFurnitureManager.instance().initFurniture(this); + this.addCollidersToWorld(); + Object addPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(itemDisplay.getEntityId(), itemDisplay.getUniqueId(), + itemDisplay.getX(), itemDisplay.getY(), itemDisplay.getZ(), itemDisplay.getPitch(), itemDisplay.getYaw(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0); + for (Player player : itemDisplay.getTrackedPlayers()) { + BukkitAdaptors.adapt(player).sendPacket(addPacket, false); + } + future.complete(true); + } else { + future.complete(false); + } + }); + return future; + } + + @SuppressWarnings("deprecation") + @Override + protected void refresh() { + ItemDisplay itemDisplay = this.metaEntity.get(); + if (itemDisplay == null) return; + Object removePacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(itemDisplay.getEntityId()); }}); + Object addPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(itemDisplay.getEntityId(), itemDisplay.getUniqueId(), + itemDisplay.getX(), itemDisplay.getY(), itemDisplay.getZ(), itemDisplay.getPitch(), itemDisplay.getYaw(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0); + for (Player player : itemDisplay.getTrackedPlayers()) { + BukkitAdaptors.adapt(player).sendPacket(removePacket, false); + BukkitAdaptors.adapt(player).sendPacket(addPacket, false); + } + } + @Override public void destroy() { Optional.ofNullable(this.metaEntity.get()).ifPresent(Entity::remove); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index 5b0f5cacc..c1cb3f717 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -323,18 +323,32 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { // 创建家具实例,并初始化碰撞实体 private BukkitFurniture createFurnitureInstance(ItemDisplay display, FurnitureConfig furniture) { BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, getFurnitureDataAccessor(display)); - this.byMetaEntityId.put(display.getEntityId(), bukkitFurniture); - for (int entityId : bukkitFurniture.virtualEntityIds()) { - this.byVirtualEntityId.put(entityId, bukkitFurniture); - } - for (Collider collisionEntity : bukkitFurniture.colliders()) { - this.byColliderEntityId.put(collisionEntity.entityId(), bukkitFurniture); - } + initFurniture(bukkitFurniture); Location location = display.getLocation(); runSafeEntityOperation(location, bukkitFurniture::addCollidersToWorld); return bukkitFurniture; } + protected void initFurniture(BukkitFurniture furniture) { + this.byMetaEntityId.put(furniture.entityId(), furniture); + for (int entityId : furniture.virtualEntityIds()) { + this.byVirtualEntityId.put(entityId, furniture); + } + for (Collider collisionEntity : furniture.colliders()) { + this.byColliderEntityId.put(collisionEntity.entityId(), furniture); + } + } + + protected void invalidateFurniture(BukkitFurniture furniture) { + this.byMetaEntityId.remove(furniture.entityId()); + for (int entityId : furniture.virtualEntityIds()) { + this.byVirtualEntityId.remove(entityId); + } + for (Collider collisionEntity : furniture.colliders()) { + this.byColliderEntityId.remove(collisionEntity.entityId()); + } + } + private void runSafeEntityOperation(Location location, Runnable action) { boolean preventChange = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4); if (preventChange) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java index 534a3b841..c71a480de 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java @@ -2,11 +2,26 @@ package net.momirealms.craftengine.bukkit.entity.furniture; import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; +import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; +import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; +import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; +import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; +import net.momirealms.craftengine.core.entity.furniture.FurnitureVariant; +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.RandomUtils; import net.momirealms.craftengine.core.world.CEWorld; +import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.chunk.CEChunk; import org.bukkit.entity.Entity; import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -14,8 +29,12 @@ import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.event.world.EntitiesLoadEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.event.world.WorldUnloadEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import java.util.ArrayList; import java.util.List; +import java.util.Map; public class FurnitureEventListener implements Listener { private final BukkitFurnitureManager manager; @@ -104,4 +123,44 @@ public class FurnitureEventListener implements Listener { this.manager.handleCollisionEntityUnload(entity); } } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onInteractFurniture(FurnitureInteractEvent event) { + Player bukkitPlayer = event.getPlayer(); + BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer); + if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) { + return; + } + Item itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND); + if (!itemInHand.vanillaId().equals(ItemKeys.DEBUG_STICK)) return; + BukkitFurniture furniture = event.furniture(); + List variants = new ArrayList<>(furniture.config.variants().keySet()); + if (variants.size() == 1) { + try { + Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance( + ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(furniture.id().asString()))), true); + player.sendPacket(systemChatPacket, false); + } catch (ReflectiveOperationException e) { + CraftEngine.instance().logger().warn("Could not create system chat packet", e); + } + } else { + String variantName = furniture.getCurrentVariant().name(); + int index = variants.indexOf(variantName) + 1; + if (index >= variants.size()) { + index = 0; + } + furniture.setVariant(variants.get(index)); + try { + Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance( + ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.update") + .arguments( + Component.text("variant"), + Component.text(variants.get(index)) + )), true); + player.sendPacket(systemChatPacket, false); + } catch (ReflectiveOperationException e) { + CraftEngine.instance().logger().warn("Could not create system chat packet", e); + } + } + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java index b3f763ce1..88d7d106c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/listener/DebugStickListener.java @@ -16,7 +16,9 @@ import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.UpdateOption; import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.util.MiscUtils; import org.bukkit.Material; import org.bukkit.block.Block; @@ -44,12 +46,10 @@ public class DebugStickListener implements Listener { public void onUseDebugStick(PlayerInteractEvent event) { Block clickedBlock = event.getClickedBlock(); if (clickedBlock == null) return; - ItemStack itemInHand = event.getItem(); - if (ItemStackUtils.isEmpty(itemInHand)) return; - Material material = itemInHand.getType(); - if (material != Material.DEBUG_STICK) return; Player bukkitPlayer = event.getPlayer(); BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer); + Item itemInHand = player.getItemInHand(event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); + if (!itemInHand.vanillaId().equals(ItemKeys.DEBUG_STICK)) return; if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) { return; } @@ -73,8 +73,7 @@ public class DebugStickListener implements Listener { ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true); player.sendPacket(systemChatPacket, false); } else { - Item wrapped = BukkitItemManager.instance().wrap(itemInHand); - Object storedData = wrapped.getJavaTag("craftengine:debug_stick_state"); + Object storedData = itemInHand.getJavaTag("craftengine:debug_stick_state"); if (storedData == null) storedData = new HashMap<>(); if (storedData instanceof Map map) { Map data = new HashMap<>(MiscUtils.castToMap(map, false)); @@ -96,7 +95,7 @@ public class DebugStickListener implements Listener { } else { currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive()); data.put(blockId, currentProperty.name()); - wrapped.setTag(data, "craftengine:debug_stick_state"); + itemInHand.setTag(data, "craftengine:debug_stick_state"); Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance( ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select") .arguments( 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 7728e1641..18cc1033c 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 @@ -67,6 +67,7 @@ import net.momirealms.craftengine.core.font.FontManager; import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult; import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipeHolder; @@ -3804,6 +3805,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes return; } + // 不处理调试棒 + if (itemInHand.vanillaId().equals(ItemKeys.DEBUG_STICK)) { + return; + } + // 必须从网络包层面处理,否则无法获取交互的具体实体 if (serverPlayer.isSecondaryUseActive() && !itemInHand.isEmpty() && hitBox.config().canUseItemOn()) { Optional> optionalCustomItem = itemInHand.getCustomItem(); diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml b/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml index 120c02811..bdd8f8131 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/sofa.yml @@ -53,6 +53,8 @@ items: behavior: type: block_item block: + events: + - template: default:rotatable_block loot: template: default:loot_table/self settings: diff --git a/common-files/src/main/resources/resources/default/configuration/templates/events.yml b/common-files/src/main/resources/resources/default/configuration/templates/events.yml new file mode 100644 index 000000000..d0727291f --- /dev/null +++ b/common-files/src/main/resources/resources/default/configuration/templates/events.yml @@ -0,0 +1,31 @@ +templates: + default:rotatable_block: + on: right_click + conditions: + - type: expression + expression: + functions: + - type: update_interaction_tick + - type: play_sound + sound: ${rotate_sound:-'minecraft:block.bamboo.place'} + - type: swing_hand + - type: cycle_block_property + property: facing + rules: + north: east + east: south + south: west + west: north + default:rotatable_furniture: + on: right_click + conditions: + - type: expression + expression: + functions: + - type: rotate_furniture + degree: 90 + on-success: + - type: swing_hand + - type: play_sound + sound: ${rotate_sound:-'minecraft:block.bamboo.place'} + on-failure: [] \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java index 23b3227ba..c3c0d50a8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java @@ -123,7 +123,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager { throw new LocalizedResourceConfigException("warning.config.furniture.missing_variants"); } - Map variants = new HashMap<>(); + Map variants = new LinkedHashMap<>(); for (Map.Entry e0 : variantsMap.entrySet()) { String variantName = e0.getKey(); Map variantArguments = ResourceConfigUtils.getAsMap(e0.getValue(), variantName); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java index 9210c649e..d5d51596e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.CompletableFuture; public abstract class Furniture implements Cullable { public final FurnitureConfig config; @@ -53,7 +54,7 @@ public abstract class Furniture implements Cullable { this.config = config; this.dataAccessor = data; this.metaDataEntity = metaDataEntity; - this.setVariant(config.getVariant(data)); + this.setVariantInternal(config.getVariant(data)); } public Entity metaDataEntity() { @@ -64,7 +65,21 @@ public abstract class Furniture implements Cullable { return this.currentVariant; } - public void setVariant(FurnitureVariant variant) { + public abstract boolean setVariant(String variantName); + + public abstract CompletableFuture moveTo(WorldPosition position); + + protected abstract void refresh(); + + protected void clearColliders() { + if (this.colliders != null) { + for (Collider collider : this.colliders) { + collider.destroy(); + } + } + } + + protected void setVariantInternal(FurnitureVariant variant) { this.currentVariant = variant; this.hitboxMap = new Int2ObjectOpenHashMap<>(); // 初始化家具元素 @@ -201,20 +216,28 @@ public abstract class Furniture implements Cullable { @Override public void show(Player player) { for (FurnitureElement element : this.elements) { - element.show(player); + if (element != null) { + element.show(player); + } } for (FurnitureHitBox hitbox : this.hitboxes) { - hitbox.show(player); + if (hitbox != null) { + hitbox.show(player); + } } } @Override public void hide(Player player) { for (FurnitureElement element : this.elements) { - element.hide(player); + if (element != null) { + element.hide(player); + } } for (FurnitureHitBox hitbox : this.hitboxes) { - hitbox.hide(player); + if (hitbox != null) { + hitbox.hide(player); + } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfigImpl.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfigImpl.java index a68613fef..2833306c8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfigImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfigImpl.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.core.entity.furniture; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedMap; import net.momirealms.craftengine.core.entity.furniture.behavior.EmptyFurnitureBehavior; import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior; import net.momirealms.craftengine.core.loot.LootTable; @@ -33,7 +34,7 @@ class FurnitureConfigImpl implements FurnitureConfig { @Nullable LootTable lootTable) { this.id = id; this.settings = settings; - this.variants = ImmutableMap.copyOf(variants); + this.variants = ImmutableSortedMap.copyOf(variants); this.lootTable = lootTable; this.behavior = behavior; this.events = events; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java index 4242b8d6a..161ea63a7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java @@ -65,6 +65,7 @@ public final class ItemKeys { public static final Key PURPLE_DYE = Key.of("minecraft:purple_dye"); public static final Key MAGENTA_DYE = Key.of("minecraft:magenta_dye"); public static final Key PINK_DYE = Key.of("minecraft:pink_dye"); + public static final Key DEBUG_STICK = Key.of("minecraft:debug_stick"); public static final Key CARROT = Key.of("minecraft:carrot"); public static final Key POTATO = Key.of("minecraft:potato"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 8c66bbff7..8ec309b93 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -471,6 +471,7 @@ public abstract class AbstractPackManager implements PackManager { plugin.saveResource("resources/default/configuration/templates/loot_tables.yml"); plugin.saveResource("resources/default/configuration/templates/recipes.yml"); plugin.saveResource("resources/default/configuration/templates/tool_levels.yml"); + plugin.saveResource("resources/default/configuration/templates/events.yml"); plugin.saveResource("resources/default/configuration/categories.yml"); plugin.saveResource("resources/default/configuration/emoji.yml"); plugin.saveResource("resources/default/configuration/translations.yml"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CycleBlockPropertyFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CycleBlockPropertyFunction.java index b99ef0e72..393468694 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CycleBlockPropertyFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CycleBlockPropertyFunction.java @@ -16,6 +16,7 @@ import net.momirealms.craftengine.core.world.WorldPosition; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Optional; @@ -71,7 +72,7 @@ public class CycleBlockPropertyFunction extends AbstractCon if (value == null) { return wrapper.cycleProperty(this.property, inverse); } - String mapValue = this.rules.get(value.toString()); + String mapValue = this.rules.get(value.toString().toLowerCase(Locale.ROOT)); if (mapValue == null) { return wrapper.cycleProperty(this.property, inverse); } From 6537a4cea9661058b50f02c2d74e84e9ab51583d Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 5 Dec 2025 01:48:50 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=89=E7=BA=BF?= =?UTF-8?q?=E8=BF=BD=E8=B8=AA=E9=83=A8=E5=88=86=E5=AE=B6=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/entity/furniture/BukkitFurniture.java | 6 +----- .../furniture/hitbox/CustomFurnitureHitboxConfig.java | 4 ++-- .../furniture/hitbox/HappyGhastFurnitureHitboxConfig.java | 4 ++-- .../furniture/hitbox/InteractionFurnitureHitboxConfig.java | 4 ++-- .../furniture/hitbox/ShulkerFurnitureHitboxConfig.java | 4 ++-- .../bukkit/item/behavior/FurnitureItemBehavior.java | 2 +- .../craftengine/bukkit/plugin/user/BukkitServerPlayer.java | 2 +- .../craftengine/core/entity/furniture/Furniture.java | 2 +- .../core/entity/furniture/hitbox/FurnitureHitBoxConfig.java | 2 +- .../core/plugin/entityculling/EntityCulling.java | 1 + 10 files changed, 14 insertions(+), 17 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java index e7fe83ce7..c8030e0d8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java @@ -9,11 +9,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityType import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.core.entity.furniture.*; import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig; -import net.momirealms.craftengine.core.entity.player.InteractionResult; -import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.QuaternionUtils; -import net.momirealms.craftengine.core.util.VersionHelper; -import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.collision.AABB; import org.bukkit.Location; @@ -75,7 +71,7 @@ public class BukkitFurniture extends Furniture { // 检查新位置是否可用 List aabbs = new ArrayList<>(); for (FurnitureHitBoxConfig hitBoxConfig : getCurrentVariant().hitBoxConfigs()) { - hitBoxConfig.prepareForPlacement(position, aabbs::add); + hitBoxConfig.prepareBoundingBox(position, aabbs::add, false); } if (!aabbs.isEmpty()) { if (!FastNMS.INSTANCE.checkEntityCollision(position.world.serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitboxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitboxConfig.java index d7147708c..bd53f0015 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitboxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitboxConfig.java @@ -71,8 +71,8 @@ public class CustomFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig aabbConsumer) { - if (this.blocksBuilding) { + public void prepareBoundingBox(WorldPosition targetPos, Consumer aabbConsumer, boolean ignoreBlocksBuilding) { + if (this.blocksBuilding || ignoreBlocksBuilding) { Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position); aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, this.width, this.height)); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitboxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitboxConfig.java index 6264b3a5f..3ee687d59 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitboxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitboxConfig.java @@ -56,8 +56,8 @@ public class HappyGhastFurnitureHitboxConfig extends AbstractFurnitureHitBoxConf } @Override - public void prepareForPlacement(WorldPosition targetPos, Consumer aabbConsumer) { - if (this.blocksBuilding) { + public void prepareBoundingBox(WorldPosition targetPos, Consumer aabbConsumer, boolean ignoreBlocksBuilding) { + if (this.blocksBuilding || ignoreBlocksBuilding) { Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position); aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, 4 * this.scale, 4 * this.scale)); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitboxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitboxConfig.java index 909335b0a..40caaf1ee 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitboxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitboxConfig.java @@ -70,8 +70,8 @@ public class InteractionFurnitureHitboxConfig extends AbstractFurnitureHitBoxCon } @Override - public void prepareForPlacement(WorldPosition targetPos, Consumer aabbConsumer) { - if (this.blocksBuilding) { + public void prepareBoundingBox(WorldPosition targetPos, Consumer aabbConsumer, boolean ignoreBlocksBuilding) { + if (this.blocksBuilding || ignoreBlocksBuilding) { Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position); aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, size.x, size.y)); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitboxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitboxConfig.java index 2b309b806..6756948bb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitboxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitboxConfig.java @@ -145,8 +145,8 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig< } @Override - public void prepareForPlacement(WorldPosition targetPos, Consumer aabbConsumer) { - if (this.blocksBuilding) { + public void prepareBoundingBox(WorldPosition targetPos, Consumer aabbConsumer, boolean ignoreBlocksBuilding) { + if (this.blocksBuilding || ignoreBlocksBuilding) { Quaternionf conjugated = QuaternionUtils.toQuaternionf(0f, (float) Math.toRadians(180 - targetPos.yRot()), 0f).conjugate(); Vector3f offset = conjugated.transform(new Vector3f(position())); aabbConsumer.accept(this.aabbCreator.create(targetPos.x, targetPos.y, targetPos.z, targetPos.yRot, offset)); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index 3c3d34027..28493cd5f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -114,7 +114,7 @@ public class FurnitureItemBehavior extends ItemBehavior { List aabbs = new ArrayList<>(); // 收集阻挡的碰撞箱 for (FurnitureHitBoxConfig hitBoxConfig : variant.hitBoxConfigs()) { - hitBoxConfig.prepareForPlacement(furniturePos, aabbs::add); + hitBoxConfig.prepareBoundingBox(furniturePos, aabbs::add, false); } // 检查方块、实体阻挡 if (!aabbs.isEmpty()) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 2bc3a8635..06653a9f4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -566,7 +566,7 @@ public class BukkitServerPlayer extends Player { FurnitureVariant currentVariant = furniture.getCurrentVariant(); List aabbs = new ArrayList<>(); for (FurnitureHitBoxConfig config : currentVariant.hitBoxConfigs()) { - config.prepareForPlacement(furniture.position(), aabbs::add); + config.prepareBoundingBox(furniture.position(), aabbs::add, true); } Key endRod = Key.of("soul_fire_flame"); for (AABB aabb : aabbs) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java index d5d51596e..ec865cdff 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java @@ -130,7 +130,7 @@ public abstract class Furniture implements Cullable { if (aabb == null) { List aabbs = new ArrayList<>(); for (FurnitureHitBoxConfig hitBoxConfig : this.currentVariant.hitBoxConfigs()) { - hitBoxConfig.prepareForPlacement(position, aabbs::add); + hitBoxConfig.prepareBoundingBox(position, aabbs::add, true); } return new CullingData(getMaxAABB(aabbs), parent.maxDistance, parent.aabbExpansion, parent.rayTracing); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBoxConfig.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBoxConfig.java index 7c8325e00..319a0f6a1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBoxConfig.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBoxConfig.java @@ -22,6 +22,6 @@ public interface FurnitureHitBoxConfig { boolean canUseItemOn(); - void prepareForPlacement(WorldPosition targetPos, Consumer aabbConsumer); + void prepareBoundingBox(WorldPosition targetPos, Consumer aabbConsumer, boolean ignoreBlocksBuilding); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/entityculling/EntityCulling.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/entityculling/EntityCulling.java index 79dac8655..183558688 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/entityculling/EntityCulling.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/entityculling/EntityCulling.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.entityculling; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.plugin.config.Config; +import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.world.ChunkPos; import net.momirealms.craftengine.core.world.MutableVec3d; From 94bc0e84824b10fbf0d94d7cdf81eba2c21cf684 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 5 Dec 2025 01:51:43 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E7=89=A9=E5=93=81=E6=A0=8F=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/context/event/EventFunctions.java | 1 + .../function/CloseInventoryFunction.java | 50 +++++++++++++++++++ .../context/function/CommonFunctions.java | 1 + 3 files changed, 52 insertions(+) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java index fbc8a4e69..4ddd76b8e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java @@ -58,6 +58,7 @@ public class EventFunctions { register(CommonFunctions.SET_EXP, new SetExpFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.SET_LEVEL, new SetLevelFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.PLAY_TOTEM_ANIMATION, new PlayTotemAnimationFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.CLOSE_INVENTORY, new CloseInventoryFunction.FactoryImpl<>(EventConditions::fromMap)); } public static void register(Key key, FunctionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java new file mode 100644 index 000000000..2b052af0f --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java @@ -0,0 +1,50 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector; +import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors; +import net.momirealms.craftengine.core.util.Key; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public class CloseInventoryFunction extends AbstractConditionalFunction { + private final PlayerSelector selector; + + public CloseInventoryFunction(List> predicates, @Nullable PlayerSelector selector) { + super(predicates); + this.selector = selector; + } + + @Override + public void runInternal(CTX ctx) { + if (this.selector == null) { + ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(Player::closeInventory); + } else { + for (Player viewer : this.selector.get(ctx)) { + viewer.closeInventory(); + } + } + } + + @Override + public Key type() { + return CommonFunctions.TITLE; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + return new CloseInventoryFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory())); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java index 937534105..128799962 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java @@ -49,4 +49,5 @@ public final class CommonFunctions { public static final Key SET_EXP = Key.of("craftengine:set_exp"); public static final Key SET_LEVEL = Key.of("craftengine:set_level"); public static final Key PLAY_TOTEM_ANIMATION = Key.of("craftengine:play_totem_animation"); + public static final Key CLOSE_INVENTORY = Key.of("craftengine:close_inventory"); } From 77bc8f8ae40f821c2a2e7b590de9e52af02e90c3 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 5 Dec 2025 01:53:32 +0800 Subject: [PATCH 4/5] Update CloseInventoryFunction.java --- .../core/plugin/context/function/CloseInventoryFunction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java index 2b052af0f..4b99be7dd 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CloseInventoryFunction.java @@ -33,7 +33,7 @@ public class CloseInventoryFunction extends AbstractConditi @Override public Key type() { - return CommonFunctions.TITLE; + return CommonFunctions.CLOSE_INVENTORY; } public static class FactoryImpl extends AbstractFactory { From f85aa51f9d18c88b2250a7c8005cafba12621b0b Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 5 Dec 2025 02:31:46 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=93=AD=E7=89=8C?= =?UTF-8?q?=E5=B8=BD=E5=AD=90=E9=AB=98=E5=BA=A6=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BukkitCompatibilityManager.java | 2 + .../tag/CustomNameplateHatSettings.java | 84 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/tag/CustomNameplateHatSettings.java diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java index 28d614af0..c56a998aa 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java @@ -19,6 +19,7 @@ import net.momirealms.craftengine.bukkit.compatibility.quickshop.QuickShopItemEx import net.momirealms.craftengine.bukkit.compatibility.region.WorldGuardRegionCondition; import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook; import net.momirealms.craftengine.bukkit.compatibility.slimeworld.SlimeFormatStorageAdaptor; +import net.momirealms.craftengine.bukkit.compatibility.tag.CustomNameplateHatSettings; import net.momirealms.craftengine.bukkit.compatibility.tag.CustomNameplateProviders; import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtils; import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister; @@ -97,6 +98,7 @@ public class BukkitCompatibilityManager implements CompatibilityManager { registerTagResolverProvider(new CustomNameplateProviders.Background()); registerTagResolverProvider(new CustomNameplateProviders.Nameplate()); registerTagResolverProvider(new CustomNameplateProviders.Bubble()); + new CustomNameplateHatSettings().register(); logHook("CustomNameplates"); } Key worldGuardRegion = Key.of("worldguard:region"); diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/tag/CustomNameplateHatSettings.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/tag/CustomNameplateHatSettings.java new file mode 100644 index 000000000..232161645 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/tag/CustomNameplateHatSettings.java @@ -0,0 +1,84 @@ +package net.momirealms.craftengine.bukkit.compatibility.tag; + +import io.papermc.paper.event.entity.EntityEquipmentChangedEvent; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.core.item.CustomItem; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemSettings; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.CustomDataType; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.customnameplates.api.CNPlayer; +import net.momirealms.customnameplates.api.CustomNameplates; +import net.momirealms.customnameplates.api.CustomNameplatesAPI; +import net.momirealms.customnameplates.api.feature.tag.TagRenderer; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public final class CustomNameplateHatSettings implements Listener { + public static final CustomDataType HAT_HEIGHT = new CustomDataType<>(); + + public void register() { + ItemSettings.Modifiers.registerFactory("hat-height", height -> { + double heightD = ResourceConfigUtils.getAsDouble(height, "hat-height"); + return settings -> settings.addCustomData(HAT_HEIGHT, heightD); + }); + Bukkit.getPluginManager().registerEvents(this, BukkitCraftEngine.instance().javaPlugin()); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onEquipmentChange(EntityEquipmentChangedEvent event) { + if (!(event.getEntity() instanceof Player player)) return; + Map equipmentChanges = event.getEquipmentChanges(); + EntityEquipmentChangedEvent.EquipmentChange equipmentChange = equipmentChanges.get(EquipmentSlot.HEAD); + if (equipmentChange == null) return; + ItemStack newItem = equipmentChange.newItem(); + updateHatHeight(player, newItem); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + // 稍微延迟一下,可以等待背包同步插件的处理 + if (VersionHelper.isFolia()) { + player.getScheduler().runDelayed(BukkitCraftEngine.instance().javaPlugin(), t1 -> { + if (player.isOnline()) { + updateHatHeight(player, player.getInventory().getItem(EquipmentSlot.HEAD)); + } + }, null, 10); + } else { + CraftEngine.instance().scheduler().sync().runLater(() -> { + if (player.isOnline()) { + updateHatHeight(player, player.getInventory().getItem(EquipmentSlot.HEAD)); + } + }, 10); + } + } + + public void updateHatHeight(Player player, ItemStack newItem) { + CNPlayer cnPlayer = CustomNameplatesAPI.getInstance().getPlayer(player.getUniqueId()); + if (cnPlayer == null) return; + TagRenderer tagRender = CustomNameplates.getInstance().getUnlimitedTagManager().getTagRender(cnPlayer); + if (tagRender == null) return; + Item wrapped = BukkitItemManager.instance().wrap(newItem); + Optional> optionalCustomItem = wrapped.getCustomItem(); + if (optionalCustomItem.isEmpty()) { + tagRender.hatOffset(0d); + return; + } + Double customHeight = optionalCustomItem.get().settings().getCustomData(HAT_HEIGHT); + tagRender.hatOffset(Objects.requireNonNullElse(customHeight, 0d)); + } +}