diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java index 57e2d48a..0cb58ada 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java @@ -128,11 +128,11 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell { protected abstract void saveDelegates(NbtCompound compound); - private Stream getDelegates(Function cast) { + protected Stream getDelegates(Function cast) { return getDelegates().stream().map(cast).filter(Objects::nonNull); } - private static boolean execute(Stream spells, Function action) { + protected static boolean execute(Stream spells, Function action) { return spells.reduce(false, (u, a) -> action.apply(a), (a, b) -> a || b); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/OrientedSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/OrientedSpell.java new file mode 100644 index 00000000..eefb5642 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/OrientedSpell.java @@ -0,0 +1,5 @@ +package com.minelittlepony.unicopia.ability.magic.spell; + +public interface OrientedSpell { + void setOrientation(float pitch, float yaw); +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java index b488c5d5..48a1b15b 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlaceableSpell.java @@ -28,7 +28,7 @@ import net.minecraft.world.World; * The spell's effects are still powered by the casting player, so if the player dies or leaves the area, their * spell loses affect until they return. */ -public class PlaceableSpell extends AbstractDelegatingSpell { +public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedSpell { /** * Dimension the spell was originally cast in */ @@ -83,41 +83,19 @@ public class PlaceableSpell extends AbstractDelegatingSpell { setDirty(); } - if (getWorld(source).map(castEntity::isUnlinked).orElse(false)) { - CastSpellEntity entity = UEntities.CAST_SPELL.create(source.getReferenceWorld()); - Vec3d pos = castEntity.getPosition().orElse(source.getOriginVector()); - entity.updatePositionAndAngles(pos.x, pos.y, pos.z, 0, 0); - PlaceableSpell copy = spell.toPlaceable(); - if (spell instanceof PlacementDelegate delegate) { - delegate.onPlaced(source, copy, entity); - } - entity.getSpellSlot().put(copy); - entity.setCaster(source); - entity.world.spawnEntity(entity); - Ether.get(entity.world).put(getType(), entity); - - castEntity.set(entity); - setDirty(); - } else { - - if (getWorld(source).map(Ether::get) - .flatMap(ether -> castEntity.getId().flatMap(id -> ether.getEntry(getType(), id))) - .isEmpty()) { - setDead(); - } - } + castEntity.getId().ifPresentOrElse( + id -> checkDetachment(source, id), + () -> spawnPlacedEntity(source) + ); } return !isDead(); } if (situation == Situation.GROUND_ENTITY) { - - if (!source.isClient()) { - if (Ether.get(source.getReferenceWorld()).getEntry(getType(), source).isEmpty()) { - setDead(); - return false; - } + if (!source.isClient() && Ether.get(source.getReferenceWorld()).getEntry(getType(), source).isEmpty()) { + setDead(); + return false; } if (spell instanceof PlacementDelegate delegate) { @@ -134,6 +112,38 @@ public class PlaceableSpell extends AbstractDelegatingSpell { return !isDead(); } + private void checkDetachment(Caster source, UUID id) { + if (getWorld(source).map(Ether::get).flatMap(ether -> ether.getEntry(getType(), id)).isEmpty()) { + setDead(); + } + } + + private void spawnPlacedEntity(Caster source) { + CastSpellEntity entity = UEntities.CAST_SPELL.create(source.getReferenceWorld()); + Vec3d pos = castEntity.getPosition().orElse(source.getOriginVector()); + entity.updatePositionAndAngles(pos.x, pos.y, pos.z, source.getEntity().getYaw(), source.getEntity().getPitch()); + PlaceableSpell copy = spell.toPlaceable(); + if (spell instanceof PlacementDelegate delegate) { + delegate.onPlaced(source, copy, entity); + } + entity.getSpellSlot().put(copy); + entity.setCaster(source); + entity.world.spawnEntity(entity); + Ether.get(entity.world).put(getType(), entity); + + castEntity.set(entity); + setDirty(); + } + + @Override + public void setOrientation(float pitch, float yaw) { + this.pitch = -90 - pitch; + this.yaw = -yaw; + getDelegates(spell -> spell instanceof OrientedSpell o ? o : null) + .forEach(oriented -> oriented.setOrientation(pitch, yaw)); + setDirty(); + } + @Override public void onDestroyed(Caster source) { if (!source.isClient()) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java index 011cd45b..2be2caf5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java @@ -26,7 +26,7 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.WorldEvents; -public class PortalSpell extends AbstractSpell implements PlaceableSpell.PlacementDelegate { +public class PortalSpell extends AbstractSpell implements PlaceableSpell.PlacementDelegate, OrientedSpell { public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder() .with(Trait.LIFE, 10) .with(Trait.KNOWLEDGE, 1) @@ -48,8 +48,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme @Override public boolean apply(Caster caster) { - pitch = caster.getEntity().getPitch(1); - yaw = caster.getEntity().getYaw(1); + setOrientation(caster.getEntity().getPitch(), caster.getEntity().getYaw()); return toPlaceable().apply(caster); } @@ -118,7 +117,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme Vec3d dest = targetPos.add(offset.rotateY(yawDifference * MathHelper.RADIANS_PER_DEGREE)).add(0, 0.05, 0); entity.resetPortalCooldown(); - entity.timeUntilRegen = 20; + entity.timeUntilRegen = 100; entity.setYaw(entity.getYaw() + yawDifference); entity.setVelocity(entity.getVelocity().rotateY(yawDifference * MathHelper.RADIANS_PER_DEGREE)); @@ -157,21 +156,18 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme return teleportationTarget.getId().flatMap(id -> Ether.get(source.getReferenceWorld()).getEntry(getType(), id)); } + @Override + public void setOrientation(float pitch, float yaw) { + this.pitch = pitch; + this.yaw = yaw; + setDirty(); + } + @Override public void onPlaced(Caster source, PlaceableSpell parent, CastSpellEntity entity) { LivingEntity caster = source.getMaster(); Vec3d targetPos = caster.getRotationVector().multiply(3).add(caster.getEyePos()); - - parent.pitch = -90 - pitch; - parent.yaw = -yaw; - - for (Spell delegate : parent.getDelegates()) { - if (delegate instanceof PortalSpell copy) { - copy.pitch = pitch; - copy.yaw = yaw; - } - } - + parent.setOrientation(pitch, yaw); entity.setPos(targetPos.x, caster.getY() + 1.5, targetPos.z); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java index d6af5658..b350209c 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityReference.java @@ -84,10 +84,6 @@ public class EntityReference implements NbtSerialisable { return entity != null && entity.getUuid().equals(uuid.orElse(null)); } - public boolean isUnlinked(World world) { - return getId().isEmpty() || getOrEmpty(world).map(e -> e.isRemoved()).orElse(false); - } - public boolean isPresent(World world) { return getOrEmpty(world).isPresent(); }