From 60a6c5124e1dcd9af549600796404ce4c98bd972 Mon Sep 17 00:00:00 2001 From: Electroblob77 <35599699+Electroblob77@users.noreply.github.com> Date: Fri, 27 Sep 2019 15:46:09 +0100 Subject: [PATCH] API improvements to spell books: - Allow spells to set which book/scroll items they can appear on - Allow spell books to set custom GUI textures - Tweaks to loot functions and wizards to accommodate the changes --- .../wizardry/WizardryGuiHandler.java | 5 ++- .../wizardry/client/gui/GuiSpellBook.java | 21 +++++------ .../wizardry/entity/living/EntityWizard.java | 1 + .../electroblob/wizardry/item/ItemScroll.java | 13 +++---- .../wizardry/item/ItemSpellBook.java | 35 +++++++++++++------ .../wizardry/loot/RandomSpell.java | 1 + .../wizardry/loot/WizardSpell.java | 10 ++++-- .../electroblob/wizardry/spell/Spell.java | 9 +++++ 8 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/main/java/electroblob/wizardry/WizardryGuiHandler.java b/src/main/java/electroblob/wizardry/WizardryGuiHandler.java index 140ed107..69ffe1ab 100644 --- a/src/main/java/electroblob/wizardry/WizardryGuiHandler.java +++ b/src/main/java/electroblob/wizardry/WizardryGuiHandler.java @@ -2,7 +2,6 @@ package electroblob.wizardry; import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.item.ItemWizardHandbook; -import electroblob.wizardry.spell.Spell; import electroblob.wizardry.tileentity.ContainerArcaneWorkbench; import electroblob.wizardry.tileentity.ContainerPortableWorkbench; import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; @@ -48,9 +47,9 @@ public class WizardryGuiHandler implements IGuiHandler { return new electroblob.wizardry.client.gui.handbook.GuiWizardHandbook(); }else if(id == SPELL_BOOK){ if(player.getHeldItemMainhand().getItem() instanceof ItemSpellBook){ - return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.byMetadata(player.getHeldItemMainhand().getItemDamage())); + return new electroblob.wizardry.client.gui.GuiSpellBook(player.getHeldItemMainhand()); }else if(player.getHeldItemOffhand().getItem() instanceof ItemSpellBook){ - return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.byMetadata(player.getHeldItemOffhand().getItemDamage())); + return new electroblob.wizardry.client.gui.GuiSpellBook(player.getHeldItemOffhand()); } }else if(id == PORTABLE_CRAFTING){ return new electroblob.wizardry.client.gui.GuiPortableCrafting(player.inventory, world, new BlockPos(x, y, z)); diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java b/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java index 868ff01d..560c3160 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java @@ -1,11 +1,11 @@ package electroblob.wizardry.client.gui; -import com.google.common.collect.ImmutableMap; import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.data.SpellGlyphData; import electroblob.wizardry.data.WizardData; +import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; @@ -14,27 +14,22 @@ import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.ResourceLocation; +import net.minecraft.item.ItemStack; import org.lwjgl.input.Keyboard; -import java.util.Map; - public class GuiSpellBook extends GuiScreen { private int xSize, ySize; + private ItemSpellBook book; private Spell spell; - private static final Map textures = ImmutableMap.of( - Tier.NOVICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_novice.png"), - Tier.APPRENTICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_apprentice.png"), - Tier.ADVANCED, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_advanced.png"), - Tier.MASTER, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_master.png")); - - public GuiSpellBook(Spell spell){ + public GuiSpellBook(ItemStack stack){ super(); xSize = 288; ySize = 180; - this.spell = spell; + if(!(stack.getItem() instanceof ItemSpellBook)) throw new ClassCastException("Cannot create spell book GUI for item that does not extend ItemSpellBook!"); + this.book = (ItemSpellBook)stack.getItem(); + this.spell = Spell.byMetadata(stack.getItemDamage()); } /** @@ -59,7 +54,7 @@ public class GuiSpellBook extends GuiScreen { Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon()); DrawingUtils.drawTexturedRect(xPos + 146, yPos + 20, 0, 0, 128, 128, 128, 128); - Minecraft.getMinecraft().renderEngine.bindTexture(textures.get(spell.getTier())); + Minecraft.getMinecraft().renderEngine.bindTexture(book.getGuiTexture(spell)); DrawingUtils.drawTexturedRect(xPos, yPos, 0, 0, xSize, ySize, xSize, 256); super.drawScreen(par1, par2, par3); diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java index 2d5ac7b0..bc25a475 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java @@ -780,6 +780,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp Tier maxTier = Tier.NOVICE; List npcSpells = Spell.getSpells(Spell.npcSpells); + npcSpells.removeIf(s -> !s.applicableForItem(WizardryItems.spell_book)); for(int i = 0; i < n; i++){ diff --git a/src/main/java/electroblob/wizardry/item/ItemScroll.java b/src/main/java/electroblob/wizardry/item/ItemScroll.java index c4584cdd..ee850f17 100644 --- a/src/main/java/electroblob/wizardry/item/ItemScroll.java +++ b/src/main/java/electroblob/wizardry/item/ItemScroll.java @@ -51,13 +51,14 @@ public class ItemScroll extends Item implements ISpellCastingItem { @Override public void getSubItems(CreativeTabs tab, NonNullList list){ + if(tab == WizardryTabs.SPELLS){ - // In this particular case, getTotalSpellCount() is a more efficient way of doing this since the spell instance - // is not required, only the metadata. - for(int i = 0; i < Spell.getTotalSpellCount(); i++){ - // i+1 is used so that the metadata ties up with the metadata() method. In other words, the none spell has metadata - // 0 and since this is not used as a spell book the metadata starts at 1. - list.add(new ItemStack(this, 1, i + 1)); + + List spells = Spell.getSpells(Spell.allSpells); + spells.removeIf(s -> !s.applicableForItem(this)); + + for(Spell spell : spells){ + list.add(new ItemStack(this, 1, spell.metadata())); } } } diff --git a/src/main/java/electroblob/wizardry/item/ItemSpellBook.java b/src/main/java/electroblob/wizardry/item/ItemSpellBook.java index 428420ac..167d2c94 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSpellBook.java +++ b/src/main/java/electroblob/wizardry/item/ItemSpellBook.java @@ -1,7 +1,9 @@ package electroblob.wizardry.item; +import com.google.common.collect.ImmutableMap; import electroblob.wizardry.Wizardry; import electroblob.wizardry.WizardryGuiHandler; +import electroblob.wizardry.constants.Tier; import electroblob.wizardry.data.SpellGlyphData; import electroblob.wizardry.registry.WizardryTabs; import electroblob.wizardry.spell.Spell; @@ -9,19 +11,23 @@ import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.util.ActionResult; -import net.minecraft.util.EnumActionResult; -import net.minecraft.util.EnumHand; -import net.minecraft.util.NonNullList; +import net.minecraft.util.*; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.oredict.OreDictionary; import java.util.List; +import java.util.Map; public class ItemSpellBook extends Item { + private static final Map guiTextures = ImmutableMap.of( + Tier.NOVICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_novice.png"), + Tier.APPRENTICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_apprentice.png"), + Tier.ADVANCED, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_advanced.png"), + Tier.MASTER, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_master.png")); + public ItemSpellBook(){ super(); setHasSubtypes(true); @@ -31,13 +37,14 @@ public class ItemSpellBook extends Item { @Override public void getSubItems(CreativeTabs tab, NonNullList list){ + if(tab == WizardryTabs.SPELLS){ - // In this particular case, getTotalSpellCount() is a more efficient way of doing this since the spell instance - // is not required, only the metadata. - for(int i = 0; i < Spell.getTotalSpellCount(); i++){ - // i+1 is used so that the metadata ties up with the metadata() method. In other words, the none spell has metadata - // 0 and since this is not used as a spell book the metadata starts at 1. - list.add(new ItemStack(this, 1, i + 1)); + + List spells = Spell.getSpells(Spell.allSpells); + spells.removeIf(s -> !s.applicableForItem(this)); + + for(Spell spell : spells){ + list.add(new ItemStack(this, 1, spell.metadata())); } } } @@ -79,4 +86,12 @@ public class ItemSpellBook extends Item { return Wizardry.proxy.getFontRenderer(stack); } + /** + * Returns the GUI texture to be used when this spell book is opened. + * @param spell The spell for the book being opened. + */ + public ResourceLocation getGuiTexture(Spell spell){ + return guiTextures.get(spell.getTier()); + } + } diff --git a/src/main/java/electroblob/wizardry/loot/RandomSpell.java b/src/main/java/electroblob/wizardry/loot/RandomSpell.java index a039ac24..5faf20cc 100644 --- a/src/main/java/electroblob/wizardry/loot/RandomSpell.java +++ b/src/main/java/electroblob/wizardry/loot/RandomSpell.java @@ -115,6 +115,7 @@ public class RandomSpell extends LootFunction { // the spell randomiser use any element) change the overall outcome at all? List spellsList = Spell.getSpells(new Spell.TierElementFilter(tier, element, spellContext)); + spellsList.removeIf(s -> !s.applicableForItem(stack.getItem())); if(stack.getItem() instanceof ItemScroll) spellsList.removeIf(s -> !s.isEnabled(SpellProperties.Context.SCROLL)); if(stack.getItem() instanceof ItemSpellBook) spellsList.removeIf(s -> !s.isEnabled(SpellProperties.Context.BOOK)); diff --git a/src/main/java/electroblob/wizardry/loot/WizardSpell.java b/src/main/java/electroblob/wizardry/loot/WizardSpell.java index 72c6d35a..81ec74bd 100644 --- a/src/main/java/electroblob/wizardry/loot/WizardSpell.java +++ b/src/main/java/electroblob/wizardry/loot/WizardSpell.java @@ -5,6 +5,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.living.ISpellCaster; +import electroblob.wizardry.item.ItemScroll; import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.spell.Spell; @@ -33,13 +34,18 @@ public class WizardSpell extends LootFunction { @Override public ItemStack apply(ItemStack stack, Random random, LootContext context){ - if(!(stack.getItem() instanceof ItemSpellBook)) Wizardry.logger + if(!(stack.getItem() instanceof ItemSpellBook) && !(stack.getItem() instanceof ItemScroll)) Wizardry.logger .warn("Applying the wizard_spell loot function to an item that isn't a spell book or scroll."); if(context.getLootedEntity() instanceof ISpellCaster){ List spells = ((ISpellCaster)context.getLootedEntity()).getSpells(); spells.remove(Spells.magic_missile); // Can't drop magic missile - stack.setItemDamage(spells.get(random.nextInt(spells.size())).metadata()); + spells.removeIf(s -> !s.applicableForItem(stack.getItem())); + if(spells.isEmpty()){ + Wizardry.logger.warn("Tried to apply the wizard_spell loot function to an item, but none of the looted entity's spells were applicable for that item. This is probably a bug!"); + }else{ + stack.setItemDamage(spells.get(random.nextInt(spells.size())).metadata()); + } }else{ Wizardry.logger.warn("Applying the wizard_spell loot function to an entity that isn't a spell caster."); } diff --git a/src/main/java/electroblob/wizardry/spell/Spell.java b/src/main/java/electroblob/wizardry/spell/Spell.java index 3a264eac..228c5d44 100644 --- a/src/main/java/electroblob/wizardry/spell/Spell.java +++ b/src/main/java/electroblob/wizardry/spell/Spell.java @@ -10,6 +10,7 @@ import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.packet.PacketSpellProperties; import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.SpellProperties; @@ -18,6 +19,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.EnumAction; +import net.minecraft.item.Item; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; @@ -559,6 +561,13 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C this.enabled = isEnabled; } + /** Returns true if the given item has a variant for this spell. By default, returns true if the given item is + * either {@link WizardryItems#spell_book} or {@link WizardryItems#scroll}. Override to give the spell a special + * type of book or scroll. */ + public boolean applicableForItem(Item item){ + return item == WizardryItems.spell_book || item == WizardryItems.scroll; + } + /** * Returns the unlocalised name of the spell, without any prefixes or suffixes, e.g. "flame_ray". This should * only be used for translation purposes.