From 50eb2a4078b35935a407ae91bce16ca8b472d3d6 Mon Sep 17 00:00:00 2001 From: 17146 <1714673995@qq.com> Date: Mon, 16 Jun 2025 00:05:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9B=B4=E5=A4=9Amixin?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mixins/ProjectileUtilMixin.java | 44 ++++++++++++++++--- .../atsuishio/superbwarfare/tools/OBB.java | 26 +++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/ProjectileUtilMixin.java b/src/main/java/com/atsuishio/superbwarfare/mixins/ProjectileUtilMixin.java index 8a921a41f..2cd667863 100644 --- a/src/main/java/com/atsuishio/superbwarfare/mixins/ProjectileUtilMixin.java +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/ProjectileUtilMixin.java @@ -22,10 +22,8 @@ import java.util.function.Predicate; public class ProjectileUtilMixin { @Inject(method = "getEntityHitResult(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;F)Lnet/minecraft/world/phys/EntityHitResult;", - at = @At("RETURN"), cancellable = true) + at = @At("HEAD"), cancellable = true) private static void getEntityHitResult(Level pLevel, Entity pProjectile, Vec3 pStartVec, Vec3 pEndVec, AABB pBoundingBox, Predicate pFilter, float pInflationAmount, CallbackInfoReturnable cir) { - Entity res = null; - for (var entity : pLevel.getEntities(pProjectile, pBoundingBox, pFilter)) { if (entity instanceof OBBEntity obbEntity) { if (pProjectile instanceof Projectile projectile && @@ -38,10 +36,44 @@ public class ProjectileUtilMixin { if (optional.isPresent()) { double d1 = pStartVec.distanceToSqr(new Vec3(optional.get())); if (d1 < Double.MAX_VALUE) { - res = entity; + cir.setReturnValue(new EntityHitResult(entity, new Vec3(optional.get()))); } - if (res != null) { - cir.setReturnValue(new EntityHitResult(res, new Vec3(optional.get()))); + } + } + } + } + + @Inject(method = "getEntityHitResult(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;D)Lnet/minecraft/world/phys/EntityHitResult;", + at = @At("HEAD"), cancellable = true) + private static void getEntityHitResult(Entity pShooter, Vec3 pStartVec, Vec3 pEndVec, AABB pBoundingBox, Predicate pFilter, double pDistance, CallbackInfoReturnable cir) { + Level level = pShooter.level(); + + for (Entity entity : level.getEntities(pShooter, pBoundingBox, pFilter)) { + if (entity instanceof OBBEntity obbEntity) { + if (entity.getPassengers().contains(pShooter)) { + continue; + } + + OBB obb = obbEntity.getOBB().inflate(entity.getPickRadius() * 2); + Optional optional = obb.clip(pStartVec.toVector3f(), pEndVec.toVector3f()); + if (obb.contains(pStartVec)) { + if (pDistance >= 0D) { + cir.setReturnValue(new EntityHitResult(entity, new Vec3(optional.orElse(pStartVec.toVector3f())))); + return; + } + } else if (optional.isPresent()) { + var vec = new Vec3(optional.get()); + double d1 = pStartVec.distanceToSqr(vec); + if (d1 < pDistance || pDistance == 0.0D) { + if (entity.getRootVehicle() == pShooter.getRootVehicle() && !entity.canRiderInteract()) { + if (pDistance == 0.0D) { + cir.setReturnValue(new EntityHitResult(entity, vec)); + return; + } + } else { + cir.setReturnValue(new EntityHitResult(entity, vec)); + return; + } } } } diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java b/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java index 5f75f683a..a0260fc6b 100644 --- a/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java +++ b/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java @@ -1,6 +1,7 @@ package com.atsuishio.superbwarfare.tools; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import org.joml.Intersectionf; import org.joml.Math; import org.joml.Quaternionf; @@ -220,4 +221,29 @@ public record OBB(Vector3f center, Vector3f extents, Quaternionf rotation) { Vector3f newExtents = new Vector3f(extents).add(x, y, z); return new OBB(center, newExtents, rotation); } + + /** + * 检查点是否在OBB内部 + * + * @return 如果点在OBB内部则返回true,否则返回false + */ + public boolean contains(Vec3 vec3) { + // 计算点到OBB中心的向量 + Vector3f rel = new Vector3f(vec3.toVector3f()).sub(center); + + Vector3f[] axes = new Vector3f[3]; + axes[0] = rotation.transform(new Vector3f(1, 0, 0)); + axes[1] = rotation.transform(new Vector3f(0, 1, 0)); + axes[2] = rotation.transform(new Vector3f(0, 0, 1)); + + // 将相对向量投影到OBB的三个轴上 + float projX = Math.abs(rel.dot(axes[0])); + float projY = Math.abs(rel.dot(axes[1])); + float projZ = Math.abs(rel.dot(axes[2])); + + // 检查投影值是否小于对应轴上的半长 + return projX <= extents.x && + projY <= extents.y && + projZ <= extents.z; + } }