diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java index 1e62c82e..fb12d723 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java @@ -111,14 +111,10 @@ public class UnicornCastingAbility implements Ability { TypedActionResult> newSpell = getNewSpell(player); if (newSpell.getResult() != ActionResult.FAIL) { - @Nullable SpellType spell = newSpell.getValue(); - if (!player.getSpellSlot().isPresent() && spell == null) { - spell = SpellType.SHIELD; - } - player.subtractEnergyCost(spell == null ? 2 : 4); - player.setSpell(spell == null ? null : spell.create()); + player.subtractEnergyCost(spell.isEmpty() ? 2 : 4); + spell.apply(player); } } } @@ -139,12 +135,12 @@ public class UnicornCastingAbility implements Ability { } private TypedActionResult> getNewSpell(Pony player) { - final SpellType current = player.getSpellSlot().get(true).map(Spell::getType).orElse(null); + final SpellType current = player.getSpellSlot().get(true).map(Spell::getType).orElse(SpellType.empty()); return Streams.stream(player.getMaster().getItemsHand()) .filter(GemstoneItem::isEnchanted) .map(stack -> GemstoneItem.consumeSpell(stack, player.getMaster(), current, SpellType::mayAttach)) .findFirst() - .orElse(TypedActionResult.>pass(null)); + .orElse(TypedActionResult.>pass(current == SpellType.EMPTY_KEY ? SpellType.SHIELD : SpellType.EMPTY_KEY)); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/Spell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/Spell.java index 665018f9..fdb1ed93 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/Spell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/Spell.java @@ -5,8 +5,6 @@ import java.util.UUID; import com.minelittlepony.unicopia.ability.magic.spell.SpellType; import com.minelittlepony.unicopia.util.NbtSerialisable; -import net.minecraft.entity.projectile.ProjectileEntity; - /** * Interface for a magic spells */ @@ -38,25 +36,17 @@ public interface Spell extends NbtSerialisable, Affine { boolean isDirty(); /** - * Marks this effect as dirty. + * Applies this spell to the supplied caster. */ - void setDirty(boolean dirty); + boolean apply(Caster caster); /** - * Called when first attached to a gem. + * Marks this effect as dirty. */ - default void onPlaced(Caster caster) { - - } + void setDirty(); /** * Called when a gem is destroyed. */ - default void onDestroyed(Caster caster) { - setDead(); - } - - default boolean handleProjectileImpact(ProjectileEntity projectile) { - return false; - } + void onDestroyed(Caster caster); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractPlacedSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractPlacedSpell.java index bb93ed5f..993891e8 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractPlacedSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractPlacedSpell.java @@ -41,7 +41,7 @@ public abstract class AbstractPlacedSpell extends AbstractSpell implements Attac if (dimension == null) { dimension = source.getWorld().getRegistryKey().getValue(); - setDirty(true); + setDirty(); } else if (!source.getWorld().getRegistryKey().getValue().equals(dimension)) { return false; } @@ -55,7 +55,7 @@ public abstract class AbstractPlacedSpell extends AbstractSpell implements Attac entity.world.spawnEntity(entity); castEntity.set(entity); - setDirty(true); + setDirty(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractSpell.java index 0add0610..670a5f93 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractSpell.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.ability.magic.spell; import java.util.UUID; import com.minelittlepony.unicopia.Affinity; +import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Spell; import net.minecraft.nbt.CompoundTag; @@ -34,6 +35,7 @@ public abstract class AbstractSpell implements Spell { @Override public void setDead() { isDead = true; + setDirty(); } @Override @@ -47,8 +49,8 @@ public abstract class AbstractSpell implements Spell { } @Override - public void setDirty(boolean dirty) { - isDirty = dirty; + public void setDirty() { + isDirty = true; } @Override @@ -56,6 +58,17 @@ public abstract class AbstractSpell implements Spell { return getType().getAffinity(); } + @Override + public boolean apply(Caster caster) { + caster.setSpell(this); + return true; + } + + @Override + public void onDestroyed(Caster caster) { + setDead(); + } + @Override public void toNBT(CompoundTag compound) { compound.putBoolean("dead", isDead); @@ -64,7 +77,7 @@ public abstract class AbstractSpell implements Spell { @Override public void fromNBT(CompoundTag compound) { - setDirty(false); + isDirty = false; if (compound.contains("uuid")) { uuid = compound.getUuid("uuid"); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java index 2853ba99..8768132a 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DisguiseSpell.java @@ -16,6 +16,8 @@ import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.PlayerDimensions; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.particle.UParticles; +import com.minelittlepony.unicopia.projectile.ProjectileImpactListener; + import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.LivingEntity; @@ -25,7 +27,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.nbt.CompoundTag; -public class DisguiseSpell extends AbstractSpell implements Attached, Suppressable, FlightType.Provider, PlayerDimensions.Provider { +public class DisguiseSpell extends AbstractSpell implements Attached, Suppressable, FlightType.Provider, PlayerDimensions.Provider, ProjectileImpactListener { private final Disguise disguise = new Disguise(); @@ -49,7 +51,7 @@ public class DisguiseSpell extends AbstractSpell implements Attached, Suppressab @Override public void onSuppressed(Caster otherSource) { suppressionCounter = 100; - setDirty(true); + setDirty(); } @Override @@ -67,12 +69,12 @@ public class DisguiseSpell extends AbstractSpell implements Attached, Suppressab } disguise.setAppearance(entity); - setDirty(true); + setDirty(); return this; } @Override - public boolean handleProjectileImpact(ProjectileEntity projectile) { + public boolean onProjectileImpact(ProjectileEntity projectile) { return disguise.getAppearance() == projectile; } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RevealingSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RevealingSpell.java index eb26619c..cce2ca37 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RevealingSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/RevealingSpell.java @@ -22,11 +22,6 @@ public class RevealingSpell extends AbstractSpell implements Attached, Thrown { super(type); } - @Override - public void onPlaced(Caster source) { - source.getLevel().set(1); - } - @Override public boolean onThrownTick(MagicProjectileEntity projectile) { return onBodyTick(projectile); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java index e9c973c9..816a6c3f 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ShieldSpell.java @@ -90,7 +90,7 @@ public class ShieldSpell extends AbstractSpell implements Attached, Thrown { cost /= 2.725D; if (!source.subtractEnergyCost(cost)) { - onDestroyed(source); + setDead(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SiphoningSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SiphoningSpell.java index 22a7b03d..33fb4fa7 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SiphoningSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SiphoningSpell.java @@ -86,14 +86,14 @@ public class SiphoningSpell extends AbstractPlacedSpell { if (ticksUpset > 0 || maxHealthGain <= 0) { if (source.getWorld().random.nextInt(3000) == 0) { - onDestroyed(source); + setDead(); } else { e.damage(damage, e.getHealth() / 4); } if (maxHealthGain <= 0) { ticksUpset = 100; } - setDirty(true); + setDirty(); } else { e.heal((float)Math.min(0.5F * (1 + source.getLevel().get()), maxHealthGain * 0.6)); ParticleUtils.spawnParticle(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, e, 0.2F), e.world, e.getPos(), Vec3d.ZERO); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellType.java index da134614..7b0356c5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellType.java @@ -10,6 +10,7 @@ import javax.annotation.Nullable; import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.ability.magic.Affine; +import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Spell; import net.minecraft.nbt.CompoundTag; @@ -117,11 +118,24 @@ public final class SpellType implements Affine, SpellPredicate< return null; } + public boolean apply(Caster caster) { + if (isEmpty()) { + caster.setSpell(null); + return false; + } + + return create().apply(caster); + } + @Override public boolean test(@Nullable Spell spell) { return spell != null && spell.getType() == this; } + public boolean isEmpty() { + return this == EMPTY_KEY; + } + public static SpellType register(Identifier id, Affinity affinity, int color, boolean obtainable, Factory factory) { SpellType type = new SpellType<>(id, affinity, color, obtainable, factory); byAffinity(affinity).add(type); @@ -133,6 +147,11 @@ public final class SpellType implements Affine, SpellPredicate< return register(new Identifier("unicopia", name), affinity, color, obtainable, factory); } + @SuppressWarnings("unchecked") + public static SpellType empty() { + return (SpellType)EMPTY_KEY; + } + @SuppressWarnings("unchecked") public static SpellType getKey(Identifier id) { return (SpellType)(EMPTY_ID.equals(id) ? EMPTY_KEY : REGISTRY.getOrDefault(id, EMPTY_KEY)); diff --git a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java index effea17b..7af1c30d 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.command; import java.util.function.Function; +import com.minelittlepony.unicopia.ability.magic.Spell; import com.minelittlepony.unicopia.ability.magic.spell.SpellType; import com.minelittlepony.unicopia.entity.player.Pony; import com.mojang.brigadier.CommandDispatcher; @@ -79,9 +80,7 @@ public class DisguiseCommand { static int reveal(ServerCommandSource source, PlayerEntity player) { Pony iplayer = Pony.of(player); - iplayer.getSpellSlot().get(SpellType.DISGUISE, true).ifPresent(disguise -> { - disguise.onDestroyed(iplayer); - }); + iplayer.getSpellSlot().get(SpellType.DISGUISE, true).ifPresent(Spell::setDead); if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { player.sendMessage(new TranslatableText("commands.disguise.removed"), false); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Equine.java b/src/main/java/com/minelittlepony/unicopia/entity/Equine.java index 11d865b8..c4976927 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Equine.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Equine.java @@ -5,6 +5,7 @@ import java.util.Optional; import javax.annotation.Nullable; import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.projectile.ProjectileImpactListener; import com.minelittlepony.unicopia.util.NbtSerialisable; import net.minecraft.entity.Entity; @@ -12,7 +13,7 @@ import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.util.Tickable; -public interface Equine extends NbtSerialisable, Tickable { +public interface Equine extends NbtSerialisable, Tickable, ProjectileImpactListener { Race getSpecies(); Physics getPhysics(); @@ -44,6 +45,7 @@ public interface Equine extends NbtSerialisable, Tickable { /** * Event triggered when this entity is hit by a projectile. */ + @Override default boolean onProjectileImpact(ProjectileEntity projectile) { return false; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index 54bb9fd0..ebe0b972 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.SpellType; import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.network.EffectSync; +import com.minelittlepony.unicopia.projectile.ProjectileImpactListener; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; @@ -139,7 +140,9 @@ public abstract class Living implements Equine, Caste @Override public boolean onProjectileImpact(ProjectileEntity projectile) { return getSpellSlot().get(true) - .filter(effect -> !effect.isDead() && effect.handleProjectileImpact(projectile)) + .filter(effect -> !effect.isDead() + && effect instanceof ProjectileImpactListener + && ((ProjectileImpactListener)effect).onProjectileImpact(projectile)) .isPresent(); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java index 093d7c0b..0bc6729e 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java @@ -66,7 +66,7 @@ public class SheepBehaviour extends EntityBehaviour { } } while (dropAmount-- > 0); } - spell.setDirty(true); + spell.setDirty(); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java b/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java index 5c21cf7c..db30309f 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java +++ b/src/main/java/com/minelittlepony/unicopia/network/EffectSync.java @@ -89,6 +89,7 @@ public class EffectSync implements SpellContainer { private void updateReference(@Nullable Spell effect) { if (spell.isPresent() && spell.get() != effect) { spell.get().setDead(); + spell.get().onDestroyed(owner); } spell = Optional.ofNullable(effect); } diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java b/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java index e950cdf5..74e22a46 100644 --- a/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/projectile/MagicProjectileEntity.java @@ -121,15 +121,6 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Magical, return effectDelegate; } - @Override - public void setSpell(Spell effect) { - Caster.super.setSpell(effect); - - if (effect != null) { - effect.onPlaced(this); - } - } - public void setThrowDamage(float damage) { getDataTracker().set(DAMAGE, Math.max(0, damage)); } diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/ProjectileImpactListener.java b/src/main/java/com/minelittlepony/unicopia/projectile/ProjectileImpactListener.java new file mode 100644 index 00000000..db417dfc --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/projectile/ProjectileImpactListener.java @@ -0,0 +1,7 @@ +package com.minelittlepony.unicopia.projectile; + +import net.minecraft.entity.projectile.ProjectileEntity; + +public interface ProjectileImpactListener { + boolean onProjectileImpact(ProjectileEntity projectile); +}