mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-26 10:29:20 +00:00
feat(entity): 初步实现快乐恶魂碰撞箱
This commit is contained in:
@@ -1,15 +1,21 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture.hitbox;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.entity.data.HappyGhastData;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitCollider;
|
||||
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.MEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
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.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
@@ -17,10 +23,16 @@ import java.util.function.Supplier;
|
||||
public class HappyGhastHitBox extends AbstractHitBox {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final double scale;
|
||||
private final boolean hardCollision;
|
||||
private final List<Object> cachedValues = new ArrayList<>();
|
||||
|
||||
public HappyGhastHitBox(Seat[] seats, Vector3f position, double scale, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile) {
|
||||
public HappyGhastHitBox(Seat[] seats, Vector3f position, double scale, boolean canUseOn, boolean blocksBuilding, boolean canBeHitByProjectile, boolean hardCollision) {
|
||||
super(seats, position, canUseOn, blocksBuilding, canBeHitByProjectile);
|
||||
this.scale = scale;
|
||||
this.hardCollision = hardCollision;
|
||||
HappyGhastData.StaysStill.addEntityDataIfNotDefaultValue(hardCollision, this.cachedValues);
|
||||
HappyGhastData.MobFlags.addEntityDataIfNotDefaultValue((byte) 0x01, this.cachedValues); // NO AI
|
||||
HappyGhastData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, this.cachedValues); // Invisible
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,12 +44,62 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public boolean hardCollision() {
|
||||
return hardCollision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
||||
public void initPacketsAndColliders(int[] entityIds, WorldPosition position, Quaternionf conjugated, BiConsumer<Object, Boolean> packets, Consumer<Collider> collider, BiConsumer<Integer, AABB> aabb) {
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
try {
|
||||
double x = position.x();
|
||||
double y = position.y();
|
||||
double z = position.z();
|
||||
float yaw = position.xRot();
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||
entityIds[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw,
|
||||
MEntityTypes.HAPPY_GHAST, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||
), true);
|
||||
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[0], List.copyOf(this.cachedValues)), true);
|
||||
if (VersionHelper.isOrAbove1_20_5() && this.scale != 1) {
|
||||
Object attributeInstance = CoreReflections.constructor$AttributeInstance.newInstance(MAttributeHolders.SCALE, (Consumer<?>) (o) -> {});
|
||||
CoreReflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, this.scale);
|
||||
packets.accept(NetworkReflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityIds[0], Collections.singletonList(attributeInstance)), false);
|
||||
}
|
||||
if (this.hardCollision) {
|
||||
collider.accept(this.createCollider(position.world(), offset, x, y, z, entityIds[0], aabb));
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to construct custom hitbox spawn packet", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collider createCollider(World world, Vector3f offset, double x, double y, double z, int entityId, BiConsumer<Integer, AABB> aabb) {
|
||||
AABB ceAABB = createAABB(offset, x, y, z);
|
||||
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(level, nmsAABB, x, y, z, this.canBeHitByProjectile(), true, this.blocksBuilding());
|
||||
}
|
||||
|
||||
public AABB createAABB(Vector3f offset, double x, double y, double z) {
|
||||
double baseSize = 4.0 * this.scale;
|
||||
double halfSize = baseSize * 0.5;
|
||||
double minX = x - halfSize + offset.x();
|
||||
double maxX = x + halfSize + offset.x();
|
||||
double minY = y + offset.y();
|
||||
double maxY = y + baseSize + offset.y();
|
||||
double minZ = z - halfSize + offset.z();
|
||||
double maxZ = z + halfSize + offset.z();
|
||||
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initShapeForPlacement(double x, double y, double z, float yaw, Quaternionf conjugated, Consumer<AABB> aabbs) {
|
||||
if (!this.hardCollision) return;
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
AABB aabb = createAABB(offset, x, y, z);
|
||||
aabbs.accept(aabb);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,14 +111,18 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
||||
|
||||
@Override
|
||||
public HitBox create(Map<String, Object> arguments) {
|
||||
if (!VersionHelper.isOrAbove1_21_6()) {
|
||||
throw new UnsupportedOperationException("HappyGhastHitBox is only supported on 1.21.6+");
|
||||
}
|
||||
double scale = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("scale", 1), "scale");
|
||||
boolean hardCollision = (boolean) arguments.getOrDefault("hard-collision", false);
|
||||
boolean canUseOn = (boolean) arguments.getOrDefault("can-use-item-on", false);
|
||||
boolean canBeHitByProjectile = (boolean) arguments.getOrDefault("can-be-hit-by-projectile", false);
|
||||
boolean blocksBuilding = (boolean) arguments.getOrDefault("blocks-building", false);
|
||||
return new HappyGhastHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
MiscUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position"),
|
||||
scale, canUseOn, blocksBuilding, canBeHitByProjectile
|
||||
scale, canUseOn, blocksBuilding, canBeHitByProjectile, hardCollision
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,4 +123,16 @@ public class AABB {
|
||||
private static boolean isWithinBounds(double value, double min, double max) {
|
||||
return (value >= min - EPSILON) && (value <= max + EPSILON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AABB{" +
|
||||
"minX=" + minX +
|
||||
", minY=" + minY +
|
||||
", minZ=" + minZ +
|
||||
", maxX=" + maxX +
|
||||
", maxY=" + maxY +
|
||||
", maxZ=" + maxZ +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user