mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Clean up raytracing
This commit is contained in:
parent
ac74b1fbd3
commit
ea34a93bbc
9 changed files with 200 additions and 211 deletions
|
@ -3,9 +3,7 @@ package com.minelittlepony.unicopia.ability;
|
|||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket;
|
||||
|
@ -38,15 +36,9 @@ public class CarryAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
protected LivingEntity findRider(PlayerEntity player, World w) {
|
||||
Entity hit = VecHelper.getLookedAtEntity(player, 10);
|
||||
|
||||
if (hit instanceof LivingEntity && !player.isConnectedThroughVehicle(hit)) {
|
||||
if (!(hit instanceof IPickupImmuned)) {
|
||||
return (LivingEntity)hit;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return RayTraceHelper.<LivingEntity>findEntity(player, 10, 1, hit -> {
|
||||
return hit instanceof LivingEntity && !player.isConnectedThroughVehicle(hit) && !(hit instanceof IPickupImmuned);
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,19 +8,14 @@ import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell;
|
|||
import com.minelittlepony.unicopia.entity.behaviour.Disguise;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.FallingBlockEntity;
|
||||
import net.minecraft.entity.LightningEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* Changeling ability to disguise themselves as other players.
|
||||
|
@ -36,33 +31,21 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
|
|||
@Override
|
||||
public void apply(Pony iplayer, Hit data) {
|
||||
PlayerEntity player = iplayer.getOwner();
|
||||
HitResult trace = VecHelper.getObjectMouseOver(player, 10, 1);
|
||||
|
||||
Entity looked = null;
|
||||
|
||||
if (trace.getType() == HitResult.Type.BLOCK) {
|
||||
BlockPos pos = ((BlockHitResult)trace).getBlockPos();
|
||||
RayTraceHelper.Trace trace = RayTraceHelper.doTrace(player, 10, 1, EntityPredicates.EXCEPT_SPECTATOR.and(e -> !(e instanceof LightningEntity)));
|
||||
|
||||
Entity looked = trace.getEntity().map(e -> {
|
||||
return e instanceof PlayerEntity ? Pony.of((PlayerEntity)e)
|
||||
.getSpellOrEmpty(DisguiseSpell.class)
|
||||
.map(DisguiseSpell::getDisguise)
|
||||
.map(Disguise::getAppearance)
|
||||
.orElse(e) : e;
|
||||
}).orElseGet(() -> trace.getBlockPos().map(pos -> {
|
||||
if (!iplayer.getWorld().isAir(pos)) {
|
||||
BlockState state = iplayer.getWorld().getBlockState(pos);
|
||||
|
||||
looked = new FallingBlockEntity(player.getEntityWorld(), 0, 0, 0, state);
|
||||
return new FallingBlockEntity(player.getEntityWorld(), 0, 0, 0, iplayer.getWorld().getBlockState(pos));
|
||||
}
|
||||
} else if (trace.getType() == HitResult.Type.ENTITY) {
|
||||
looked = ((EntityHitResult)trace).getEntity();
|
||||
|
||||
if (looked instanceof PlayerEntity) {
|
||||
looked = Pony.of((PlayerEntity)looked)
|
||||
.getSpellOrEmpty(DisguiseSpell.class)
|
||||
.map(DisguiseSpell::getDisguise)
|
||||
.map(Disguise::getAppearance)
|
||||
.orElse(looked);
|
||||
}
|
||||
|
||||
if (looked instanceof LightningEntity) {
|
||||
looked = null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}).orElse(null));
|
||||
|
||||
player.getEntityWorld().playSound(null, player.getBlockPos(), SoundEvents.ENTITY_PARROT_IMITATE_RAVAGER, SoundCategory.PLAYERS, 1.4F, 0.4F);
|
||||
|
||||
|
@ -72,8 +55,8 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
|
|||
iplayer.setSpell(disc);
|
||||
return disc;
|
||||
}).setDisguise(looked);
|
||||
player.calculateDimensions();
|
||||
|
||||
player.calculateDimensions();
|
||||
iplayer.setDirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
|||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -78,12 +79,11 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
protected List<LivingEntity> getTargets(Pony player) {
|
||||
List<Entity> list = VecHelper.getWithinRange(player.getOwner(), 3, this::canDrain);
|
||||
List<Entity> list = VecHelper.getWithinReach(player.getOwner(), 3, this::canDrain);
|
||||
|
||||
Entity looked = VecHelper.getLookedAtEntity(player.getOwner(), 17);
|
||||
if (looked != null && !list.contains(looked) && canDrain(looked)) {
|
||||
list.add(looked);
|
||||
}
|
||||
RayTraceHelper.<LivingEntity>findEntity(player.getOwner(), 17, 1,
|
||||
looked -> looked instanceof LivingEntity && !list.contains(looked) && canDrain(looked))
|
||||
.ifPresent(list::add);
|
||||
|
||||
return list.stream().map(i -> (LivingEntity)i).collect(Collectors.toList());
|
||||
}
|
||||
|
|
|
@ -5,14 +5,11 @@ import com.minelittlepony.unicopia.ability.data.Hit;
|
|||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.BoneMealItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -39,13 +36,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
|
||||
@Override
|
||||
public Pos tryActivate(Pony player) {
|
||||
HitResult ray = VecHelper.getObjectMouseOver(player.getOwner(), 3, 1);
|
||||
|
||||
if (ray instanceof BlockHitResult && ray.getType() == HitResult.Type.BLOCK) {
|
||||
return new Pos(((BlockHitResult)ray).getBlockPos());
|
||||
}
|
||||
|
||||
return null;
|
||||
return RayTraceHelper.doTrace(player.getOwner(), 3, 1).getBlockPos().map(Pos::new).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.ability;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -14,7 +15,7 @@ import com.minelittlepony.unicopia.ability.data.Multi;
|
|||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||
import com.minelittlepony.unicopia.util.PosHelper;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
import com.minelittlepony.unicopia.util.WorldEvent;
|
||||
import com.minelittlepony.unicopia.util.shape.Shape;
|
||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||
|
@ -31,8 +32,6 @@ import net.minecraft.entity.player.PlayerEntity;
|
|||
import net.minecraft.particle.BlockStateParticleEffect;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
@ -70,10 +69,10 @@ public class EarthPonyStompAbility implements Ability<Multi> {
|
|||
@Nullable
|
||||
@Override
|
||||
public Multi tryActivate(Pony player) {
|
||||
HitResult mop = VecHelper.getObjectMouseOver(player.getOwner(), 6, 1);
|
||||
Optional<BlockPos> p = RayTraceHelper.doTrace(player.getOwner(), 6, 1).getBlockPos();
|
||||
|
||||
if (mop instanceof BlockHitResult && mop.getType() == HitResult.Type.BLOCK) {
|
||||
BlockPos pos = ((BlockHitResult)mop).getBlockPos();
|
||||
if (p.isPresent()) {
|
||||
BlockPos pos = p.get();
|
||||
BlockState state = player.getWorld().getBlockState(pos);
|
||||
|
||||
if (state.getBlock().isIn(BlockTags.LOGS)) {
|
||||
|
|
|
@ -5,8 +5,7 @@ import com.minelittlepony.unicopia.ability.data.Hit;
|
|||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FenceBlock;
|
||||
|
@ -15,6 +14,7 @@ import net.minecraft.block.WallBlock;
|
|||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
|
@ -45,7 +45,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
|
||||
@Override
|
||||
public Pos tryActivate(Pony player) {
|
||||
HitResult ray = VecHelper.getObjectMouseOver(player.getOwner(), 100, 1);
|
||||
HitResult ray = RayTraceHelper.doTrace(player.getOwner(), 100, 1, EntityPredicates.EXCEPT_SPECTATOR).getResult();
|
||||
|
||||
World w = player.getWorld();
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package com.minelittlepony.unicopia.item;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
import com.minelittlepony.unicopia.item.toxin.Toxicity;
|
||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LightningEntity;
|
||||
|
@ -18,6 +19,7 @@ import net.minecraft.item.Item;
|
|||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
@ -25,8 +27,6 @@ import net.minecraft.util.Hand;
|
|||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Rarity;
|
||||
import net.minecraft.util.TypedActionResult;
|
||||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
|
@ -38,16 +38,12 @@ public class ZapAppleItem extends AppleItem {
|
|||
|
||||
@Override
|
||||
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
||||
HitResult mop = VecHelper.getObjectMouseOver(player, 5, 0);
|
||||
ItemStack stack = player.getStackInHand(hand);
|
||||
|
||||
if (mop != null && mop.getType() == HitResult.Type.ENTITY) {
|
||||
ItemStack stack = player.getStackInHand(hand);
|
||||
Optional<Entity> entity = RayTraceHelper.doTrace(player, 5, 1, EntityPredicates.EXCEPT_SPECTATOR.and(e -> canFeedTo(stack, e))).getEntity();
|
||||
|
||||
EntityHitResult ehr = ((EntityHitResult)mop);
|
||||
|
||||
if (canFeedTo(stack, ehr.getEntity())) {
|
||||
return onFedTo(stack, player, ehr.getEntity());
|
||||
}
|
||||
if (entity.isPresent()) {
|
||||
return onFedTo(stack, player, entity.get());
|
||||
}
|
||||
|
||||
return super.use(world, player, hand);
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
package com.minelittlepony.unicopia.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.RayTraceContext;
|
||||
|
||||
public class RayTraceHelper {
|
||||
public static <T extends Entity> Optional<T> findEntity(Entity e, double distance) {
|
||||
return doTrace(e, distance, 1).getEntity();
|
||||
}
|
||||
|
||||
public static <T extends Entity> Optional<T> findEntity(Entity e, double distance, float partialTick, Predicate<Entity> predicate) {
|
||||
return doTrace(e, distance, partialTick, EntityPredicates.EXCEPT_SPECTATOR.and(predicate)).getEntity();
|
||||
}
|
||||
|
||||
public static Trace doTrace(Entity e, double distance, float partialTick) {
|
||||
return doTrace(e, distance, partialTick, EntityPredicates.EXCEPT_SPECTATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a ray trace from the given entity and returns a result for the first Entity that passing the given predicate or block that the ray intercepts.
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* @param e Entity to start from
|
||||
* @param distance Maximum distance
|
||||
* @param partialTick Client partial ticks
|
||||
* @param predicate Predicate test to filter entities
|
||||
*
|
||||
* @return A OptionalHit describing what was found.
|
||||
*/
|
||||
public static Trace doTrace(Entity e, double distance, float partialTick, Predicate<Entity> predicate) {
|
||||
HitResult tracedBlock = traceBlocks(e, distance, partialTick, false);
|
||||
|
||||
double totalTraceDistance = distance;
|
||||
|
||||
Vec3d pos = e.getCameraPosVec(partialTick);
|
||||
|
||||
if (tracedBlock != null) {
|
||||
totalTraceDistance = tracedBlock.getPos().distanceTo(pos);
|
||||
}
|
||||
|
||||
Vec3d look = e.getRotationVec(partialTick);
|
||||
Vec3d ray = pos.add(look.multiply(distance));
|
||||
|
||||
Vec3d hit = null;
|
||||
Entity pointedEntity = null;
|
||||
List<Entity> entitiesWithinRange = e.world.getOtherEntities(e, e.getBoundingBox()
|
||||
.expand(look.x * distance, look.y * distance, look.z * distance)
|
||||
.expand(1, 1, 1), predicate);
|
||||
|
||||
double traceDistance = totalTraceDistance;
|
||||
|
||||
for (Entity entity : entitiesWithinRange) {
|
||||
if (entity.collides()) {
|
||||
Box entityAABB = entity.getBoundingBox().expand(entity.getTargetingMargin());
|
||||
|
||||
Optional<Vec3d> intercept = entityAABB.rayTrace(pos, ray);
|
||||
|
||||
if (entityAABB.contains(pos)) {
|
||||
if (traceDistance <= 0) {
|
||||
pointedEntity = entity;
|
||||
hit = intercept.orElse(null);
|
||||
traceDistance = 0;
|
||||
}
|
||||
} else if (intercept.isPresent()) {
|
||||
Vec3d inter = intercept.get();
|
||||
double distanceToHit = pos.distanceTo(inter);
|
||||
|
||||
if (distanceToHit < traceDistance || traceDistance == 0) {
|
||||
if (entity.getRootVehicle() == e.getRootVehicle()) {
|
||||
if (traceDistance == 0) {
|
||||
pointedEntity = entity;
|
||||
hit = inter;
|
||||
}
|
||||
} else {
|
||||
pointedEntity = entity;
|
||||
hit = inter;
|
||||
traceDistance = distanceToHit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pointedEntity != null && (traceDistance < totalTraceDistance || tracedBlock == null)) {
|
||||
return new Trace(new EntityHitResult(pointedEntity, hit));
|
||||
}
|
||||
|
||||
return new Trace(tracedBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-available version of Entity.rayTrace
|
||||
*/
|
||||
public static HitResult traceBlocks(Entity e, double maxDistance, float tickDelta, boolean includeFluids) {
|
||||
Vec3d start = e.getCameraPosVec(tickDelta);
|
||||
Vec3d end = e.getRotationVec(tickDelta).multiply(maxDistance).add(start);
|
||||
|
||||
return e.world.rayTrace(new RayTraceContext(start, end,
|
||||
RayTraceContext.ShapeType.OUTLINE,
|
||||
includeFluids ? RayTraceContext.FluidHandling.ANY : RayTraceContext.FluidHandling.NONE,
|
||||
e)
|
||||
);
|
||||
}
|
||||
|
||||
public static class Trace {
|
||||
@Nullable
|
||||
private final HitResult result;
|
||||
|
||||
Trace(@Nullable HitResult result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HitResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Entity> Optional<T> getEntity() {
|
||||
if (result != null && result.getType() == HitResult.Type.ENTITY) {
|
||||
return Optional.of((T)((EntityHitResult)result).getEntity());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Optional<BlockPos> getBlockPos() {
|
||||
if (result != null && result.getType() == HitResult.Type.BLOCK) {
|
||||
return Optional.of(((BlockHitResult)result).getBlockPos());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Trace ifEntity(Consumer<Entity> consumer) {
|
||||
getEntity().ifPresent(consumer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Trace ifBlock(Consumer<BlockPos> consumer) {
|
||||
getBlockPos().ifPresent(consumer);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +1,19 @@
|
|||
package com.minelittlepony.unicopia.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.RayTraceContext;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface VecHelper {
|
||||
/**
|
||||
* Performs a ray cast from the given entity and returns a result for the first block that ray intercepts.
|
||||
*
|
||||
* Server-available version of Entity.rayTrace
|
||||
*
|
||||
* @param e Entity to start from
|
||||
* @param distance Maximum distance
|
||||
* @param partialTick Client partial ticks
|
||||
*
|
||||
* @return RayTraceResult result or null
|
||||
*/
|
||||
static HitResult rayTrace(Entity e, double distance, float partialTick) {
|
||||
Vec3d cam = e.getCameraPosVec(partialTick);
|
||||
Vec3d look = e.getRotationVec(partialTick).multiply(distance);
|
||||
|
||||
return e.world.rayTrace(
|
||||
new RayTraceContext(cam, cam.add(look),
|
||||
RayTraceContext.ShapeType.OUTLINE,
|
||||
RayTraceContext.FluidHandling.NONE,
|
||||
e)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity the player is currently looking at, or null.
|
||||
*/
|
||||
@Nullable
|
||||
static Entity getLookedAtEntity(LivingEntity e, int reach) {
|
||||
HitResult objectMouseOver = getObjectMouseOver(e, reach, 1);
|
||||
|
||||
if (objectMouseOver instanceof EntityHitResult && objectMouseOver.getType() == BlockHitResult.Type.ENTITY) {
|
||||
return ((EntityHitResult)objectMouseOver).getEntity();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Stream<Entity> findAllEntitiesInRange(@Nullable Entity origin, World w, BlockPos pos, double radius) {
|
||||
return w.getOtherEntities(origin, new Box(pos).expand(radius), e -> {
|
||||
double dist = Math.sqrt(e.squaredDistanceTo(pos.getX(), pos.getY(), pos.getZ()));
|
||||
|
@ -70,7 +26,7 @@ public interface VecHelper {
|
|||
/**
|
||||
* Gets all entities within a given range from the player.
|
||||
*/
|
||||
static List<Entity> getWithinRange(PlayerEntity player, double reach, @Nullable Predicate<? super Entity> predicate) {
|
||||
static List<Entity> getWithinReach(PlayerEntity player, double reach, @Nullable Predicate<? super Entity> predicate) {
|
||||
Vec3d look = player.getCameraPosVec(1).multiply(reach);
|
||||
|
||||
return player.world.getOtherEntities(player, player
|
||||
|
@ -78,90 +34,4 @@ public interface VecHelper {
|
|||
.expand(look.x, look.y, look.z)
|
||||
.expand(1, 1, 1), predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a ray trace from the given entity and returns a result for the first Entity or block that the ray intercepts.
|
||||
*
|
||||
* @param e Entity to start from
|
||||
* @param distance Maximum distance
|
||||
* @param partialTick Client partial ticks
|
||||
*
|
||||
* @return RayTraceResult result or null
|
||||
*/
|
||||
static HitResult getObjectMouseOver(Entity e, double distance, float partialTick) {
|
||||
return getObjectMouseOver(e, distance, partialTick, EntityPredicates.EXCEPT_SPECTATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a ray trace from the given entity and returns a result for the first Entity that passing the given predicate or block that the ray intercepts.
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* @param e Entity to start from
|
||||
* @param distance Maximum distance
|
||||
* @param partialTick Client partial ticks
|
||||
* @param predicate Predicate test to filter entities
|
||||
*
|
||||
* @return RayTraceResult result or null
|
||||
*/
|
||||
static HitResult getObjectMouseOver(Entity e, double distance, float partialTick, Predicate<Entity> predicate) {
|
||||
HitResult tracedBlock = rayTrace(e, distance, partialTick);
|
||||
|
||||
double totalTraceDistance = distance;
|
||||
|
||||
Vec3d pos = e.getCameraPosVec(partialTick);
|
||||
|
||||
if (tracedBlock != null) {
|
||||
totalTraceDistance = tracedBlock.getPos().distanceTo(pos);
|
||||
}
|
||||
|
||||
Vec3d look = e.getRotationVec(partialTick);
|
||||
Vec3d ray = pos.add(look.multiply(distance));
|
||||
|
||||
Vec3d hit = null;
|
||||
Entity pointedEntity = null;
|
||||
List<Entity> entitiesWithinRange = e.world.getOtherEntities(e, e.getBoundingBox()
|
||||
.expand(look.x * distance, look.y * distance, look.z * distance)
|
||||
.expand(1, 1, 1), predicate);
|
||||
|
||||
double traceDistance = totalTraceDistance;
|
||||
|
||||
for (Entity entity : entitiesWithinRange) {
|
||||
if (entity.collides()) {
|
||||
Box entityAABB = entity.getBoundingBox().expand(entity.getTargetingMargin());
|
||||
|
||||
Optional<Vec3d> intercept = entityAABB.rayTrace(pos, ray);
|
||||
|
||||
if (entityAABB.contains(pos)) {
|
||||
if (traceDistance <= 0) {
|
||||
pointedEntity = entity;
|
||||
hit = intercept.orElse(null);
|
||||
traceDistance = 0;
|
||||
}
|
||||
} else if (intercept.isPresent()) {
|
||||
Vec3d inter = intercept.get();
|
||||
double distanceToHit = pos.distanceTo(inter);
|
||||
|
||||
if (distanceToHit < traceDistance || traceDistance == 0) {
|
||||
if (entity.getRootVehicle() == e.getRootVehicle()) {
|
||||
if (traceDistance == 0) {
|
||||
pointedEntity = entity;
|
||||
hit = inter;
|
||||
}
|
||||
} else {
|
||||
pointedEntity = entity;
|
||||
hit = inter;
|
||||
traceDistance = distanceToHit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pointedEntity != null && (traceDistance < totalTraceDistance || tracedBlock == null)) {
|
||||
return new EntityHitResult(pointedEntity, hit);
|
||||
}
|
||||
|
||||
return tracedBlock;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue