diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java index 4e3b83ce..fb38dc89 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornCastingAbility.java @@ -8,8 +8,8 @@ import com.google.common.collect.Streams; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; -import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.AmuletItem; import com.minelittlepony.unicopia.item.GemstoneItem; @@ -109,13 +109,13 @@ public class UnicornCastingAbility implements Ability { } } } else { - TypedActionResult> newSpell = getNewSpell(player); + TypedActionResult> newSpell = getNewSpell(player); if (newSpell.getResult() != ActionResult.FAIL) { - SpellType spell = newSpell.getValue(); + CustomisedSpellType spell = newSpell.getValue(); player.subtractEnergyCost(spell.isEmpty() ? 2 : 4); - spell.apply(player, SpellTraits.EMPTY); + spell.apply(player); } } } @@ -135,13 +135,13 @@ public class UnicornCastingAbility implements Ability { return TypedActionResult.pass(stack); } - private TypedActionResult> getNewSpell(Pony player) { + private TypedActionResult> getNewSpell(Pony player) { 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, null)) .findFirst() - .orElse(TypedActionResult.>pass(current == SpellType.EMPTY_KEY ? SpellType.SHIELD : SpellType.EMPTY_KEY)); + .orElse(TypedActionResult.>pass((current == SpellType.EMPTY_KEY ? SpellType.SHIELD : SpellType.EMPTY_KEY).withTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java index b29a8852..78ff0a2d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/UnicornProjectileAbility.java @@ -5,9 +5,8 @@ import org.jetbrains.annotations.Nullable; import com.google.common.collect.Streams; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; +import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; -import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.GemstoneItem; import com.minelittlepony.unicopia.particle.MagicParticleEffect; @@ -63,27 +62,27 @@ public class UnicornProjectileAbility implements Ability { @Override public void apply(Pony player, Hit data) { - TypedActionResult> thrown = getNewSpell(player); + TypedActionResult> thrown = getNewSpell(player); if (thrown.getResult() != ActionResult.FAIL) { @Nullable - SpellType spell = thrown.getValue(); + CustomisedSpellType spell = thrown.getValue(); if (spell == null) { - spell = SpellType.VORTEX; + spell = SpellType.VORTEX.withTraits(); } player.subtractEnergyCost(getCostEstimate(player)); - ((ProjectileCapable)spell.create(SpellTraits.EMPTY)).toss(player); + spell.create().toThrowable().throwProjectile(player); } } - private TypedActionResult> getNewSpell(Pony player) { + private TypedActionResult> getNewSpell(Pony player) { return Streams.stream(player.getMaster().getItemsHand()) .filter(GemstoneItem::isEnchanted) .map(stack -> GemstoneItem.consumeSpell(stack, player.getMaster(), null, null)) .findFirst() - .orElse(TypedActionResult.>pass(null)); + .orElse(TypedActionResult.>pass(null)); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java index 0ecd3859..dc25f687 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/SpellPredicate.java @@ -2,11 +2,11 @@ package com.minelittlepony.unicopia.ability.magic; import java.util.function.Predicate; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; +import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell; import com.minelittlepony.unicopia.ability.magic.spell.Spell; public interface SpellPredicate extends Predicate { - SpellPredicate IS_THROWN = s -> s instanceof ProjectileCapable; + SpellPredicate IS_THROWN = s -> s instanceof ProjectileSpell; SpellPredicate IS_SUPPRESSABLE = s -> s instanceof Suppressable; default boolean isOn(Caster caster) { 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 a71c83fa..d074cdd7 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 @@ -10,13 +10,14 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; +import com.minelittlepony.unicopia.projectile.ProjectileDelegate; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; -public abstract class AbstractDelegatingSpell implements Spell, ProjectileCapable { +public abstract class AbstractDelegatingSpell implements ProjectileSpell { private boolean isDirty; @@ -76,27 +77,30 @@ public abstract class AbstractDelegatingSpell implements Spell, ProjectileCapabl getDelegates().forEach(spell -> spell.onDestroyed(caster)); } + @Override + public boolean tick(Caster source, Situation situation) { + return execute(getDelegates().stream(), spell -> spell.tick(source, situation)); + } + @Override public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { - getDelegates().stream().filter(a -> a instanceof ProjectileCapable).forEach(a -> { - ((ProjectileCapable)a).onImpact(projectile, pos, state); + getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> { + ((ProjectileDelegate)a).onImpact(projectile, pos, state); }); } @Override public void onImpact(MagicProjectileEntity projectile, Entity entity) { - getDelegates().stream().filter(a -> a instanceof ProjectileCapable).forEach(a -> { - ((ProjectileCapable)a).onImpact(projectile, entity); + getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> { + ((ProjectileDelegate)a).onImpact(projectile, entity); }); } @Override - public boolean tick(Caster source, Situation situation) { - return execute(getDelegates().stream(), spell -> spell.tick(source, situation)); - } - - private boolean execute(Stream spells, Function action) { - return spells.reduce(false, (u, a) -> action.apply(a), (a, b) -> a || b); + public void configureProjectile(MagicProjectileEntity projectile, Caster caster) { + getDelegates().stream().filter(a -> a instanceof ProjectileSpell).forEach(a -> { + ((ProjectileSpell)a).configureProjectile(projectile, caster); + }); } @Override @@ -111,4 +115,8 @@ public abstract class AbstractDelegatingSpell implements Spell, ProjectileCapabl uuid = compound.getUuid("uuid"); } } + + private 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/CompoundSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/CompoundSpell.java index d72c02b5..1c9a25eb 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/CompoundSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/CompoundSpell.java @@ -26,8 +26,8 @@ public class CompoundSpell extends AbstractDelegatingSpell { @Override public Spell combineWith(Spell other) { - if (other instanceof CompoundSpell) { - spells.addAll(((CompoundSpell)other).spells); + if (other instanceof AbstractDelegatingSpell) { + spells.addAll(((AbstractDelegatingSpell)other).getDelegates()); } else { spells.add(other); } 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 4b5df60f..92e135f0 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 @@ -86,7 +86,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell { spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.MAGIC_RUNES, 90, 0), source.getOriginVector(), Vec3d.ZERO); }).ifPresent(p -> { p.attach(source); - p.setAttribute(1, getType().getColor()); + p.setAttribute(1, spell.getType().getColor()); }); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ProjectileCapable.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ProjectileCapable.java deleted file mode 100644 index 328d1edc..00000000 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ProjectileCapable.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.minelittlepony.unicopia.ability.magic.spell; - -import org.jetbrains.annotations.Nullable; - -import com.minelittlepony.unicopia.ability.magic.Caster; -import com.minelittlepony.unicopia.item.GemstoneItem; -import com.minelittlepony.unicopia.item.UItems; -import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; -import com.minelittlepony.unicopia.projectile.ProjectileDelegate; - -import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; -import net.minecraft.sound.SoundEvents; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -/** - * Magic effects that can be thrown. - */ -public interface ProjectileCapable extends Spell, ProjectileDelegate { - - @Override - default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { - if (!projectile.isClient()) { - tick(projectile, Situation.PROJECTILE); - } - } - - @Override - default void onImpact(MagicProjectileEntity projectile, Entity entity) { - - } - - /** - * The amount of damage to be dealt when the projectile collides with an entity. - */ - default int getThrowDamage(Caster stack) { - return 0; - } - - /** - * The sound made when thrown. - */ - default SoundEvent getThrowSound(Caster caster) { - return SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT; - } - - /** - * Gets the appearance to be used when projecting this spell. - */ - default ItemStack getCastAppearance(Caster caster) { - return GemstoneItem.enchanted(UItems.GEMSTONE.getDefaultStack(), getType()); - } - - /** - * Projects this spell. - * - * Returns the resulting projectile entity for customization (or null if on the client). - */ - @Nullable - default MagicProjectileEntity toss(Caster caster) { - World world = caster.getWorld(); - - LivingEntity entity = caster.getMaster(); - - world.playSound(null, entity.getX(), entity.getY(), entity.getZ(), getThrowSound(caster), SoundCategory.NEUTRAL, 0.7F, 0.4F / (world.random.nextFloat() * 0.4F + 0.8F)); - - if (!caster.isClient()) { - MagicProjectileEntity projectile = new MagicProjectileEntity(world, entity); - - projectile.setItem(getCastAppearance(caster)); - projectile.setThrowDamage(getThrowDamage(caster)); - projectile.setSpell(this); - projectile.setHydrophobic(); - projectile.setProperties(entity, entity.getPitch(), entity.getYaw(), 0, 1.5F, 1); - - world.spawnEntity(projectile); - - return projectile; - } - - return null; - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ProjectileSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ProjectileSpell.java new file mode 100644 index 00000000..cbfade3e --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ProjectileSpell.java @@ -0,0 +1,23 @@ +package com.minelittlepony.unicopia.ability.magic.spell; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; +import com.minelittlepony.unicopia.projectile.ProjectileDelegate; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; + +/** + * Magic effects that can be thrown. + */ +public interface ProjectileSpell extends Spell, ProjectileDelegate { + + @Override + default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { + if (!projectile.isClient()) { + tick(projectile, Situation.PROJECTILE); + } + } + + default void configureProjectile(MagicProjectileEntity projectile, Caster caster) { } +} 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 260d27a0..5326251b 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 @@ -75,4 +75,12 @@ public interface Spell extends NbtSerialisable, Affine { default PlaceableSpell toPlaceable() { return SpellType.PLACED_SPELL.create(SpellTraits.EMPTY).setSpell(this); } + + /** + * Converts this spell into a throwable spell. + * @return + */ + default ThrowableSpell toThrowable() { + return SpellType.THROWN_SPELL.create(SpellTraits.EMPTY).setSpell(this); + } } 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 new file mode 100644 index 00000000..b9fe94cc --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/ThrowableSpell.java @@ -0,0 +1,69 @@ +package com.minelittlepony.unicopia.ability.magic.spell; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.minelittlepony.unicopia.item.GemstoneItem; +import com.minelittlepony.unicopia.item.UItems; +import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; +import net.minecraft.world.World; + +public class ThrowableSpell extends AbstractDelegatingSpell { + + private Spell spell; + + public ThrowableSpell(SpellType type, SpellTraits traits) { + super(type, traits); + } + + public ThrowableSpell setSpell(Spell spell) { + this.spell = spell; + return this; + } + + @Override + protected Collection getDelegates() { + return List.of(spell); + } + + /** + * Projects this spell. + * + * Returns the resulting projectile entity for customization (or null if on the client). + */ + public Optional throwProjectile(Caster caster) { + World world = caster.getWorld(); + + LivingEntity entity = caster.getMaster(); + + world.playSound(null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.NEUTRAL, 0.7F, 0.4F / (world.random.nextFloat() * 0.4F + 0.8F)); + + if (!caster.isClient()) { + MagicProjectileEntity projectile = new MagicProjectileEntity(world, entity); + + projectile.setItem(GemstoneItem.enchanted(UItems.GEMSTONE.getDefaultStack(), spell.getType())); + projectile.setSpell(this); + projectile.setProperties(entity, entity.getPitch(), entity.getYaw(), 0, 1.5F, 1); + projectile.setHydrophobic(); + configureProjectile(projectile, caster); + world.spawnEntity(projectile); + + return Optional.of(projectile); + } + + return Optional.empty(); + } + + @Override + public ThrowableSpell toThrowable() { + return this; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java index 802efe76..4cb20719 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java @@ -5,7 +5,6 @@ import java.util.List; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.util.shape.Sphere; @@ -17,7 +16,7 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; -public class AwkwardSpell extends AbstractSpell implements ProjectileCapable { +public class AwkwardSpell extends AbstractSpell { protected AwkwardSpell(SpellType type, SpellTraits traits) { super(type, traits); 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 new file mode 100644 index 00000000..77106780 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/CustomisedSpellType.java @@ -0,0 +1,31 @@ +package com.minelittlepony.unicopia.ability.magic.spell.effect; + +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.ability.magic.Caster; +import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; + +public class CustomisedSpellType { + + private final SpellType type; + private final SpellTraits traits; + + public CustomisedSpellType(SpellType type, SpellTraits traits) { + this.type = type; + this.traits = traits; + } + + public boolean isEmpty() { + return type.isEmpty(); + } + + public T create() { + return type.create(traits); + } + + @Nullable + public T apply(Caster caster) { + return type.apply(caster, traits); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java index 35fe7c91..0924d90d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireSpell.java @@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; +import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.block.state.StateMaps; import com.minelittlepony.unicopia.particle.ParticleUtils; @@ -35,7 +35,7 @@ import net.minecraft.world.explosion.Explosion.DestructionType; /** * Simple fire spell that triggers an effect when used on a block. */ -public class FireSpell extends AbstractSpell implements ProjectileCapable { +public class FireSpell extends AbstractSpell implements ProjectileSpell { private static final Shape EFFECT_RANGE = new Sphere(false, 4); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java index 2e3385a4..432992f6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/IceSpell.java @@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.block.state.StateMaps; import com.minelittlepony.unicopia.particle.ParticleUtils; @@ -27,7 +26,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class IceSpell extends AbstractSpell implements ProjectileCapable { +public class IceSpell extends AbstractSpell { private final int rad = 3; private final Shape effect_range = new Sphere(false, rad); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/RevealingSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/RevealingSpell.java index b6c3fff3..5f99b8fb 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/RevealingSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/RevealingSpell.java @@ -3,7 +3,6 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.particle.MagicParticleEffect; import com.minelittlepony.unicopia.util.shape.Shape; @@ -16,7 +15,7 @@ import net.minecraft.util.math.Vec3d; /** * A spell for revealing changelings. */ -public class RevealingSpell extends AbstractSpell implements ProjectileCapable { +public class RevealingSpell extends AbstractSpell { private static final Shape AREA = new Sphere(false, 15); protected RevealingSpell(SpellType type, SpellTraits traits) { 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 33f2d40f..d1e8af14 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,5 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect; -import org.jetbrains.annotations.Nullable; - import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; @@ -42,14 +40,7 @@ public class ScorchSpell extends FireSpell { } @Override - @Nullable - public MagicProjectileEntity toss(Caster caster) { - MagicProjectileEntity projectile = super.toss(caster); - - if (projectile != null) { - projectile.setNoGravity(true); - } - - return projectile; + public void configureProjectile(MagicProjectileEntity projectile, Caster caster) { + projectile.setNoGravity(true); } } 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 abe22e6e..ea98cecd 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 @@ -10,7 +10,7 @@ import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; +import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.FriendshipBraceletItem; @@ -35,7 +35,7 @@ import net.minecraft.entity.vehicle.BoatEntity; import net.minecraft.sound.SoundEvents; import net.minecraft.util.math.Vec3d; -public class ShieldSpell extends AbstractSpell implements ProjectileCapable { +public class ShieldSpell extends AbstractSpell implements ProjectileSpell { private final ParticleHandle particlEffect = new ParticleHandle(); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java index d97f44e8..4dec3942 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/SpellType.java @@ -17,6 +17,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; import com.minelittlepony.unicopia.ability.magic.spell.JoustingSpell; import com.minelittlepony.unicopia.ability.magic.spell.PlaceableSpell; import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.ThrowableSpell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.util.Registries; @@ -37,6 +38,7 @@ public final class SpellType implements Affine, SpellPredicate< public static final SpellType COMPOUND_SPELL = register("compound", Affinity.NEUTRAL, 0, false, CompoundSpell::new); public static final SpellType PLACED_SPELL = register("placed", Affinity.NEUTRAL, 0, false, PlaceableSpell::new); + public static final SpellType THROWN_SPELL = register("thrown", Affinity.NEUTRAL, 0, false, ThrowableSpell::new); public static final SpellType DISGUISE = register("disguise", Affinity.BAD, 0x19E48E, false, DisguiseSpell::new); public static final SpellType RAINBOOM = register("rainboom", Affinity.GOOD, 0xBDBDF9, false, JoustingSpell::new); @@ -66,12 +68,15 @@ public final class SpellType implements Affine, SpellPredicate< @Nullable private String translationKey; + private final CustomisedSpellType traited; + private SpellType(Identifier id, Affinity affinity, int color, boolean obtainable, Factory factory) { this.id = id; this.affinity = affinity; this.color = color; this.obtainable = obtainable; this.factory = factory; + traited = new CustomisedSpellType<>(this, SpellTraits.EMPTY); } public boolean isObtainable() { @@ -105,6 +110,14 @@ public final class SpellType implements Affine, SpellPredicate< return new TranslatableText(getTranslationKey()); } + public CustomisedSpellType withTraits() { + return traited; + } + + public CustomisedSpellType withTraits(SpellTraits traits) { + return traits.isEmpty() ? withTraits() : new CustomisedSpellType<>(this, traits); + } + @Nullable public T create(SpellTraits traits) { try { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TransformationSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TransformationSpell.java index 446f0abc..fcbc9c80 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TransformationSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/TransformationSpell.java @@ -9,7 +9,7 @@ import java.util.Set; import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Situation; -import com.minelittlepony.unicopia.ability.magic.spell.ProjectileCapable; +import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell; import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import com.minelittlepony.unicopia.entity.UEntities; import com.minelittlepony.unicopia.particle.ParticleUtils; @@ -22,7 +22,7 @@ import net.minecraft.particle.ParticleTypes; import net.minecraft.sound.SoundEvents; import net.minecraft.util.Util; -public class TransformationSpell extends AbstractSpell implements ProjectileCapable { +public class TransformationSpell extends AbstractSpell implements ProjectileSpell { protected TransformationSpell(SpellType type, SpellTraits traits) { super(type, traits); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java index 3c7408c4..e4fe6835 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java @@ -43,19 +43,19 @@ public final class SpellTraits { return nbt; } - public Optional of(Collection stacks) { + public static Optional of(Collection stacks) { return fromEntries(stacks.stream().flatMap(a -> of(a).entries().stream())); } - public SpellTraits of(ItemStack stack) { + public static SpellTraits of(ItemStack stack) { return getEmbeddedTraits(stack).orElseGet(() -> of(stack.getItem())); } - public SpellTraits of(Item item) { + public static SpellTraits of(Item item) { return TraitLoader.INSTANCE.values.getOrDefault(Registry.ITEM.getId(item), null); } - public SpellTraits of(Block block) { + public static SpellTraits of(Block block) { return of(block.asItem()); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java b/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java index 1d710569..33329c12 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/GemstoneItem.java @@ -9,7 +9,9 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.Affinity; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.player.PlayerEntity; @@ -79,19 +81,20 @@ public class GemstoneItem extends Item { return super.getName(); } - public static TypedActionResult> consumeSpell(ItemStack stack, PlayerEntity player, @Nullable SpellType exclude, @Nullable Predicate> test) { + public static TypedActionResult> consumeSpell(ItemStack stack, PlayerEntity player, @Nullable SpellType exclude, @Nullable Predicate> test) { if (!isEnchanted(stack)) { return TypedActionResult.pass(null); } SpellType key = getSpellKey(stack); + SpellTraits traits = SpellTraits.of(stack); if (Objects.equals(key, exclude)) { return TypedActionResult.fail(null); } - if (key == SpellType.EMPTY_KEY || (test == null || !test.test(key))) { + if (key.isEmpty() || (test == null || !test.test(key))) { return TypedActionResult.fail(null); } @@ -105,7 +108,7 @@ public class GemstoneItem extends Item { } } - return TypedActionResult.consume(key); + return TypedActionResult.consume(key.withTraits(traits)); } public static boolean isEnchanted(ItemStack stack) { diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/ProjectileDelegate.java b/src/main/java/com/minelittlepony/unicopia/projectile/ProjectileDelegate.java index 9c4c33d4..7bd80e3c 100644 --- a/src/main/java/com/minelittlepony/unicopia/projectile/ProjectileDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/projectile/ProjectileDelegate.java @@ -8,10 +8,10 @@ public interface ProjectileDelegate { /** * Called once the projectile lands either hitting the ground or an entity. */ - void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state); + default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {} /** * Called once the projectile lands either hitting the ground or an entity. */ - void onImpact(MagicProjectileEntity projectile, Entity entity); + default void onImpact(MagicProjectileEntity projectile, Entity entity) {} }