Fixed shields being offset and fixed shields applying to entities that they shouldn't

This commit is contained in:
Sollace 2021-01-29 18:37:41 +02:00
parent 543fd7aee0
commit b43ed1975b
13 changed files with 70 additions and 29 deletions

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.ability.magic;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.annotation.Nullable;
@ -107,7 +108,11 @@ public interface Caster<E extends LivingEntity> extends Owned<E>, Levelled, Affi
return CasterUtils.findInRange(this, radius);
}
default Stream<Entity> findAllEntitiesInRange(double radius, @Nullable Predicate<Entity> test) {
return VecHelper.findInRange(getEntity(), getWorld(), getOriginVector(), radius, test).stream();
}
default Stream<Entity> findAllEntitiesInRange(double radius) {
return VecHelper.findInRange(getEntity(), getWorld(), getOrigin(), radius, null).stream();
return findAllEntitiesInRange(radius, null);
}
}

View file

@ -7,8 +7,6 @@ import javax.annotation.Nullable;
import com.minelittlepony.unicopia.EquinePredicates;
import com.minelittlepony.unicopia.entity.PonyContainer;
import com.minelittlepony.unicopia.util.VecHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
@ -17,8 +15,7 @@ public class CasterUtils {
* Finds all surrounding spells within range from the given caster.
*/
static Stream<Caster<?>> findInRange(Caster<?> source, double radius) {
return VecHelper.findInRange(source.getEntity(), source.getWorld(), source.getOrigin(), radius, EquinePredicates.IS_CASTER)
.stream()
return source.findAllEntitiesInRange(radius, EquinePredicates.IS_CASTER)
.map(e -> toCaster(e).filter(o -> o != source))
.filter(Optional::isPresent)
.map(Optional::get);

View file

@ -60,7 +60,7 @@ public class AttractiveSpell extends ShieldSpell implements Thrown {
protected List<Entity> getTargets(Caster<?> source, double radius) {
if (homingPos != null) {
return VecHelper.findInRange(source.getEntity(), source.getWorld(), source.getOrigin(), radius, i -> i instanceof ItemEntity);
return VecHelper.findInRange(source.getEntity(), source.getWorld(), source.getOriginVector(), radius, i -> i instanceof ItemEntity);
}
return super.getTargets(source, radius);

View file

@ -66,7 +66,7 @@ public class FireSpell extends AbstractRangedAreaSpell implements Thrown {
return PosHelper.getAllInRegionMutable(source.getOrigin(), EFFECT_RANGE).reduce(false,
(r, i) -> applyBlocks(source.getWorld(), i),
(a, b) -> a || b)
|| applyEntities(null, source.getWorld(), source.getOrigin());
|| applyEntities(null, source.getWorld(), source.getOriginVector());
}
@Override
@ -130,7 +130,7 @@ public class FireSpell extends AbstractRangedAreaSpell implements Thrown {
return false;
}
protected boolean applyEntities(Entity owner, World world, BlockPos pos) {
protected boolean applyEntities(Entity owner, World world, Vec3d pos) {
return !VecHelper.findInRange(owner, world, pos, 3, i -> applyEntitySingle(owner, world, i)).isEmpty();
}

View file

@ -21,6 +21,7 @@ import net.minecraft.entity.TntEntity;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class IceSpell extends AbstractRangedAreaSpell implements Thrown {
@ -50,14 +51,14 @@ public class IceSpell extends AbstractRangedAreaSpell implements Thrown {
PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range)
.forEach(i -> applyBlockSingle(owner, source.getWorld(), i));
return applyEntities(source.getMaster(), source.getWorld(), source.getOrigin());
return applyEntities(source.getMaster(), source.getWorld(), source.getOriginVector());
}
@Override
public void render(Caster<?> source) {
}
protected boolean applyEntities(LivingEntity owner, World world, BlockPos pos) {
protected boolean applyEntities(LivingEntity owner, World world, Vec3d pos) {
return !VecHelper.findInRange(owner, world, pos, 3, i -> applyEntitySingle(owner, i)).isEmpty();
}

View file

@ -57,10 +57,10 @@ public class InfernoSpell extends FireSpell {
shape = new Sphere(false, radius - 1);
for (int i = 0; i < radius * 2; i++) {
if (w.random.nextInt(12) == 0) {
BlockPos pos = new BlockPos(shape.computePoint(w.random).add(origin));
Vec3d vec = shape.computePoint(w.random).add(origin);
if (!applyBlocks(w, pos)) {
applyEntities(source.getMaster(), w, pos);
if (!applyBlocks(w, new BlockPos(vec))) {
applyEntities(source.getMaster(), w, vec);
}
}
}

View file

@ -5,7 +5,6 @@ import java.util.List;
import com.google.common.collect.Lists;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.util.VecHelper;
import com.minelittlepony.unicopia.util.WorldEvent;
import com.minelittlepony.unicopia.util.shape.Shape;
import com.minelittlepony.unicopia.util.shape.Sphere;
@ -62,7 +61,7 @@ public class NecromancySpell extends AbstractRangedAreaSpell {
Vec3d origin = source.getOriginVector();
if (VecHelper.findInRange(source.getEntity(), source.getWorld(), source.getOrigin(), radius * 4, e -> e instanceof ZombieEntity).size() >= 10 * (1 + additional)) {
if (source.findAllEntitiesInRange(radius * 4, e -> e instanceof ZombieEntity).count() >= 10 * (1 + additional)) {
return true;
}

View file

@ -16,9 +16,14 @@ import com.minelittlepony.unicopia.projectile.ProjectileUtil;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.EyeOfEnderEntity;
import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.TntEntity;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.Vec3d;
@ -100,7 +105,19 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
boolean ownerIsValid = source.getAffinity() != Affinity.BAD && EquinePredicates.PLAYER_UNICORN.test(owner);
return source.findAllEntitiesInRange(radius)
.filter(entity -> !(entity instanceof ItemEntity || (ownerIsValid && Pony.equal(entity, owner))))
.filter(entity -> {
return
(entity instanceof LivingEntity
|| entity instanceof TntEntity
|| entity instanceof FallingBlockEntity
|| entity instanceof EyeOfEnderEntity
|| entity instanceof BoatEntity
|| ProjectileUtil.isFlyingProjectile(entity)
|| entity instanceof AbstractMinecartEntity)
&& !(entity instanceof ArmorStandEntity)
&& !(owner.isConnectedThroughVehicle(entity))
&& !(ownerIsValid && Pony.equal(entity, owner));
})
.collect(Collectors.toList());
}
@ -126,7 +143,7 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) {
Vec3d pos = source.getOriginVector();
if (ProjectileUtil.isProjectile(target)) {
if (ProjectileUtil.isFlyingProjectile(target)) {
if (!ProjectileUtil.isProjectileThrownBy(target, source.getMaster())) {
if (distance < 1) {
target.playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1F, 1);

View file

@ -196,7 +196,7 @@ public class Disguise implements NbtSerialisable {
|| entity instanceof VexEntity
|| entity instanceof ShulkerBulletEntity
|| entity instanceof Flutterer
|| ProjectileUtil.isProjectile(entity)) {
|| ProjectileUtil.isFlyingProjectile(entity)) {
return FlightType.INSECTOID;
}

View file

@ -0,0 +1,12 @@
package com.minelittlepony.unicopia.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
@Mixin(PersistentProjectileEntity.class)
public interface MixinPersistentProjectileEntity {
@Accessor("inGround")
boolean isInGround();
}

View file

@ -2,23 +2,32 @@ package com.minelittlepony.unicopia.projectile;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.mixin.MixinPersistentProjectileEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.util.math.Vec3d;
public class ProjectileUtil {
public interface ProjectileUtil {
/**
* Checks if the given entity is a projectile.
*/
public static boolean isProjectile(Entity e) {
static boolean isProjectile(Entity e) {
return e instanceof ProjectileEntity;
}
/**
* Checks if the given entity is a projectile that is not stuck in the ground.
*/
static boolean isFlyingProjectile(Entity e) {
return isProjectile(e) && !(e instanceof MixinPersistentProjectileEntity && ((MixinPersistentProjectileEntity)e).isInGround());
}
/**
* Checks if the given projectile was thrown by the given entity
*/
public static <T extends Entity> boolean isProjectileThrownBy(Entity throwable, @Nullable T e) {
static <T extends Entity> boolean isProjectileThrownBy(Entity throwable, @Nullable T e) {
return e != null && isProjectile(throwable) && e.equals(((ProjectileEntity) throwable).getOwner());
}
@ -31,7 +40,7 @@ public class ProjectileUtil {
* @param inaccuracy Inaccuracy
* @return True the projectile's heading was set, false otherwise
*/
public static void setThrowableHeading(Entity throwable, Vec3d heading, float velocity, float inaccuracy) {
static void setThrowableHeading(Entity throwable, Vec3d heading, float velocity, float inaccuracy) {
if (throwable instanceof ProjectileEntity) {
((ProjectileEntity)throwable).setVelocity(heading.x, heading.y, heading.z, velocity, inaccuracy);

View file

@ -6,25 +6,25 @@ import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public interface VecHelper {
static Predicate<Entity> inRange(BlockPos center, double range) {
static Predicate<Entity> inRange(Vec3d center, double range) {
double rad = Math.pow(range, 2);
return e -> {
return e.squaredDistanceTo(center.getX(), center.getY(), center.getZ()) <= rad
|| e.squaredDistanceTo(center.getX(), center.getY() - e.getStandingEyeHeight(), center.getZ()) <= rad;
return e.squaredDistanceTo(center) <= rad
|| e.squaredDistanceTo(center.getX(), center.getY() - e.getStandingEyeHeight(), center.getZ()) <= rad;
};
}
static List<Entity> findInRange(@Nullable Entity origin, World w, BlockPos pos, double radius, @Nullable Predicate<Entity> predicate) {
return w.getOtherEntities(origin, new Box(pos).expand(radius), predicate == null ? inRange(pos, radius) : inRange(pos, radius).and(predicate));
static List<Entity> findInRange(@Nullable Entity origin, World w, Vec3d pos, double radius, @Nullable Predicate<Entity> predicate) {
return w.getOtherEntities(origin, Box.method_29968(pos).expand(radius), predicate == null ? inRange(pos, radius) : inRange(pos, radius).and(predicate));
}
/**
* Gets all entities within a given range from the player.
*/

View file

@ -13,6 +13,7 @@
"MixinItems",
"MixinLivingEntity",
"MixinMilkBucketItem",
"MixinPersistentProjectileEntity",
"MixinPlayerEntity",
"MixinProjectileEntity",
"MixinServerPlayerEntity",