From 6dd62fed3fc19e2044e498fab426e48f0b4c126d Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Mon, 31 Mar 2025 04:56:46 +0800 Subject: [PATCH] new hitbox types --- .../bukkit/entity/furniture/BoatHitBox.java | 44 +++++++++++ .../furniture/BukkitFurnitureManager.java | 4 +- .../entity/furniture/BukkitHitBoxTypes.java | 2 + .../entity/furniture/InteractionHitBox.java | 21 ++--- .../entity/furniture/LoadedFurniture.java | 78 +++++++++---------- .../entity/furniture/ShulkerHitBox.java | 76 ++++++++++++++++++ .../bukkit/item/ItemEventListener.java | 2 +- .../core/entity/furniture/AbstractHitBox.java | 10 ++- .../core/entity/furniture/HitBox.java | 8 +- .../core/entity/furniture/HitBoxTypes.java | 1 + 10 files changed, 191 insertions(+), 55 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BoatHitBox.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/ShulkerHitBox.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BoatHitBox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BoatHitBox.java new file mode 100644 index 000000000..004ed7131 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BoatHitBox.java @@ -0,0 +1,44 @@ +package net.momirealms.craftengine.bukkit.entity.furniture; + +import net.momirealms.craftengine.core.entity.furniture.*; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import org.joml.Vector3f; + +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class BoatHitBox extends AbstractHitBox { + public static final Factory FACTORY = new Factory(); + + public BoatHitBox(Seat[] seats, Vector3f position) { + super(seats, position); + } + + @Override + public Key type() { + return HitBoxTypes.BOAT; + } + + @Override + public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Consumer packets) { + // 生成无重力船 + } + + @Override + public int[] acquireEntityIds(Supplier entityIdSupplier) { + return new int[] {entityIdSupplier.get()}; + } + + public static class Factory implements HitBoxFactory { + + @Override + public HitBox create(Map arguments) { + return new BoatHitBox( + HitBoxFactory.getSeats(arguments), + MiscUtils.getVector3f(arguments.getOrDefault("position", "0")) + ); + } + } +} 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 0b29a6ecd..b8f673fc4 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 @@ -237,7 +237,7 @@ public class BukkitFurnitureManager implements FurnitureManager { LoadedFurniture furniture = this.furnitureByBaseEntityId.remove(id); if (furniture != null) { furniture.destroySeats(); - for (int sub : furniture.interactionEntityIds()) { + for (int sub : furniture.hitBoxEntityIds()) { this.furnitureByInteractionEntityId.remove(sub); } } else if (entity instanceof Interaction interaction) { @@ -307,7 +307,7 @@ public class BukkitFurnitureManager implements FurnitureManager { private synchronized LoadedFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture, AnchorType anchorType) { LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, anchorType); this.furnitureByBaseEntityId.put(loadedFurniture.baseEntityId(), loadedFurniture); - for (int entityId : loadedFurniture.interactionEntityIds()) { + for (int entityId : loadedFurniture.hitBoxEntityIds()) { this.furnitureByInteractionEntityId.put(entityId, loadedFurniture); } return loadedFurniture; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitHitBoxTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitHitBoxTypes.java index 55d5035a0..aa689fa40 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitHitBoxTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitHitBoxTypes.java @@ -8,5 +8,7 @@ public class BukkitHitBoxTypes extends HitBoxTypes { static { register(INTERACTION, InteractionHitBox.FACTORY); + register(SHULKER, ShulkerHitBox.FACTORY); + register(BOAT, BoatHitBox.FACTORY); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/InteractionHitBox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/InteractionHitBox.java index a2b1231ab..b8a9d5b97 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/InteractionHitBox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/InteractionHitBox.java @@ -13,18 +13,18 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Consumer; +import java.util.function.Supplier; public class InteractionHitBox extends AbstractHitBox { public static final Factory FACTORY = new Factory(); public static final InteractionHitBox DEFAULT = new InteractionHitBox(new Seat[0], new Vector3f(), new Vector3f(1,1,1), true); - private final Vector3f position; + private final Vector3f size; private final boolean responsive; private final List cachedValues = new ArrayList<>(); public InteractionHitBox(Seat[] seats, Vector3f position, Vector3f size, boolean responsive) { - super(seats); - this.position = position; + super(seats, position); this.size = size; this.responsive = responsive; InteractionEntityData.Height.addEntityDataIfNotDefaultValue(size.y, cachedValues); @@ -36,10 +36,6 @@ public class InteractionHitBox extends AbstractHitBox { return responsive; } - public Vector3f position() { - return position; - } - public Vector3f size() { return size; } @@ -50,19 +46,24 @@ public class InteractionHitBox extends AbstractHitBox { } @Override - public void addSpawnPackets(int entityId, double x, double y, double z, float yaw, Consumer packets) { + public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Consumer packets) { Vector3f offset = QuaternionUtils.toQuaternionf(0f, Math.toRadians(180f - yaw), 0f).conjugate().transform(new Vector3f(position())); try { packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance( - entityId, UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw, + entityId[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw, Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0 )); - packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId, List.copyOf(this.cachedValues))); + packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId[0], List.copyOf(this.cachedValues))); } catch (ReflectiveOperationException e) { throw new RuntimeException("Failed to construct hitbox spawn packet", e); } } + @Override + public int[] acquireEntityIds(Supplier entityIdSupplier) { + return new int[] {entityIdSupplier.get()}; + } + public static class Factory implements HitBoxFactory { @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java index 8fbbc5a40..fdc49801b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java @@ -26,21 +26,18 @@ public class LoadedFurniture { private final Key id; private final CustomFurniture furniture; private final AnchorType anchorType; - private final Map elements; - private final Map hitBoxes; // location private Location location; // base entity private final WeakReference baseEntity; private final int baseEntityId; - // includes elements + interactions - private final List subEntityIds; - // interactions - private final List interactionEntityIds; + // cache + private final List fakeEntityIds; + private final List hitBoxEntityIds; + private final Map hitBoxes; // seats private final Set occupiedSeats = Collections.synchronizedSet(new HashSet<>()); private final Vector seats = new Vector<>(); - // cached spawn packet private Object cachedSpawnPacket; @@ -54,40 +51,36 @@ public class LoadedFurniture { this.baseEntity = new WeakReference<>(baseEntity); this.furniture = furniture; this.hitBoxes = new HashMap<>(); - this.elements = new HashMap<>(); - List entityIds = new ArrayList<>(); + List fakeEntityIds = new ArrayList<>(); List hitBoxEntityIds = new ArrayList<>(); CustomFurniture.Placement placement = furniture.getPlacement(anchorType); + + List packets = new ArrayList<>(); for (FurnitureElement element : placement.elements()) { int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); - entityIds.add(entityId); - this.elements.put(entityId, element); + fakeEntityIds.add(entityId); + element.addSpawnPackets(entityId, this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add); } for (HitBox hitBox : placement.hitboxes()) { - int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); - entityIds.add(entityId); - hitBoxEntityIds.add(entityId); - this.hitBoxes.put(entityId, hitBox); - } - this.subEntityIds = entityIds; - this.interactionEntityIds = hitBoxEntityIds; - } - - public synchronized Object spawnPacket() { - if (this.cachedSpawnPacket == null) { - try { - List packets = new ArrayList<>(); - for (Map.Entry entry : this.elements.entrySet()) { - entry.getValue().addSpawnPackets(entry.getKey(), this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add); - } - for (Map.Entry entry : this.hitBoxes.entrySet()) { - entry.getValue().addSpawnPackets(entry.getKey(), this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add); - } - this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e); + int[] ids = hitBox.acquireEntityIds(Reflections.instance$Entity$ENTITY_COUNTER::incrementAndGet); + for (int entityId : ids) { + fakeEntityIds.add(entityId); + hitBoxEntityIds.add(entityId); + hitBox.addSpawnPackets(ids, this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add); + this.hitBoxes.put(entityId, hitBox); } } + try { + this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e); + } + this.fakeEntityIds = fakeEntityIds; + this.hitBoxEntityIds = hitBoxEntityIds; + } + + @NotNull + public Object spawnPacket() { return this.cachedSpawnPacket; } @@ -178,27 +171,32 @@ public class LoadedFurniture { } public int baseEntityId() { - return baseEntityId; + return this.baseEntityId; } - public List interactionEntityIds() { - return interactionEntityIds; + @NotNull + public List hitBoxEntityIds() { + return this.hitBoxEntityIds; } + @NotNull public List subEntityIds() { - return this.subEntityIds; + return this.fakeEntityIds; } + @NotNull public AnchorType anchorType() { - return anchorType; + return this.anchorType; } + @NotNull public Key furnitureId() { - return id; + return this.id; } + @NotNull public CustomFurniture furniture() { - return furniture; + return this.furniture; } public void mountSeat(org.bukkit.entity.Player player, Seat seat) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/ShulkerHitBox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/ShulkerHitBox.java new file mode 100644 index 000000000..262bc35b2 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/ShulkerHitBox.java @@ -0,0 +1,76 @@ +package net.momirealms.craftengine.bukkit.entity.furniture; + +import net.momirealms.craftengine.core.entity.furniture.*; +import net.momirealms.craftengine.core.util.Direction; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import org.joml.Vector3f; + +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ShulkerHitBox extends AbstractHitBox { + public static final Factory FACTORY = new Factory(); + // 1.20.6+ + private final double scale; + private final byte peek; + // todo或许还能做个方向,但是会麻烦点,和 yaw 有关 + private final Direction direction; + + public ShulkerHitBox(Seat[] seats, Vector3f position, double scale, byte peek, Direction direction) { + super(seats, position); + this.scale = scale; + this.peek = peek; + this.direction = direction; + } + + public Direction direction() { + return direction; + } + + public byte peek() { + return peek; + } + + public double scale() { + return scale; + } + + @Override + public Key type() { + return HitBoxTypes.SHULKER; + } + + @Override + public void addSpawnPackets(int[] entityIds, double x, double y, double z, float yaw, Consumer packets) { + // 1.生成假的展示实体 + // 2.生成假的潜影贝 + // 3.潜影贝骑展示实体 + // 4.潜影贝数据设置(隐身,尺寸,peek,方向) + } + + @Override + public int[] acquireEntityIds(Supplier entityIdSupplier) { + // 展示实体 // 潜影贝 + return new int[] {entityIdSupplier.get(), entityIdSupplier.get()}; + } + + public static class Factory implements HitBoxFactory { + + @Override + public HitBox create(Map arguments) { + Vector3f position = MiscUtils.getVector3f(arguments.getOrDefault("position", "0")); + double scale = MiscUtils.getAsDouble(arguments.getOrDefault("scale", "1")); + byte peek = (byte) MiscUtils.getAsInt(arguments.getOrDefault("peek", 0)); + Direction directionEnum = Optional.ofNullable(arguments.get("direction")).map(it -> Direction.valueOf(it.toString().toUpperCase(Locale.ENGLISH))).orElse(Direction.UP); + return new ShulkerHitBox( + HitBoxFactory.getSeats(arguments), + position, + scale, peek, directionEnum + ); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java index d99707c35..93d669faf 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java @@ -69,7 +69,7 @@ public class ItemEventListener implements Listener { block, event.getBlockFace(), event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, - action == Action.RIGHT_CLICK_BLOCK ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK + action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK ); if (EventUtils.fireAndCheckCancel(interactEvent)) { event.setCancelled(true); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractHitBox.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractHitBox.java index e7958a1c7..a8d0fb934 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractHitBox.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractHitBox.java @@ -1,10 +1,14 @@ package net.momirealms.craftengine.core.entity.furniture; +import org.joml.Vector3f; + public abstract class AbstractHitBox implements HitBox { protected final Seat[] seats; + protected final Vector3f position; - public AbstractHitBox(Seat[] seats) { + public AbstractHitBox(Seat[] seats, Vector3f position) { this.seats = seats; + this.position = position; } @Override @@ -12,4 +16,8 @@ public abstract class AbstractHitBox implements HitBox { return seats; } + @Override + public Vector3f position() { + return position; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java index 3b77677b3..67eae16bf 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java @@ -1,14 +1,20 @@ package net.momirealms.craftengine.core.entity.furniture; import net.momirealms.craftengine.core.util.Key; +import org.joml.Vector3f; import java.util.function.Consumer; +import java.util.function.Supplier; public interface HitBox { Key type(); - void addSpawnPackets(int entityId, double x, double y, double z, float yaw, Consumer packets); + void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Consumer packets); + + int[] acquireEntityIds(Supplier entityIdSupplier); Seat[] seats(); + + Vector3f position(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxTypes.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxTypes.java index 994bef69b..9a5b93417 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxTypes.java @@ -13,6 +13,7 @@ import java.util.Optional; public class HitBoxTypes { public static final Key INTERACTION = Key.of("minecraft:interaction"); public static final Key SHULKER = Key.of("minecraft:shulker"); + public static final Key BOAT = Key.of("minecraft:boat"); public static void register(Key key, HitBoxFactory factory) { Holder.Reference holder = ((WritableRegistry) BuiltInRegistries.HITBOX_FACTORY)