diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java index c8ab62b47..096f42b67 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java @@ -330,7 +330,7 @@ public final class CraftEngineFurniture { public static BukkitFurniture getLoadedFurnitureByCollider(@NotNull Entity collider) { Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(collider); if (nmsEntity instanceof CollisionEntity collisionEntity) { - return BukkitFurnitureManager.instance().loadedFurnitureByColliderEntityId(collisionEntity.getId()); + return BukkitFurnitureManager.instance().loadedFurnitureByColliderEntityId(collisionEntity.getEntityId()); } return null; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCollider.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCollider.java index 69b8c9775..7b330e60a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCollider.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCollider.java @@ -21,7 +21,7 @@ public class BukkitCollider implements Collider { @Override public int entityId() { - return this.collisionEntity.getId(); + return this.collisionEntity.getEntityId(); } @Override 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 4455884dc..d7bbe6f9d 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 @@ -31,10 +31,12 @@ public class BukkitFurniture extends Furniture { public void addCollidersToWorld() { Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld()); for (Collider entity : super.colliders) { - FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle()); Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity.handle()); bukkitEntity.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_COLLISION, PersistentDataType.BYTE, (byte) 1); bukkitEntity.setPersistent(false); + if (!bukkitEntity.isValid()) { + FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle()); + } } } 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 21693ed18..0451bcf32 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 @@ -1,15 +1,19 @@ package net.momirealms.craftengine.bukkit.entity.furniture; +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionFurnitureHitboxConfig; import net.momirealms.craftengine.bukkit.nms.CollisionEntity; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; +import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.KeyUtils; 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.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Key; @@ -29,6 +33,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; +import java.util.function.Consumer; public class BukkitFurnitureManager extends AbstractFurnitureManager { public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY); @@ -73,7 +78,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } catch (IOException e) { this.plugin.logger().warn("Failed to set furniture PDC for " + furniture.id().toString(), e); } - handleMetaEntityAfterChunkLoad(display); + handleMetaEntityDuringChunkLoad(display); }); if (playSound) { SoundData sound = furniture.settings().sounds().placeSound(); @@ -228,6 +233,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { createFurnitureInstance(entity, customFurniture); } + @SuppressWarnings("deprecation") protected void handleMetaEntityAfterChunkLoad(ItemDisplay entity) { // 实体可能不是持久的 if (!entity.isPersistent()) { @@ -239,7 +245,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { if (id == null) return; // 这个区块还处于加载实体中,这个时候不处理 - if (!isEntitiesLoaded(entity.getLocation())) { + Location location = entity.getLocation(); + if (!isEntitiesLoaded(location)) { return; } @@ -254,13 +261,16 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { if (previous != null) return; createFurnitureInstance(entity, customFurniture); + // 补发一次包 + for (Player player : entity.getTrackedPlayers()) { + BukkitAdaptors.adapt(player).sendPacket(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entity.getEntityId(), entity.getUniqueId(), location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw(), + MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 + ), false); + } } protected void handleCollisionEntityAfterChunkLoad(Entity entity) { - // 实体可能不是持久的 - if (!entity.isPersistent()) { - return; - } // 如果是碰撞实体,那么就忽略 if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) { return; @@ -271,11 +281,13 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { return; } // 实体未加载 - if (!isEntitiesLoaded(entity.getLocation())) { + Location location = entity.getLocation(); + if (!isEntitiesLoaded(location)) { return; } + // 移除被WorldEdit错误复制的碰撞实体 - entity.remove(); + runSafeEntityOperation(location, entity::remove); } public void handleCollisionEntityDuringChunkLoad(Entity collisionEntity) { @@ -306,7 +318,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } // 创建家具实例,并初始化碰撞实体 - private void createFurnitureInstance(ItemDisplay display, FurnitureConfig furniture) { + 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()) { @@ -315,7 +327,18 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { for (Collider collisionEntity : bukkitFurniture.colliders()) { this.byColliderEntityId.put(collisionEntity.entityId(), bukkitFurniture); } - bukkitFurniture.addCollidersToWorld(); + Location location = display.getLocation(); + runSafeEntityOperation(location, bukkitFurniture::addCollidersToWorld); + return bukkitFurniture; + } + + 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) { + this.plugin.scheduler().sync().runLater(action, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); + } else { + action.run(); + } } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitbox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitbox.java index 461f4ea07..900909794 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitbox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomFurnitureHitbox.java @@ -27,6 +27,7 @@ public class CustomFurnitureHitbox extends AbstractFurnitureHitBox { private final Object spawnPacket; private final Object despawnPacket; private final FurnitureHitboxPart part; + private final int entityId; public CustomFurnitureHitbox(Furniture furniture, CustomFurnitureHitboxConfig config) { super(furniture, config); @@ -54,6 +55,7 @@ public class CustomFurnitureHitbox extends AbstractFurnitureHitBox { this.spawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets); this.part = new FurnitureHitboxPart(entityId, aabb, pos, false); this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(entityId); }}); + this.entityId = entityId; } @Override @@ -76,6 +78,11 @@ public class CustomFurnitureHitbox extends AbstractFurnitureHitBox { player.sendPacket(this.despawnPacket, false); } + @Override + public void collectVirtualEntityId(Consumer collector) { + collector.accept(this.entityId); + } + @Override public CustomFurnitureHitboxConfig config() { return this.config; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitbox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitbox.java index 750ee7c1c..e5306701a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitbox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastFurnitureHitbox.java @@ -83,6 +83,11 @@ public class HappyGhastFurnitureHitbox extends AbstractFurnitureHitBox { player.sendPacket(this.despawnPacket, false); } + @Override + public void collectVirtualEntityId(Consumer collector) { + collector.accept(this.entityId); + } + @Override public HappyGhastFurnitureHitboxConfig config() { return this.config; 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 65b0ffd9e..4b4a34110 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 @@ -14,6 +14,7 @@ import net.momirealms.craftengine.core.world.collision.AABB; import java.util.List; import java.util.UUID; +import java.util.function.Consumer; public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox { private final InteractionFurnitureHitboxConfig config; @@ -21,6 +22,7 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox { private final Object spawnPacket; private final Object despawnPacket; private final FurnitureHitboxPart part; + private final int entityId; public InteractionFurnitureHitbox(Furniture furniture, InteractionFurnitureHitboxConfig config) { super(furniture, config); @@ -39,6 +41,7 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox { )); this.part = new FurnitureHitboxPart(interactionId, aabb, pos, config.responsive()); this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(interactionId); }}); + this.entityId = interactionId; } @Override @@ -56,6 +59,11 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox { return this.config; } + @Override + public void collectVirtualEntityId(Consumer collector) { + collector.accept(this.entityId); + } + @Override public void show(Player player) { player.sendPacket(this.spawnPacket, 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 index e4ef37a2a..db6c0b865 100644 --- 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 @@ -17,10 +17,7 @@ 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.*; import java.util.function.Consumer; import java.util.function.Supplier; @@ -30,11 +27,12 @@ public class ShulkerFurnitureHitbox extends AbstractFurnitureHitBox { private final List colliders; private final Object spawnPacket; private final Object despawnPacket; + private final int[] entityIds; public ShulkerFurnitureHitbox(Furniture furniture, ShulkerFurnitureHitboxConfig config) { super(furniture, config); this.config = config; - int[] entityIds = acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet); + this.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())); @@ -99,6 +97,13 @@ public class ShulkerFurnitureHitbox extends AbstractFurnitureHitBox { return this.parts; } + @Override + public void collectVirtualEntityId(Consumer collector) { + for (int entityId : entityIds) { + collector.accept(entityId); + } + } + @Override public void show(Player player) { player.sendPacket(this.spawnPacket, false); 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 ebc750c2a..c418fd36b 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 @@ -80,10 +80,8 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig< 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.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive)); - } + Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y, z - offset.z); + aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive)); } }; this.aabbCreator = (x, y, z, yaw, offset) -> createAABB(Direction.UP, offset, x, y, z); @@ -100,10 +98,8 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig< 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.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive)); - } + Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y - shulkerHeight + scale, z - offset.z); + aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive)); } }; this.aabbCreator = (x, y, z, yaw, offset) -> createAABB(Direction.DOWN, offset, x, y, z); @@ -130,12 +126,10 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig< 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.makeBoundingBox(vec3d1, scale, scale), vec3d1, interactive)); - aabb.accept(new FurnitureHitboxPart(entityIds[3], AABB.makeBoundingBox(vec3d2, scale, scale), vec3d2, interactive)); - } + 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.makeBoundingBox(vec3d1, scale, scale), vec3d1, interactive)); + aabb.accept(new FurnitureHitboxPart(entityIds[3], AABB.makeBoundingBox(vec3d2, scale, scale), vec3d2, interactive)); } }; this.aabbCreator = (x, y, z, yaw, offset) -> { 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 afa959aec..e6c351aaa 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 @@ -3954,14 +3954,16 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user; BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByMetaEntityId(id); if (furniture != null) { - serverPlayer.entityPacketHandlers().put(id, new FurniturePacketHandler(id, furniture.virtualEntityIds())); + EntityPacketHandler previous = serverPlayer.entityPacketHandlers().put(id, new FurniturePacketHandler(id, furniture.virtualEntityIds())); if (Config.enableEntityCulling()) { serverPlayer.addTrackedFurniture(id, furniture); } else { - furniture.show(serverPlayer); + // 修复addEntityToWorld,包比事件先发的问题 (WE) + if (previous == null || previous instanceof ItemDisplayPacketHandler) { + furniture.show(serverPlayer); + } } - // fixme 外部模型 - if (Config.hideBaseEntity() && true) { + if (Config.hideBaseEntity() && !furniture.hasExternalModel()) { event.setCancelled(true); } } else { diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml index 95815b4c5..5e33a6b41 100644 --- a/common-files/src/main/resources/config.yml +++ b/common-files/src/main/resources/config.yml @@ -558,7 +558,7 @@ chunk-system: client-optimization: # Requires a restart to fully apply. entity-culling: - enable: true + enable: false # Using server-side ray tracing algorithms to hide block entities/furniture and reduce client-side rendering pressure. ray-tracing: true # Cull entities based on distance diff --git a/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml b/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml index 7ad0017fe..a399a75d3 100644 --- a/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml +++ b/common-files/src/main/resources/resources/default/configuration/furniture/wooden_chair.yml @@ -27,14 +27,25 @@ items: billboard: FIXED translation: 0,0.5,0 hitboxes: - - position: 0,0,0 - type: custom - entity-type: slime - invisible: true - can-use-item-on: true - blocks-building: true - seats: - - 0,0,-0.1 0 + $$>=1.20.5: + - position: 0,0,0 + type: custom + entity-type: slime + invisible: true + can-use-item-on: true + blocks-building: true + seats: + - 0,0,-0.1 0 + $$fallback: + - position: 0,0,0 + type: interaction + blocks-building: true + invisible: true + width: 0.7 + height: 1.2 + interactive: true + seats: + - 0,0,-0.1 0 loot: template: default:loot_table/furniture arguments: 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 a69ccd26f..5099472cf 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 @@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.momirealms.craftengine.core.entity.AbstractEntity; import net.momirealms.craftengine.core.entity.Entity; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; @@ -13,6 +14,7 @@ import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxCo 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.CraftEngine; import net.momirealms.craftengine.core.plugin.entityculling.CullingData; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.QuaternionUtils; @@ -25,6 +27,7 @@ import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; import org.joml.Vector3f; +import java.util.Optional; import java.util.UUID; public abstract class Furniture implements Cullable { @@ -41,6 +44,8 @@ public abstract class Furniture implements Cullable { protected int[] virtualEntityIds; protected int[] colliderEntityIds; + private boolean hasExternalModel; + protected Furniture(Entity metaDataEntity, FurnitureDataAccessor data, FurnitureConfig config) { this.config = config; this.dataAccessor = data; @@ -77,8 +82,8 @@ public abstract class Furniture implements Cullable { this.hitboxes[i] = hitbox; for (FurnitureHitboxPart part : hitbox.parts()) { this.hitboxMap.put(part.entityId(), hitbox); - virtualEntityIds.add(part.entityId()); } + hitbox.collectVirtualEntityId(virtualEntityIds::addLast); colliders.addAll(hitbox.colliders()); } // 虚拟碰撞箱的实体id @@ -86,6 +91,18 @@ public abstract class Furniture implements Cullable { this.colliders = colliders.toArray(new Collider[0]); this.colliderEntityIds = colliders.stream().mapToInt(Collider::entityId).toArray(); this.cullingData = createCullingData(variant.cullingData()); + // 外部模型 + Optional externalModel = variant.externalModel(); + if (externalModel.isPresent()) { + this.hasExternalModel = true; + try { + externalModel.get().bindModel((AbstractEntity) this.metaDataEntity); + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to load external model for furniture " + id(), e); + } + } else { + this.hasExternalModel = false; + } } private CullingData createCullingData(CullingData parent) { @@ -181,6 +198,10 @@ public abstract class Furniture implements Cullable { return this.metaDataEntity.entityID(); } + public boolean hasExternalModel() { + return hasExternalModel; + } + public Vec3d getRelativePosition(Vector3f position) { return getRelativePosition(this.position(), position); } 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 0a249acd4..95f7b652a 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 @@ -9,6 +9,7 @@ import net.momirealms.craftengine.core.world.Vec3d; import java.util.List; import java.util.Optional; +import java.util.function.Consumer; public interface FurnitureHitBox extends SeatOwner { @@ -24,6 +25,8 @@ public interface FurnitureHitBox extends SeatOwner { FurnitureHitBoxConfig config(); + void collectVirtualEntityId(Consumer collector); + default Optional clip(Vec3d min, Vec3d max) { for (FurnitureHitboxPart value : parts()) { Optional clip = value.aabb().clip(min, max); diff --git a/gradle.properties b/gradle.properties index 46db05f12..15594bad8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -48,7 +48,7 @@ byte_buddy_version=1.18.1 ahocorasick_version=0.6.3 snake_yaml_version=2.5 anti_grief_version=1.0.5 -nms_helper_version=1.0.138 +nms_helper_version=1.0.140 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.38.7