Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 53 additions & 93 deletions src/main/java/net/torocraft/torohealth/util/RayTrace.java
Original file line number Diff line number Diff line change
@@ -1,120 +1,80 @@
package net.torocraft.torohealth.util;

import java.util.function.Predicate;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileUtil;
import net.minecraft.fluid.FluidState;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.hit.HitResult.Type;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.World;
import net.minecraft.world.BlockView;
import net.minecraft.world.RaycastContext;
import net.minecraft.world.RaycastContext.FluidHandling;

public class RayTrace implements BlockView {
private static Predicate<Entity> isVisible = entity -> !entity.isSpectator() && entity.collides();
private static MinecraftClient minecraft = MinecraftClient.getInstance();

@Override
public BlockEntity getBlockEntity(BlockPos pos) {
return minecraft.world.getBlockEntity(pos);
}

@Override
public BlockState getBlockState(BlockPos pos) {
return minecraft.world.getBlockState(pos);
}

@Override
public FluidState getFluidState(BlockPos pos) {
return minecraft.world.getFluidState(pos);
}

public LivingEntity getEntityInCrosshair(float partialTicks, double reachDistance) {
MinecraftClient client = MinecraftClient.getInstance();
Entity viewer = client.getCameraEntity();
public class RayTrace {
// modified from minecraft.client.render.GameRender.updateTargetedEntity
public LivingEntity getEntityInCrosshair(float tickDelta, float reachDistance) {
MinecraftClient client = MinecraftClient.getInstance();
Entity entity2 = client.getCameraEntity();
if (entity2 == null) {
return null;
}
if (client.world == null) {
return null;
}
HitResult crosshairTarget = this.raycastEntity(entity2, reachDistance, tickDelta, false);
Vec3d vec3d = entity2.getCameraPosVec(tickDelta);
double e = reachDistance;

if (viewer == null) {
return null;
e *= e;
if (crosshairTarget != null) {
e = crosshairTarget.getPos().squaredDistanceTo(vec3d);
}
Vec3d vec3d2 = entity2.getRotationVec(1.0f);
Vec3d vec3d3 = vec3d.add(vec3d2.x * reachDistance, vec3d2.y * reachDistance, vec3d2.z * reachDistance);
Box box = entity2.getBoundingBox().stretch(vec3d2.multiply(reachDistance)).expand(1.0, 1.0, 1.0);
EntityHitResult entityHitResult = ProjectileUtil.raycast(entity2, vec3d, vec3d3, box, entity -> !entity.isSpectator() && entity.collides(), e);
if (entityHitResult != null) {
Entity entity22 = entityHitResult.getEntity();
Vec3d vec3d4 = entityHitResult.getPos();
double g = vec3d.squaredDistanceTo(vec3d4);
if (g < e || crosshairTarget == null) {
if (entity22 instanceof LivingEntity) {
return (LivingEntity) entity22;
}
}
}
return null;
}

Vec3d position = viewer.getCameraPosVec(partialTicks);
Vec3d look = viewer.getRotationVec(1.0F);
Vec3d max = position.add(look.x * reachDistance, look.y * reachDistance, look.z * reachDistance);
Box searchBox = viewer.getBoundingBox().stretch(look.multiply(reachDistance)).expand(1.0D, 1.0D, 1.0D);

EntityHitResult result = ProjectileUtil.raycast(viewer, position, max, searchBox, isVisible, reachDistance * reachDistance);

if (result == null || result.getEntity() == null) {
return null;
// modified from net.minecraft.entity.Entity.raycast, adding ignore opaque blocks feature
private BlockHitResult raycastEntity(Entity entity, double maxDistance, float tickDelta, boolean includeFluids) {
Vec3d vec3d = entity.getCameraPosVec(tickDelta);
Vec3d vec3d2 = entity.getRotationVec(tickDelta);
Vec3d vec3d3 = vec3d.add(vec3d2.x * maxDistance, vec3d2.y * maxDistance, vec3d2.z * maxDistance);
return raycastBlockView(entity.world, new RaycastContext(vec3d, vec3d3, RaycastContext.ShapeType.OUTLINE, includeFluids ? RaycastContext.FluidHandling.ANY : RaycastContext.FluidHandling.NONE, entity));
}

if (result.getEntity() instanceof LivingEntity) {
LivingEntity target = (LivingEntity) result.getEntity();

HitResult blockHit = raycast(setupRayTraceContext(client.player, reachDistance, FluidHandling.NONE));

if (!blockHit.getType().equals(Type.MISS)) {
double blockDistance = blockHit.getPos().distanceTo(position);
if (blockDistance > target.distanceTo(client.player)) {
return target;
}
} else {
return target;
}
private BlockHitResult raycastBlockView(World world, RaycastContext context) {
return BlockView.raycast(context.getStart(), context.getEnd(), context, (c, pos) -> {
BlockState block = world.getBlockState(pos);
if (!block.isOpaque()) {
return null;
}
VoxelShape blockShape = c.getBlockShape(block, world, pos);
return world.raycastBlock(c.getStart(), c.getEnd(), pos, blockShape, block);
}, (c) -> {
Vec3d v = c.getStart().subtract(c.getEnd());
return BlockHitResult.createMissed(c.getEnd(), Direction.getFacing(v.x, v.y, v.z), new BlockPos(c.getEnd()));
});
}

return null;
}

private RaycastContext setupRayTraceContext(PlayerEntity player, double distance, RaycastContext.FluidHandling fluidHandling) {
float pitch = player.getPitch();
float yaw = player.getYaw();
Vec3d fromPos = player.getCameraPosVec(1.0F);
float float_3 = MathHelper.cos(-yaw * 0.017453292F - 3.1415927F);
float float_4 = MathHelper.sin(-yaw * 0.017453292F - 3.1415927F);
float float_5 = -MathHelper.cos(-pitch * 0.017453292F);
float xComponent = float_4 * float_5;
float yComponent = MathHelper.sin(-pitch * 0.017453292F);
float zComponent = float_3 * float_5;
Vec3d toPos = fromPos.add((double)xComponent * distance, (double)yComponent * distance, (double)zComponent * distance);
return new RaycastContext(fromPos, toPos, RaycastContext.ShapeType.OUTLINE, fluidHandling, player);
}

@Override
public BlockHitResult raycast(RaycastContext context) {
return BlockView.raycast(context.getStart(), context.getEnd(), context, (c, pos) -> {
BlockState block = this.getBlockState(pos);
if (!block.isOpaque()) {
return null;
}
VoxelShape blockShape = c.getBlockShape(block, this, pos);
return this.raycastBlock(c.getStart(), c.getEnd(), pos, blockShape, block);
}, (c) -> {
Vec3d v = c.getStart().subtract(c.getEnd());
return BlockHitResult.createMissed(c.getEnd(), Direction.getFacing(v.x, v.y, v.z), new BlockPos(c.getEnd()));
});
}

@Override
public int getBottomY() {
return 0;
}

@Override
public int getHeight() {
return 0;
}
}
}