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
This commit is contained in:
Electroblob77
2019-09-27 15:46:09 +01:00
parent 028b753be6
commit 60a6c5124e
8 changed files with 61 additions and 34 deletions
@@ -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));
@@ -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<Tier, ResourceLocation> 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);
@@ -780,6 +780,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
Tier maxTier = Tier.NOVICE;
List<Spell> npcSpells = Spell.getSpells(Spell.npcSpells);
npcSpells.removeIf(s -> !s.applicableForItem(WizardryItems.spell_book));
for(int i = 0; i < n; i++){
@@ -51,13 +51,14 @@ public class ItemScroll extends Item implements ISpellCastingItem {
@Override
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> 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<Spell> spells = Spell.getSpells(Spell.allSpells);
spells.removeIf(s -> !s.applicableForItem(this));
for(Spell spell : spells){
list.add(new ItemStack(this, 1, spell.metadata()));
}
}
}
@@ -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<Tier, ResourceLocation> 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<ItemStack> 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<Spell> 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());
}
}
@@ -115,6 +115,7 @@ public class RandomSpell extends LootFunction {
// the spell randomiser use any element) change the overall outcome at all?
List<Spell> 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));
@@ -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<Spell> 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.");
}
@@ -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<Spell> 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". <b>This should
* only be used for translation purposes.</b>