Clean up raytrace helper code

This commit is contained in:
Sollace 2022-10-01 18:20:53 +02:00
parent 3ca28335bd
commit 2b00977e7f
19 changed files with 248 additions and 228 deletions

View file

@ -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);
} }

View file

@ -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))

View file

@ -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);
} }

View file

@ -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));
} }

View file

@ -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);

View file

@ -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

View file

@ -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));

View file

@ -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);
} }

View file

@ -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);

View file

@ -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);
});
} }
}); });
} }

View file

@ -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,55 +70,46 @@ 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; boolean airAbove = enterable(w, pos.up()) && enterable(w, pos.up(2));
if (ray.getType() == HitResult.Type.ENTITY) { if (exception(w, pos, player.getMaster())) {
pos = new BlockPos(ray.getPos()); final BlockPos p = pos;
} else { pos = trace.getSide().map(sideHit -> {
pos = ((BlockHitResult)ray).getBlockPos(); if (player.getMaster().isSneaking()) {
} sideHit = sideHit.getOpposite();
}
boolean airAbove = enterable(w, pos.up()) && enterable(w, pos.up(2)); return p.offset(sideHit);
}).orElse(pos);
if (exception(w, pos, player.getMaster()) && ray.getType() == HitResult.Type.BLOCK) {
Direction sideHit = ((BlockHitResult)ray).getSide();
if (player.getMaster().isSneaking()) {
sideHit = sideHit.getOpposite();
} }
pos = pos.offset(sideHit);
}
if (enterable(w, pos.down())) {
pos = pos.down();
if (enterable(w, pos.down())) { if (enterable(w, pos.down())) {
if (!airAbove) { pos = pos.down();
return null;
if (enterable(w, pos.down())) {
if (!airAbove) {
return null;
}
pos = originalPos.up(2);
} }
pos = new BlockPos(
ray.getPos().getX(),
pos.getY() + 2,
ray.getPos().getZ());
} }
}
if ((!enterable(w, pos) && exception(w, pos, player.getMaster())) if ((!enterable(w, pos) && exception(w, pos, player.getMaster()))
|| (!enterable(w, pos.up()) && exception(w, pos.up(), player.getMaster()))) { || (!enterable(w, pos.up()) && exception(w, pos.up(), player.getMaster()))) {
return null; return null;
} }
return new Pos(pos.getX(), pos.getY(), pos.getZ()); return new Pos(pos);
}).orElse(null);
} }
@Override @Override

View file

@ -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;
}
} }

View file

@ -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) {

View file

@ -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();
} }

View file

@ -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));
} }

View file

@ -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

View file

@ -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;
}
}
}

View 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;
}
}

View file

@ -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))
);
}
}