diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/ProjectileUtilMixin.java b/src/main/java/com/atsuishio/superbwarfare/mixins/ProjectileUtilMixin.java new file mode 100644 index 000000000..6f38c28c2 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/ProjectileUtilMixin.java @@ -0,0 +1,45 @@ +package com.atsuishio.superbwarfare.mixins; + +import com.atsuishio.superbwarfare.entity.OBBEntity; +import com.atsuishio.superbwarfare.tools.OBB; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.projectile.ProjectileUtil; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; +import java.util.function.Predicate; + +@Mixin(ProjectileUtil.class) +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) + 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) { + OBB obb = obbEntity.getOBB().inflate(pInflationAmount * 2); + + Optional optional = obb.clip(pStartVec.toVector3f(), pEndVec.toVector3f()); + if (optional.isPresent()) { + double d1 = pStartVec.distanceToSqr(new Vec3(optional.get())); + if (d1 < Double.MAX_VALUE) { + res = entity; + } + if (res != null) { + cir.setReturnValue(new EntityHitResult(res, new Vec3(optional.get()))); + } + } + } + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java b/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java index 06dc4bb54..5f75f683a 100644 --- a/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java +++ b/src/main/java/com/atsuishio/superbwarfare/tools/OBB.java @@ -185,14 +185,11 @@ public record OBB(Vector3f center, Vector3f extents, Quaternionf rotation) { } // 检查是否有有效交点 - if (tEnter >= 0 && tEnter <= 1) { - // 计算局部坐标系中的交点 - Vector3f localHit = new Vector3f(dir).mul((float) tEnter).add(localFrom); - // 转换回世界坐标系 - return Optional.of(localToWorld(localHit, axes)); - } + // 计算局部坐标系中的交点 + Vector3f localHit = new Vector3f(dir).mul((float) tEnter).add(localFrom); + // 转换回世界坐标系 + return Optional.of(localToWorld(localHit, axes)); - return Optional.empty(); } // 世界坐标转局部坐标 @@ -213,4 +210,14 @@ public record OBB(Vector3f center, Vector3f extents, Quaternionf rotation) { result.add(axes[2].mul(localPoint.z, new Vector3f())); return result; } + + public OBB inflate(float amount) { + Vector3f newExtents = new Vector3f(extents).add(amount, amount, amount); + return new OBB(center, newExtents, rotation); + } + + public OBB inflate(float x, float y, float z) { + Vector3f newExtents = new Vector3f(extents).add(x, y, z); + return new OBB(center, newExtents, rotation); + } } diff --git a/src/main/resources/mixins.superbwarfare.json b/src/main/resources/mixins.superbwarfare.json index d04d9c658..1c8e5175c 100644 --- a/src/main/resources/mixins.superbwarfare.json +++ b/src/main/resources/mixins.superbwarfare.json @@ -11,6 +11,7 @@ "LevelMixin", "LivingEntityMixin", "PlayerMixin", + "ProjectileUtilMixin", "VillagerMixin" ], "client": [