2025-11-24 22:52:51 +03:00

224 lines
11 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.mojang.datafixers.util.Either
* org.jspecify.annotations.Nullable
*/
package net.minecraft.world.entity.projectile;
import com.mojang.datafixers.util.Either;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.item.ArrowItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import org.jspecify.annotations.Nullable;
public final class ProjectileUtil {
public static final float DEFAULT_ENTITY_HIT_RESULT_MARGIN = 0.3f;
public static HitResult getHitResultOnMoveVector(Entity source, Predicate<Entity> matching) {
Vec3 movement = source.getDeltaMovement();
Level level = source.level();
Vec3 from = source.position();
return ProjectileUtil.getHitResult(from, source, matching, movement, level, ProjectileUtil.computeMargin(source), ClipContext.Block.COLLIDER);
}
public static Collection<EntityHitResult> getHitEntitiesAlong(LivingEntity jabber, float minReach, float maxReach, float margin, Predicate<Entity> matching) {
Vec3 look = jabber.getHeadLookAngle();
Vec3 eyePosition = jabber.getEyePosition();
Vec3 from = eyePosition.add(look.scale(minReach));
double movementComponent = jabber.getKnownMovement().dot(look);
Vec3 to = eyePosition.add(look.scale((double)maxReach + Math.max(0.0, movementComponent)));
return (Collection)ProjectileUtil.getHitEntitiesAlong(jabber, eyePosition, from, matching, to, margin, ClipContext.Block.COLLIDER).map(a -> List.of(), e -> e);
}
public static HitResult getHitResultOnMoveVector(Entity source, Predicate<Entity> matching, ClipContext.Block clipType) {
Vec3 movement = source.getDeltaMovement();
Level level = source.level();
Vec3 from = source.position();
return ProjectileUtil.getHitResult(from, source, matching, movement, level, ProjectileUtil.computeMargin(source), clipType);
}
public static HitResult getHitResultOnViewVector(Entity source, Predicate<Entity> matching, double distance) {
Vec3 viewVector = source.getViewVector(0.0f).scale(distance);
Level level = source.level();
Vec3 from = source.getEyePosition();
return ProjectileUtil.getHitResult(from, source, matching, viewVector, level, 0.0f, ClipContext.Block.COLLIDER);
}
private static HitResult getHitResult(Vec3 from, Entity source, Predicate<Entity> matching, Vec3 delta, Level level, float entityMargin, ClipContext.Block clipType) {
EntityHitResult entityHit;
Vec3 to = from.add(delta);
HitResult hitResult = level.clipIncludingBorder(new ClipContext(from, to, clipType, ClipContext.Fluid.NONE, source));
if (((HitResult)hitResult).getType() != HitResult.Type.MISS) {
to = hitResult.getLocation();
}
if ((entityHit = ProjectileUtil.getEntityHitResult(level, source, from, to, source.getBoundingBox().expandTowards(delta).inflate(1.0), matching, entityMargin)) != null) {
hitResult = entityHit;
}
return hitResult;
}
private static Either<BlockHitResult, Collection<EntityHitResult>> getHitEntitiesAlong(Entity source, Vec3 origin, Vec3 from, Predicate<Entity> matching, Vec3 to, float entityMargin, ClipContext.Block clipType) {
Level level = source.level();
BlockHitResult hitResult = level.clipIncludingBorder(new ClipContext(origin, to, clipType, ClipContext.Fluid.NONE, source));
if (hitResult.getType() != HitResult.Type.MISS && origin.distanceToSqr(to = hitResult.getLocation()) < origin.distanceToSqr(from)) {
return Either.left((Object)hitResult);
}
AABB searchArea = AABB.ofSize(from, entityMargin, entityMargin, entityMargin).expandTowards(to.subtract(from)).inflate(1.0);
Collection<EntityHitResult> entityHit = ProjectileUtil.getManyEntityHitResult(level, source, from, to, searchArea, matching, entityMargin, clipType, true);
if (!entityHit.isEmpty()) {
return Either.right(entityHit);
}
return Either.left((Object)hitResult);
}
public static @Nullable EntityHitResult getEntityHitResult(Entity except, Vec3 from, Vec3 to, AABB box, Predicate<Entity> matching, double maxValue) {
Level level = except.level();
double nearest = maxValue;
Entity hovered = null;
Vec3 hoveredPos = null;
for (Entity entity : level.getEntities(except, box, matching)) {
Vec3 location;
double dd;
AABB bb = entity.getBoundingBox().inflate(entity.getPickRadius());
Optional<Vec3> clipPoint = bb.clip(from, to);
if (bb.contains(from)) {
if (!(nearest >= 0.0)) continue;
hovered = entity;
hoveredPos = clipPoint.orElse(from);
nearest = 0.0;
continue;
}
if (!clipPoint.isPresent() || !((dd = from.distanceToSqr(location = clipPoint.get())) < nearest) && nearest != 0.0) continue;
if (entity.getRootVehicle() == except.getRootVehicle()) {
if (nearest != 0.0) continue;
hovered = entity;
hoveredPos = location;
continue;
}
hovered = entity;
hoveredPos = location;
nearest = dd;
}
if (hovered == null) {
return null;
}
return new EntityHitResult(hovered, hoveredPos);
}
public static @Nullable EntityHitResult getEntityHitResult(Level level, Projectile source, Vec3 from, Vec3 to, AABB targetSearchArea, Predicate<Entity> matching) {
return ProjectileUtil.getEntityHitResult(level, source, from, to, targetSearchArea, matching, ProjectileUtil.computeMargin(source));
}
public static float computeMargin(Entity source) {
return Math.max(0.0f, Math.min(0.3f, (float)(source.tickCount - 2) / 20.0f));
}
public static @Nullable EntityHitResult getEntityHitResult(Level level, Entity source, Vec3 from, Vec3 to, AABB targetSearchArea, Predicate<Entity> matching, float entityMargin) {
double nearest = Double.MAX_VALUE;
Optional<Object> nearestLocation = Optional.empty();
Entity hitEntity = null;
for (Entity entity : level.getEntities(source, targetSearchArea, matching)) {
double dd;
AABB bb = entity.getBoundingBox().inflate(entityMargin);
Optional<Vec3> location = bb.clip(from, to);
if (!location.isPresent() || !((dd = from.distanceToSqr(location.get())) < nearest)) continue;
hitEntity = entity;
nearest = dd;
nearestLocation = location;
}
if (hitEntity == null) {
return null;
}
return new EntityHitResult(hitEntity, (Vec3)nearestLocation.get());
}
public static Collection<EntityHitResult> getManyEntityHitResult(Level level, Entity source, Vec3 from, Vec3 to, AABB targetSearchArea, Predicate<Entity> matching, boolean includeFromEntity) {
return ProjectileUtil.getManyEntityHitResult(level, source, from, to, targetSearchArea, matching, ProjectileUtil.computeMargin(source), ClipContext.Block.COLLIDER, includeFromEntity);
}
public static Collection<EntityHitResult> getManyEntityHitResult(Level level, Entity source, Vec3 from, Vec3 to, AABB targetSearchArea, Predicate<Entity> matching, float entityMargin, ClipContext.Block clipType, boolean includeFromEntity) {
ArrayList<EntityHitResult> collector = new ArrayList<EntityHitResult>();
for (Entity entity : level.getEntities(source, targetSearchArea, matching)) {
Optional<Vec3> surfaceHit;
Vec3 towardsTarget;
Optional<Vec3> outsideHit;
AABB entityBB = entity.getBoundingBox();
if (includeFromEntity && entityBB.contains(from)) {
collector.add(new EntityHitResult(entity, from));
continue;
}
Optional<Vec3> exactHit = entityBB.clip(from, to);
if (exactHit.isPresent()) {
collector.add(new EntityHitResult(entity, exactHit.get()));
continue;
}
if ((double)entityMargin <= 0.0 || (outsideHit = entityBB.inflate(entityMargin).clip(from, to)).isEmpty()) continue;
Vec3 outsideHitPosition = outsideHit.get();
BlockHitResult hitResult = level.clipIncludingBorder(new ClipContext(outsideHitPosition, towardsTarget = entityBB.getCenter(), clipType, ClipContext.Fluid.NONE, source));
if (hitResult.getType() != HitResult.Type.MISS) {
towardsTarget = hitResult.getLocation();
}
if (!(surfaceHit = entity.getBoundingBox().clip(outsideHitPosition, towardsTarget)).isPresent()) continue;
collector.add(new EntityHitResult(entity, surfaceHit.get()));
}
return collector;
}
public static void rotateTowardsMovement(Entity projectile, float rotationSpeed) {
Vec3 movement = projectile.getDeltaMovement();
if (movement.lengthSqr() == 0.0) {
return;
}
double sd = movement.horizontalDistance();
projectile.setYRot((float)(Mth.atan2(movement.z, movement.x) * 57.2957763671875) + 90.0f);
projectile.setXRot((float)(Mth.atan2(sd, movement.y) * 57.2957763671875) - 90.0f);
while (projectile.getXRot() - projectile.xRotO < -180.0f) {
projectile.xRotO -= 360.0f;
}
while (projectile.getXRot() - projectile.xRotO >= 180.0f) {
projectile.xRotO += 360.0f;
}
while (projectile.getYRot() - projectile.yRotO < -180.0f) {
projectile.yRotO -= 360.0f;
}
while (projectile.getYRot() - projectile.yRotO >= 180.0f) {
projectile.yRotO += 360.0f;
}
projectile.setXRot(Mth.lerp(rotationSpeed, projectile.xRotO, projectile.getXRot()));
projectile.setYRot(Mth.lerp(rotationSpeed, projectile.yRotO, projectile.getYRot()));
}
public static InteractionHand getWeaponHoldingHand(LivingEntity mob, Item weaponItem) {
return mob.getMainHandItem().is(weaponItem) ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
}
public static AbstractArrow getMobArrow(LivingEntity mob, ItemStack projectile, float power, @Nullable ItemStack firedFromWeapon) {
ArrowItem arrowItem = (ArrowItem)(projectile.getItem() instanceof ArrowItem ? projectile.getItem() : Items.ARROW);
AbstractArrow arrow = arrowItem.createArrow(mob.level(), projectile, mob, firedFromWeapon);
arrow.setBaseDamageFromMob(power);
return arrow;
}
}