mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-06 15:52:03 +00:00
添加custom碰撞箱
This commit is contained in:
@@ -10,7 +10,7 @@ public class BukkitFurnitureHitboxTypes extends FurnitureHitBoxTypes {
|
||||
static {
|
||||
register(INTERACTION, InteractionFurnitureHitboxConfig.FACTORY);
|
||||
register(SHULKER, ShulkerFurnitureHitboxConfig.FACTORY);
|
||||
// register(CUSTOM, CustomFurnitureHitboxConfig.FACTORY);
|
||||
register(CUSTOM, CustomFurnitureHitboxConfig.FACTORY);
|
||||
if (VersionHelper.isOrAbove1_21_6()) {
|
||||
register(HAPPY_GHAST, HappyGhastFurnitureHitboxConfig.FACTORY);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.hitbox;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Collider;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitboxPart;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CustomFurnitureHitbox extends AbstractFurnitureHitBox {
|
||||
private final CustomFurnitureHitboxConfig config;
|
||||
private final Collider collider;
|
||||
private final Object spawnPacket;
|
||||
private final Object despawnPacket;
|
||||
private final FurnitureHitboxPart part;
|
||||
|
||||
public CustomFurnitureHitbox(Furniture furniture, CustomFurnitureHitboxConfig config) {
|
||||
super(furniture, config);
|
||||
this.config = config;
|
||||
WorldPosition position = furniture.position();
|
||||
Vec3d pos = Furniture.getRelativePosition(position, config.position());
|
||||
AABB aabb = AABB.makeBoundingBox(pos, config.width(), config.height());
|
||||
this.collider = createCollider(furniture.world(), pos, aabb, false, config.blocksBuilding(), config.canBeHitByProjectile());
|
||||
int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
List<Object> packets = new ArrayList<>(3);
|
||||
packets.add(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
entityId, UUID.randomUUID(), position.x, position.y, position.z, 0, position.yRot,
|
||||
config.entityType(), 0, CoreReflections.instance$Vec3$Zero, 0
|
||||
));
|
||||
packets.add(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, config.cachedValues()));
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
try {
|
||||
Object attributeInstance = CoreReflections.constructor$AttributeInstance.newInstance(MAttributeHolders.SCALE, (Consumer<?>) (o) -> {});
|
||||
CoreReflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, config.scale());
|
||||
packets.add(NetworkReflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityId, Collections.singletonList(attributeInstance)));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to apply scale attribute", e);
|
||||
}
|
||||
}
|
||||
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); }});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Collider> colliders() {
|
||||
return List.of(this.collider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FurnitureHitboxPart> parts() {
|
||||
return List.of(this.part);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Player player) {
|
||||
player.sendPacket(this.spawnPacket, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(Player player) {
|
||||
player.sendPacket(this.despawnPacket, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomFurnitureHitboxConfig config() {
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.AbstractFurnitureHitBoxConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfigFactory;
|
||||
import net.momirealms.craftengine.core.entity.seat.SeatConfig;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CustomFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<CustomFurnitureHitbox> {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final float scale;
|
||||
private final Object entityType;
|
||||
private final List<Object> cachedValues = new ArrayList<>();
|
||||
private final float width;
|
||||
private final float height;
|
||||
|
||||
public CustomFurnitureHitboxConfig(SeatConfig[] seats,
|
||||
Vector3f position,
|
||||
boolean canUseItemOn,
|
||||
boolean blocksBuilding,
|
||||
boolean canBeHitByProjectile,
|
||||
float width,
|
||||
float height,
|
||||
boolean fixed,
|
||||
float scale,
|
||||
Object type) {
|
||||
super(seats, position, canUseItemOn, blocksBuilding, canBeHitByProjectile);
|
||||
this.scale = scale;
|
||||
this.entityType = type;
|
||||
this.width = fixed ? width : width * scale;
|
||||
this.height = fixed ? height : height * scale;
|
||||
BaseEntityData.NoGravity.addEntityDataIfNotDefaultValue(true, this.cachedValues);
|
||||
BaseEntityData.Silent.addEntityDataIfNotDefaultValue(true, this.cachedValues);
|
||||
BaseEntityData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, this.cachedValues);
|
||||
}
|
||||
|
||||
public float scale() {
|
||||
return this.scale;
|
||||
}
|
||||
|
||||
public Object entityType() {
|
||||
return this.entityType;
|
||||
}
|
||||
|
||||
public List<Object> cachedValues() {
|
||||
return this.cachedValues;
|
||||
}
|
||||
|
||||
public float width() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public float height() {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
||||
if (this.blocksBuilding) {
|
||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, this.width, this.height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomFurnitureHitbox create(Furniture furniture) {
|
||||
return new CustomFurnitureHitbox(furniture, this);
|
||||
}
|
||||
|
||||
public static class Factory implements FurnitureHitBoxConfigFactory<CustomFurnitureHitbox> {
|
||||
|
||||
@Override
|
||||
public CustomFurnitureHitboxConfig create(Map<String, Object> arguments) {
|
||||
Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position");
|
||||
float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", 1), "scale");
|
||||
String type = (String) arguments.getOrDefault("entity-type", "slime");
|
||||
Object nmsEntityType = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ENTITY_TYPE, KeyUtils.toResourceLocation(Key.of(type)));
|
||||
if (nmsEntityType == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.hitbox.custom.invalid_entity", new IllegalArgumentException("EntityType not found: " + type), type);
|
||||
}
|
||||
float width;
|
||||
float height;
|
||||
boolean fixed;
|
||||
try {
|
||||
Object dimensions = CoreReflections.field$EntityType$dimensions.get(nmsEntityType);
|
||||
width = CoreReflections.field$EntityDimensions$width.getFloat(dimensions);
|
||||
height = CoreReflections.field$EntityDimensions$height.getFloat(dimensions);
|
||||
fixed = CoreReflections.field$EntityDimensions$fixed.getBoolean(dimensions);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to get dimensions for " + nmsEntityType, e);
|
||||
}
|
||||
boolean canUseItemOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", false), "can-use-item-on");
|
||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", false), "can-be-hit-by-projectile");
|
||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
||||
return new CustomFurnitureHitboxConfig(SeatConfig.fromObj(arguments.get("seats")), position, canUseItemOn, blocksBuilding, canBeHitByProjectile, width, height, fixed, scale, nmsEntityType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public class HappyGhastFurnitureHitbox extends AbstractFurnitureHitBox {
|
||||
WorldPosition position = furniture.position();
|
||||
this.pos = Furniture.getRelativePosition(position, config.position());
|
||||
double bbSize = 4 * config.scale();
|
||||
AABB aabb = AABB.fromInteraction(this.pos, bbSize, bbSize);
|
||||
AABB aabb = AABB.makeBoundingBox(this.pos, bbSize, bbSize);
|
||||
this.yaw = position.yRot;
|
||||
this.entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
this.packets = new ArrayList<>(3);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class HappyGhastFurnitureHitboxConfig extends AbstractFurnitureHitBoxConf
|
||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
||||
if (this.blocksBuilding) {
|
||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||
aabbConsumer.accept(AABB.fromInteraction(relativePosition, 4 * this.scale, 4 * this.scale));
|
||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, 4 * this.scale, 4 * this.scale));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox {
|
||||
this.config = config;
|
||||
WorldPosition position = furniture.position();
|
||||
Vec3d pos = Furniture.getRelativePosition(position, config.position());
|
||||
AABB aabb = AABB.fromInteraction(pos, config.size().x, config.size().y);
|
||||
AABB aabb = AABB.makeBoundingBox(pos, config.size().x, config.size().y);
|
||||
this.collider = createCollider(furniture.world(), pos, aabb, false, config.blocksBuilding(), config.canBeHitByProjectile());
|
||||
int interactionId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||
this.spawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of(
|
||||
|
||||
@@ -73,7 +73,7 @@ public class InteractionFurnitureHitboxConfig extends AbstractFurnitureHitBoxCon
|
||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
||||
if (this.blocksBuilding) {
|
||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||
aabbConsumer.accept(AABB.fromInteraction(relativePosition, size.x, size.y));
|
||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, size.x, size.y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
||||
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.fromInteraction(vec3d, scale, shulkerHeight), vec3d, interactive));
|
||||
aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -102,7 +102,7 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
||||
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.fromInteraction(vec3d, scale, shulkerHeight), vec3d, interactive));
|
||||
aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -133,8 +133,8 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
||||
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.fromInteraction(vec3d1, scale, scale), vec3d1, interactive));
|
||||
aabb.accept(new FurnitureHitboxPart(entityIds[3], AABB.fromInteraction(vec3d2, scale, scale), vec3d2, interactive));
|
||||
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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4594,4 +4594,27 @@ public final class CoreReflections {
|
||||
throw new ReflectionInitException("Failed to init EmptyBlockGetter$INSTANCE", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$EntityDimensions = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.entity.EntitySize",
|
||||
"world.entity.EntityDimensions"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$EntityType$dimensions = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$EntityType, clazz$EntityDimensions, 0)
|
||||
);
|
||||
|
||||
public static final Field field$EntityDimensions$width = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$EntityDimensions, float.class, 0)
|
||||
);
|
||||
|
||||
public static final Field field$EntityDimensions$height = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$EntityDimensions, float.class, 1)
|
||||
);
|
||||
|
||||
public static final Field field$EntityDimensions$fixed = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$EntityDimensions, boolean.class, 0)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,12 +27,11 @@ items:
|
||||
translation: 0,0.5,0
|
||||
hitboxes:
|
||||
- position: 0,0,0
|
||||
type: interaction
|
||||
blocks-building: true
|
||||
type: custom
|
||||
entity-type: slime
|
||||
invisible: true
|
||||
width: 0.7
|
||||
height: 1.2
|
||||
interactive: true
|
||||
can-use-item-on: true
|
||||
blocks-building: true
|
||||
seats:
|
||||
- 0,0,-0.1 0
|
||||
loot:
|
||||
|
||||
@@ -57,7 +57,7 @@ public class AABB {
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
public static AABB fromInteraction(Vec3d pos, double width, double height) {
|
||||
public static AABB makeBoundingBox(Vec3d pos, double width, double height) {
|
||||
return new AABB(
|
||||
pos.x - width / 2,
|
||||
pos.y,
|
||||
|
||||
Reference in New Issue
Block a user