diff --git a/src/main/java/com/minelittlepony/unicopia/item/IMagicalItem.java b/src/main/java/com/minelittlepony/unicopia/item/IMagicalItem.java index bf4693e7..a21d634b 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/IMagicalItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/IMagicalItem.java @@ -1,10 +1,11 @@ package com.minelittlepony.unicopia.item; +import com.minelittlepony.unicopia.spell.IAligned; import com.minelittlepony.unicopia.spell.SpellAffinity; import net.minecraft.item.ItemStack; -public interface IMagicalItem { +public interface IMagicalItem extends IAligned { /** * If true this item serves as host to its own inner dimensional space. * Bag of Holding will explode if you try to store items of this kind inside of it. @@ -18,6 +19,6 @@ public interface IMagicalItem { * What this returns may have effects on the behaviour of certain spells and effects. */ default SpellAffinity getAffinity(ItemStack stack) { - return SpellAffinity.NEUTRAL; + return getAffinity(); } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemCurse.java b/src/main/java/com/minelittlepony/unicopia/item/ItemCurse.java index 16b2e1be..dd40538f 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/ItemCurse.java +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemCurse.java @@ -52,7 +52,7 @@ public class ItemCurse extends ItemSpell { } @Override - public SpellAffinity getAffinity(ItemStack stack) { + public SpellAffinity getAffinity() { return SpellAffinity.BAD; } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemOfHolding.java b/src/main/java/com/minelittlepony/unicopia/item/ItemOfHolding.java index 287b9fa7..5e4a9d14 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/ItemOfHolding.java +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemOfHolding.java @@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.Predicates; import com.minelittlepony.unicopia.UClient; import com.minelittlepony.unicopia.inventory.ContainerOfHolding; import com.minelittlepony.unicopia.inventory.InventoryOfHolding; +import com.minelittlepony.unicopia.spell.SpellAffinity; import com.minelittlepony.util.vector.VecHelper; import net.minecraft.client.util.ITooltipFlag; @@ -121,6 +122,11 @@ public class ItemOfHolding extends Item implements IMagicalItem { return new ActionResult<>(EnumActionResult.SUCCESS, stack); } + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.NEUTRAL; + } + @Override public boolean hasInnerSpace() { return true; diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java b/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java index b95c85e8..fb34977f 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java @@ -184,7 +184,7 @@ public class ItemSpell extends Item implements ICastable { if (SpellRegistry.stackHasEnchantment(stack)) { SpellAffinity affinity = getAffinity(stack); - tooltip.add(affinity.getColourCode() + I18n.format(String.format("%s.%s.name", + tooltip.add(affinity.getColourCode() + I18n.format(String.format("%s.%s.tagline", affinity.getTranslationKey(), SpellRegistry.getKeyFromStack(stack) ))); @@ -213,7 +213,7 @@ public class ItemSpell extends Item implements ICastable { super.getSubItems(tab, subItems); if (isInCreativeTab(tab)) { - for (String name : SpellRegistry.instance().getAllNames()) { + for (String name : SpellRegistry.instance().getAllNames(getAffinity())) { subItems.add(SpellRegistry.instance().enchantStack(new ItemStack(this, 1), name)); } } @@ -236,7 +236,7 @@ public class ItemSpell extends Item implements ICastable { } @Override - public SpellAffinity getAffinity(ItemStack stack) { + public SpellAffinity getAffinity() { return SpellAffinity.GOOD; } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java index 63583e27..456223aa 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java @@ -12,6 +12,11 @@ public abstract class AbstractSpell implements IMagicEffect { @Override public void setCurrentLevel(int level) { + } + + @Override + public boolean isCraftable() { + return true; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/spell/IAligned.java b/src/main/java/com/minelittlepony/unicopia/spell/IAligned.java new file mode 100644 index 00000000..29144a07 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/IAligned.java @@ -0,0 +1,12 @@ +package com.minelittlepony.unicopia.spell; + +/** + * Interface for things that have an affine alignment. + */ +public interface IAligned { + /** + * Gets the current alignment. + * Good/Bad/Neutral + */ + SpellAffinity getAffinity(); +} diff --git a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java index fb163ea4..dcd7b26e 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java @@ -15,14 +15,12 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public interface ICaster extends IOwned, ILevelled { +public interface ICaster extends IOwned, ILevelled, IAligned { void setEffect(IMagicEffect effect); IMagicEffect getEffect(); - SpellAffinity getAffinity(); - default boolean hasEffect() { return getEffect() != null; } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java index c20f8e9d..fd3e05de 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java @@ -5,7 +5,7 @@ import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable; /** * Interface for a magic spells */ -public interface IMagicEffect extends InbtSerialisable, ILevelled { +public interface IMagicEffect extends InbtSerialisable, ILevelled, IAligned { /** * Gets the name used to identify this effect. @@ -27,6 +27,11 @@ public interface IMagicEffect extends InbtSerialisable, ILevelled { */ boolean getDead(); + /** + * Returns true if this effect can be crafted into a gem. + */ + boolean isCraftable(); + /** * Called when first attached to a gem. */ diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java index 5ac0394a..6843326d 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java @@ -11,6 +11,8 @@ public enum SpellAffinity { private final int corruption; + private SpellAffinity[] implications; + SpellAffinity(TextFormatting color, int corruption) { this.color = color; this.corruption = corruption; @@ -31,4 +33,18 @@ public enum SpellAffinity { public boolean isNeutral() { return this == NEUTRAL; } + + public SpellAffinity[] getImplicators() { + if (implications != null) { + return implications; + } + + if (this == NEUTRAL) { + implications = values(); + } else { + implications = new SpellAffinity[] { this }; + } + + return implications; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java index 42712057..e4304cfe 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java @@ -32,6 +32,11 @@ public class SpellCharge extends AbstractSpell { return "charge"; } + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.GOOD; + } + @Override public int getTint() { return 0x0000AA; diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java index de15e46b..0d84f6e0 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellDisguise.java @@ -31,6 +31,16 @@ public class SpellDisguise extends AbstractSpell { return "disguise"; } + @Override + public boolean isCraftable() { + return false; + } + + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.BAD; + } + @Override public int getTint() { return 0; diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java index 578ea0f4..a8656751 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java @@ -73,6 +73,11 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl return "fire"; } + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.GOOD; + } + @Override public int getTint() { return 0xFF0000; diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java index 608559df..d2f8bfec 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java @@ -61,6 +61,11 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable return "ice"; } + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.GOOD; + } + @Override public int getTint() { return 0xADD8E6; diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellPortal.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellPortal.java index b38f671a..1ea36894 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellPortal.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellPortal.java @@ -67,6 +67,11 @@ public class SpellPortal extends AbstractSpell implements IUseAction { return 0x384C38; } + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.GOOD; + } + @Override public void setDead() { super.setDead(); diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java index d5505850..f8b5f4ae 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java @@ -1,12 +1,15 @@ package com.minelittlepony.unicopia.spell; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -23,7 +26,9 @@ public class SpellRegistry { return stack.hasTagCompound() && stack.getTagCompound().hasKey("spell"); } - private final Map entries = new HashMap<>(); + private final Map> entries = new HashMap<>(); + + private final Map> keysByAffinity = new HashMap<>(); private SpellRegistry() { registerSpell(SpellShield::new); @@ -35,6 +40,7 @@ public class SpellRegistry { registerSpell(SpellDisguise::new); } + @Nullable public IMagicEffect getSpellFromName(String name) { if (entries.containsKey(name)) { return entries.get(name).create(); @@ -65,41 +71,28 @@ public class SpellRegistry { return compound; } + private Optional> getEntryFromStack(ItemStack stack) { + return Optional.ofNullable(entries.get(getKeyFromStack(stack))); + } + @Nullable public IDispenceable getDispenseActionFrom(ItemStack stack) { - String key = getKeyFromStack(stack); - - if (entries.containsKey(key)) { - Entry entry = entries.get(key); - if (entry.canDispense) { - return entry.create(); - } - } - - return null; + return getEntryFromStack(stack).map(Entry::dispensable).orElse(null); } @Nullable public IUseAction getUseActionFrom(ItemStack stack) { - String key = getKeyFromStack(stack); - - if (entries.containsKey(key)) { - Entry entry = entries.get(key); - if (entry.canUse) { - return entry.create(); - } - } - - return null; + return getEntryFromStack(stack).map(Entry::useable).orElse(null); } + @Nullable public IMagicEffect getSpellFromItemStack(ItemStack stack) { return getSpellFromName(getKeyFromStack(stack)); } - public void registerSpell(Callable factory) { + public void registerSpell(Callable factory) { try { - new Entry(factory); + new Entry(factory); } catch (Exception e) { e.printStackTrace(); } @@ -118,10 +111,7 @@ public class SpellRegistry { } public ItemStack enchantStack(ItemStack stack, ItemStack from) { - stack.setTagCompound(new NBTTagCompound()); - stack.getTagCompound().setString("spell", getKeyFromStack(from)); - - return stack; + return enchantStack(stack, getKeyFromStack(from)); } public ItemStack enchantStack(ItemStack stack, String name) { @@ -152,33 +142,58 @@ public class SpellRegistry { return 0xffffff; } - public Set getAllNames() { - return entries.keySet(); + public Set getAllNames(SpellAffinity affinity) { + return keysByAffinity.get(affinity); } - class Entry { - Callable factory; + @Immutable + class Entry { + final Callable factory; - int color; + final int color; - boolean canDispense; - boolean canUse; + final boolean canDispense; + final boolean canUse; - Entry(Callable factory) throws Exception { - IMagicEffect inst = factory.call(); + final SpellAffinity affinity; + + Entry(Callable factory) throws Exception { + T inst = factory.call(); this.factory = factory; this.color = inst.getTint(); this.canDispense = inst instanceof IDispenceable; this.canUse = inst instanceof IUseAction; + this.affinity = inst.getAffinity(); + + if (inst.isCraftable()) { + for (SpellAffinity affinity : affinity.getImplicators()) { + keysByAffinity.computeIfAbsent(affinity, a -> new HashSet<>()).add(inst.getName()); + } + } entries.put(inst.getName(), this); } - @SuppressWarnings("unchecked") - T create() { + IUseAction useable() { + if (!canUse) { + return null; + } + + return (IUseAction)create(); + } + + IDispenceable dispensable() { + if (!canDispense) { + return null; + } + + return (IDispenceable)create(); + } + + T create() { try { - return (T) factory.call(); + return factory.call(); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java index 55484bd7..60b424e3 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java @@ -35,6 +35,11 @@ public class SpellShield extends AbstractSpell { return "shield"; } + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.NEUTRAL; + } + @Override public int getTint() { return 0x66CDAA; diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java index 98ea7c02..2725ce00 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellVortex.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.spell; import com.minelittlepony.unicopia.UParticles; import com.minelittlepony.unicopia.particle.Particles; import com.minelittlepony.unicopia.player.PlayerSpeciesList; +import com.minelittlepony.util.MagicalDamageSource; import com.minelittlepony.util.shape.Sphere; import net.minecraft.entity.Entity; @@ -16,6 +17,11 @@ public class SpellVortex extends SpellShield { return "vortex"; } + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.NEUTRAL; + } + @Override protected void spawnParticles(ICaster source, int strength) { Vec3d pos = source.getOriginVector(); @@ -35,6 +41,10 @@ public class SpellVortex extends SpellShield { force *= calculateAdjustedForce(PlayerSpeciesList.instance().getPlayer((EntityPlayer)target)); } + if (source.getAffinity() == SpellAffinity.BAD && source.getWorld().rand.nextInt(4500) == 0) { + source.getEntity().attackEntityFrom(MagicalDamageSource.create("vortex"), 4); + } + applyForce(pos, target, -force, 0); float maxVel = source.getAffinity() == SpellAffinity.BAD ? 1 : 1.6f; diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index 85a8f6ab..0d887441 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -31,22 +31,31 @@ item.corrupted_gem.name=Fractured Gem item.corrupted_gem.enchanted.name=Fractured Gem of %s spell.shield.name=Defense -spell.charge.name=Chanelling -spell.fire.name=Flame -spell.infero.name=Burning -spell.ice.name=Frost +spell.shield.tagline=Protection I + spell.portal.name=Transportation +spell.portal.tagline=Teleportation I + +spell.fire.name=Flame +spell.fire.tagline=Fire I + spell.vortex.name=Retention -spell.minion.name=Obedience +spell.vortex.tagline=Containment I + +spell.charge.name=Chanelling +spell.charge.tagline=Energy I + +spell.ice.name=Frost +spell.ice.tagline=Ice I curse.shield.name=Repulsion -curse.charge.name=Draining -curse.fire.name=Hades -curse.inferno.name=Inferno -curse.ice.name=Freezing -curse.portal.name=Summoning -curse.attract.name=Entrapment -curse.minion.name=Slavery +curse.shield.tagline=Hostility I + +curse.vortex.name=Suffering +curse.vortex.tagline=Torture I + +curse.necromany.name=Necromancy +curse.necromancy.tagline=Resurrection I item.spellbook.name=Spellbook item.bag_of_holding.name=Bag of Holding