package com.nisovin.magicspells.spells.command;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.Spell;
import com.nisovin.magicspells.materials.ItemNameResolver;
import com.nisovin.magicspells.materials.MagicMaterial;
import com.nisovin.magicspells.spells.CommandSpell;
import com.nisovin.magicspells.util.MagicConfig;
import com.nisovin.magicspells.util.SpellReagents;
import com.nisovin.magicspells.util.Util;
public class ImbueSpell extends CommandSpell {
private String key;
private int defaultUses;
private int maxUses;
private boolean allowSpecifyUses;
private boolean chargeReagentsForSpellPerUse;
private boolean requireTeachPerm;
private boolean consumeItem;
private boolean rightClickCast;
private boolean leftClickCast;
private Set<Material> allowedItemTypes;
private List<MagicMaterial> allowedItemMaterials;
private boolean nameAndLoreHasUses;
private String strItemName;
private String strItemLore;
private String strUsage;
private String strCantImbueItem;
private String strCantImbueSpell;
public ImbueSpell(MagicConfig config, String spellName) {
super(config, spellName);
key = "Imb" + internalName;
defaultUses = getConfigInt("default-uses", 5);
maxUses = getConfigInt("max-uses", 10);
allowSpecifyUses = getConfigBoolean("allow-specify-uses", true);
chargeReagentsForSpellPerUse = getConfigBoolean("charge-reagents-for-spell-per-use", true);
requireTeachPerm = getConfigBoolean("require-teach-perm", true);
consumeItem = getConfigBoolean("consume-item", false);
rightClickCast = getConfigBoolean("right-click-cast", false);
leftClickCast = getConfigBoolean("left-click-cast", true);
allowedItemTypes = new HashSet<Material>();
allowedItemMaterials = new ArrayList<MagicMaterial>();
List<String> allowed = getConfigStringList("allowed-items", null);
if (allowed != null) {
ItemNameResolver resolver = MagicSpells.getItemNameResolver();
for (String s : allowed) {
MagicMaterial m = resolver.resolveItem(s);
if (m != null) {
allowedItemTypes.add(m.getMaterial());
allowedItemMaterials.add(m);
}
}
}
strItemName = getConfigString("str-item-name", "");
strItemLore = getConfigString("str-item-lore", "Imbued: %s");
strUsage = getConfigString("str-usage", "Usage: /cast imbue <spell> [uses]");
strCantImbueItem = getConfigString("str-cant-imbue-item", "You can't imbue that item.");
strCantImbueSpell = getConfigString("str-cant-imbue-spell", "You can't imbue that spell.");
nameAndLoreHasUses = (strItemName.contains("%u") || strItemLore.contains("%u"));
}
@Override
public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) {
if (state == SpellCastState.NORMAL) {
if (args == null || args.length == 0) {
// usage
sendMessage(player, strUsage);
return PostCastAction.ALREADY_HANDLED;
}
// get item
ItemStack inHand = player.getItemInHand();
if (!allowedItemTypes.contains(inHand.getType())) {
// disallowed item
sendMessage(player, strCantImbueItem);
return PostCastAction.ALREADY_HANDLED;
}
boolean allowed = false;
for (MagicMaterial m : allowedItemMaterials) {
if (m.equals(inHand)) {
allowed = true;
break;
}
}
if (!allowed) {
// disallowed item
sendMessage(player, strCantImbueItem);
return PostCastAction.ALREADY_HANDLED;
}
// check for already imbued
if (getImbueData(inHand) != null) {
// already imbued
sendMessage(player, strCantImbueItem);
return PostCastAction.ALREADY_HANDLED;
}
// get spell
Spell spell = MagicSpells.getSpellByInGameName(args[0]);
if (spell == null) {
// no spell
sendMessage(player, strCantImbueSpell);
return PostCastAction.ALREADY_HANDLED;
}
if (!MagicSpells.getSpellbook(player).hasSpell(spell)) {
// doesn't know spell
sendMessage(player, strCantImbueSpell);
return PostCastAction.ALREADY_HANDLED;
}
// check teach perm
if (requireTeachPerm && !MagicSpells.getSpellbook(player).canTeach(spell)) {
// can't teach
sendMessage(player, strCantImbueSpell);
return PostCastAction.ALREADY_HANDLED;
}
// get uses
int uses = defaultUses;
if (args.length > 1 && args[1].matches("[0-9]+") && (allowSpecifyUses || player.hasPermission("magicspells.advanced.imbue"))) {
uses = Integer.parseInt(args[1]);
if (uses > maxUses) {
uses = maxUses;
} else if (uses <= 0) {
uses = 1;
}
}
// get additional reagent cost
if (chargeReagentsForSpellPerUse && !player.hasPermission("magicspells.noreagents")) {
SpellReagents reagents = spell.getReagents().multiply(uses);
if (!hasReagents(player, reagents)) {
// missing reagents
sendMessage(player, strMissingReagents);
return PostCastAction.ALREADY_HANDLED;
} else {
// has reagents, so just remove them
removeReagents(player, reagents);
}
}
// imbue item
setItemNameAndLore(inHand, spell, uses);
setImbueData(inHand, spell.getInternalName() + "," + uses);
player.setItemInHand(inHand);
}
return PostCastAction.HANDLE_NORMALLY;
}
@EventHandler(priority=EventPriority.HIGHEST)
public void onInteract(PlayerInteractEvent event) {
if (event.useItemInHand() == Result.DENY) return;
if (event.hasItem() && (
(rightClickCast && (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)) ||
(leftClickCast && (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK))
)) {
ItemStack item = event.getItem();
if (allowedItemTypes.contains(item.getType())) {
boolean allowed = false;
for (MagicMaterial m : allowedItemMaterials) {
if (m.equals(item)) {
allowed = true;
break;
}
}
if (!allowed) return;
String imbueData = getImbueData(item);
if (imbueData != null && !imbueData.isEmpty()) {
String[] data = imbueData.split(",");
Spell spell = MagicSpells.getSpellByInternalName(data[0]);
int uses = Integer.parseInt(data[1]);
if (spell != null && uses > 0) {
spell.castSpell(event.getPlayer(), SpellCastState.NORMAL, 1.0F, null);
uses--;
if (uses <= 0) {
if (consumeItem) {
event.getPlayer().setItemInHand(null);
} else {
Util.removeLoreData(item);
if (nameAndLoreHasUses) {
setItemNameAndLore(item, spell, 0);
}
}
} else {
if (nameAndLoreHasUses) {
setItemNameAndLore(item, spell, uses);
}
setImbueData(item, spell.getInternalName() + "," + uses);
}
} else {
Util.removeLoreData(item);
}
}
}
}
}
private void setItemNameAndLore(ItemStack item, Spell spell, int uses) {
ItemMeta meta = item.getItemMeta();
if (!strItemName.isEmpty()) {
meta.setDisplayName(strItemName.replace("%s", spell.getName()).replace("%u", uses+""));
}
if (!strItemLore.isEmpty()) {
meta.setLore(Arrays.asList(strItemLore.replace("%s", spell.getName()).replace("%u", uses+"")));
}
item.setItemMeta(meta);
}
private void setImbueData(ItemStack item, String data) {
Util.setLoreData(item, key + ":" + data);
}
private String getImbueData(ItemStack item) {
String s = Util.getLoreData(item);
if (s != null && s.startsWith(key + ":")) {
return s.replace(key + ":", "");
}
return null;
}
@Override
public boolean castFromConsole(CommandSender sender, String[] args) {
return false;
}
@Override
public List<String> tabComplete(CommandSender sender, String partial) {
return null;
}
}