mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-30 16:28:00 +01:00
Fix shields targetting the entity it belongs to
This commit is contained in:
parent
bbe9eb0068
commit
4151b66e99
12 changed files with 71 additions and 59 deletions
|
@ -5,6 +5,8 @@ import java.util.UUID;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,14 +29,23 @@ public interface Owned<E extends Entity> {
|
||||||
* Since {@link Owned#getMaster()} will only return if the owner is loaded, use this to perform checks
|
* Since {@link Owned#getMaster()} will only return if the owner is loaded, use this to perform checks
|
||||||
* in the owner's absence.
|
* in the owner's absence.
|
||||||
*/
|
*/
|
||||||
default Optional<UUID> getMasterId() {
|
Optional<UUID> getMasterId();
|
||||||
return Optional.of(getMaster()).map(Entity::getUuid);
|
|
||||||
|
default boolean isOwnerOrFriend(Entity target) {
|
||||||
|
return FriendshipBraceletItem.isComrade(this, target) || isOwnerOrVehicle(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isOwnerOrVehicle(@Nullable Entity target) {
|
||||||
|
if (isOwnedBy(target)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity owner = getMaster();
|
||||||
|
return target != null && owner != null && owner.isConnectedThroughVehicle(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isOwnedBy(@Nullable Object owner) {
|
default boolean isOwnedBy(@Nullable Object owner) {
|
||||||
return owner instanceof Entity e
|
return owner instanceof Entity e && e.getUuid().equals(getMasterId().orElse(null));
|
||||||
&& getMasterId().isPresent()
|
|
||||||
&& e.getUuid().equals(getMasterId().get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean hasCommonOwner(Owned<?> sibling) {
|
default boolean hasCommonOwner(Owned<?> sibling) {
|
||||||
|
|
|
@ -19,4 +19,8 @@ public interface Affine {
|
||||||
default boolean isFriendlyTogether(Affine other) {
|
default boolean isFriendlyTogether(Affine other) {
|
||||||
return getAffinity() != Affinity.BAD && other.getAffinity() != Affinity.BAD;
|
return getAffinity() != Affinity.BAD && other.getAffinity() != Affinity.BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default boolean applyInversion(Affine other, boolean friendly) {
|
||||||
|
return isEnemy(other) ? !friendly : friendly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,6 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFriendlyTogether(Affine other) {
|
public boolean isFriendlyTogether(Affine other) {
|
||||||
return accumulatedMass < 4;
|
return accumulatedMass < 4;
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell,
|
||||||
if (caster instanceof MagicProjectileEntity && getTraits().get(Trait.FOCUS) >= 50) {
|
if (caster instanceof MagicProjectileEntity && getTraits().get(Trait.FOCUS) >= 50) {
|
||||||
caster.findAllEntitiesInRange(
|
caster.findAllEntitiesInRange(
|
||||||
getTraits().get(Trait.FOCUS) - 49,
|
getTraits().get(Trait.FOCUS) - 49,
|
||||||
EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.notOwnerOrFriend(this, caster))
|
EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.validTarget(this, caster))
|
||||||
).findFirst().ifPresent(target -> {
|
).findFirst().ifPresent(target -> {
|
||||||
((MagicProjectileEntity)caster).setHomingTarget(target);
|
((MagicProjectileEntity)caster).setHomingTarget(target);
|
||||||
});
|
});
|
||||||
|
@ -60,7 +60,7 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell,
|
||||||
if (getTraits().get(Trait.FOCUS) >= 50 && target.getOrEmpty(caster.asWorld()).isEmpty()) {
|
if (getTraits().get(Trait.FOCUS) >= 50 && target.getOrEmpty(caster.asWorld()).isEmpty()) {
|
||||||
target.set(caster.findAllEntitiesInRange(
|
target.set(caster.findAllEntitiesInRange(
|
||||||
getTraits().get(Trait.FOCUS) - 49,
|
getTraits().get(Trait.FOCUS) - 49,
|
||||||
EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.notOwnerOrFriend(this, caster))
|
EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.validTarget(this, caster))
|
||||||
).findFirst().orElse(null));
|
).findFirst().orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.network.packet.s2c.play.PositionFlag;
|
import net.minecraft.network.packet.s2c.play.PositionFlag;
|
||||||
import net.minecraft.particle.ParticleEffect;
|
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -101,13 +100,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme
|
||||||
if (situation == Situation.GROUND) {
|
if (situation == Situation.GROUND) {
|
||||||
|
|
||||||
if (source.isClient()) {
|
if (source.isClient()) {
|
||||||
Vec3d origin = source.getOriginVector();
|
source.spawnParticles(particleArea, 5, pos -> {
|
||||||
|
|
||||||
ParticleEffect effect = getTarget()
|
|
||||||
.map(target -> (ParticleEffect)new FollowingParticleEffect(UParticles.HEALTH_DRAIN, target.pos(), 0.2F).withChild(ParticleTypes.ELECTRIC_SPARK))
|
|
||||||
.orElse(ParticleTypes.ELECTRIC_SPARK);
|
|
||||||
|
|
||||||
source.spawnParticles(origin, particleArea, 5, pos -> {
|
|
||||||
source.addParticle(ParticleTypes.ELECTRIC_SPARK, pos, Vec3d.ZERO);
|
source.addParticle(ParticleTypes.ELECTRIC_SPARK, pos, Vec3d.ZERO);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
.with(Trait.AIR, 9)
|
.with(Trait.AIR, 9)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final TargetSelecter targetSelecter = new TargetSelecter(this);
|
private final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget);
|
||||||
|
|
||||||
private float prevRadius;
|
private float prevRadius;
|
||||||
private float radius;
|
private float radius;
|
||||||
|
@ -174,11 +174,8 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long applyEntities(Caster<?> source) {
|
protected long applyEntities(Caster<?> source) {
|
||||||
double radius = this.radius;
|
|
||||||
|
|
||||||
Vec3d origin = getOrigin(source);
|
Vec3d origin = getOrigin(source);
|
||||||
|
targetSelecter.getEntities(source, radius).forEach(i -> {
|
||||||
targetSelecter.getEntities(source, radius, this::isValidTarget).forEach(i -> {
|
|
||||||
try {
|
try {
|
||||||
applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius);
|
applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
@ -11,26 +11,31 @@ import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Affine;
|
import com.minelittlepony.unicopia.ability.magic.Affine;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
|
||||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
|
|
||||||
public class TargetSelecter {
|
public class TargetSelecter {
|
||||||
|
|
||||||
private final Map<UUID, Target> targets = new TreeMap<>();
|
private final Map<UUID, Target> targets = new TreeMap<>();
|
||||||
|
|
||||||
private final Spell spell;
|
private final Spell spell;
|
||||||
|
|
||||||
|
private BiPredicate<Caster<?>, Entity> filter = (a, b) -> true;
|
||||||
|
|
||||||
public TargetSelecter(Spell spell) {
|
public TargetSelecter(Spell spell) {
|
||||||
this.spell = spell;
|
this.spell = spell;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<Entity> getEntities(Caster<?> source, double radius, BiPredicate<Caster<?>, Entity> filter) {
|
public TargetSelecter setFilter(BiPredicate<Caster<?>, Entity> filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<Entity> getEntities(Caster<?> source, double radius) {
|
||||||
targets.values().removeIf(Target::tick);
|
targets.values().removeIf(Target::tick);
|
||||||
return source.findAllEntitiesInRange(radius)
|
return source.findAllEntitiesInRange(radius)
|
||||||
.filter(entity -> entity.isAlive() && !entity.isRemoved() && notOwnerOrFriend(spell, source, entity))
|
.filter(EntityPredicates.VALID_ENTITY)
|
||||||
.filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE)
|
.filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE)
|
||||||
.filter(e -> filter.test(source, e))
|
.filter(entity -> entity != source.asEntity() && validTarget(spell, source, entity) && filter.test(source, entity))
|
||||||
.map(i -> {
|
.map(i -> {
|
||||||
targets.computeIfAbsent(i.getUuid(), Target::new);
|
targets.computeIfAbsent(i.getUuid(), Target::new);
|
||||||
return i;
|
return i;
|
||||||
|
@ -41,35 +46,19 @@ public class TargetSelecter {
|
||||||
return targets.values().stream().filter(Target::canHurt).count();
|
return targets.values().stream().filter(Target::canHurt).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Entity> Predicate<T> notOwnerOrFriend(Affine affine, Caster<?> source) {
|
public static <T extends Entity> Predicate<T> validTarget(Affine affine, Caster<?> source) {
|
||||||
return target -> notOwnerOrFriend(affine, source, target);
|
return target -> validTarget(affine, source, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Entity> Predicate<T> isOwnerOrFriend(Affine affine, Caster<?> source) {
|
public static boolean validTarget(Affine affine, Caster<?> source, Entity target) {
|
||||||
return target -> isOwnerOrFriend(affine, source, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Entity> boolean notOwnerOrFriend(Affine affine, Caster<?> source, Entity target) {
|
|
||||||
return !isOwnerOrFriend(affine, source, target);
|
return !isOwnerOrFriend(affine, source, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Entity> boolean isOwnerOrFriend(Affine affine, Caster<?> source, Entity target) {
|
public static boolean isOwnerOrFriend(Affine affine, Caster<?> source, Entity target) {
|
||||||
Entity owner = source.getMaster();
|
return affine.applyInversion(source, source.isOwnerOrFriend(target));
|
||||||
|
|
||||||
var equine = Pony.of(target);
|
|
||||||
if (equine.isPresent() && !affine.isFriendlyTogether(equine.get())) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (affine.isEnemy(source)) {
|
private static final class Target {
|
||||||
return FriendshipBraceletItem.isComrade(source, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FriendshipBraceletItem.isComrade(source, target)
|
|
||||||
|| (owner != null && (Pony.equal(target, owner) || owner.isConnectedThroughVehicle(target)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class Target {
|
|
||||||
private int cooldown = 20;
|
private int cooldown = 20;
|
||||||
|
|
||||||
Target(UUID id) { }
|
Target(UUID id) { }
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
||||||
private boolean discordedChanged = true;
|
private boolean discordedChanged = true;
|
||||||
private int smittenTicks;
|
private int smittenTicks;
|
||||||
|
|
||||||
private final Predicate<LivingEntity> targetPredicate = TargetSelecter.<LivingEntity>notOwnerOrFriend(() -> getOriginatingCaster().getAffinity(), this).and(e -> {
|
private final Predicate<LivingEntity> targetPredicate = TargetSelecter.<LivingEntity>validTarget(() -> getOriginatingCaster().getAffinity(), this).and(e -> {
|
||||||
return Equine.of(e)
|
return Equine.of(e)
|
||||||
.filter(eq -> eq instanceof Creature)
|
.filter(eq -> eq instanceof Creature)
|
||||||
.filter(eq -> isDiscorded() != ((Creature)eq).hasCommonOwner(this))
|
.filter(eq -> isDiscorded() != ((Creature)eq).hasCommonOwner(this))
|
||||||
|
|
|
@ -362,6 +362,11 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
return asEntity();
|
return asEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<UUID> getMasterId() {
|
||||||
|
return Optional.of(asEntity().getUuid());
|
||||||
|
}
|
||||||
|
|
||||||
public void onSpawn() {
|
public void onSpawn() {
|
||||||
if (entity.getWorld() instanceof ServerWorld sw && sw.getServer().getSaveProperties().getGameMode() != GameMode.ADVENTURE) {
|
if (entity.getWorld() instanceof ServerWorld sw && sw.getServer().getSaveProperties().getGameMode() != GameMode.ADVENTURE) {
|
||||||
boolean mustAvoidSun = getObservedSpecies() == Race.BAT && MeteorlogicalUtil.isPositionExposedToSun(sw, getOrigin());
|
boolean mustAvoidSun = getObservedSpecies() == Race.BAT && MeteorlogicalUtil.isPositionExposedToSun(sw, getOrigin());
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package com.minelittlepony.unicopia.entity.player.dummy;
|
package com.minelittlepony.unicopia.entity.player.dummy;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
@ -13,6 +16,7 @@ import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
import net.minecraft.client.network.PlayerListEntry;
|
import net.minecraft.client.network.PlayerListEntry;
|
||||||
import net.minecraft.client.render.entity.PlayerModelPart;
|
import net.minecraft.client.render.entity.PlayerModelPart;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -79,4 +83,9 @@ public class DummyClientPlayerEntity extends AbstractClientPlayerEntity implemen
|
||||||
public void setMaster(PlayerEntity owner) {
|
public void setMaster(PlayerEntity owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<UUID> getMasterId() {
|
||||||
|
return Optional.ofNullable(owner).map(Entity::getUuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package com.minelittlepony.unicopia.entity.player.dummy;
|
package com.minelittlepony.unicopia.entity.player.dummy;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.InteractionManager;
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
|
@ -7,6 +10,7 @@ import com.minelittlepony.unicopia.Owned;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -42,6 +46,11 @@ public class DummyPlayerEntity extends PlayerEntity implements Owned<PlayerEntit
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<UUID> getMasterId() {
|
||||||
|
return Optional.ofNullable(owner).map(Entity::getUuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldRenderName() {
|
public boolean shouldRenderName() {
|
||||||
return !InteractionManager.instance().isClientPlayer(getMaster());
|
return !InteractionManager.instance().isClientPlayer(getMaster());
|
||||||
|
|
|
@ -7,6 +7,7 @@ import java.util.stream.Stream;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
|
import com.minelittlepony.unicopia.Owned;
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||||
|
@ -113,16 +114,11 @@ public class FriendshipBraceletItem extends WearableItem implements DyeableItem,
|
||||||
&& ((FriendshipBraceletItem)stack.getItem()).checkSignature(stack, player);
|
&& ((FriendshipBraceletItem)stack.getItem()).checkSignature(stack, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isComrade(Caster<?> caster, Entity entity) {
|
public static boolean isComrade(Owned<?> caster, Entity entity) {
|
||||||
if (entity instanceof LivingEntity) {
|
return entity instanceof LivingEntity l && caster.getMasterId()
|
||||||
return caster.getMasterId()
|
.filter(id -> getWornBangles(l).anyMatch(stack -> isSignedBy(stack, id)))
|
||||||
.filter(id -> getWornBangles((LivingEntity)entity)
|
|
||||||
.anyMatch(stack -> isSignedBy(stack, id))
|
|
||||||
)
|
|
||||||
.isPresent();
|
.isPresent();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Stream<Pony> getPartyMembers(Caster<?> caster, double radius) {
|
public static Stream<Pony> getPartyMembers(Caster<?> caster, double radius) {
|
||||||
return Pony.stream(caster.findAllEntitiesInRange(radius, entity -> isComrade(caster, entity)));
|
return Pony.stream(caster.findAllEntitiesInRange(radius, entity -> isComrade(caster, entity)));
|
||||||
|
|
Loading…
Reference in a new issue