package com.nisovin.magicspells.spells.command; import java.util.List; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import com.nisovin.magicspells.MagicSpells; import com.nisovin.magicspells.Spell; import com.nisovin.magicspells.Spellbook; import com.nisovin.magicspells.events.SpellLearnEvent; import com.nisovin.magicspells.events.SpellLearnEvent.LearnSource; import com.nisovin.magicspells.spelleffects.EffectPosition; import com.nisovin.magicspells.spells.CommandSpell; import com.nisovin.magicspells.util.MagicConfig; import com.nisovin.magicspells.util.Util; public class TomeSpell extends CommandSpell { private boolean cancelReadOnLearn; private boolean consumeBook; private boolean allowOverwrite; private int defaultUses; private int maxUses; private boolean requireTeachPerm; private String strUsage; private String strNoSpell; private String strCantTeach; private String strNoBook; private String strAlreadyHasSpell; private String strAlreadyKnown; private String strCantLearn; private String strLearned; public TomeSpell(MagicConfig config, String spellName) { super(config, spellName); cancelReadOnLearn = getConfigBoolean("cancel-read-on-learn", true); consumeBook = getConfigBoolean("consume-book", false); allowOverwrite = getConfigBoolean("allow-overwrite", false); defaultUses = getConfigInt("default-uses", -1); maxUses = getConfigInt("max-uses", 5); requireTeachPerm = getConfigBoolean("require-teach-perm", true); strUsage = getConfigString("str-usage", "Usage: While holding a book, /cast " + name + " <spell> [uses]"); strNoSpell = getConfigString("str-no-spell", "You do not know a spell with that name."); strCantTeach = getConfigString("str-cant-teach", "You cannot create a tome with that spell."); strNoBook = getConfigString("str-no-book", "You must be holding a book."); strAlreadyHasSpell = getConfigString("str-already-has-spell", "That book already contains a spell."); strAlreadyKnown = getConfigString("str-already-known", "You already know the %s spell."); strCantLearn = getConfigString("str-cant-learn", "You cannot learn the spell in this tome."); strLearned = getConfigString("str-learned", "You have learned the %s spell."); } @Override public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) { if (state == SpellCastState.NORMAL) { Spell spell; if (args == null || args.length == 0) { // fail -- no args sendMessage(player, strUsage); return PostCastAction.ALREADY_HANDLED; } else { Spellbook spellbook = MagicSpells.getSpellbook(player); spell = MagicSpells.getSpellByInGameName(args[0]); if (spell == null || spellbook == null || !spellbook.hasSpell(spell)) { // fail -- no spell sendMessage(player, strNoSpell); return PostCastAction.ALREADY_HANDLED; } else if (requireTeachPerm && !MagicSpells.getSpellbook(player).canTeach(spell)) { sendMessage(player, strCantTeach); return PostCastAction.ALREADY_HANDLED; } } ItemStack item = player.getItemInHand(); if (item.getType() != Material.WRITTEN_BOOK) { // fail -- no book sendMessage(player, strNoBook); return PostCastAction.ALREADY_HANDLED; } if (!allowOverwrite && getSpellDataFromTome(item) != null) { // fail -- already has a spell sendMessage(player, strAlreadyHasSpell); return PostCastAction.ALREADY_HANDLED; } else { int uses = defaultUses; if (args.length > 1 && args[1].matches("^[0-9]+$")) { uses = Integer.parseInt(args[1]); } item = createTome(spell, uses, item); player.setItemInHand(item); } } return PostCastAction.HANDLE_NORMALLY; } public ItemStack createTome(Spell spell, int uses, ItemStack item) { if (maxUses > 0 && uses > maxUses) { uses = maxUses; } else if (uses < 0) { uses = defaultUses; } if (item == null) { item = new ItemStack(Material.WRITTEN_BOOK, 1); BookMeta bookMeta = (BookMeta)item.getItemMeta(); bookMeta.setTitle(getName() + ": " + spell.getName()); item.setItemMeta(bookMeta); } Util.setLoreData(item, internalName + ":" + spell.getInternalName() + (uses>0?","+uses:"")); return item; } @Override public boolean castFromConsole(CommandSender sender, String[] args) { return false; } @Override public List<String> tabComplete(CommandSender sender, String partial) { return null; } private String getSpellDataFromTome(ItemStack item) { String loreData = Util.getLoreData(item); if (loreData != null && loreData.startsWith(internalName + ":")) { return loreData.replace(internalName + ":", ""); } return null; } @EventHandler public void onInteract(PlayerInteractEvent event) { if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (!event.hasItem()) return; ItemStack item = event.getItem(); if (item.getType() != Material.WRITTEN_BOOK) return; String spellData = getSpellDataFromTome(item); if (spellData == null || spellData.isEmpty()) return; String[] data = spellData.split(","); Spell spell = MagicSpells.getSpellByInternalName(data[0]); int uses = -1; if (data.length > 1) { uses = Integer.parseInt(data[1]); } Spellbook spellbook = MagicSpells.getSpellbook(event.getPlayer()); if (spell != null && spellbook != null) { if (spellbook.hasSpell(spell)) { // fail -- already known sendMessage(event.getPlayer(), formatMessage(strAlreadyKnown, "%s", spell.getName())); } else if (!spellbook.canLearn(spell)) { // fail -- can't learn sendMessage(event.getPlayer(), formatMessage(strCantLearn, "%s", spell.getName())); } else { // call event SpellLearnEvent learnEvent = new SpellLearnEvent(spell, event.getPlayer(), LearnSource.TOME, event.getPlayer().getItemInHand()); Bukkit.getPluginManager().callEvent(learnEvent); if (learnEvent.isCancelled()) { // fail -- plugin cancelled sendMessage(event.getPlayer(), formatMessage(strCantLearn, "%s", spell.getName())); } else { // give spell spellbook.addSpell(spell); spellbook.save(); sendMessage(event.getPlayer(), formatMessage(strLearned, "%s", spell.getName())); if (cancelReadOnLearn) { event.setCancelled(true); } // remove use if (uses > 0) { uses--; if (uses > 0) { Util.setLoreData(item, internalName + ":" + data[0] + "," + uses); } else { Util.removeLoreData(item); } } // consume if (uses <= 0 && consumeBook) { event.getPlayer().setItemInHand(null); } playSpellEffects(EffectPosition.DELAYED, event.getPlayer()); } } } } }