mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-18 11:13:44 +01:00
196 lines
5.2 KiB
Java
196 lines
5.2 KiB
Java
package com.simibubi.create.foundation.utility;
|
|
|
|
import java.util.function.Predicate;
|
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.util.Direction;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.BlockRayTraceResult;
|
|
import net.minecraft.util.math.MathHelper;
|
|
import net.minecraft.util.math.RayTraceContext;
|
|
import net.minecraft.util.math.RayTraceContext.BlockMode;
|
|
import net.minecraft.util.math.RayTraceContext.FluidMode;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraft.world.World;
|
|
|
|
public class RaycastHelper {
|
|
|
|
public static BlockRayTraceResult rayTraceRange(World worldIn, PlayerEntity playerIn, double range) {
|
|
Vec3d origin = getTraceOrigin(playerIn);
|
|
Vec3d target = getTraceTarget(playerIn, range, origin);
|
|
RayTraceContext context = new RayTraceContext(origin, target, BlockMode.COLLIDER, FluidMode.NONE, playerIn);
|
|
return worldIn.rayTraceBlocks(context);
|
|
}
|
|
|
|
public static PredicateTraceResult rayTraceUntil(PlayerEntity playerIn, double range,
|
|
Predicate<BlockPos> predicate) {
|
|
Vec3d origin = getTraceOrigin(playerIn);
|
|
Vec3d target = getTraceTarget(playerIn, range, origin);
|
|
return rayTraceUntil(origin, target, predicate);
|
|
}
|
|
|
|
public static Vec3d getTraceTarget(PlayerEntity playerIn, double range, Vec3d origin) {
|
|
float f = playerIn.rotationPitch;
|
|
float f1 = playerIn.rotationYaw;
|
|
float f2 = MathHelper.cos(-f1 * 0.017453292F - (float) Math.PI);
|
|
float f3 = MathHelper.sin(-f1 * 0.017453292F - (float) Math.PI);
|
|
float f4 = -MathHelper.cos(-f * 0.017453292F);
|
|
float f5 = MathHelper.sin(-f * 0.017453292F);
|
|
float f6 = f3 * f4;
|
|
float f7 = f2 * f4;
|
|
double d3 = range;
|
|
Vec3d vec3d1 = origin.add((double) f6 * d3, (double) f5 * d3, (double) f7 * d3);
|
|
return vec3d1;
|
|
}
|
|
|
|
public static Vec3d getTraceOrigin(PlayerEntity playerIn) {
|
|
double d0 = playerIn.getX();
|
|
double d1 = playerIn.getY() + (double) playerIn.getEyeHeight();
|
|
double d2 = playerIn.getZ();
|
|
Vec3d vec3d = new Vec3d(d0, d1, d2);
|
|
return vec3d;
|
|
}
|
|
|
|
public static PredicateTraceResult rayTraceUntil(Vec3d start, Vec3d end, Predicate<BlockPos> predicate) {
|
|
if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z))
|
|
return null;
|
|
if (Double.isNaN(end.x) || Double.isNaN(end.y) || Double.isNaN(end.z))
|
|
return null;
|
|
|
|
int dx = MathHelper.floor(end.x);
|
|
int dy = MathHelper.floor(end.y);
|
|
int dz = MathHelper.floor(end.z);
|
|
int x = MathHelper.floor(start.x);
|
|
int y = MathHelper.floor(start.y);
|
|
int z = MathHelper.floor(start.z);
|
|
|
|
BlockPos currentPos = new BlockPos(x, y, z);
|
|
|
|
if (predicate.test(currentPos))
|
|
return new PredicateTraceResult(currentPos, Direction.getFacingFromVector(dx - x, dy - y, dz - z));
|
|
|
|
int remainingDistance = 200;
|
|
|
|
while (remainingDistance-- >= 0) {
|
|
if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) {
|
|
return null;
|
|
}
|
|
|
|
if (x == dx && y == dy && z == dz) {
|
|
return new PredicateTraceResult();
|
|
}
|
|
|
|
boolean flag2 = true;
|
|
boolean flag = true;
|
|
boolean flag1 = true;
|
|
double d0 = 999.0D;
|
|
double d1 = 999.0D;
|
|
double d2 = 999.0D;
|
|
|
|
if (dx > x) {
|
|
d0 = (double) x + 1.0D;
|
|
} else if (dx < x) {
|
|
d0 = (double) x + 0.0D;
|
|
} else {
|
|
flag2 = false;
|
|
}
|
|
|
|
if (dy > y) {
|
|
d1 = (double) y + 1.0D;
|
|
} else if (dy < y) {
|
|
d1 = (double) y + 0.0D;
|
|
} else {
|
|
flag = false;
|
|
}
|
|
|
|
if (dz > z) {
|
|
d2 = (double) z + 1.0D;
|
|
} else if (dz < z) {
|
|
d2 = (double) z + 0.0D;
|
|
} else {
|
|
flag1 = false;
|
|
}
|
|
|
|
double d3 = 999.0D;
|
|
double d4 = 999.0D;
|
|
double d5 = 999.0D;
|
|
double d6 = end.x - start.x;
|
|
double d7 = end.y - start.y;
|
|
double d8 = end.z - start.z;
|
|
|
|
if (flag2) {
|
|
d3 = (d0 - start.x) / d6;
|
|
}
|
|
|
|
if (flag) {
|
|
d4 = (d1 - start.y) / d7;
|
|
}
|
|
|
|
if (flag1) {
|
|
d5 = (d2 - start.z) / d8;
|
|
}
|
|
|
|
if (d3 == -0.0D) {
|
|
d3 = -1.0E-4D;
|
|
}
|
|
|
|
if (d4 == -0.0D) {
|
|
d4 = -1.0E-4D;
|
|
}
|
|
|
|
if (d5 == -0.0D) {
|
|
d5 = -1.0E-4D;
|
|
}
|
|
|
|
Direction enumfacing;
|
|
|
|
if (d3 < d4 && d3 < d5) {
|
|
enumfacing = dx > x ? Direction.WEST : Direction.EAST;
|
|
start = new Vec3d(d0, start.y + d7 * d3, start.z + d8 * d3);
|
|
} else if (d4 < d5) {
|
|
enumfacing = dy > y ? Direction.DOWN : Direction.UP;
|
|
start = new Vec3d(start.x + d6 * d4, d1, start.z + d8 * d4);
|
|
} else {
|
|
enumfacing = dz > z ? Direction.NORTH : Direction.SOUTH;
|
|
start = new Vec3d(start.x + d6 * d5, start.y + d7 * d5, d2);
|
|
}
|
|
|
|
x = MathHelper.floor(start.x) - (enumfacing == Direction.EAST ? 1 : 0);
|
|
y = MathHelper.floor(start.y) - (enumfacing == Direction.UP ? 1 : 0);
|
|
z = MathHelper.floor(start.z) - (enumfacing == Direction.SOUTH ? 1 : 0);
|
|
currentPos = new BlockPos(x, y, z);
|
|
|
|
if (predicate.test(currentPos))
|
|
return new PredicateTraceResult(currentPos, enumfacing);
|
|
}
|
|
|
|
return new PredicateTraceResult();
|
|
}
|
|
|
|
public static class PredicateTraceResult {
|
|
private BlockPos pos;
|
|
private Direction facing;
|
|
|
|
public PredicateTraceResult(BlockPos pos, Direction facing) {
|
|
this.pos = pos;
|
|
this.facing = facing;
|
|
}
|
|
|
|
public PredicateTraceResult() {
|
|
// missed, no result
|
|
}
|
|
|
|
public Direction getFacing() {
|
|
return facing;
|
|
}
|
|
|
|
public BlockPos getPos() {
|
|
return pos;
|
|
}
|
|
|
|
public boolean missed() {
|
|
return this.pos == null;
|
|
}
|
|
}
|
|
|
|
}
|