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 043418e5b..77e8964d3 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 @@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.entity.furniture; import net.momirealms.craftengine.bukkit.compatibility.bettermodel.BetterModelModel; import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineModel; import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBox; +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.util.EntityUtils; @@ -26,6 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -42,6 +44,7 @@ public class BukkitFurnitureManager implements FurnitureManager { private final Map furnitureByBaseEntityId = new ConcurrentHashMap<>(256, 0.5f); private final Map furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f); + private final Map furnitureByCollisionEntitiesId = new ConcurrentHashMap<>(256, 0.5f); // Event listeners private final Listener dismountListener; private final FurnitureEventListener furnitureEventListener; @@ -270,6 +273,11 @@ public class BukkitFurnitureManager implements FurnitureManager { return this.furnitureByEntityId.get(entityId); } + @Nullable + public LoadedFurniture getLoadedFurnitureByCollisionEntityId(int entityId) { + return this.furnitureByCollisionEntitiesId.get(entityId); + } + protected void handleBaseFurnitureUnload(Entity entity) { int id = entity.getEntityId(); LoadedFurniture furniture = this.furnitureByBaseEntityId.remove(id); @@ -348,6 +356,14 @@ public class BukkitFurnitureManager implements FurnitureManager { for (int entityId : loadedFurniture.entityIds()) { this.furnitureByEntityId.put(entityId, loadedFurniture); } + for (CollisionEntity collisionEntity : loadedFurniture.collisionEntities()) { + try { + int collisionEntityId = (int) Reflections.method$Entity$getId.invoke(collisionEntity); + this.furnitureByCollisionEntitiesId.put(collisionEntityId, loadedFurniture); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } return loadedFurniture; } 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 6d79a3080..b35a11ee5 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 @@ -240,6 +240,10 @@ public class LoadedFurniture { return Collections.unmodifiableList(this.fakeEntityIds); } + public CollisionEntity[] collisionEntities() { + return this.collisionEntities; + } + @NotNull public AnchorType anchorType() { return this.anchorType; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index e90e59dfb..f59be62d1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -626,9 +626,13 @@ public class PacketConsumers { event.setCancelled(true); } } - } else if (entityType.equals(CollisionEntity.class)) { + } else if (entityType == Reflections.instance$EntityType$INTERACTION) { // 取消服务端碰撞实体 - event.setCancelled(true); + int entityId = (int) Reflections.field$ClientboundAddEntityPacket$entityId.get(packet); + LoadedFurniture furniture = BukkitFurnitureManager.instance().getLoadedFurnitureByCollisionEntityId(entityId); + if (furniture != null) { + event.setCancelled(true); + } } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to handle ClientboundAddEntityPacket", e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 073b30bdf..5a7fda845 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -5917,4 +5917,16 @@ public class Reflections { clazz$CraftEntity, clazz$Entity, 0 ) ); + + public static final Method method$Entity$getId = requireNonNull( + VersionHelper.isVersionNewerThan1_20_5() + ? ReflectionUtils.getMethod(clazz$Entity, int.class, new String[]{"getId"}) + : VersionHelper.isVersionNewerThan1_20_3() + ? ReflectionUtils.getMethod(clazz$Entity, int.class, new String[]{"aj"}) + : VersionHelper.isVersionNewerThan1_20_2() + ? ReflectionUtils.getMethod(clazz$Entity, int.class, new String[]{"ah"}) + : VersionHelper.isVersionNewerThan1_20() + ? ReflectionUtils.getMethod(clazz$Entity, int.class, new String[]{"af"}) + : ReflectionUtils.getMethod(clazz$Entity, int.class, new String[]{"getId", "aj", "ah", "af"}) + ); }