mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-31 04:46:37 +00:00
更好的碰撞方案
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Collider;
|
||||
import net.momirealms.craftengine.core.entity.furniture.ColliderType;
|
||||
|
||||
public class BukkitCollider implements Collider {
|
||||
private final CollisionEntity collisionEntity;
|
||||
private final ColliderType type;
|
||||
|
||||
public BukkitCollider(CollisionEntity collisionEntity, ColliderType type) {
|
||||
this.collisionEntity = collisionEntity;
|
||||
this.type = type;
|
||||
public BukkitCollider(Object world, Object aabb, double x, double y, double z, boolean canProjectileHit, boolean canCollide, boolean blocksBuilding) {
|
||||
this.collisionEntity = BukkitFurnitureManager.COLLISION_ENTITY_TYPE == ColliderType.INTERACTION ?
|
||||
FastNMS.INSTANCE.createCollisionInteraction(world, aabb, x, y, z, canProjectileHit, canCollide, blocksBuilding) :
|
||||
FastNMS.INSTANCE.createCollisionBoat(world, aabb, x, y, z, canProjectileHit, canCollide, blocksBuilding);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,11 +24,6 @@ public class BukkitCollider implements Collider {
|
||||
return this.collisionEntity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColliderType type() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return this.collisionEntity;
|
||||
|
||||
@@ -39,6 +39,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_to_base_entity"));
|
||||
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_vector"));
|
||||
public static final NamespacedKey FURNITURE_COLLISION = Objects.requireNonNull(NamespacedKey.fromString("craftengine:collision"));
|
||||
public static Class<?> COLLISION_ENTITY_CLASS = Interaction.class;
|
||||
public static Object NMS_COLLISION_ENTITY_TYPE = Reflections.instance$EntityType$INTERACTION;
|
||||
public static ColliderType COLLISION_ENTITY_TYPE = ColliderType.INTERACTION;
|
||||
private static BukkitFurnitureManager instance;
|
||||
private final BukkitCraftEngine plugin;
|
||||
private final FurnitureParser furnitureParser;
|
||||
@@ -204,6 +207,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
|
||||
@Override
|
||||
public void delayedInit() {
|
||||
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
|
||||
NMS_COLLISION_ENTITY_TYPE = Config.colliderType() == ColliderType.INTERACTION ? Reflections.instance$EntityType$INTERACTION : Reflections.instance$EntityType$OAK_BOAT;
|
||||
COLLISION_ENTITY_TYPE = Config.colliderType();
|
||||
Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.bootstrap());
|
||||
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.bootstrap());
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
@@ -211,8 +217,11 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay display) {
|
||||
handleBaseEntityLoadEarly(display);
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
handleCollisionEntityLoadOnEntitiesLoad(interaction);
|
||||
} else if (COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
handleCollisionEntityLoadOnEntitiesLoad(entity);
|
||||
} else if (entity instanceof Shulker shulker) {
|
||||
// TODO 移除这一行,预计过一个月
|
||||
handleCollisionEntityLoadOnEntitiesLoad(shulker);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,29 +319,29 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
this.plugin.scheduler().sync().runLater(() -> handleBaseEntityLoadLate(display, depth + 1), 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
}
|
||||
|
||||
protected void handleCollisionEntityLoadLate(Interaction interaction, int depth) {
|
||||
// remove the interaction if it's not a collision entity, it might be wrongly copied by WorldEdit
|
||||
if (FastNMS.INSTANCE.method$CraftEntity$getHandle(interaction) instanceof CollisionEntity) {
|
||||
protected void handleCollisionEntityLoadLate(Entity entity, int depth) {
|
||||
// remove the entity if it's not a collision entity, it might be wrongly copied by WorldEdit
|
||||
if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) {
|
||||
return;
|
||||
}
|
||||
// not a collision entity
|
||||
Byte flag = interaction.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
Byte flag = entity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
if (flag == null || flag != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location location = interaction.getLocation();
|
||||
Location location = entity.getLocation();
|
||||
World world = location.getWorld();
|
||||
int chunkX = location.getBlockX() >> 4;
|
||||
int chunkZ = location.getBlockZ() >> 4;
|
||||
if (!FastNMS.INSTANCE.isPreventingStatusUpdates(world, chunkX, chunkZ)) {
|
||||
interaction.remove();
|
||||
entity.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (depth > 2) return;
|
||||
plugin.scheduler().sync().runLater(() -> {
|
||||
handleCollisionEntityLoadLate(interaction, depth + 1);
|
||||
handleCollisionEntityLoadLate(entity, depth + 1);
|
||||
}, 1, world, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
@@ -364,20 +373,20 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleCollisionEntityLoadOnEntitiesLoad(Interaction interaction) {
|
||||
public void handleCollisionEntityLoadOnEntitiesLoad(Entity collisionEntity) {
|
||||
// faster
|
||||
if (FastNMS.INSTANCE.method$CraftEntity$getHandle(interaction) instanceof CollisionEntity) {
|
||||
interaction.remove();
|
||||
if (FastNMS.INSTANCE.method$CraftEntity$getHandle(collisionEntity) instanceof CollisionEntity) {
|
||||
collisionEntity.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// not a collision entity
|
||||
Byte flag = interaction.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
Byte flag = collisionEntity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE);
|
||||
if (flag == null || flag != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
interaction.remove();
|
||||
collisionEntity.remove();
|
||||
}
|
||||
|
||||
private AnchorType getAnchorType(Entity baseEntity, CustomFurniture furniture) {
|
||||
|
||||
@@ -2,7 +2,10 @@ package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@@ -33,8 +36,8 @@ public class FurnitureEventListener implements Listener {
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay itemDisplay) {
|
||||
this.manager.handleBaseEntityLoadEarly(itemDisplay);
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
this.manager.handleCollisionEntityLoadOnEntitiesLoad(interaction);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,8 +48,8 @@ public class FurnitureEventListener implements Listener {
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay itemDisplay) {
|
||||
this.manager.handleBaseEntityLoadEarly(itemDisplay);
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
this.manager.handleCollisionEntityLoadOnEntitiesLoad(interaction);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,8 +59,8 @@ public class FurnitureEventListener implements Listener {
|
||||
Entity entity = event.getEntity();
|
||||
if (entity instanceof ItemDisplay itemDisplay) {
|
||||
this.manager.handleBaseEntityLoadLate(itemDisplay, 0);
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
this.manager.handleCollisionEntityLoadLate(interaction, 0);
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityLoadLate(entity, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +73,7 @@ public class FurnitureEventListener implements Listener {
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay) {
|
||||
this.manager.handleBaseEntityUnload(entity);
|
||||
} else if (entity instanceof Interaction) {
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityUnload(entity);
|
||||
}
|
||||
}
|
||||
@@ -82,7 +85,7 @@ public class FurnitureEventListener implements Listener {
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof ItemDisplay) {
|
||||
this.manager.handleBaseEntityUnload(entity);
|
||||
} else if (entity instanceof Interaction) {
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityUnload(entity);
|
||||
}
|
||||
}
|
||||
@@ -93,7 +96,7 @@ public class FurnitureEventListener implements Listener {
|
||||
Entity entity = event.getEntity();
|
||||
if (entity instanceof ItemDisplay) {
|
||||
this.manager.handleBaseEntityUnload(entity);
|
||||
} else if (entity instanceof Interaction) {
|
||||
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
|
||||
this.manager.handleCollisionEntityUnload(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,10 +65,7 @@ public class InteractionHitBox extends AbstractHitBox {
|
||||
if (blocksBuilding() || this.canBeHitByProjectile()) {
|
||||
AABB ceAABB = AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), this.size.x, this.size.y);
|
||||
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
||||
collider.accept(new BukkitCollider(
|
||||
FastNMS.INSTANCE.createCollisionInteraction(world.serverWorld(), nmsAABB, x, y, z, this.canBeHitByProjectile(), false, this.blocksBuilding()),
|
||||
ColliderType.SHULKER
|
||||
));
|
||||
collider.accept(new BukkitCollider(world.serverWorld(), nmsAABB, x, y, z, this.canBeHitByProjectile(), false, this.blocksBuilding()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,10 +127,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
Object level = world.serverWorld();
|
||||
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(ceAABB.minX, ceAABB.minY, ceAABB.minZ, ceAABB.maxX, ceAABB.maxY, ceAABB.maxZ);
|
||||
aabb.accept(entityId, ceAABB);
|
||||
return new BukkitCollider(
|
||||
FastNMS.INSTANCE.createCollisionInteraction(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding()),
|
||||
ColliderType.SHULKER
|
||||
);
|
||||
return new BukkitCollider(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding());
|
||||
}
|
||||
|
||||
public AABB createAABB(Direction direction, Vector3f offset, double x, double y, double z) {
|
||||
|
||||
@@ -24,7 +24,6 @@ import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.joml.Quaternionf;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -1516,7 +1516,7 @@ public class PacketConsumers {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
} else if (entityType == Reflections.instance$EntityType$INTERACTION) {
|
||||
} else if (entityType == BukkitFurnitureManager.NMS_COLLISION_ENTITY_TYPE) {
|
||||
// Cancel collider entity packet
|
||||
int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId);
|
||||
|
||||
@@ -3773,6 +3773,7 @@ public class Reflections {
|
||||
public static final Object instance$EntityType$FALLING_BLOCK;
|
||||
public static final Object instance$EntityType$INTERACTION;
|
||||
public static final Object instance$EntityType$SHULKER;
|
||||
public static final Object instance$EntityType$OAK_BOAT;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -3790,6 +3791,8 @@ public class Reflections {
|
||||
instance$EntityType$SHULKER = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, shulker);
|
||||
Object armorStand = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "armor_stand");
|
||||
instance$EntityType$ARMOR_STAND = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, armorStand);
|
||||
Object oakBoat = VersionHelper.isVersionNewerThan1_21_2() ? FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "oak_boat") : FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "boat");
|
||||
instance$EntityType$OAK_BOAT = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, oakBoat);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user