From 9a0041e295fd08aec5b3330154352f7c64066e8f Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 6 Aug 2023 18:26:17 +0100 Subject: [PATCH] Fixed unable to place the necromancy spell --- .../minelittlepony/unicopia/WeaklyOwned.java | 3 +- .../ability/ChangelingDisguiseAbility.java | 3 +- .../ability/PegasusRainboomAbility.java | 3 +- .../ability/UnicornCastingAbility.java | 3 +- .../unicopia/ability/magic/Caster.java | 7 - .../magic/spell/AbstractAreaEffectSpell.java | 4 +- .../ability/magic/spell/CastingMethod.java | 24 +++ .../ability/magic/spell/PlaceableSpell.java | 26 +-- .../unicopia/ability/magic/spell/Spell.java | 8 + .../ability/magic/spell/ThrowableSpell.java | 7 +- .../magic/spell/effect/AttractiveSpell.java | 13 +- .../magic/spell/effect/BubbleSpell.java | 2 +- .../spell/effect/CustomisedSpellType.java | 5 +- .../magic/spell/effect/DarkVortexSpell.java | 6 +- .../magic/spell/effect/DisplacementSpell.java | 4 +- .../magic/spell/effect/FireBoltSpell.java | 2 +- .../magic/spell/effect/LightSpell.java | 10 +- .../magic/spell/effect/MindSwapSpell.java | 5 +- .../magic/spell/effect/NecromancySpell.java | 28 ++-- .../magic/spell/effect/PortalSpell.java | 20 +-- .../magic/spell/effect/ScorchSpell.java | 6 +- .../magic/spell/effect/ShieldSpell.java | 9 +- .../magic/spell/effect/TargetSelecter.java | 16 +- .../unicopia/command/CastCommand.java | 3 +- .../unicopia/command/DisguiseCommand.java | 3 +- .../unicopia/entity/CastSpellEntity.java | 5 - .../unicopia/entity/EntityReference.java | 157 +++++++++++------- .../unicopia/item/EnchantedStaffItem.java | 5 +- 28 files changed, 234 insertions(+), 153 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/magic/spell/CastingMethod.java diff --git a/src/main/java/com/minelittlepony/unicopia/WeaklyOwned.java b/src/main/java/com/minelittlepony/unicopia/WeaklyOwned.java index f1d20651..514c22fd 100644 --- a/src/main/java/com/minelittlepony/unicopia/WeaklyOwned.java +++ b/src/main/java/com/minelittlepony/unicopia/WeaklyOwned.java @@ -6,6 +6,7 @@ import java.util.UUID; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.entity.EntityReference.EntityValues; import net.minecraft.entity.Entity; @@ -26,7 +27,7 @@ public interface WeaklyOwned extends Owned, WorldConvertabl @Override default Optional getMasterId() { - return getMasterReference().getId(); + return getMasterReference().getTarget().map(EntityValues::uuid); } interface Mutable extends WeaklyOwned, Owned.Mutable { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java index 2ebaa7e7..c0711973 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ChangelingDisguiseAbility.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity; @@ -51,7 +52,7 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility { player.getEntityWorld().playSound(null, player.getBlockPos(), USounds.ENTITY_PLAYER_CHANGELING_TRANSFORM, SoundCategory.PLAYERS, 1.4F, 0.4F); iplayer.getSpellSlot().get(SpellType.CHANGELING_DISGUISE, true) - .orElseGet(() -> SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer)) + .orElseGet(() -> SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer, CastingMethod.INNATE)) .setDisguise(looked); if (!player.isCreative()) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java index e50fbbc6..36557587 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.MagicParticleEffect; @@ -78,7 +79,7 @@ public class PegasusRainboomAbility implements Ability { player.subtractEnergyCost(9); player.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, player.getPhysics().getMotionAngle()), player.getOriginVector(), Vec3d.ZERO); - SpellType.RAINBOOM.withTraits().apply(player); + SpellType.RAINBOOM.withTraits().apply(player, CastingMethod.INNATE); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java index 048dd4b3..8b5a0d2d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.*; import com.minelittlepony.unicopia.ability.data.Hit; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; @@ -106,7 +107,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility { }, true); player.subtractEnergyCost(removed ? 2 : 4); if (!removed) { - Spell s = spell.apply(player); + Spell s = spell.apply(player, CastingMethod.GEM); if (s == null) { player.spawnParticles(ParticleTypes.LARGE_SMOKE, 6); player.playSound(USounds.SPELL_CAST_FAIL, 1, 0.5F); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/Caster.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/Caster.java index d8797f45..98264836 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/Caster.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/Caster.java @@ -45,13 +45,6 @@ public interface Caster extends */ boolean subtractEnergyCost(double amount); - /** - * Gets the entity who originally cast the currently active spell. - * @return - */ - @Override - LivingEntity getMaster(); - /** * Gets the original caster responsible for this spell. * If none is found, will return itself. diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java index 374a9049..c0f63418 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java @@ -9,7 +9,7 @@ public abstract class AbstractAreaEffectSpell extends AbstractSpell { } @Override - public boolean apply(Caster source) { - return toPlaceable().apply(source); + public Spell prepareForCast(Caster caster, CastingMethod method) { + return toPlaceable(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/CastingMethod.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/CastingMethod.java new file mode 100644 index 00000000..b67a1493 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/CastingMethod.java @@ -0,0 +1,24 @@ +package com.minelittlepony.unicopia.ability.magic.spell; + +public enum CastingMethod { + /** + * Casting from a gem or a unicorn's equipped spell. + */ + GEM, + /** + * Casting a projectile form from a gem or unicorn's equipped spell + */ + GEM_PROJECTILE, + /** + * Result of a projectile impact + */ + PROJECTILE, + /** + * Casting from a magic staff + */ + STAFF, + /** + * Result of an entities innate ability + */ + INNATE +} \ No newline at end of file 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 6f23df66..d1bc68ac 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 @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.entity.CastSpellEntity; import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.entity.EntityReference.EntityValues; import com.minelittlepony.unicopia.entity.UEntities; import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect; import com.minelittlepony.unicopia.particle.ParticleHandle; @@ -86,8 +87,8 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS setDirty(); } - castEntity.getId().ifPresentOrElse( - id -> checkDetachment(source, id), + castEntity.getTarget().ifPresentOrElse( + target -> checkDetachment(source, target), () -> spawnPlacedEntity(source) ); } @@ -96,9 +97,12 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS } if (situation == Situation.GROUND_ENTITY) { - if (!source.isClient() && Ether.get(source.asWorld()).getEntry(getType(), source).isEmpty()) { - setDead(); - return false; + if (!source.isClient()) { + Ether ether = Ether.get(source.asWorld()); + if (ether.getEntry(getType(), source).isEmpty()) { + setDead(); + return false; + } } if (spell instanceof PlacementDelegate delegate) { @@ -115,15 +119,15 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS return !isDead(); } - private void checkDetachment(Caster source, UUID id) { - if (getWorld(source).map(Ether::get).flatMap(ether -> ether.getEntry(getType(), id)).isEmpty()) { + private void checkDetachment(Caster source, EntityValues target) { + if (getWorld(source).map(Ether::get).flatMap(ether -> ether.getEntry(getType(), target.uuid())).isEmpty()) { setDead(); } } private void spawnPlacedEntity(Caster source) { CastSpellEntity entity = UEntities.CAST_SPELL.create(source.asWorld()); - Vec3d pos = castEntity.getPosition().orElse(position.orElse(source.getOriginVector())); + Vec3d pos = getPosition().orElse(position.orElse(source.getOriginVector())); entity.updatePositionAndAngles(pos.x, pos.y, pos.z, source.asEntity().getYaw(), source.asEntity().getPitch()); PlaceableSpell copy = spell.toPlaceable(); if (spell instanceof PlacementDelegate delegate) { @@ -162,9 +166,9 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS @Override public void onDestroyed(Caster source) { if (!source.isClient()) { - castEntity.getId().ifPresent(id -> { + castEntity.getTarget().ifPresent(target -> { getWorld(source).map(Ether::get) - .flatMap(ether -> ether.getEntry(getType(), id)) + .flatMap(ether -> ether.getEntry(getType(), target.uuid())) .ifPresent(Ether.Entry::markDead); }); castEntity.set(null); @@ -184,7 +188,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS } public Optional getPosition() { - return castEntity.getPosition(); + return castEntity.getTarget().map(EntityValues::pos); } public Optional getParticleEffectAttachment(Caster source) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java index 70763235..750af98d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java @@ -74,6 +74,14 @@ public interface Spell extends NbtSerialisable, Affine { return true; } + /** + * Gets the default form of this spell used to apply to a caster. + * @param caster + */ + default Spell prepareForCast(Caster caster, CastingMethod method) { + return this; + } + /** * Called to generate this spell's effects. * @param caster The caster currently fueling this spell diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java index f0f8bc15..80687e59 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java @@ -33,6 +33,11 @@ public final class ThrowableSpell extends AbstractDelegatingSpell { return List.of(spell); } + @Override + public boolean apply(Caster source) { + return throwProjectile(source).isPresent(); + } + /** * Projects this spell. * @@ -59,7 +64,7 @@ public final class ThrowableSpell extends AbstractDelegatingSpell { projectile.setPosition(entity.getX(), entity.getEyeY() - 0.1F, entity.getZ()); projectile.setOwner(entity); projectile.setItem(UItems.GEMSTONE.getDefaultStack(spell.getType())); - projectile.getSpellSlot().put(spell); + spell.prepareForCast(caster, CastingMethod.PROJECTILE).apply(projectile); projectile.setVelocity(entity, entity.getPitch(), entity.getYaw(), 0, 1.5F, divergance); projectile.setNoGravity(true); configureProjectile(projectile, caster); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java index 2336c4bd..0f857102 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java @@ -45,11 +45,12 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp } setDirty(); - - Vec3d pos = caster.getOriginVector(); - if (target.isPresent(caster.asWorld()) && target.get(caster.asWorld()).distanceTo(caster.asEntity()) > getDrawDropOffRange(caster)) { - target.get(caster.asWorld()).requestTeleport(pos.x, pos.y, pos.z); - } + target.getOrEmpty(caster.asWorld()) + .filter(entity -> entity.distanceTo(caster.asEntity()) > getDrawDropOffRange(caster)) + .ifPresent(entity -> { + Vec3d pos = caster.getOriginVector(); + entity.requestTeleport(pos.x, pos.y, pos.z); + }); return super.tick(caster, situation); } @@ -145,7 +146,7 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) { if (!isDead() && getTraits().get(Trait.CHAOS) > 0) { setDead(); - Caster.of(hit.getEntity()).ifPresent(getTypeAndTraits()::apply); + Caster.of(hit.getEntity()).ifPresent(caster -> getTypeAndTraits().apply(caster, CastingMethod.PROJECTILE)); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java index 323e8555..f473a416 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java @@ -154,7 +154,7 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell, @Override public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) { Caster.of(hit.getEntity()).ifPresent(caster -> { - getTypeAndTraits().apply(caster); + getTypeAndTraits().apply(caster, CastingMethod.PROJECTILE); }); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java index b00053f4..f3c8991c 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; @@ -32,13 +33,13 @@ public record CustomisedSpellType ( @Nullable - public T apply(Caster caster) { + public T apply(Caster caster, CastingMethod method) { if (isEmpty()) { return null; } T spell = create(); - if (spell != null && spell.apply(caster)) { + if (spell != null && spell.prepareForCast(caster, method).apply(caster)) { return spell; } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java index bfd2123a..a64f1493 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DarkVortexSpell.java @@ -5,7 +5,9 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Affine; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; +import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.damage.UDamageTypes; @@ -66,8 +68,8 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega } @Override - public boolean apply(Caster source) { - return toPlaceable().apply(source); + public Spell prepareForCast(Caster caster, CastingMethod method) { + return method == CastingMethod.STAFF ? toThrowable() : toPlaceable(); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java index bc9235a1..fbc22bed 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -27,8 +27,8 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pla } @Override - public boolean apply(Caster caster) { - return toPlaceable().apply(caster); + public Spell prepareForCast(Caster caster, CastingMethod method) { + return toPlaceable(); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java index 8a5ea3cd..c2324a5f 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java @@ -57,7 +57,7 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, return true; } - if (getTraits().get(Trait.FOCUS) >= 50 && !target.isPresent(caster.asWorld())) { + if (getTraits().get(Trait.FOCUS) >= 50 && target.getOrEmpty(caster.asWorld()).isEmpty()) { target.set(caster.findAllEntitiesInRange( getTraits().get(Trait.FOCUS) - 49, EntityPredicates.VALID_LIVING_ENTITY.and(TargetSelecter.notOwnerOrFriend(this, caster)) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java index afa33e74..400e9af6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java @@ -4,11 +4,13 @@ import java.util.ArrayList; import java.util.List; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.entity.EntityReference.EntityValues; import com.minelittlepony.unicopia.entity.FairyEntity; import com.minelittlepony.unicopia.entity.UEntities; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; @@ -60,14 +62,14 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD if (lights.isEmpty()) { int size = 2 + caster.asWorld().random.nextInt(2) + (int)(getTraits().get(Trait.LIFE, 10, 20) - 10)/10; while (lights.size() < size) { - lights.add(new EntityReference()); + lights.add(new EntityReference<>()); } } lights.forEach(ref -> { - if (!ref.isPresent(caster.asWorld())) { + if (ref.getOrEmpty(caster.asWorld()).isEmpty()) { FairyEntity entity = UEntities.TWITTERMITE.create(caster.asWorld()); - entity.setPosition(ref.getPosition().orElseGet(() -> { + entity.setPosition(ref.getTarget().map(EntityValues::pos).orElseGet(() -> { return caster.getOriginVector().add(VecHelper.supply(() -> caster.asWorld().random.nextInt(3) - 1)); })); entity.setMaster(caster); @@ -84,7 +86,7 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD @Override public void onImpact(MagicProjectileEntity projectile) { - Caster.of(projectile.getMaster()).ifPresent(getTypeAndTraits()::apply); + Caster.of(projectile.getMaster()).ifPresent(caster -> getTypeAndTraits().apply(caster, CastingMethod.PROJECTILE)); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MindSwapSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MindSwapSpell.java index 829104cf..14fbb580 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MindSwapSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MindSwapSpell.java @@ -4,6 +4,7 @@ import java.util.Optional; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.entity.EntityReference; import com.minelittlepony.unicopia.entity.behaviour.EntitySwap; @@ -65,7 +66,7 @@ public class MindSwapSpell extends MimicSpell { setDisguise(e); Caster other = Caster.of(e).get(); - SpellType.MIMIC.withTraits().apply(other).setDisguise(master); + SpellType.MIMIC.withTraits().apply(other, CastingMethod.PROJECTILE).setDisguise(master); EntitySwap.ALL.accept(master, e); Inventory.swapInventories( @@ -80,7 +81,7 @@ public class MindSwapSpell extends MimicSpell { }); } - if (counterpart.getId().isPresent() && counterpart.get(caster.asWorld()) == null) { + if (counterpart.isSet() && counterpart.get(caster.asWorld()) == null) { caster.getOriginatingCaster().asEntity().damage(caster.asWorld().getDamageSources().magic(), Float.MAX_VALUE); setDead(); return false; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java index ddd8f605..8c15c9a3 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/NecromancySpell.java @@ -72,9 +72,15 @@ public class NecromancySpell extends AbstractAreaEffectSpell implements Projecti super(type); } + @Override + public Spell prepareForCast(Caster caster, CastingMethod method) { + return method == CastingMethod.GEM ? toPlaceable() : super.prepareForCast(caster, method); + } + @Override public boolean tick(Caster source, Situation situation) { - float radius = source.getLevel().getScaled(4) * 4 + getTraits().get(Trait.POWER); + + float radius = 4 + source.getLevel().getScaled(4) * 4 + getTraits().get(Trait.POWER); if (radius <= 0) { return false; @@ -82,22 +88,22 @@ public class NecromancySpell extends AbstractAreaEffectSpell implements Projecti boolean rainy = source.asWorld().hasRain(source.getOrigin()); - if (source.isClient()) { - source.spawnParticles(new Sphere(true, radius * 2), rainy ? 98 : 125, pos -> { - BlockPos bpos = BlockPos.ofFloored(pos); + source.spawnParticles(new Sphere(true, radius * 2), rainy ? 98 : 125, pos -> { + BlockPos bpos = BlockPos.ofFloored(pos); - if (!source.asWorld().isAir(bpos.down())) { - source.addParticle(source.asWorld().hasRain(bpos) ? ParticleTypes.SMOKE : ParticleTypes.FLAME, pos, Vec3d.ZERO); - } - }); - return true; - } + if (source.asWorld().isAir(bpos) && !source.asWorld().isAir(bpos.down())) { + source.addParticle(source.asWorld().hasRain(bpos) ? ParticleTypes.SMOKE : ParticleTypes.FLAME, pos, Vec3d.ZERO); + } + }); - if (source.asWorld().getDifficulty() == Difficulty.PEACEFUL) { + if (source.isClient() || source.asWorld().getDifficulty() == Difficulty.PEACEFUL) { return true; } summonedEntities.removeIf(ref -> ref.getOrEmpty(source.asWorld()).filter(e -> { + if (e.isRemoved()) { + return false; + } if (e.getPos().distanceTo(source.getOriginVector()) > radius * 2) { e.getWorld().sendEntityStatus(e, (byte)60); e.discard(); 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 dc0fd4b0..2ef4d347 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 @@ -62,10 +62,10 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme if (source.isClient()) { Vec3d origin = source.getOriginVector(); - ParticleEffect effect = teleportationTarget.getPosition() + ParticleEffect effect = teleportationTarget.getTarget() .map(target -> { getType(); - return new FollowingParticleEffect(UParticles.HEALTH_DRAIN, target, 0.2F).withChild(ParticleTypes.ELECTRIC_SPARK); + return new FollowingParticleEffect(UParticles.HEALTH_DRAIN, target.pos(), 0.2F).withChild(ParticleTypes.ELECTRIC_SPARK); }) .orElse(ParticleTypes.ELECTRIC_SPARK); @@ -73,7 +73,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme source.addParticle(effect, pos, Vec3d.ZERO); }); - teleportationTarget.getPosition().ifPresentOrElse(position -> { + teleportationTarget.getTarget().ifPresentOrElse(target -> { particleEffect.update(getUuid(), source, spawner -> { spawner.addParticle(new SphereParticleEffect(UParticles.DISK, getType().getColor(), 0.8F, 1.8F, new Vec3d(pitch, yaw, 0)), source.getOriginVector(), Vec3d.ZERO); }); @@ -81,9 +81,9 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme particleEffect.destroy(); }); } else { - teleportationTarget.getId().ifPresent(id -> { - if (Ether.get(source.asWorld()).getEntry(getType(), id).isEmpty()) { - Unicopia.LOGGER.debug("Lost sibling, breaking connection to " + id); + teleportationTarget.getTarget().ifPresent(target -> { + if (Ether.get(source.asWorld()).getEntry(getType(), target.uuid()).isEmpty()) { + Unicopia.LOGGER.debug("Lost sibling, breaking connection to " + target.uuid()); teleportationTarget.set(null); setDirty(); source.asWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, source.getOrigin(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState())); @@ -109,12 +109,12 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme private void tickWithTargetLink(Caster source, Ether.Entry destination) { - destination.entity.getPosition().ifPresent(targetPos -> { + destination.entity.getTarget().ifPresent(target -> { source.findAllEntitiesInRange(1).forEach(entity -> { if (!entity.hasPortalCooldown() && entity.timeUntilRegen <= 0) { Vec3d offset = entity.getPos().subtract(source.getOriginVector()); float yawDifference = pitch < 15 ? (180 - yaw + destination.yaw) : 0; - Vec3d dest = targetPos.add(offset.rotateY(yawDifference * MathHelper.RADIANS_PER_DEGREE)).add(0, 0.05, 0); + Vec3d dest = target.pos().add(offset.rotateY(yawDifference * MathHelper.RADIANS_PER_DEGREE)).add(0, 0.05, 0); entity.resetPortalCooldown(); entity.timeUntilRegen = 100; @@ -145,7 +145,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme Ether ether = Ether.get(source.asWorld()); ether.getEntries(getType()) .stream() - .filter(entry -> entry.isAvailable() && !entry.entity.referenceEquals(source.asEntity()) && entry.entity.getId().isPresent()) + .filter(entry -> entry.isAvailable() && !entry.entity.referenceEquals(source.asEntity()) && entry.entity.isSet()) .findAny() .ifPresent(entry -> { entry.setTaken(true); @@ -155,7 +155,7 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme } private Optional getTarget(Caster source) { - return teleportationTarget.getId().flatMap(id -> Ether.get(source.asWorld()).getEntry(getType(), id)); + return teleportationTarget.getTarget().flatMap(target -> Ether.get(source.asWorld()).getEntry(getType(), target.uuid())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java index 59ec591b..24c8a632 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ScorchSpell.java @@ -1,7 +1,9 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; +import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.block.state.StateMaps; @@ -25,8 +27,8 @@ public class ScorchSpell extends FireSpell implements ProjectileDelegate.Configu } @Override - public boolean apply(Caster source) { - return toPlaceable().apply(source); + public Spell prepareForCast(Caster caster, CastingMethod method) { + return method == CastingMethod.STAFF ? this : toPlaceable(); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java index 6ff5e50b..3f011958 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/ShieldSpell.java @@ -4,7 +4,9 @@ import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Situation; +import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.entity.player.Pony; @@ -47,11 +49,8 @@ public class ShieldSpell extends AbstractSpell { } @Override - public boolean apply(Caster source) { - if (getTraits().get(Trait.GENEROSITY) > 0) { - return toPlaceable().apply(source); - } - return super.apply(source); + public Spell prepareForCast(Caster caster, CastingMethod method) { + return method == CastingMethod.STAFF || getTraits().get(Trait.GENEROSITY) > 0 ? toPlaceable() : this; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java index 209ec2d4..29bc1f96 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TargetSelecter.java @@ -43,22 +43,22 @@ public class TargetSelecter { return targets.values().stream().filter(Target::canHurt).count(); } - public static Predicate notOwnerOrFriend(Affine spell, Caster source) { - return target -> notOwnerOrFriend(spell, source, target); + public static Predicate notOwnerOrFriend(Affine affine, Caster source) { + return target -> notOwnerOrFriend(affine, source, target); } - public static Predicate isOwnerOrFriend(Affine spell, Caster source) { - return target -> isOwnerOrFriend(spell, source, target); + public static Predicate isOwnerOrFriend(Affine affine, Caster source) { + return target -> isOwnerOrFriend(affine, source, target); } - public static boolean notOwnerOrFriend(Affine spell, Caster source, Entity target) { - return !isOwnerOrFriend(spell, source, target); + public static boolean notOwnerOrFriend(Affine affine, Caster source, Entity target) { + return !isOwnerOrFriend(affine, source, target); } - public static boolean isOwnerOrFriend(Affine spell, Caster source, Entity target) { + public static boolean isOwnerOrFriend(Affine affine, Caster source, Entity target) { Entity owner = source.getMaster(); - if (!(spell.isFriendlyTogether(source) && EquinePredicates.PLAYER_UNICORN.test(owner))) { + if (affine.isEnemy(source) || !EquinePredicates.PLAYER_UNICORN.test(owner)) { return FriendshipBraceletItem.isComrade(source, target); } diff --git a/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java b/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java index 9614bffb..f114dca9 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/CastCommand.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.command; import java.util.Optional; import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.PlaceableSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; @@ -112,7 +113,7 @@ public class CastCommand { private static int apply(CommandContext source, TraitsFunc traits) throws CommandSyntaxException { CustomisedSpellType spellType = getSpell(source, traits); EntityArgumentType.getEntities(source, "targets").forEach(target -> { - Caster.of(target).ifPresent(caster -> spellType.apply(caster)); + Caster.of(target).ifPresent(caster -> spellType.apply(caster, CastingMethod.INNATE)); }); return 0; diff --git a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java index 5fbcd174..8dbca1b1 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java @@ -5,6 +5,7 @@ import java.util.function.Function; import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.player.Pony; import com.mojang.authlib.GameProfile; @@ -83,7 +84,7 @@ public class DisguiseCommand { Pony iplayer = Pony.of(player); iplayer.getSpellSlot().get(SpellType.CHANGELING_DISGUISE, true) - .orElseGet(() -> SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer)) + .orElseGet(() -> SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer, CastingMethod.INNATE)) .setDisguise(entity); if (source.getEntity() == player) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/CastSpellEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/CastSpellEntity.java index 63592f7f..81cf9fc6 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/CastSpellEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/CastSpellEntity.java @@ -88,11 +88,6 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster The type of the entity this reference points to. */ public class EntityReference implements NbtSerialisable { + @Nullable + private EntityValues reference; - /** - * Server UUID of the entity used to look up the entity instance on the server. - */ - private Optional uuid = Optional.empty(); - /** - * Corresponding client id used to look up the entity instance on the client. - */ - private int clientId; - /** - * The last-known position of the entity. - */ - private Optional pos = Optional.empty(); + private WeakReference directReference = new WeakReference<>(null); public EntityReference() {} @@ -48,48 +46,42 @@ public class EntityReference implements NbtSerialisable { fromNBT(nbt); } + @SuppressWarnings("unchecked") public void copyFrom(EntityReference other) { - uuid = other.uuid; - clientId = other.clientId; - pos = other.pos; + this.reference = ((EntityReference)other).reference; + this.directReference = new WeakReference<>(other.directReference.get()); } - public void set(@Nullable T entity) { - if (entity != null) { - uuid = Optional.of(entity.getUuid()); - clientId = entity.getId(); - pos = Optional.of(entity.getPos()); - } else { - uuid = Optional.empty(); - clientId = 0; - pos = Optional.empty(); + public boolean set(@Nullable T entity) { + this.directReference = new WeakReference<>(entity); + this.reference = entity == null ? null : new EntityValues<>(entity); + return entity != null; + } + + public Optional> getTarget() { + T value = directReference.get(); + if (value != null) { + set(value); } - } - - /** - * Gets the assigned entity's UUID - */ - public Optional getId() { - return uuid; - } - - /** - * Gets the last known position of the assigned entity. - */ - public Optional getPosition() { - return pos; + return Optional.ofNullable(reference); } public boolean isSet() { - return getId().isPresent(); + return reference != null; } public boolean referenceEquals(Entity entity) { - return entity != null && entity.getUuid().equals(uuid.orElse(null)); + return entity != null && referenceEquals(entity.getUuid()); } - public boolean isPresent(World world) { - return getOrEmpty(world).isPresent(); + public boolean referenceEquals(UUID uuid) { + return (reference == null ? Util.NIL_UUID : reference.uuid()).equals(uuid); + } + + public boolean referenceEquals(@Nullable EntityReference other) { + final EntityValues st = reference; + final EntityValues ot = other == null ? null : other.reference; + return st == ot || (st != null && ot != null && Objects.equals(st.uuid(), ot.uuid())); } public void ifPresent(World world, Consumer consumer) { @@ -101,35 +93,74 @@ public class EntityReference implements NbtSerialisable { return getOrEmpty(world).orElse(null); } - @SuppressWarnings("unchecked") public Optional getOrEmpty(World world) { - if (uuid.isPresent() && world instanceof ServerWorld serverWorld) { - return uuid.map(serverWorld::getEntity).map(e -> (T)e).filter(this::checkReference); - } - - if (clientId != 0) { - return Optional.ofNullable((T)world.getEntityById(clientId)).filter(this::checkReference); - } - - return Optional.empty(); - } - - private boolean checkReference(Entity e) { - pos = Optional.of(e.getPos()); - return e instanceof PlayerEntity || !e.isRemoved(); + return Optional.ofNullable(directReference.get()) + .or(() -> reference == null ? Optional.empty() : reference.resolve(world)) + .filter(this::set); } @Override public void toNBT(NbtCompound tag) { - uuid.ifPresent(uuid -> tag.putUuid("uuid", uuid)); - pos.ifPresent(p -> tag.put("pos", NbtSerialisable.writeVector(p))); - tag.putInt("clientId", clientId); + getTarget().ifPresent(ref -> ref.toNBT(tag)); } @Override public void fromNBT(NbtCompound tag) { - uuid = tag.containsUuid("uuid") ? Optional.of(tag.getUuid("uuid")) : Optional.empty(); - pos = tag.contains("pos") ? Optional.ofNullable(NbtSerialisable.readVector(tag.getList("pos", NbtElement.DOUBLE_TYPE))) : Optional.empty(); - clientId = tag.getInt("clientId"); + this.reference = tag.contains("uuid") ? new EntityValues<>(tag) : null; + } + + @Override + public int hashCode() { + return getTarget().map(EntityValues::uuid).orElse(Util.NIL_UUID).hashCode(); + } + + public record EntityValues( + UUID uuid, + Vec3d pos, + int clientId, + boolean isPlayer, + boolean isDead, + Levelled.LevelStore level, + Levelled.LevelStore corruption) { + public EntityValues(Entity entity) { + this( + entity.getUuid(), + entity.getPos(), + entity.getId(), entity instanceof PlayerEntity, + !entity.isAlive(), + Caster.of(entity).map(Caster::getLevel).map(Levelled::copyOf).orElse(Levelled.EMPTY), + Caster.of(entity).map(Caster::getCorruption).map(Levelled::copyOf).orElse(Levelled.EMPTY) + ); + } + + public EntityValues(NbtCompound tag) { + this( + tag.getUuid("uuid"), + NbtSerialisable.readVector(tag.getList("pos", NbtElement.DOUBLE_TYPE)), + tag.getInt("clientId"), + tag.getBoolean("isPlayer"), + tag.getBoolean("isDead"), + Levelled.fromNbt(tag.getCompound("level")), + Levelled.fromNbt(tag.getCompound("corruption")) + ); + } + + @SuppressWarnings("unchecked") + public Optional resolve(World world) { + if (world instanceof ServerWorld serverWorld) { + return Optional.ofNullable((T)serverWorld.getEntity(uuid)); + } + return Optional.ofNullable((T)world.getEntityById(clientId())); + } + + public void toNBT(NbtCompound tag) { + tag.putUuid("uuid", uuid); + tag.put("pos", NbtSerialisable.writeVector(pos)); + tag.putInt("clientId", clientId); + tag.putBoolean("isPlayer", isPlayer); + tag.putBoolean("isDead", isDead); + tag.put("level", level.toNbt()); + tag.put("corruption", corruption.toNbt()); + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java b/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java index 4d276bed..4d729704 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/EnchantedStaffItem.java @@ -9,6 +9,7 @@ import javax.annotation.Nullable; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; +import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; @@ -152,7 +153,7 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch if (attacker.isSneaking() && hasCharge(stack)) { stack.damage(50, attacker, p -> p.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND)); Caster.of(attacker).ifPresent(c -> c.subtractEnergyCost(4)); - Caster.of(target).ifPresent(c -> getSpellEffect(stack).create().apply(c)); + Caster.of(target).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF)); ChargeableItem.consumeEnergy(stack, 1); return true; @@ -182,7 +183,7 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch living.clearActiveItem(); living.damage(entity.getDamageSources().magic(), 1); if (EnchantableItem.isEnchanted(stack) && hasCharge(stack)) { - Caster.of(entity).ifPresent(c -> getSpellEffect(stack).create().apply(c)); + Caster.of(entity).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF)); ChargeableItem.consumeEnergy(stack, 1); } }