mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 23:27:59 +01:00
Clean up raytrace helper code
This commit is contained in:
parent
3ca28335bd
commit
2b00977e7f
19 changed files with 248 additions and 228 deletions
|
@ -7,9 +7,10 @@ import com.minelittlepony.unicopia.entity.Equine;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
|
||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.*;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.decoration.AbstractDecorationEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
|
|
||||||
public interface EquinePredicates {
|
public interface EquinePredicates {
|
||||||
Predicate<Entity> IS_PLAYER = e -> e instanceof PlayerEntity;
|
Predicate<Entity> IS_PLAYER = e -> e instanceof PlayerEntity;
|
||||||
|
@ -28,6 +29,8 @@ public interface EquinePredicates {
|
||||||
|
|
||||||
Predicate<LivingEntity> HAS_WANT_IT_NEED_IT = e -> EnchantmentHelper.getEquipmentLevel(UEnchantments.WANT_IT_NEED_IT, e) > 0;
|
Predicate<LivingEntity> HAS_WANT_IT_NEED_IT = e -> EnchantmentHelper.getEquipmentLevel(UEnchantments.WANT_IT_NEED_IT, e) > 0;
|
||||||
|
|
||||||
|
Predicate<Entity> VALID_FOR_DISGUISE = EntityPredicates.EXCEPT_SPECTATOR.and(e -> !(e instanceof LightningEntity || e instanceof AbstractDecorationEntity));
|
||||||
|
|
||||||
static Predicate<Entity> ofRace(Race race) {
|
static Predicate<Entity> ofRace(Race race) {
|
||||||
return raceMatches(race::equals);
|
return raceMatches(race::equals);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,8 @@ package com.minelittlepony.unicopia.ability;
|
||||||
import com.minelittlepony.unicopia.Race;
|
import com.minelittlepony.unicopia.Race;
|
||||||
import com.minelittlepony.unicopia.ability.data.Multi;
|
import com.minelittlepony.unicopia.ability.data.Multi;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
|
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +40,7 @@ public class BatPonyHangAbility implements Ability<Multi> {
|
||||||
return new Multi(BlockPos.ZERO, 0);
|
return new Multi(BlockPos.ZERO, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RayTraceHelper.doTrace(player.getMaster(), 5, 1, EntityPredicates.EXCEPT_SPECTATOR).getBlockPos()
|
return TraceHelper.findBlock(player.getMaster(), 5, 1)
|
||||||
.map(BlockPos::down)
|
.map(BlockPos::down)
|
||||||
.filter(player::canHangAt)
|
.filter(player::canHangAt)
|
||||||
.map(pos -> new Multi(pos, 1))
|
.map(pos -> new Multi(pos, 1))
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.ability;
|
||||||
import com.minelittlepony.unicopia.Race;
|
import com.minelittlepony.unicopia.Race;
|
||||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
@ -42,7 +42,7 @@ public class CarryAbility implements Ability<Hit> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LivingEntity findRider(PlayerEntity player, World w) {
|
protected LivingEntity findRider(PlayerEntity player, World w) {
|
||||||
return RayTraceHelper.<LivingEntity>findEntity(player, 10, 1, hit -> {
|
return TraceHelper.<LivingEntity>findEntity(player, 10, 1, hit -> {
|
||||||
return hit instanceof LivingEntity && !player.isConnectedThroughVehicle(hit) && !(hit instanceof IPickupImmuned);
|
return hit instanceof LivingEntity && !player.isConnectedThroughVehicle(hit) && !(hit instanceof IPickupImmuned);
|
||||||
}).orElse(null);
|
}).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,18 @@ package com.minelittlepony.unicopia.ability;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell;
|
import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance;
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity;
|
import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.Trace;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LightningEntity;
|
|
||||||
import net.minecraft.entity.decoration.AbstractDecorationEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,16 +39,9 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RayTraceHelper.Trace trace = RayTraceHelper.doTrace(player, 10, 1, EntityPredicates.EXCEPT_SPECTATOR.and(e -> !(e instanceof LightningEntity)));
|
Trace trace = Trace.create(player, 10, 1, EquinePredicates.VALID_FOR_DISGUISE);
|
||||||
|
|
||||||
Entity looked = trace.getEntity().filter(e -> !(e instanceof AbstractDecorationEntity)).map(e -> {
|
Entity looked = trace.getEntity().map(AbstractDisguiseSpell::getAppearance).orElseGet(() -> trace.getBlockPos().map(pos -> {
|
||||||
return e instanceof PlayerEntity ? Pony.of((PlayerEntity)e)
|
|
||||||
.getSpellSlot()
|
|
||||||
.get(SpellPredicate.IS_DISGUISE, true)
|
|
||||||
.map(AbstractDisguiseSpell::getDisguise)
|
|
||||||
.map(EntityAppearance::getAppearance)
|
|
||||||
.orElse(e) : e;
|
|
||||||
}).orElseGet(() -> trace.getBlockPos().map(pos -> {
|
|
||||||
if (!iplayer.getReferenceWorld().isAir(pos)) {
|
if (!iplayer.getReferenceWorld().isAir(pos)) {
|
||||||
return MixinFallingBlockEntity.createInstance(player.getEntityWorld(), 0, 0, 0, iplayer.getReferenceWorld().getBlockState(pos));
|
return MixinFallingBlockEntity.createInstance(player.getEntityWorld(), 0, 0, 0, iplayer.getReferenceWorld().getBlockState(pos));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
import com.minelittlepony.unicopia.util.VecHelper;
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
@ -82,7 +82,7 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
||||||
protected List<LivingEntity> getTargets(Pony player) {
|
protected List<LivingEntity> getTargets(Pony player) {
|
||||||
List<Entity> list = VecHelper.findInRange(player.getMaster(), player.getReferenceWorld(), player.getOriginVector(), 3, this::canDrain);
|
List<Entity> list = VecHelper.findInRange(player.getMaster(), player.getReferenceWorld(), player.getOriginVector(), 3, this::canDrain);
|
||||||
|
|
||||||
RayTraceHelper.<LivingEntity>findEntity(player.getMaster(), 17, 1,
|
TraceHelper.<LivingEntity>findEntity(player.getMaster(), 17, 1,
|
||||||
looked -> looked instanceof LivingEntity && !list.contains(looked) && canDrain(looked))
|
looked -> looked instanceof LivingEntity && !list.contains(looked) && canDrain(looked))
|
||||||
.ifPresent(list::add);
|
.ifPresent(list::add);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import com.minelittlepony.unicopia.ability.data.Hit;
|
||||||
import com.minelittlepony.unicopia.ability.data.Pos;
|
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.item.BoneMealItem;
|
import net.minecraft.item.BoneMealItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -36,7 +36,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pos tryActivate(Pony player) {
|
public Pos tryActivate(Pony player) {
|
||||||
return RayTraceHelper.doTrace(player.getMaster(), 3, 1).getBlockPos().map(Pos::new).orElse(null);
|
return TraceHelper.findBlock(player.getMaster(), 3, 1).map(Pos::new).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -60,8 +60,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
||||||
public double getCostEstimate(Pony player) {
|
public double getCostEstimate(Pony player) {
|
||||||
double distance = MineLPDelegate.getInstance().getPlayerPonyRace(player.getMaster()).isDefault() ? 6 : -6;
|
double distance = MineLPDelegate.getInstance().getPlayerPonyRace(player.getMaster()).isDefault() ? 6 : -6;
|
||||||
|
|
||||||
return RayTraceHelper.doTrace(player.getMaster(), distance, 1)
|
return TraceHelper.findBlock(player.getMaster(), distance, 1)
|
||||||
.getBlockPos()
|
|
||||||
.filter(pos -> TreeType.at(pos, player.getReferenceWorld()) != TreeType.NONE)
|
.filter(pos -> TreeType.at(pos, player.getReferenceWorld()) != TreeType.NONE)
|
||||||
.isPresent() ? 3 : 1;
|
.isPresent() ? 3 : 1;
|
||||||
}
|
}
|
||||||
|
@ -107,8 +106,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Pos tryActivate(Pony player) {
|
public Pos tryActivate(Pony player) {
|
||||||
return RayTraceHelper.doTrace(player.getMaster(), 6 * getKickDirection(player), 1)
|
return TraceHelper.findBlock(player.getMaster(), 6 * getKickDirection(player), 1)
|
||||||
.getBlockPos()
|
|
||||||
.filter(pos -> TreeType.at(pos, player.getReferenceWorld()) != TreeType.NONE)
|
.filter(pos -> TreeType.at(pos, player.getReferenceWorld()) != TreeType.NONE)
|
||||||
.map(Pos::new)
|
.map(Pos::new)
|
||||||
.orElseGet(() -> getDefaultKickLocation(player));
|
.orElseGet(() -> getDefaultKickLocation(player));
|
||||||
|
|
|
@ -12,7 +12,7 @@ import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.item.AmuletItem;
|
import com.minelittlepony.unicopia.item.AmuletItem;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
import com.minelittlepony.unicopia.util.VecHelper;
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -117,7 +117,7 @@ public class UnicornCastingAbility implements Ability<Hit> {
|
||||||
} else {
|
} else {
|
||||||
player.setAnimation(Animation.ARMS_UP);
|
player.setAnimation(Animation.ARMS_UP);
|
||||||
if (s instanceof HomingSpell homer) {
|
if (s instanceof HomingSpell homer) {
|
||||||
RayTraceHelper.doTrace(player.getMaster(), homer.getRange(player), 1, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(EntityPredicates.VALID_ENTITY)).getEntity().ifPresent(homer::setTarget);
|
TraceHelper.findEntity(player.getMaster(), homer.getRange(player), 1, EntityPredicates.VALID_ENTITY).ifPresent(homer::setTarget);
|
||||||
}
|
}
|
||||||
player.playSound(USounds.SPELL_CAST_SUCCESS, 0.05F, 2.2F);
|
player.playSound(USounds.SPELL_CAST_SUCCESS, 0.05F, 2.2F);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
import com.minelittlepony.unicopia.util.VecHelper;
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
@ -83,14 +83,9 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
||||||
|
|
||||||
private Optional<Caster<?>> getTarget(Pony player) {
|
private Optional<Caster<?>> getTarget(Pony player) {
|
||||||
int maxDistance = player.getMaster().isCreative() ? 1000 : 100;
|
int maxDistance = player.getMaster().isCreative() ? 1000 : 100;
|
||||||
return RayTraceHelper.doTrace(player.getMaster(), maxDistance, 1,
|
return TraceHelper.findEntity(player.getMaster(), maxDistance, 1, EquinePredicates.IS_PLACED_SPELL).flatMap(Caster::of);
|
||||||
EquinePredicates.IS_PLACED_SPELL)
|
|
||||||
.getEntity()
|
|
||||||
.flatMap(Caster::of);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preApply(Pony player, AbilitySlot slot) {
|
public void preApply(Pony player, AbilitySlot slot) {
|
||||||
player.getMagicalReserves().getExhaustion().multiply(3.3F);
|
player.getMagicalReserves().getExhaustion().multiply(3.3F);
|
||||||
|
|
|
@ -8,9 +8,8 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellTyp
|
||||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
|
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
@ -94,9 +93,7 @@ public class UnicornProjectileAbility implements Ability<Hit> {
|
||||||
projectile.setHydrophobic();
|
projectile.setHydrophobic();
|
||||||
|
|
||||||
if (spell instanceof HomingSpell) {
|
if (spell instanceof HomingSpell) {
|
||||||
RayTraceHelper.doTrace(player.getMaster(), 600, 1, EntityPredicates.EXCEPT_SPECTATOR).getEntity().filter(((HomingSpell)spell)::setTarget).ifPresent(target -> {
|
TraceHelper.findEntity(player.getMaster(), 600, 1).filter(((HomingSpell)spell)::setTarget).ifPresent(projectile::setHomingTarget);
|
||||||
projectile.setHomingTarget(target);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ import com.minelittlepony.unicopia.ability.data.Pos;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.Trace;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.FenceBlock;
|
import net.minecraft.block.FenceBlock;
|
||||||
|
@ -21,10 +22,7 @@ import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
|
||||||
import net.minecraft.util.hit.HitResult;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
@ -72,32 +70,25 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxDistance = player.getMaster().isCreative() ? 1000 : 100;
|
int maxDistance = player.getMaster().isCreative() ? 1000 : 100;
|
||||||
HitResult ray = RayTraceHelper.doTrace(player.getMaster(), maxDistance, 1, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR).getResult();
|
|
||||||
|
|
||||||
World w = player.getReferenceWorld();
|
World w = player.getReferenceWorld();
|
||||||
|
|
||||||
if (ray.getType() == HitResult.Type.MISS) {
|
Trace trace = Trace.create(player.getMaster(), maxDistance, 1, EntityPredicates.EXCEPT_SPECTATOR);
|
||||||
return null;
|
return trace.getBlockOrEntityPos().map(pos -> {
|
||||||
}
|
final BlockPos originalPos = pos;
|
||||||
|
|
||||||
BlockPos pos;
|
|
||||||
|
|
||||||
if (ray.getType() == HitResult.Type.ENTITY) {
|
|
||||||
pos = new BlockPos(ray.getPos());
|
|
||||||
} else {
|
|
||||||
pos = ((BlockHitResult)ray).getBlockPos();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean airAbove = enterable(w, pos.up()) && enterable(w, pos.up(2));
|
boolean airAbove = enterable(w, pos.up()) && enterable(w, pos.up(2));
|
||||||
|
|
||||||
if (exception(w, pos, player.getMaster()) && ray.getType() == HitResult.Type.BLOCK) {
|
if (exception(w, pos, player.getMaster())) {
|
||||||
Direction sideHit = ((BlockHitResult)ray).getSide();
|
final BlockPos p = pos;
|
||||||
|
pos = trace.getSide().map(sideHit -> {
|
||||||
if (player.getMaster().isSneaking()) {
|
if (player.getMaster().isSneaking()) {
|
||||||
sideHit = sideHit.getOpposite();
|
sideHit = sideHit.getOpposite();
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = pos.offset(sideHit);
|
return p.offset(sideHit);
|
||||||
|
}).orElse(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enterable(w, pos.down())) {
|
if (enterable(w, pos.down())) {
|
||||||
|
@ -108,10 +99,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = new BlockPos(
|
pos = originalPos.up(2);
|
||||||
ray.getPos().getX(),
|
|
||||||
pos.getY() + 2,
|
|
||||||
ray.getPos().getZ());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +108,8 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Pos(pos.getX(), pos.getY(), pos.getZ());
|
return new Pos(pos);
|
||||||
|
}).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,12 +3,15 @@ package com.minelittlepony.unicopia.ability.magic.spell;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.*;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.*;
|
||||||
import com.minelittlepony.unicopia.entity.behaviour.Disguise;
|
import com.minelittlepony.unicopia.entity.behaviour.Disguise;
|
||||||
import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance;
|
import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
|
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.projectile.ProjectileEntity;
|
import net.minecraft.entity.projectile.ProjectileEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
|
||||||
|
@ -70,4 +73,13 @@ public abstract class AbstractDisguiseSpell extends AbstractSpell implements Dis
|
||||||
public Optional<EntityAppearance> getAppearance() {
|
public Optional<EntityAppearance> getAppearance() {
|
||||||
return Optional.ofNullable(disguise);
|
return Optional.ofNullable(disguise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Entity getAppearance(Entity e) {
|
||||||
|
return e instanceof PlayerEntity ? Pony.of((PlayerEntity)e)
|
||||||
|
.getSpellSlot()
|
||||||
|
.get(SpellPredicate.IS_DISGUISE, true)
|
||||||
|
.map(AbstractDisguiseSpell::getDisguise)
|
||||||
|
.map(EntityAppearance::getAppearance)
|
||||||
|
.orElse(e) : e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -12,15 +11,12 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity;
|
import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity;
|
||||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.Trace;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.FallingBlockEntity;
|
import net.minecraft.entity.FallingBlockEntity;
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
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.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -87,16 +83,14 @@ public class CatapultSpell extends AbstractSpell implements ProjectileSpell {
|
||||||
|
|
||||||
double maxDistance = 2 + (getTraits().get(Trait.FOCUS) - 50) * 8;
|
double maxDistance = 2 + (getTraits().get(Trait.FOCUS) - 50) * 8;
|
||||||
|
|
||||||
HitResult ray = RayTraceHelper.doTrace(caster.getEntity(), maxDistance, 1, EntityPredicates.EXCEPT_SPECTATOR).getResult();
|
Trace trace = Trace.create(caster.getEntity(), maxDistance, 1, EntityPredicates.EXCEPT_SPECTATOR);
|
||||||
|
trace.getEntity().ifPresentOrElse(apply, () -> {
|
||||||
if (ray.getType() == HitResult.Type.ENTITY) {
|
trace.ifBlock(pos -> {
|
||||||
EntityHitResult result = (EntityHitResult)ray;
|
if (caster.canModifyAt(pos)) {
|
||||||
Optional.ofNullable(result.getEntity()).ifPresent(apply);
|
createBlockEntity(caster.getReferenceWorld(), pos, apply);
|
||||||
} else if (ray.getType() == HitResult.Type.BLOCK) {
|
|
||||||
if (caster.canModifyAt(((BlockHitResult)ray).getBlockPos())) {
|
|
||||||
createBlockEntity(caster.getReferenceWorld(), ((BlockHitResult)ray).getBlockPos(), apply);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void createBlockEntity(World world, BlockPos bpos, @Nullable Consumer<Entity> apply) {
|
static void createBlockEntity(World world, BlockPos bpos, @Nullable Consumer<Entity> apply) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.command;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.InteractionManager;
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
|
@ -20,7 +21,6 @@ import net.minecraft.command.argument.NbtCompoundArgumentType;
|
||||||
import net.minecraft.command.suggestion.SuggestionProviders;
|
import net.minecraft.command.suggestion.SuggestionProviders;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.decoration.AbstractDecorationEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
|
@ -77,7 +77,7 @@ public class DisguiseCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int disguise(ServerCommandSource source, PlayerEntity player, Entity entity) throws CommandSyntaxException {
|
static int disguise(ServerCommandSource source, PlayerEntity player, Entity entity) throws CommandSyntaxException {
|
||||||
if (entity == null || entity instanceof AbstractDecorationEntity) {
|
if (entity == null || !EquinePredicates.VALID_FOR_DISGUISE.test(entity)) {
|
||||||
throw FAILED_EXCEPTION.create();
|
throw FAILED_EXCEPTION.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.minelittlepony.unicopia.entity.behaviour;
|
package com.minelittlepony.unicopia.entity.behaviour;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.mob.MobEntity;
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
@ -26,7 +26,7 @@ public class MobBehaviour<T extends MobEntity> extends EntityBehaviour<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LivingEntity findTarget(Pony player, T entity) {
|
protected LivingEntity findTarget(Pony player, T entity) {
|
||||||
return RayTraceHelper.<LivingEntity>findEntity(player.getEntity(), 6, 1,
|
return TraceHelper.<LivingEntity>findEntity(player.getEntity(), 6, 1,
|
||||||
e -> e instanceof LivingEntity && e != entity && !player.isOwnedBy(e))
|
e -> e instanceof LivingEntity && e != entity && !player.isOwnedBy(e))
|
||||||
.orElseGet(() -> getDummy(entity));
|
.orElseGet(() -> getDummy(entity));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.minelittlepony.unicopia.item;
|
package com.minelittlepony.unicopia.item;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.UTags;
|
import com.minelittlepony.unicopia.UTags;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||||
|
@ -10,7 +8,7 @@ import com.minelittlepony.unicopia.item.toxin.*;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
import com.minelittlepony.unicopia.util.Registries;
|
import com.minelittlepony.unicopia.util.Registries;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
@ -22,7 +20,6 @@ import net.minecraft.entity.passive.PigEntity;
|
||||||
import net.minecraft.entity.passive.VillagerEntity;
|
import net.minecraft.entity.passive.VillagerEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.*;
|
import net.minecraft.item.*;
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
@ -44,14 +41,9 @@ public class ZapAppleItem extends Item implements ChameleonItem, ToxicHolder {
|
||||||
@Override
|
@Override
|
||||||
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
||||||
ItemStack stack = player.getStackInHand(hand);
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
return TraceHelper.findEntity(player, 5, 1, e -> canFeedTo(stack, e))
|
||||||
Optional<Entity> entity = RayTraceHelper.doTrace(player, 5, 1, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(e -> canFeedTo(stack, e))).getEntity();
|
.map(entity -> onFedTo(stack, player, entity))
|
||||||
|
.orElseGet(() -> super.use(world, player, hand));
|
||||||
if (entity.isPresent()) {
|
|
||||||
return onFedTo(stack, player, entity.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.use(world, player, hand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.util;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.projectile.ProjectileUtil;
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class RayTraceHelper {
|
|
||||||
public static <T extends Entity> Optional<T> findEntity(Entity e, double distance, float tickDelta, Predicate<Entity> predicate) {
|
|
||||||
return doTrace(e, distance, tickDelta, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(predicate)).getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 tickDelta Client partial ticks
|
|
||||||
*
|
|
||||||
* @return A Trace describing what was found.
|
|
||||||
*/
|
|
||||||
public static Trace doTrace(Entity e, double distance, float tickDelta) {
|
|
||||||
return doTrace(e, distance, tickDelta, EntityPredicates.EXCEPT_SPECTATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs a ray trace from the given entity and returns
|
|
||||||
* a result for the first Entity that passes the given predicate
|
|
||||||
* or block that the ray intercepts.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param e Entity to start from
|
|
||||||
* @param distance Maximum distance
|
|
||||||
* @param tickDelta Client partial ticks
|
|
||||||
* @param predicate Predicate test to filter entities
|
|
||||||
*
|
|
||||||
* @return A Trace describing what was found.
|
|
||||||
*/
|
|
||||||
public static Trace doTrace(Entity e, double distance, float tickDelta, Predicate<Entity> predicate) {
|
|
||||||
final Vec3d orientation = e.getRotationVec(tickDelta);
|
|
||||||
final Vec3d start = e.getCameraPosVec(tickDelta);
|
|
||||||
|
|
||||||
final Box box = e.getBoundingBox().stretch(orientation.multiply(Math.abs(distance))).expand(10);
|
|
||||||
|
|
||||||
EntityHitResult pointedEntity = ProjectileUtil.raycast(e, start, start.add(orientation.multiply(distance)), box, predicate, Math.abs(distance));
|
|
||||||
|
|
||||||
if (pointedEntity != null) {
|
|
||||||
return new Trace(pointedEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Trace(e.raycast(distance, tickDelta, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Entity> Optional<T> getEntity(Predicate<T> predicate) {
|
|
||||||
if (result != null && result.getType() == HitResult.Type.ENTITY) {
|
|
||||||
return Optional.of((T)((EntityHitResult)result).getEntity()).filter(predicate);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
76
src/main/java/com/minelittlepony/unicopia/util/Trace.java
Normal file
76
src/main/java/com/minelittlepony/unicopia/util/Trace.java
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
package com.minelittlepony.unicopia.util;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.hit.*;
|
||||||
|
import net.minecraft.util.math.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public record Trace(
|
||||||
|
Optional<? extends HitResult> result
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Performs a ray trace from the given entity and returns
|
||||||
|
* a result for the first Entity that passes the given predicate
|
||||||
|
* or block that the ray intercepts.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param e Entity to start from
|
||||||
|
* @param distance Maximum distance
|
||||||
|
* @param tickDelta Client partial ticks
|
||||||
|
* @param predicate Predicate test to filter entities
|
||||||
|
*
|
||||||
|
* @return A Trace describing what was found.
|
||||||
|
*/
|
||||||
|
public static Trace create(Entity e, double distance, float tickDelta, Predicate<Entity> predicate) {
|
||||||
|
return new Trace(
|
||||||
|
((Optional<HitResult>)(Optional<?>)TraceHelper.traceEntity(e, distance, tickDelta, predicate))
|
||||||
|
.or(() -> Optional.ofNullable(e.raycast(distance, tickDelta, false)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T extends Entity> T toEntity(EntityHitResult hit) {
|
||||||
|
return (T)hit.getEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<EntityHitResult> getEntityResult() {
|
||||||
|
return result()
|
||||||
|
.filter(s -> s.getType() == HitResult.Type.ENTITY)
|
||||||
|
.map(EntityHitResult.class::cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<BlockHitResult> getBlockResult() {
|
||||||
|
return result()
|
||||||
|
.filter(s -> s.getType() == HitResult.Type.BLOCK)
|
||||||
|
.map(BlockHitResult.class::cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Entity> Optional<T> getEntity() {
|
||||||
|
return getEntityResult().map(Trace::toEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<BlockPos> getBlockPos() {
|
||||||
|
return getBlockResult().map(BlockHitResult::getBlockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<BlockPos> getBlockOrEntityPos() {
|
||||||
|
return getBlockPos().or(() -> getEntity().map(Entity::getBlockPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Direction> getSide() {
|
||||||
|
return getBlockResult().map(BlockHitResult::getSide);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trace ifEntity(Consumer<Entity> consumer) {
|
||||||
|
getEntity().ifPresent(consumer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trace ifBlock(Consumer<BlockPos> consumer) {
|
||||||
|
getBlockPos().ifPresent(consumer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
package com.minelittlepony.unicopia.util;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.projectile.ProjectileUtil;
|
||||||
|
import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
|
import net.minecraft.util.math.*;
|
||||||
|
import net.minecraft.world.BlockView;
|
||||||
|
|
||||||
|
public class TraceHelper {
|
||||||
|
/**
|
||||||
|
* Performs a ray trace from the given entity and returns
|
||||||
|
* a result for the first Entity that the ray intercepts.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param e Entity to start from
|
||||||
|
* @param distance Maximum distance
|
||||||
|
* @param tickDelta Client partial ticks
|
||||||
|
*/
|
||||||
|
public static <T extends Entity> Optional<T> findEntity(Entity e, double distance, float tickDelta, Predicate<Entity> predicate) {
|
||||||
|
return traceEntity(e, distance, tickDelta, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(predicate)).map(Trace::toEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a ray trace from the given entity and returns
|
||||||
|
* a result for the first Entity that the ray intercepts.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param e Entity to start from
|
||||||
|
* @param distance Maximum distance
|
||||||
|
* @param tickDelta Client partial ticks
|
||||||
|
*/
|
||||||
|
public static <T extends Entity> Optional<T> findEntity(Entity e, double distance, float tickDelta) {
|
||||||
|
return traceEntity(e, distance, tickDelta, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR).map(Trace::toEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a ray trace from the given entity and returns
|
||||||
|
* a result for the first block that the ray intercepts.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param e Entity to start from
|
||||||
|
* @param distance Maximum distance
|
||||||
|
* @param tickDelta Client partial ticks
|
||||||
|
*/
|
||||||
|
public static Optional<BlockPos> findBlock(Entity e, double distance, float tickDelta) {
|
||||||
|
return Trace.create(e, distance, tickDelta, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR).getBlockPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a raytrace and returns all matching blocks the ray passed through.
|
||||||
|
*
|
||||||
|
* @param e Entity to start from
|
||||||
|
* @param distance Maximum distance
|
||||||
|
* @param tickDelta Client partial ticks
|
||||||
|
* @param predicate Predicate test to filter block states
|
||||||
|
*
|
||||||
|
* @return List of matching positions
|
||||||
|
*/
|
||||||
|
public static List<BlockPos> findBlocks(Entity e, double distance, float tickDelta, Predicate<BlockState> predicate) {
|
||||||
|
final Vec3d orientation = e.getRotationVec(tickDelta);
|
||||||
|
final Vec3d start = e.getCameraPosVec(tickDelta);
|
||||||
|
|
||||||
|
return BlockView.raycast(start, start.add(orientation.multiply(distance)), new ArrayList<BlockPos>(), (ctx, pos) -> {
|
||||||
|
if (predicate.test(e.world.getBlockState(pos))) {
|
||||||
|
ctx.add(pos);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, ctx -> {
|
||||||
|
return ctx;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static Optional<EntityHitResult> traceEntity(Entity e, double distance, float tickDelta, Predicate<Entity> predicate) {
|
||||||
|
final Vec3d orientation = e.getRotationVec(tickDelta);
|
||||||
|
final Vec3d start = e.getCameraPosVec(tickDelta);
|
||||||
|
|
||||||
|
final Box box = e.getBoundingBox().stretch(orientation.multiply(Math.abs(distance))).expand(10);
|
||||||
|
|
||||||
|
return Optional.ofNullable(
|
||||||
|
ProjectileUtil.raycast(e, start, start.add(orientation.multiply(distance)), box, predicate, Math.abs(distance))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue