mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-29 03:49:15 +00:00
new hitbox types
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BoatHitBox extends AbstractHitBox {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
|
||||
public BoatHitBox(Seat[] seats, Vector3f position) {
|
||||
super(seats, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return HitBoxTypes.BOAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Consumer<Object> packets) {
|
||||
// 生成无重力船
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] acquireEntityIds(Supplier<Integer> entityIdSupplier) {
|
||||
return new int[] {entityIdSupplier.get()};
|
||||
}
|
||||
|
||||
public static class Factory implements HitBoxFactory {
|
||||
|
||||
@Override
|
||||
public HitBox create(Map<String, Object> arguments) {
|
||||
return new BoatHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
MiscUtils.getVector3f(arguments.getOrDefault("position", "0"))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,7 +237,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
LoadedFurniture furniture = this.furnitureByBaseEntityId.remove(id);
|
||||
if (furniture != null) {
|
||||
furniture.destroySeats();
|
||||
for (int sub : furniture.interactionEntityIds()) {
|
||||
for (int sub : furniture.hitBoxEntityIds()) {
|
||||
this.furnitureByInteractionEntityId.remove(sub);
|
||||
}
|
||||
} else if (entity instanceof Interaction interaction) {
|
||||
@@ -307,7 +307,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
private synchronized LoadedFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture, AnchorType anchorType) {
|
||||
LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, anchorType);
|
||||
this.furnitureByBaseEntityId.put(loadedFurniture.baseEntityId(), loadedFurniture);
|
||||
for (int entityId : loadedFurniture.interactionEntityIds()) {
|
||||
for (int entityId : loadedFurniture.hitBoxEntityIds()) {
|
||||
this.furnitureByInteractionEntityId.put(entityId, loadedFurniture);
|
||||
}
|
||||
return loadedFurniture;
|
||||
|
||||
@@ -8,5 +8,7 @@ public class BukkitHitBoxTypes extends HitBoxTypes {
|
||||
|
||||
static {
|
||||
register(INTERACTION, InteractionHitBox.FACTORY);
|
||||
register(SHULKER, ShulkerHitBox.FACTORY);
|
||||
register(BOAT, BoatHitBox.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,18 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
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);
|
||||
private final Vector3f position;
|
||||
|
||||
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);
|
||||
this.position = position;
|
||||
super(seats, position);
|
||||
this.size = size;
|
||||
this.responsive = responsive;
|
||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(size.y, cachedValues);
|
||||
@@ -36,10 +36,6 @@ public class InteractionHitBox extends AbstractHitBox {
|
||||
return responsive;
|
||||
}
|
||||
|
||||
public Vector3f position() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Vector3f size() {
|
||||
return size;
|
||||
}
|
||||
@@ -50,19 +46,24 @@ public class InteractionHitBox extends AbstractHitBox {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnPackets(int entityId, double x, double y, double z, float yaw, Consumer<Object> packets) {
|
||||
public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Consumer<Object> packets) {
|
||||
Vector3f offset = QuaternionUtils.toQuaternionf(0f, Math.toRadians(180f - yaw), 0f).conjugate().transform(new Vector3f(position()));
|
||||
try {
|
||||
packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance(
|
||||
entityId, UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
||||
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
|
||||
));
|
||||
packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId, List.copyOf(this.cachedValues)));
|
||||
packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId[0], List.copyOf(this.cachedValues)));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to construct hitbox spawn packet", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] acquireEntityIds(Supplier<Integer> entityIdSupplier) {
|
||||
return new int[] {entityIdSupplier.get()};
|
||||
}
|
||||
|
||||
public static class Factory implements HitBoxFactory {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,21 +26,18 @@ public class LoadedFurniture {
|
||||
private final Key id;
|
||||
private final CustomFurniture furniture;
|
||||
private final AnchorType anchorType;
|
||||
private final Map<Integer, FurnitureElement> elements;
|
||||
private final Map<Integer, HitBox> hitBoxes;
|
||||
// location
|
||||
private Location location;
|
||||
// base entity
|
||||
private final WeakReference<Entity> baseEntity;
|
||||
private final int baseEntityId;
|
||||
// includes elements + interactions
|
||||
private final List<Integer> subEntityIds;
|
||||
// interactions
|
||||
private final List<Integer> interactionEntityIds;
|
||||
// cache
|
||||
private final List<Integer> fakeEntityIds;
|
||||
private final List<Integer> hitBoxEntityIds;
|
||||
private final Map<Integer, HitBox> hitBoxes;
|
||||
// seats
|
||||
private final Set<Vector3f> occupiedSeats = Collections.synchronizedSet(new HashSet<>());
|
||||
private final Vector<Entity> seats = new Vector<>();
|
||||
|
||||
// cached spawn packet
|
||||
private Object cachedSpawnPacket;
|
||||
|
||||
@@ -54,40 +51,36 @@ public class LoadedFurniture {
|
||||
this.baseEntity = new WeakReference<>(baseEntity);
|
||||
this.furniture = furniture;
|
||||
this.hitBoxes = new HashMap<>();
|
||||
this.elements = new HashMap<>();
|
||||
List<Integer> entityIds = new ArrayList<>();
|
||||
List<Integer> fakeEntityIds = new ArrayList<>();
|
||||
List<Integer> hitBoxEntityIds = new ArrayList<>();
|
||||
CustomFurniture.Placement placement = furniture.getPlacement(anchorType);
|
||||
|
||||
List<Object> packets = new ArrayList<>();
|
||||
for (FurnitureElement element : placement.elements()) {
|
||||
int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
entityIds.add(entityId);
|
||||
this.elements.put(entityId, element);
|
||||
fakeEntityIds.add(entityId);
|
||||
element.addSpawnPackets(entityId, this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add);
|
||||
}
|
||||
for (HitBox hitBox : placement.hitboxes()) {
|
||||
int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
entityIds.add(entityId);
|
||||
hitBoxEntityIds.add(entityId);
|
||||
this.hitBoxes.put(entityId, hitBox);
|
||||
}
|
||||
this.subEntityIds = entityIds;
|
||||
this.interactionEntityIds = hitBoxEntityIds;
|
||||
}
|
||||
|
||||
public synchronized Object spawnPacket() {
|
||||
if (this.cachedSpawnPacket == null) {
|
||||
try {
|
||||
List<Object> packets = new ArrayList<>();
|
||||
for (Map.Entry<Integer, FurnitureElement> entry : this.elements.entrySet()) {
|
||||
entry.getValue().addSpawnPackets(entry.getKey(), this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add);
|
||||
}
|
||||
for (Map.Entry<Integer, HitBox> entry : this.hitBoxes.entrySet()) {
|
||||
entry.getValue().addSpawnPackets(entry.getKey(), this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add);
|
||||
}
|
||||
this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e);
|
||||
int[] ids = hitBox.acquireEntityIds(Reflections.instance$Entity$ENTITY_COUNTER::incrementAndGet);
|
||||
for (int entityId : ids) {
|
||||
fakeEntityIds.add(entityId);
|
||||
hitBoxEntityIds.add(entityId);
|
||||
hitBox.addSpawnPackets(ids, this.location.getX(), this.location.getY(), this.location.getZ(), this.location.getYaw(), packets::add);
|
||||
this.hitBoxes.put(entityId, hitBox);
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e);
|
||||
}
|
||||
this.fakeEntityIds = fakeEntityIds;
|
||||
this.hitBoxEntityIds = hitBoxEntityIds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Object spawnPacket() {
|
||||
return this.cachedSpawnPacket;
|
||||
}
|
||||
|
||||
@@ -178,27 +171,32 @@ public class LoadedFurniture {
|
||||
}
|
||||
|
||||
public int baseEntityId() {
|
||||
return baseEntityId;
|
||||
return this.baseEntityId;
|
||||
}
|
||||
|
||||
public List<Integer> interactionEntityIds() {
|
||||
return interactionEntityIds;
|
||||
@NotNull
|
||||
public List<Integer> hitBoxEntityIds() {
|
||||
return this.hitBoxEntityIds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Integer> subEntityIds() {
|
||||
return this.subEntityIds;
|
||||
return this.fakeEntityIds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AnchorType anchorType() {
|
||||
return anchorType;
|
||||
return this.anchorType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Key furnitureId() {
|
||||
return id;
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CustomFurniture furniture() {
|
||||
return furniture;
|
||||
return this.furniture;
|
||||
}
|
||||
|
||||
public void mountSeat(org.bukkit.entity.Player player, Seat seat) {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ShulkerHitBox extends AbstractHitBox {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
// 1.20.6+
|
||||
private final double scale;
|
||||
private final byte peek;
|
||||
// todo或许还能做个方向,但是会麻烦点,和 yaw 有关
|
||||
private final Direction direction;
|
||||
|
||||
public ShulkerHitBox(Seat[] seats, Vector3f position, double scale, byte peek, Direction direction) {
|
||||
super(seats, position);
|
||||
this.scale = scale;
|
||||
this.peek = peek;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public Direction direction() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public byte peek() {
|
||||
return peek;
|
||||
}
|
||||
|
||||
public double scale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return HitBoxTypes.SHULKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawnPackets(int[] entityIds, double x, double y, double z, float yaw, Consumer<Object> packets) {
|
||||
// 1.生成假的展示实体
|
||||
// 2.生成假的潜影贝
|
||||
// 3.潜影贝骑展示实体
|
||||
// 4.潜影贝数据设置(隐身,尺寸,peek,方向)
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] acquireEntityIds(Supplier<Integer> entityIdSupplier) {
|
||||
// 展示实体 // 潜影贝
|
||||
return new int[] {entityIdSupplier.get(), entityIdSupplier.get()};
|
||||
}
|
||||
|
||||
public static class Factory implements HitBoxFactory {
|
||||
|
||||
@Override
|
||||
public HitBox create(Map<String, Object> arguments) {
|
||||
Vector3f position = MiscUtils.getVector3f(arguments.getOrDefault("position", "0"));
|
||||
double scale = MiscUtils.getAsDouble(arguments.getOrDefault("scale", "1"));
|
||||
byte peek = (byte) MiscUtils.getAsInt(arguments.getOrDefault("peek", 0));
|
||||
Direction directionEnum = Optional.ofNullable(arguments.get("direction")).map(it -> Direction.valueOf(it.toString().toUpperCase(Locale.ENGLISH))).orElse(Direction.UP);
|
||||
return new ShulkerHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
position,
|
||||
scale, peek, directionEnum
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public class ItemEventListener implements Listener {
|
||||
block,
|
||||
event.getBlockFace(),
|
||||
event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND,
|
||||
action == Action.RIGHT_CLICK_BLOCK ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK
|
||||
action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK
|
||||
);
|
||||
if (EventUtils.fireAndCheckCancel(interactEvent)) {
|
||||
event.setCancelled(true);
|
||||
|
||||
Reference in New Issue
Block a user