mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-31 04:46:37 +00:00
优化碰撞计算
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.collisionEntity.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int entityId() {
|
||||
return this.collisionEntity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColliderType type() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return this.collisionEntity;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.entity.furniture.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.joml.Quaternionf;
|
||||
@@ -34,7 +35,7 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPackets(int entityId, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<Object> packets) {
|
||||
public void initPackets(int entityId, World world, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<Object> packets) {
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
entityId, UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
||||
|
||||
@@ -260,10 +260,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
for (int sub : furniture.entityIds()) {
|
||||
this.furnitureByEntityId.remove(sub);
|
||||
}
|
||||
// for (CollisionEntity collision : furniture.collisionEntities()) {
|
||||
// this.furnitureByRealEntityId.remove(FastNMS.INSTANCE.method$Entity$getId(collision));
|
||||
// if (!isPreventing) collision.destroy();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,8 +402,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
for (int entityId : loadedFurniture.entityIds()) {
|
||||
this.furnitureByEntityId.put(entityId, loadedFurniture);
|
||||
}
|
||||
for (CollisionEntity collisionEntity : loadedFurniture.collisionEntities()) {
|
||||
int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity);
|
||||
for (Collider collisionEntity : loadedFurniture.collisionEntities()) {
|
||||
int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity.handle());
|
||||
this.furnitureByRealEntityId.put(collisionEntityId, loadedFurniture);
|
||||
}
|
||||
return loadedFurniture;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils;
|
||||
@@ -15,13 +14,14 @@ import net.momirealms.craftengine.core.util.QuaternionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -37,16 +37,17 @@ public class LoadedFurniture implements Furniture {
|
||||
private final WeakReference<Entity> baseEntity;
|
||||
private final int baseEntityId;
|
||||
// colliders
|
||||
private final CollisionEntity[] collisionEntities;
|
||||
private final Collider[] colliderEntities;
|
||||
// cache
|
||||
private final List<Integer> fakeEntityIds;
|
||||
private final List<Integer> entityIds;
|
||||
private final Map<Integer, HitBox> hitBoxes;
|
||||
private final Map<Integer, HitBox> hitBoxes = new HashMap<>();
|
||||
private final Map<Integer, AABB> aabb = new HashMap<>();
|
||||
private final boolean minimized;
|
||||
private final boolean hasExternalModel;
|
||||
// seats
|
||||
private final Set<Vector3f> occupiedSeats = Collections.synchronizedSet(new HashSet<>());
|
||||
private final Vector<Entity> seats = new Vector<>();
|
||||
private final Vector<WeakReference<Entity>> seats = new Vector<>();
|
||||
// cached spawn packet
|
||||
private Object cachedSpawnPacket;
|
||||
private Object cachedMinimizedSpawnPacket;
|
||||
@@ -60,7 +61,6 @@ public class LoadedFurniture implements Furniture {
|
||||
this.location = baseEntity.getLocation();
|
||||
this.baseEntity = new WeakReference<>(baseEntity);
|
||||
this.furniture = furniture;
|
||||
this.hitBoxes = new HashMap<>();
|
||||
this.minimized = furniture.settings().minimized();
|
||||
List<Integer> fakeEntityIds = new ArrayList<>();
|
||||
List<Integer> mainEntityIds = new ArrayList<>();
|
||||
@@ -92,10 +92,11 @@ public class LoadedFurniture implements Furniture {
|
||||
List<Object> minimizedPackets = new ArrayList<>();
|
||||
List<Collider> colliders = new ArrayList<>();
|
||||
|
||||
World world = world();
|
||||
for (FurnitureElement element : placement.elements()) {
|
||||
int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
fakeEntityIds.add(entityId);
|
||||
element.initPackets(entityId, x, y, z, yaw, conjugated, packet -> {
|
||||
element.initPackets(entityId, world, x, y, z, yaw, conjugated, packet -> {
|
||||
packets.add(packet);
|
||||
if (this.minimized) minimizedPackets.add(packet);
|
||||
});
|
||||
@@ -107,12 +108,12 @@ public class LoadedFurniture implements Furniture {
|
||||
mainEntityIds.add(entityId);
|
||||
this.hitBoxes.put(entityId, hitBox);
|
||||
}
|
||||
hitBox.initPacketsAndColliders(ids, x, y, z, yaw, conjugated, (packet, canBeMinimized) -> {
|
||||
hitBox.initPacketsAndColliders(ids, world, x, y, z, yaw, conjugated, (packet, canBeMinimized) -> {
|
||||
packets.add(packet);
|
||||
if (this.minimized && !canBeMinimized) {
|
||||
minimizedPackets.add(packet);
|
||||
}
|
||||
}, colliders::add);
|
||||
}, colliders::add, this.aabb::put);
|
||||
}
|
||||
try {
|
||||
this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
|
||||
@@ -124,34 +125,15 @@ public class LoadedFurniture implements Furniture {
|
||||
}
|
||||
this.fakeEntityIds = fakeEntityIds;
|
||||
this.entityIds = mainEntityIds;
|
||||
int colliderSize = colliders.size();
|
||||
this.collisionEntities = new CollisionEntity[colliderSize];
|
||||
if (colliderSize != 0) {
|
||||
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld());
|
||||
for (int i = 0; i < colliderSize; i++) {
|
||||
Collider collider = colliders.get(i);
|
||||
Vector3f offset = conjugated.transform(new Vector3f(collider.position()));
|
||||
Vector3d offset1 = collider.point1();
|
||||
Vector3d offset2 = collider.point2();
|
||||
double x1 = x + offset1.x() + offset.x();
|
||||
double x2 = x + offset2.x() + offset.x();
|
||||
double y1 = y + offset1.y() + offset.y();
|
||||
double y2 = y + offset2.y() + offset.y();
|
||||
double z1 = z + offset1.z() - offset.z();
|
||||
double z2 = z + offset2.z() - offset.z();
|
||||
Object aabb = FastNMS.INSTANCE.constructor$AABB(x1, y1, z1, x2, y2, z2);
|
||||
CollisionEntity entity = FastNMS.INSTANCE.createCollisionShulker(world, aabb, x, y, z, collider.canBeHitByProjectile());
|
||||
this.collisionEntities[i] = entity;
|
||||
}
|
||||
}
|
||||
this.colliderEntities = colliders.toArray(new Collider[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeColliders() {
|
||||
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld());
|
||||
for (CollisionEntity entity : this.collisionEntities) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity);
|
||||
Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity);
|
||||
for (Collider entity : this.colliderEntities) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -201,11 +183,13 @@ public class LoadedFurniture implements Furniture {
|
||||
return;
|
||||
}
|
||||
this.baseEntity().remove();
|
||||
for (CollisionEntity entity : this.collisionEntities) {
|
||||
for (Collider entity : this.colliderEntities) {
|
||||
if (entity != null)
|
||||
entity.destroy();
|
||||
}
|
||||
for (Entity entity : this.seats) {
|
||||
for (WeakReference<Entity> r : this.seats) {
|
||||
Entity entity = r.get();
|
||||
if (entity == null) continue;
|
||||
for (Entity passenger : entity.getPassengers()) {
|
||||
entity.removePassenger(passenger);
|
||||
}
|
||||
@@ -216,8 +200,11 @@ public class LoadedFurniture implements Furniture {
|
||||
|
||||
@Override
|
||||
public void destroySeats() {
|
||||
for (Entity entity : this.seats) {
|
||||
entity.remove();
|
||||
for (WeakReference<Entity> entity : this.seats) {
|
||||
Entity e = entity.get();
|
||||
if (e != null) {
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
this.seats.clear();
|
||||
}
|
||||
@@ -269,8 +256,18 @@ public class LoadedFurniture implements Furniture {
|
||||
return Collections.unmodifiableList(this.fakeEntityIds);
|
||||
}
|
||||
|
||||
public CollisionEntity[] collisionEntities() {
|
||||
return this.collisionEntities;
|
||||
public Collider[] collisionEntities() {
|
||||
return this.colliderEntities;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HitBox hitBoxByEntityId(int id) {
|
||||
return this.hitBoxes.get(id);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AABB aabbByEntityId(int id) {
|
||||
return this.aabb.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -326,7 +323,7 @@ public class LoadedFurniture implements Furniture {
|
||||
itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER, this.baseEntityId());
|
||||
itemDisplay.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_SEAT_VECTOR_3F_KEY, PersistentDataType.STRING, seat.offset().x + ", " + seat.offset().y + ", " + seat.offset().z);
|
||||
});
|
||||
this.seats.add(seatEntity);
|
||||
this.seats.add(new WeakReference<>(seatEntity));
|
||||
seatEntity.addPassenger(player);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@@ -25,7 +27,7 @@ public class CustomHitBox extends AbstractHitBox {
|
||||
private final List<Object> cachedValues = new ArrayList<>();
|
||||
|
||||
public CustomHitBox(Seat[] seats, Vector3f position, EntityType type, float scale) {
|
||||
super(seats, position);
|
||||
super(seats, position, false);
|
||||
this.scale = scale;
|
||||
this.entityType = type;
|
||||
BaseEntityData.NoGravity.addEntityDataIfNotDefaultValue(true, this.cachedValues);
|
||||
@@ -47,7 +49,7 @@ public class CustomHitBox extends AbstractHitBox {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPacketsAndColliders(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider) {
|
||||
public void initPacketsAndColliders(int[] entityId, World world, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
try {
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.momirealms.craftengine.bukkit.entity.furniture.hitbox;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@@ -15,8 +17,8 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final double scale;
|
||||
|
||||
public HappyGhastHitBox(Seat[] seats, Vector3f position, double scale) {
|
||||
super(seats, position);
|
||||
public HappyGhastHitBox(Seat[] seats, Vector3f position, double scale, boolean canUseOn) {
|
||||
super(seats, position, canUseOn);
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@@ -30,7 +32,7 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPacketsAndColliders(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider) {
|
||||
public void initPacketsAndColliders(int[] entityId, World world, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
||||
// todo 乐魂
|
||||
}
|
||||
|
||||
@@ -44,10 +46,11 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
||||
@Override
|
||||
public HitBox create(Map<String, Object> arguments) {
|
||||
double scale = MiscUtils.getAsDouble(arguments.getOrDefault("scale", "1"));
|
||||
boolean canUseOn = (boolean) arguments.getOrDefault("can-use-item-on", false);
|
||||
return new HappyGhastHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
MiscUtils.getVector3f(arguments.getOrDefault("position", "0")),
|
||||
scale
|
||||
scale, canUseOn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
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.World;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@@ -19,14 +22,14 @@ import java.util.function.Supplier;
|
||||
|
||||
public class InteractionHitBox extends AbstractHitBox {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public static final InteractionHitBox DEFAULT = new InteractionHitBox(new Seat[0], new Vector3f(), new Vector3f(1,1,1), true);
|
||||
public static final InteractionHitBox DEFAULT = new InteractionHitBox(new Seat[0], new Vector3f(), new Vector3f(1,1,1), true, false);
|
||||
|
||||
private final Vector3f size;
|
||||
private final boolean responsive;
|
||||
private final List<Object> cachedValues = new ArrayList<>();
|
||||
|
||||
public InteractionHitBox(Seat[] seats, Vector3f position, Vector3f size, boolean responsive) {
|
||||
super(seats, position);
|
||||
public InteractionHitBox(Seat[] seats, Vector3f position, Vector3f size, boolean responsive, boolean canUseOn) {
|
||||
super(seats, position, canUseOn);
|
||||
this.size = size;
|
||||
this.responsive = responsive;
|
||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(size.y, cachedValues);
|
||||
@@ -48,13 +51,16 @@ public class InteractionHitBox extends AbstractHitBox {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPacketsAndColliders(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider) {
|
||||
public void initPacketsAndColliders(int[] entityId, World world, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
entityId[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
||||
Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0
|
||||
), true);
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true);
|
||||
if (canPlaceAgainst()) {
|
||||
aabb.accept(entityId[0], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), this.size.x, this.size.y));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,11 +83,13 @@ public class InteractionHitBox extends AbstractHitBox {
|
||||
width = MiscUtils.getAsFloat(arguments.getOrDefault("width", "1"));
|
||||
height = MiscUtils.getAsFloat(arguments.getOrDefault("height", "1"));
|
||||
}
|
||||
boolean canUseOn = (boolean) arguments.getOrDefault("can-use-item-on", false);
|
||||
boolean interactive = (boolean) arguments.getOrDefault("interactive", true);
|
||||
return new InteractionHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
position,
|
||||
new Vector3f(width, height, width),
|
||||
(boolean) arguments.getOrDefault("interactive", true)
|
||||
interactive, canUseOn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,16 @@ 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.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.*;
|
||||
@@ -27,8 +30,8 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
private final List<Object> cachedShulkerValues = new ArrayList<>();
|
||||
private final DirectionalShulkerSpawner spawner;
|
||||
|
||||
public ShulkerHitBox(Seat[] seats, Vector3f position, Direction direction, float scale, byte peek, boolean interactionEntity, boolean interactive) {
|
||||
super(seats, position);
|
||||
public ShulkerHitBox(Seat[] seats, Vector3f position, Direction direction, float scale, byte peek, boolean interactionEntity, boolean interactive, boolean canUseOn) {
|
||||
super(seats, position, canUseOn);
|
||||
this.direction = direction;
|
||||
this.scale = scale;
|
||||
this.peek = peek;
|
||||
@@ -45,27 +48,28 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
float shulkerHeight = (getPhysicalPeek(peek * 0.01F) + 1) * scale;
|
||||
List<Object> cachedInteractionValues = new ArrayList<>();
|
||||
if (this.direction == Direction.UP) {
|
||||
Collider c = createCollider(Direction.UP);
|
||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(shulkerHeight + 0.01f, cachedInteractionValues);
|
||||
InteractionEntityData.Width.addEntityDataIfNotDefaultValue(scale + 0.005f, cachedInteractionValues);
|
||||
InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(interactive, cachedInteractionValues);
|
||||
this.spawner = (entityIds, x, y, z, yaw, offset, packets, collider) -> {
|
||||
collider.accept(c);
|
||||
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,
|
||||
Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0
|
||||
), true);
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
||||
if (canUseOn) {
|
||||
aabb.accept(entityIds[2], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), scale, shulkerHeight));
|
||||
}
|
||||
}
|
||||
};
|
||||
} else if (this.direction == Direction.DOWN) {
|
||||
Collider c = createCollider(Direction.DOWN);
|
||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(shulkerHeight + 0.01f, cachedInteractionValues);
|
||||
InteractionEntityData.Width.addEntityDataIfNotDefaultValue(scale + 0.005f, cachedInteractionValues);
|
||||
InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(interactive, cachedInteractionValues);
|
||||
this.spawner = (entityIds, x, y, z, yaw, offset, packets, collider) -> {
|
||||
collider.accept(c);
|
||||
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(Reflections.instance$Direction$UP))), false);
|
||||
if (interactionEntity) {
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
@@ -73,16 +77,19 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0
|
||||
), true);
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)), true);
|
||||
if (canUseOn) {
|
||||
aabb.accept(entityIds[2], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y - shulkerHeight + scale, z - offset.z), scale, shulkerHeight));
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(scale + 0.01f, cachedInteractionValues);
|
||||
InteractionEntityData.Width.addEntityDataIfNotDefaultValue(scale + 0.005f, cachedInteractionValues);
|
||||
InteractionEntityData.Responsive.addEntityDataIfNotDefaultValue(interactive, cachedInteractionValues);
|
||||
this.spawner = (entityIds, x, y, z, yaw, offset, packets, collider) -> {
|
||||
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));
|
||||
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)))), false);
|
||||
if (interactionEntity) {
|
||||
// first interaction
|
||||
@@ -98,12 +105,16 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0
|
||||
), true);
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[3], List.copyOf(cachedInteractionValues)), true);
|
||||
if (canUseOn) {
|
||||
aabb.accept(entityIds[2], AABB.fromInteraction(new Vec3d(x + offset.x, y + offset.y, z - offset.z), scale, scale));
|
||||
aabb.accept(entityIds[3], AABB.fromInteraction(new Vec3d(x + offset.x + shulkerDirection.stepX() * distance, y + offset.y, z - offset.z + shulkerDirection.stepZ() * distance), scale, scale));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public Collider createCollider(Direction d) {
|
||||
public Collider createCollider(Direction direction, World world, Vector3f offset, double x, double y, double z, int entityId, BiConsumer<Integer, AABB> aabb) {
|
||||
float peek = getPhysicalPeek(this.peek() * 0.01F);
|
||||
double x1 = -this.scale * 0.5;
|
||||
double y1 = 0.0;
|
||||
@@ -112,29 +123,37 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
double y2 = this.scale;
|
||||
double z2 = this.scale * 0.5;
|
||||
|
||||
double dx = (double) d.stepX() * peek * (double) this.scale;
|
||||
double dx = (double) direction.stepX() * peek * (double) this.scale;
|
||||
if (dx > 0) {
|
||||
x2 += dx;
|
||||
} else if (dx < 0) {
|
||||
x1 += dx;
|
||||
}
|
||||
double dy = (double) d.stepY() * peek * (double) this.scale;
|
||||
double dy = (double) direction.stepY() * peek * (double) this.scale;
|
||||
if (dy > 0) {
|
||||
y2 += dy;
|
||||
} else if (dy < 0) {
|
||||
y1 += dy;
|
||||
}
|
||||
double dz = (double) d.stepZ() * peek * (double) this.scale;
|
||||
double dz = (double) direction.stepZ() * peek * (double) this.scale;
|
||||
if (dz > 0) {
|
||||
z2 += dz;
|
||||
} else if (dz < 0) {
|
||||
z1 += dz;
|
||||
}
|
||||
return new Collider(
|
||||
true,
|
||||
this.position,
|
||||
new Vector3d(x1, y1, z1),
|
||||
new Vector3d(x2, y2, z2)
|
||||
|
||||
Object level = world.serverWorld();
|
||||
double minX = x + x1 + offset.x();
|
||||
double maxX = x + x2 + offset.x();
|
||||
double minY = y + y1 + offset.y();
|
||||
double maxY = y + y2 + offset.y();
|
||||
double minZ = z + z1 - offset.z();
|
||||
double maxZ = z + z2 - offset.z();
|
||||
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
aabb.accept(entityId, new AABB(minX, minY, minZ, maxX, maxY, maxZ));
|
||||
return new BukkitCollider(
|
||||
FastNMS.INSTANCE.createCollisionShulker(level, nmsAABB, x, y, z, true),
|
||||
ColliderType.SHULKER
|
||||
);
|
||||
}
|
||||
|
||||
@@ -168,7 +187,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPacketsAndColliders(int[] entityIds, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider) {
|
||||
public void initPacketsAndColliders(int[] entityIds, World world, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
try {
|
||||
double originalY = y + offset.y;
|
||||
@@ -200,7 +219,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
Reflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, this.scale);
|
||||
packets.accept(Reflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityIds[1], Collections.singletonList(attributeInstance)), false);
|
||||
}
|
||||
this.spawner.accept(entityIds, x, y, z, yaw, offset, packets, collider);
|
||||
this.spawner.accept(entityIds, world, x, y, z, yaw, offset, packets, collider, aabb);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to construct shulker hitbox spawn packet", e);
|
||||
}
|
||||
@@ -209,7 +228,7 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
@FunctionalInterface
|
||||
interface DirectionalShulkerSpawner {
|
||||
|
||||
void accept(int[] entityIds, double x, double y, double z, float yaw, Vector3f offset, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider);
|
||||
void accept(int[] entityIds, World world, double x, double y, double z, float yaw, Vector3f offset, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,10 +257,11 @@ public class ShulkerHitBox extends AbstractHitBox {
|
||||
Direction directionEnum = Optional.ofNullable(arguments.get("direction")).map(it -> Direction.valueOf(it.toString().toUpperCase(Locale.ENGLISH))).orElse(Direction.UP);
|
||||
boolean interactive = (boolean) arguments.getOrDefault("interactive", true);
|
||||
boolean interactionEntity = (boolean) arguments.getOrDefault("interaction-entity", true);
|
||||
boolean canUseItemOn = (boolean) arguments.getOrDefault("can-use-item-on", true);
|
||||
return new ShulkerHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
position, directionEnum,
|
||||
scale, peek, interactionEntity, interactive
|
||||
scale, peek, interactionEntity, interactive, canUseItemOn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.modelengine.ModelEngineUtils;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.pack.BukkitPackManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
@@ -22,6 +23,9 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData;
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
@@ -30,19 +34,21 @@ import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetworkManager;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.WorldEvents;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
import net.momirealms.craftengine.core.world.chunk.Palette;
|
||||
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
|
||||
import net.momirealms.craftengine.core.world.chunk.packet.MCSection;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -1621,13 +1627,36 @@ public class PacketConsumers {
|
||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||
return;
|
||||
}
|
||||
if (player.isSneaking())
|
||||
return;
|
||||
furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> {
|
||||
if (furniture.tryOccupySeat(seatPos)) {
|
||||
furniture.spawnSeatEntityForPlayer(Objects.requireNonNull(player.getPlayer()), seatPos);
|
||||
}
|
||||
});
|
||||
if (player.isSneaking()) {
|
||||
// try placing another furniture above it
|
||||
AABB hitBox = furniture.aabbByEntityId(entityId);
|
||||
if (hitBox == null) return;
|
||||
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
if (itemInHand == null) return;
|
||||
itemInHand.getCustomItem().ifPresent(customItem -> {
|
||||
Location eyeLocation = player.getEyeLocation();
|
||||
Vector direction = eyeLocation.getDirection();
|
||||
Location endLocation = eyeLocation.clone();
|
||||
endLocation.add(direction.multiply(serverPlayer.getCachedInteractionRange()));
|
||||
Optional<EntityHitResult> result = hitBox.clip(LocationUtils.toVec3d(eyeLocation), LocationUtils.toVec3d(endLocation));
|
||||
if (result.isPresent()) {
|
||||
EntityHitResult hitResult = result.get();
|
||||
Vec3d vec3d = hitResult.position();
|
||||
for (ItemBehavior behavior : customItem.behaviors()) {
|
||||
if (behavior instanceof FurnitureItemBehavior) {
|
||||
behavior.useOnBlock(new UseOnContext(serverPlayer, InteractionHand.MAIN_HAND, new BlockHitResult(vec3d, hitResult.direction(), BlockPos.fromVec3d(vec3d), false)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
furniture.findFirstAvailableSeat(entityId).ifPresent(seatPos -> {
|
||||
if (furniture.tryOccupySeat(seatPos)) {
|
||||
furniture.spawnSeatEntityForPlayer(Objects.requireNonNull(player.getPlayer()), seatPos);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, player.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
} catch (Exception e) {
|
||||
|
||||
Reference in New Issue
Block a user