diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java index d7d053413..7e492239e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java @@ -1,12 +1,10 @@ package net.momirealms.craftengine.bukkit.api.event; -import net.momirealms.craftengine.core.entity.furniture.AnchorType; import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig; import net.momirealms.craftengine.core.entity.furniture.FurnitureVariant; import net.momirealms.craftengine.core.entity.player.InteractionHand; import org.bukkit.Location; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; 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 a1dee6c88..21693ed18 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 @@ -153,7 +153,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } // 当元数据实体被卸载了 - protected void handleMetaEntityUnload(Entity entity) { + protected void handleMetaEntityUnload(ItemDisplay entity) { // 不是持久化的 if (!entity.isPersistent()) { return; 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 a8b0e8da5..534a3b841 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 @@ -75,8 +75,8 @@ public class FurnitureEventListener implements Listener { public void onChunkUnload(ChunkUnloadEvent event) { Entity[] entities = event.getChunk().getEntities(); for (Entity entity : entities) { - if (entity instanceof ItemDisplay) { - this.manager.handleMetaEntityUnload(entity); + if (entity instanceof ItemDisplay itemDisplay) { + this.manager.handleMetaEntityUnload(itemDisplay); } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { this.manager.handleCollisionEntityUnload(entity); } @@ -87,8 +87,8 @@ public class FurnitureEventListener implements Listener { public void onWorldUnload(WorldUnloadEvent event) { List entities = event.getWorld().getEntities(); for (Entity entity : entities) { - if (entity instanceof ItemDisplay) { - this.manager.handleMetaEntityUnload(entity); + if (entity instanceof ItemDisplay itemDisplay) { + this.manager.handleMetaEntityUnload(itemDisplay); } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { this.manager.handleCollisionEntityUnload(entity); } @@ -98,8 +98,8 @@ public class FurnitureEventListener implements Listener { @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onEntityUnload(EntityRemoveFromWorldEvent event) { Entity entity = event.getEntity(); - if (entity instanceof ItemDisplay) { - this.manager.handleMetaEntityUnload(entity); + if (entity instanceof ItemDisplay itemDisplay) { + this.manager.handleMetaEntityUnload(itemDisplay); } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { this.manager.handleCollisionEntityUnload(entity); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java index cf58886a5..caa972e9b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java @@ -2,11 +2,11 @@ package net.momirealms.craftengine.bukkit.entity.furniture.element; import it.unimi.dsi.fastutil.ints.IntArrayList; import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; -import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.core.entity.display.Billboard; import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigFactory; import net.momirealms.craftengine.core.entity.player.Player; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/AbstractFurnitureHitBox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/AbstractFurnitureHitBox.java index 2789d4347..f40ead283 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/AbstractFurnitureHitBox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/AbstractFurnitureHitBox.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.entity.furniture.hitbox; -import it.unimi.dsi.fastutil.ints.IntArrayList; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitCollider; import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat; import net.momirealms.craftengine.bukkit.nms.FastNMS; @@ -8,7 +7,6 @@ import net.momirealms.craftengine.core.entity.furniture.Collider; import net.momirealms.craftengine.core.entity.furniture.Furniture; import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBox; import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig; -import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.entity.seat.Seat; import net.momirealms.craftengine.core.entity.seat.SeatConfig; import net.momirealms.craftengine.core.world.Vec3d; @@ -51,13 +49,4 @@ public abstract class AbstractFurnitureHitBox implements FurnitureHitBox { Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ); return new BukkitCollider(world.serverWorld(), nmsAABB, position.x, position.y, position.z, canBeHitByProjectile, canCollide, blocksBuilding); } - - protected Object createDespawnPacket(int[] entityIds) { - return FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList(entityIds)); - } - - @Override - public void hide(Player player) { - player.sendPacket(createDespawnPacket(this.virtualEntityIds()), false); - } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitFurnitureHitboxTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitFurnitureHitboxTypes.java index c1ef83ddb..b930275bc 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitFurnitureHitboxTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitFurnitureHitboxTypes.java @@ -8,7 +8,7 @@ public class BukkitFurnitureHitboxTypes extends FurnitureHitBoxTypes { static { register(INTERACTION, InteractionFurnitureHitboxConfig.FACTORY); -// register(SHULKER, ShulkerFurnitureHitboxConfig.FACTORY); + register(SHULKER, ShulkerFurnitureHitboxConfig.FACTORY); // register(HAPPY_GHAST, HappyGhastFurnitureHitboxConfig.FACTORY); // register(CUSTOM, CustomFurnitureHitboxConfig.FACTORY); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitbox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitbox.java index 65836a4b5..836434808 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitbox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionFurnitureHitbox.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.entity.furniture.hitbox; +import it.unimi.dsi.fastutil.ints.IntArrayList; import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData; import net.momirealms.craftengine.bukkit.entity.data.InteractionEntityData; import net.momirealms.craftengine.bukkit.nms.FastNMS; @@ -7,6 +8,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; import net.momirealms.craftengine.core.entity.furniture.Collider; import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitboxPart; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldPosition; @@ -15,24 +17,22 @@ import net.momirealms.craftengine.core.world.collision.AABB; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import java.util.function.Consumer; public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox { private final InteractionFurnitureHitboxConfig config; - private final Vec3d position; - private final AABB aabb; private final Collider collider; - private final int interactionId; private final Object spawnPacket; + private final Object despawnPacket; + private final FurnitureHitboxPart part; public InteractionFurnitureHitbox(Furniture furniture, InteractionFurnitureHitboxConfig config) { super(furniture, config); this.config = config; WorldPosition position = furniture.position(); - this.position = Furniture.getRelativePosition(position, config.position()); - this.aabb = AABB.fromInteraction(this.position, config.size.x, config.size.y); - this.collider = createCollider(furniture.world(), this.position, this.aabb, false, config.blocksBuilding(), config.canBeHitByProjectile()); - this.interactionId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + Vec3d pos = Furniture.getRelativePosition(position, config.position()); + AABB aabb = AABB.fromInteraction(pos, config.size.x, config.size.y); + this.collider = createCollider(furniture.world(), pos, aabb, false, config.blocksBuilding(), config.canBeHitByProjectile()); + int interactionId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); List values = new ArrayList<>(4); InteractionEntityData.Height.addEntityDataIfNotDefaultValue(config.size.y, values); InteractionEntityData.Width.addEntityDataIfNotDefaultValue(config.size.x, values); @@ -42,11 +42,28 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox { } this.spawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of( FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( - this.interactionId, UUID.randomUUID(), position.x, position.y, position.z, 0, position.yRot, + interactionId, UUID.randomUUID(), position.x, position.y, position.z, 0, position.yRot, MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0 ), - FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.interactionId, values) + FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(interactionId, values) )); + this.part = new FurnitureHitboxPart(interactionId, aabb, pos); + this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(interactionId); }}); + } + + @Override + public List colliders() { + return List.of(this.collider); + } + + @Override + public List parts() { + return List.of(this.part); + } + + @Override + public InteractionFurnitureHitboxConfig config() { + return this.config; } @Override @@ -55,31 +72,7 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox { } @Override - public AABB[] aabb() { - return new AABB[] { this.aabb }; - } - - @Override - public Vec3d position() { - return this.position; - } - - @Override - public List colliders() { - return List.of(this.collider); - } - - @Override - public int[] virtualEntityIds() { - return new int[] { this.interactionId }; - } - - @Override - public void collectVirtualEntityIds(Consumer collector) { - collector.accept(this.interactionId); - } - - public InteractionFurnitureHitboxConfig config() { - return this.config; + public void hide(Player player) { + player.sendPacket(this.despawnPacket, false); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitbox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitbox.java new file mode 100644 index 000000000..69842ded6 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitbox.java @@ -0,0 +1,131 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.hitbox; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; +import net.momirealms.craftengine.core.entity.furniture.Collider; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitboxPart; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.QuaternionUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.craftengine.core.world.WorldPosition; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ShulkerFurnitureHitbox extends AbstractFurnitureHitBox { + private final ShulkerFurnitureHitboxConfig config; + private final List parts; + private final List colliders; + private final Object spawnPacket; + private final Object despawnPacket; + + public ShulkerFurnitureHitbox(Furniture furniture, ShulkerFurnitureHitboxConfig config) { + super(furniture, config); + this.config = config; + int[] entityIds = acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet); + WorldPosition position = furniture.position(); + Quaternionf conjugated = QuaternionUtils.toQuaternionf(0f, (float) Math.toRadians(180 - position.yRot()), 0f).conjugate(); + Vector3f offset = conjugated.transform(new Vector3f(config.position())); + double x = position.x(); + double y = position.y(); + double z = position.z(); + float yaw = position.yRot(); + double originalY = y + offset.y; + double integerPart = Math.floor(originalY); + double fractionalPart = originalY - integerPart; + double processedY = (fractionalPart >= 0.5) ? integerPart + 1 : originalY; + List packets = new ArrayList<>(); + List colliders = new ArrayList<>(); + List parts = new ArrayList<>(); + + packets.add(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityIds[0], UUID.randomUUID(), x + offset.x, originalY, z - offset.z, 0, yaw, + MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 + )); + packets.add(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityIds[1], UUID.randomUUID(), x + offset.x, processedY, z - offset.z, 0, yaw, + MEntityTypes.SHULKER, 0, CoreReflections.instance$Vec3$Zero, 0 + )); + packets.add(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[1], List.copyOf(config.cachedShulkerValues))); + packets.add(FastNMS.INSTANCE.constructor$ClientboundSetPassengersPacket(entityIds[0], entityIds[1])); + + // fix some special occasions + if (originalY != processedY) { + double deltaY = originalY - processedY; + short ya = (short) (deltaY * 8192); + try { + packets.add(NetworkReflections.constructor$ClientboundMoveEntityPacket$Pos.newInstance( + entityIds[1], (short) 0, ya, (short) 0, true + )); + } catch (ReflectiveOperationException e) { + CraftEngine.instance().logger().warn("Failed to construct ClientboundMoveEntityPacket$Pos", e); + } + } + if (VersionHelper.isOrAbove1_20_5() && config.scale != 1) { + try { + Object attributeInstance = CoreReflections.constructor$AttributeInstance.newInstance(MAttributeHolders.SCALE, (Consumer) (o) -> {}); + CoreReflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, config.scale); + packets.add(NetworkReflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityIds[1], Collections.singletonList(attributeInstance))); + } catch (ReflectiveOperationException e) { + CraftEngine.instance().logger().warn("Failed to apply scale attribute", e); + } + } + config.spawner.accept(entityIds, position.world(), x, y, z, yaw, offset, packets::add, colliders::add, parts::add); + this.parts = parts; + this.colliders = colliders; + this.spawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets); + this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList(entityIds)); + } + + @Override + public List colliders() { + return this.colliders; + } + + @Override + public List parts() { + return this.parts; + } + + @Override + public void show(Player player) { + player.sendPacket(this.spawnPacket, false); + } + + @Override + public void hide(Player player) { + player.sendPacket(this.despawnPacket, false); + } + + @Override + public ShulkerFurnitureHitboxConfig config() { + return this.config; + } + + public int[] acquireEntityIds(Supplier entityIdSupplier) { + if (config.interactionEntity) { + if (config.direction.stepY() != 0) { + // 展示实体 // 潜影贝 // 交互实体 + return new int[] {entityIdSupplier.get(), entityIdSupplier.get(), entityIdSupplier.get()}; + } else { + // 展示实体 // 潜影贝 // 交互实体1 // 交互实体2 + return new int[] {entityIdSupplier.get(), entityIdSupplier.get(), entityIdSupplier.get(), entityIdSupplier.get()}; + } + } else { + // 展示实体 // 潜影贝 + return new int[] {entityIdSupplier.get(), entityIdSupplier.get()}; + } + } +} 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 new file mode 100644 index 000000000..4a86ba359 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerFurnitureHitboxConfig.java @@ -0,0 +1,317 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.hitbox; + +import net.momirealms.craftengine.bukkit.entity.data.InteractionEntityData; +import net.momirealms.craftengine.bukkit.entity.data.ShulkerData; +import net.momirealms.craftengine.bukkit.entity.furniture.BukkitCollider; +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.bukkit.util.DirectionUtils; +import net.momirealms.craftengine.core.entity.furniture.Collider; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.hitbox.AbstractFurnitureHitBoxConfig; +import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfigFactory; +import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitboxPart; +import net.momirealms.craftengine.core.entity.seat.SeatConfig; +import net.momirealms.craftengine.core.util.Direction; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.QuaternionUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; +import net.momirealms.craftengine.core.world.collision.AABB; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig { + public static final Factory FACTORY = new Factory(); + public final float scale; + public final byte peek; + public final boolean interactive; + public final boolean interactionEntity; + public final Direction direction; + public final DirectionalShulkerSpawner spawner; + public final List cachedShulkerValues = new ArrayList<>(); + public final AABBCreator aabbCreator; + + public ShulkerFurnitureHitboxConfig(SeatConfig[] seats, + Vector3f position, + boolean canUseItemOn, + boolean blocksBuilding, + boolean canBeHitByProjectile, + float scale, + byte peek, + boolean interactive, + boolean interactionEntity, + Direction direction) { + super(seats, position, canUseItemOn, blocksBuilding, canBeHitByProjectile); + this.scale = scale; + this.peek = peek; + this.interactive = interactive; + this.interactionEntity = interactionEntity; + this.direction = direction; + + ShulkerData.Peek.addEntityDataIfNotDefaultValue(peek, this.cachedShulkerValues); + ShulkerData.Color.addEntityDataIfNotDefaultValue((byte) 0, this.cachedShulkerValues); + ShulkerData.NoGravity.addEntityDataIfNotDefaultValue(true, this.cachedShulkerValues); + ShulkerData.Silent.addEntityDataIfNotDefaultValue(true, this.cachedShulkerValues); + ShulkerData.MobFlags.addEntityDataIfNotDefaultValue((byte) 0x01, this.cachedShulkerValues); // NO AI + ShulkerData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, this.cachedShulkerValues); // Invisible + + List cachedInteractionValues = new ArrayList<>(); + float shulkerHeight = (getPhysicalPeek(peek * 0.01F) + 1) * scale; + if (direction == Direction.UP) { + InteractionEntityData.Height.addEntityDataIfNotDefaultValue(shulkerHeight + 0.01f, cachedInteractionValues); + InteractionEntityData.Width.addEntityDataIfNotDefaultValue(scale + 0.005f, cachedInteractionValues); + InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(interactive, cachedInteractionValues); + this.spawner = (entityIds, world, x, y, z, yaw, offset, packets, collider, aabb) -> { + collider.accept(this.createCollider(Direction.UP, world, offset, x, y, z, entityIds[1], aabb)); + if (interactionEntity) { + packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f, z - offset.z, 0, yaw, + MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0 + )); + packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues))); + if (canUseItemOn) { + Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y, z - offset.z); + aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.fromInteraction(vec3d, scale, shulkerHeight), vec3d)); + } + } + }; + this.aabbCreator = (x, y, z, yaw, offset) -> createAABB(Direction.UP, offset, x, y, z); + } else if (direction == Direction.DOWN) { + InteractionEntityData.Height.addEntityDataIfNotDefaultValue(shulkerHeight + 0.01f, cachedInteractionValues); + InteractionEntityData.Width.addEntityDataIfNotDefaultValue(scale + 0.005f, cachedInteractionValues); + InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(interactive, cachedInteractionValues); + this.spawner = (entityIds, world, x, y, z, yaw, offset, packets, collider, aabb) -> { + collider.accept(this.createCollider(Direction.DOWN, world, offset, x, y, z, entityIds[1], aabb)); + packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[1], List.of(ShulkerData.AttachFace.createEntityDataIfNotDefaultValue(CoreReflections.instance$Direction$UP)))); + if (interactionEntity) { + packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f - shulkerHeight + scale, z - offset.z, 0, yaw, + MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0 + )); + packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues))); + if (canUseItemOn) { + Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y - shulkerHeight + scale, z - offset.z); + aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.fromInteraction(vec3d, scale, shulkerHeight), vec3d)); + } + } + }; + this.aabbCreator = (x, y, z, yaw, offset) -> createAABB(Direction.DOWN, offset, x, y, z); + } else { + InteractionEntityData.Height.addEntityDataIfNotDefaultValue(scale + 0.01f, cachedInteractionValues); + InteractionEntityData.Width.addEntityDataIfNotDefaultValue(scale + 0.005f, cachedInteractionValues); + InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(interactive, cachedInteractionValues); + this.spawner = (entityIds, world, x, y, z, yaw, offset, packets, collider, aabb) -> { + Direction shulkerAnchor = getOriginalDirection(direction, Direction.fromYaw(yaw)); + Direction shulkerDirection = shulkerAnchor.opposite(); + collider.accept(this.createCollider(shulkerDirection, world, offset, x, y, z, entityIds[1], aabb)); + packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[1], List.of(ShulkerData.AttachFace.createEntityDataIfNotDefaultValue(DirectionUtils.toNMSDirection(shulkerAnchor))))); + if (interactionEntity) { + // first interaction + packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.005f, z - offset.z, 0, yaw, + MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0 + )); + packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues))); + // second interaction + double distance = shulkerHeight - scale; + packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityIds[3], UUID.randomUUID(), x + offset.x + shulkerDirection.stepX() * distance, y + offset.y - 0.005f, z - offset.z + shulkerDirection.stepZ() * distance, 0, yaw, + MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0 + )); + packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[3], List.copyOf(cachedInteractionValues))); + if (canUseItemOn) { + Vec3d vec3d1 = new Vec3d(x + offset.x, y + offset.y, z - offset.z); + Vec3d vec3d2 = new Vec3d(x + offset.x + shulkerDirection.stepX() * distance, y + offset.y, z - offset.z + shulkerDirection.stepZ() * distance); + aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.fromInteraction(vec3d1, scale, scale), vec3d1)); + aabb.accept(new FurnitureHitboxPart(entityIds[3], AABB.fromInteraction(vec3d2, scale, scale), vec3d2)); + } + } + }; + this.aabbCreator = (x, y, z, yaw, offset) -> { + Direction shulkerAnchor = getOriginalDirection(direction, Direction.fromYaw(yaw)); + Direction shulkerDirection = shulkerAnchor.opposite(); + return createAABB(shulkerDirection, offset, x, y, z); + }; + } + } + + public static float getPhysicalPeek(float peek) { + return 0.5F - MiscUtils.sin((0.5F + peek) * 3.1415927F) * 0.5F; + } + + @Override + public void prepareForPlacement(WorldPosition targetPos, Consumer aabbConsumer) { + if (this.blocksBuilding) { + 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)); + } + } + + public float scale() { + return scale; + } + + public byte peek() { + return peek; + } + + public boolean interactive() { + return interactive; + } + + public boolean interactionEntity() { + return interactionEntity; + } + + public Direction direction() { + return direction; + } + + @Override + public ShulkerFurnitureHitbox create(Furniture furniture) { + return new ShulkerFurnitureHitbox(furniture, this); + } + + @FunctionalInterface + public interface AABBCreator { + + AABB create(double x, double y, double z, float yaw, Vector3f offset); + } + + @FunctionalInterface + public interface DirectionalShulkerSpawner { + + void accept(int[] entityIds, + World world, + double x, + double y, + double z, + float yaw, + Vector3f offset, + Consumer packets, + Consumer collider, + Consumer aabb); + } + + public Collider createCollider(Direction direction, World world, + Vector3f offset, double x, double y, double z, + int entityId, + Consumer aabb) { + AABB ceAABB = createAABB(direction, offset, x, y, z); + Object level = world.serverWorld(); + Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ); + aabb.accept(new FurnitureHitboxPart(entityId, ceAABB, new Vec3d(x, y, z))); + return new BukkitCollider(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding()); + } + + public AABB createAABB(Direction direction, Vector3f relativePos, double x, double y, double z) { + float peek = getPhysicalPeek(this.peek * 0.01F); + double x1 = -this.scale * 0.5; + double y1 = 0.0; + double z1 = -this.scale * 0.5; + double x2 = this.scale * 0.5; + double y2 = this.scale; + double z2 = this.scale * 0.5; + + double dx = (double) direction.stepX() * peek * (double) this.scale; + if (dx > 0) { + x2 += dx; + } else if (dx < 0) { + x1 += dx; + } + double dy = (double) direction.stepY() * peek * (double) this.scale; + if (dy > 0) { + y2 += dy; + } else if (dy < 0) { + y1 += dy; + } + double dz = (double) direction.stepZ() * peek * (double) this.scale; + if (dz > 0) { + z2 += dz; + } else if (dz < 0) { + z1 += dz; + } + double minX = x + x1 + relativePos.x(); + double maxX = x + x2 + relativePos.x(); + double minY = y + y1 + relativePos.y(); + double maxY = y + y2 + relativePos.y(); + double minZ = z + z1 - relativePos.z(); + double maxZ = z + z2 - relativePos.z(); + return new AABB(minX, minY, minZ, maxX, maxY, maxZ); + } + + public static Direction getOriginalDirection(Direction newDirection, Direction oldDirection) { + switch (newDirection) { + case NORTH -> { + return switch (oldDirection) { + case NORTH -> Direction.NORTH; + case SOUTH -> Direction.SOUTH; + case WEST -> Direction.EAST; + case EAST -> Direction.WEST; + default -> throw new IllegalStateException("Unexpected value: " + oldDirection); + }; + } + case SOUTH -> { + return switch (oldDirection) { + case SOUTH -> Direction.NORTH; + case WEST -> Direction.WEST; + case EAST -> Direction.EAST; + case NORTH -> Direction.SOUTH; + default -> throw new IllegalStateException("Unexpected value: " + oldDirection); + }; + } + case WEST -> { + return switch (oldDirection) { + case SOUTH -> Direction.EAST; + case WEST -> Direction.NORTH; + case EAST -> Direction.SOUTH; + case NORTH -> Direction.WEST; + default -> throw new IllegalStateException("Unexpected value: " + oldDirection); + }; + } + case EAST -> { + return switch (oldDirection) { + case SOUTH -> Direction.WEST; + case WEST -> Direction.SOUTH; + case EAST -> Direction.NORTH; + case NORTH -> Direction.EAST; + default -> throw new IllegalStateException("Unexpected value: " + oldDirection); + }; + } + default -> throw new IllegalStateException("Unexpected value: " + newDirection); + } + } + + public static class Factory implements FurnitureHitBoxConfigFactory { + + @Override + public ShulkerFurnitureHitboxConfig create(Map arguments) { + Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position"); + float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", "1"), "scale"); + byte peek = (byte) ResourceConfigUtils.getAsInt(arguments.getOrDefault("peek", 0), "peek"); + Direction directionEnum = ResourceConfigUtils.getAsEnum(arguments.get("direction"), Direction.class, Direction.UP); + boolean interactive = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("interactive", true), "interactive"); + boolean interactionEntity = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("interaction-entity", true), "interaction-entity"); + boolean canUseItemOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on"); + boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile"); + boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building"); + return new ShulkerFurnitureHitboxConfig( + SeatConfig.fromObj(arguments.get("seats")), + position, + canUseItemOn, blocksBuilding, canBeHitByProjectile, + scale, peek, interactive, interactionEntity, directionEnum + ); + } + } +} 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 3b85c0ef7..19a9aea16 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 @@ -6,13 +6,11 @@ import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.util.DirectionUtils; import net.momirealms.craftengine.bukkit.util.EventUtils; import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig; import net.momirealms.craftengine.core.entity.furniture.FurnitureDataAccessor; import net.momirealms.craftengine.core.entity.furniture.FurnitureVariant; -import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBox; import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig; import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.entity.player.Player; @@ -28,7 +26,10 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; -import net.momirealms.craftengine.core.util.*; +import net.momirealms.craftengine.core.util.Cancellable; +import net.momirealms.craftengine.core.util.ItemUtils; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.collision.AABB; 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 57a5f59cc..578925913 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 @@ -60,6 +60,7 @@ import net.momirealms.craftengine.core.advancement.network.AdvancementHolder; import net.momirealms.craftengine.core.advancement.network.AdvancementProgress; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBox; +import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitboxPart; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.seat.Seat; import net.momirealms.craftengine.core.font.FontManager; @@ -358,8 +359,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerNMSPacketConsumer(new EntityEventListener(), NetworkReflections.clazz$ClientboundEntityEventPacket); registerNMSPacketConsumer(new MovePosAndRotateEntityListener(), NetworkReflections.clazz$ClientboundMoveEntityPacket$PosRot); registerNMSPacketConsumer(new MovePosEntityListener(), NetworkReflections.clazz$ClientboundMoveEntityPacket$Pos); - registerNMSPacketConsumer(new RotateHeadListener(), NetworkReflections.clazz$ClientboundRotateHeadPacket); - registerNMSPacketConsumer(new SetEntityMotionListener(), NetworkReflections.clazz$ClientboundSetEntityMotionPacket); registerNMSPacketConsumer(new FinishConfigurationListener(), NetworkReflections.clazz$ClientboundFinishConfigurationPacket); registerNMSPacketConsumer(new LoginFinishedListener(), NetworkReflections.clazz$ClientboundLoginFinishedPacket); registerNMSPacketConsumer(new UpdateTagsListener(), NetworkReflections.clazz$ClientboundUpdateTagsPacket); @@ -1765,43 +1764,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes } } - public static class RotateHeadListener implements NMSPacketListener { - - @Override - public void onPacketSend(NetWorkUser user, NMSPacketEvent event, Object packet) { - int entityId; - try { - entityId = (int) NetworkReflections.methodHandle$ClientboundRotateHeadPacket$entityIdGetter.invokeExact(packet); - } catch (Throwable t) { - CraftEngine.instance().logger().warn("Failed to get entity id from ClientboundRotateHeadPacket", t); - return; - } - if (BukkitFurnitureManager.instance().isFurnitureMetaEntity(entityId)) { - System.out.println("RotateHeadListener"); - event.setCancelled(true); - } - } - } - - public static class SetEntityMotionListener implements NMSPacketListener { - - @Override - public void onPacketSend(NetWorkUser user, NMSPacketEvent event, Object packet) { - if (!VersionHelper.isOrAbove1_21_6()) return; - int entityId; - try { - entityId = (int) NetworkReflections.methodHandle$ClientboundSetEntityMotionPacket$idGetter.invokeExact(packet); - } catch (Throwable t) { - CraftEngine.instance().logger().warn("Failed to get entity id from ClientboundSetEntityMotionPacket", t); - return; - } - if (BukkitFurnitureManager.instance().isFurnitureMetaEntity(entityId)) { - System.out.println("SetEntityMotionListener"); - event.setCancelled(true); - } - } - } - public static class FinishConfigurationListener implements NMSPacketListener { @SuppressWarnings("unchecked") @@ -3726,11 +3688,13 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes // 先检查碰撞箱部分是否存在 FurnitureHitBox hitBox = furniture.hitboxByEntityId(entityId); if (hitBox == null) return; - Vec3d pos = hitBox.position(); - - // 检查玩家是否能破坏此点 - if (!serverPlayer.canInteractPoint(pos, 16d)) { - return; + for (FurnitureHitboxPart part : hitBox.parts()) { + if (part.entityId() == entityId) { + // 检查玩家是否能破坏此点 + if (!serverPlayer.canInteractPoint(part.pos(), 16d)) { + return; + } + } } FurnitureAttemptBreakEvent preBreakEvent = new FurnitureAttemptBreakEvent(serverPlayer.platformPlayer(), furniture); @@ -3787,10 +3751,18 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes // 先检查碰撞箱部分是否存在 FurnitureHitBox hitBox = furniture.hitboxByEntityId(entityId); if (hitBox == null) return; - Vec3d pos = hitBox.position(); - - // 检测距离 - if (!serverPlayer.canInteractPoint(pos, 16d)) { + FurnitureHitboxPart part = null; + for (FurnitureHitboxPart p : hitBox.parts()) { + if (p.entityId() == entityId) { + Vec3d pos = p.pos(); + // 检测距离 + if (!serverPlayer.canInteractPoint(pos, 16d)) { + return; + } + part = p; + } + } + if (part == null) { return; } @@ -3799,7 +3771,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes Vector direction = eyeLocation.getDirection(); Location endLocation = eyeLocation.clone(); endLocation.add(direction.multiply(serverPlayer.getCachedInteractionRange())); - Optional result = hitBox.clip(LocationUtils.toVec3d(eyeLocation), LocationUtils.toVec3d(endLocation)); + Optional result = part.aabb().clip(LocationUtils.toVec3d(eyeLocation), LocationUtils.toVec3d(endLocation)); if (result.isEmpty()) { return; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/FurniturePacketHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/FurniturePacketHandler.java index 3e7277429..a73ebc3e2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/FurniturePacketHandler.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/FurniturePacketHandler.java @@ -33,9 +33,4 @@ public class FurniturePacketHandler implements EntityPacketHandler { public void handleMove(NetWorkUser user, NMSPacketEvent event, Object packet) { event.setCancelled(true); } - - @Override - public void handleMoveAndRotate(NetWorkUser user, NMSPacketEvent event, Object packet) { - event.setCancelled(true); - } } 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 32f0b7c4a..a69ccd26f 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 @@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBox; import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig; +import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitboxPart; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.entity.seat.Seat; import net.momirealms.craftengine.core.plugin.entityculling.CullingData; @@ -24,13 +25,12 @@ import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.lang.ref.WeakReference; import java.util.UUID; public abstract class Furniture implements Cullable { public final FurnitureConfig config; public final FurnitureDataAccessor dataAccessor; - public final WeakReference metaDataEntity; + public final Entity metaDataEntity; protected CullingData cullingData; protected FurnitureVariant currentVariant; @@ -44,11 +44,11 @@ public abstract class Furniture implements Cullable { protected Furniture(Entity metaDataEntity, FurnitureDataAccessor data, FurnitureConfig config) { this.config = config; this.dataAccessor = data; - this.metaDataEntity = new WeakReference<>(metaDataEntity); + this.metaDataEntity = metaDataEntity; this.setVariant(config.getVariant(data)); } - public WeakReference metaDataEntity() { + public Entity metaDataEntity() { return this.metaDataEntity; } @@ -75,11 +75,11 @@ public abstract class Furniture implements Cullable { for (int i = 0; i < furnitureHitBoxConfigs.length; i++) { FurnitureHitBox hitbox = furnitureHitBoxConfigs[i].create(this); this.hitboxes[i] = hitbox; - for (int hitboxEntityId : hitbox.virtualEntityIds()) { - this.hitboxMap.put(hitboxEntityId, hitbox); + for (FurnitureHitboxPart part : hitbox.parts()) { + this.hitboxMap.put(part.entityId(), hitbox); + virtualEntityIds.add(part.entityId()); } colliders.addAll(hitbox.colliders()); - hitbox.collectVirtualEntityIds(virtualEntityIds::addLast); } // 虚拟碰撞箱的实体id this.virtualEntityIds = virtualEntityIds.toIntArray(); @@ -122,9 +122,7 @@ public abstract class Furniture implements Cullable { } public UUID uuid() { - Entity entity = this.metaDataEntity.get(); - if (entity == null) return null; - return entity.uuid(); + return this.metaDataEntity.uuid(); } @Override @@ -158,9 +156,7 @@ public abstract class Furniture implements Cullable { } public boolean isValid() { - Entity entity = this.metaDataEntity.get(); - if (entity == null) return false; - return entity.isValid(); + return this.metaDataEntity.isValid(); } public abstract void destroy(); @@ -178,15 +174,11 @@ public abstract class Furniture implements Cullable { } public WorldPosition position() { - Entity entity = this.metaDataEntity.get(); - if (entity == null) return null; - return entity.position(); + return this.metaDataEntity.position(); } public int entityId() { - Entity entity = this.metaDataEntity.get(); - if (entity == null) return -1; - return entity.entityID(); + return this.metaDataEntity.entityID(); } public Vec3d getRelativePosition(Vector3f position) { @@ -200,8 +192,6 @@ public abstract class Furniture implements Cullable { } public World world() { - Entity entity = this.metaDataEntity.get(); - if (entity == null) return null; - return entity.world(); + return this.metaDataEntity.world(); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfig.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfig.java index 7ef9ffd4c..b9f34c864 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfig.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfig.java @@ -5,7 +5,6 @@ import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.entityculling.CullingData; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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 632e4fe80..a68613fef 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 @@ -7,7 +7,6 @@ import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.plugin.entityculling.CullingData; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBox.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBox.java index 7f3d894c4..0a249acd4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBox.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitBox.java @@ -6,25 +6,17 @@ import net.momirealms.craftengine.core.entity.seat.Seat; import net.momirealms.craftengine.core.entity.seat.SeatOwner; import net.momirealms.craftengine.core.world.EntityHitResult; import net.momirealms.craftengine.core.world.Vec3d; -import net.momirealms.craftengine.core.world.collision.AABB; import java.util.List; import java.util.Optional; -import java.util.function.Consumer; public interface FurnitureHitBox extends SeatOwner { - Vec3d position(); - Seat[] seats(); - AABB[] aabb(); - List colliders(); - int[] virtualEntityIds(); - - void collectVirtualEntityIds(Consumer collector); + List parts(); void show(Player player); @@ -33,8 +25,8 @@ public interface FurnitureHitBox extends SeatOwner { FurnitureHitBoxConfig config(); default Optional clip(Vec3d min, Vec3d max) { - for (AABB value : aabb()) { - Optional clip = value.clip(min, max); + for (FurnitureHitboxPart value : parts()) { + Optional clip = value.aabb().clip(min, max); if (clip.isPresent()) { return clip; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitboxPart.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitboxPart.java new file mode 100644 index 000000000..e69a747f5 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/FurnitureHitboxPart.java @@ -0,0 +1,7 @@ +package net.momirealms.craftengine.core.entity.furniture.hitbox; + +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.collision.AABB; + +public record FurnitureHitboxPart(int entityId, AABB aabb, Vec3d pos) { +}