package com.nisovin.magicspells.spells.command;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerAnimationEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ItemStack;
import com.nisovin.magicspells.spells.CommandSpell;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.Spell;
import com.nisovin.magicspells.util.MagicConfig;
import com.nisovin.magicspells.util.Util;
public class KeybindSpell extends CommandSpell {
private ItemStack wandItem;
private ItemStack defaultSpellIcon;
private HashMap<String,Keybinds> playerKeybinds;
public KeybindSpell(MagicConfig config, String spellName) {
super(config, spellName);
wandItem = Util.getItemStackFromString(getConfigString("wand-item", "blaze_rod"));
defaultSpellIcon = Util.getItemStackFromString(getConfigString("default-spell-icon", "redstone"));
playerKeybinds = new HashMap<String, KeybindSpell.Keybinds>();
}
@Override
protected void initialize() {
super.initialize();
for (Player p : Bukkit.getOnlinePlayers()) {
loadKeybinds(p);
}
}
private void loadKeybinds(Player player) {
File file = new File(MagicSpells.plugin.getDataFolder(), "spellbooks" + File.separator + "keybinds-" + player.getName().toLowerCase() + ".txt");
if (file.exists()) {
try {
Keybinds keybinds = new Keybinds(player);
YamlConfiguration conf = new YamlConfiguration();
conf.load(file);
for (String key : conf.getKeys(false)) {
int slot = Integer.parseInt(key);
String spellName = conf.getString(key);
Spell spell = MagicSpells.getSpellByInternalName(spellName);
if (spell != null) {
keybinds.setKeybind(slot, spell);
}
}
playerKeybinds.put(player.getName(), keybinds);
} catch (Exception e) {
MagicSpells.plugin.getLogger().severe("Failed to load player keybinds for " + player.getName());
e.printStackTrace();
}
}
}
private void saveKeybinds(Keybinds keybinds) {
File file = new File(MagicSpells.plugin.getDataFolder(), "spellbooks" + File.separator + "keybinds-" + keybinds.player.getName().toLowerCase() + ".txt");
YamlConfiguration conf = new YamlConfiguration();
Spell[] binds = keybinds.keybinds;
for (int i = 0; i < binds.length; i++) {
if (binds[i] != null) {
conf.set(i+"", binds[i].getInternalName());
}
}
try {
conf.save(file);
} catch (IOException e) {
MagicSpells.plugin.getLogger().severe("Failed to save keybinds for " + keybinds.player.getName());
e.printStackTrace();
}
}
@Override
public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) {
if (state == SpellCastState.NORMAL) {
if (args.length != 1) {
// fail
player.sendMessage("invalid args");
return PostCastAction.ALREADY_HANDLED;
}
Keybinds keybinds = playerKeybinds.get(player.getName());
if (keybinds == null) {
keybinds = new Keybinds(player);
playerKeybinds.put(player.getName(), keybinds);
}
int slot = player.getInventory().getHeldItemSlot();
ItemStack item = player.getItemInHand();
if (args[0].equalsIgnoreCase("clear")) {
keybinds.clearKeybind(slot);
saveKeybinds(keybinds);
} else if (args[0].equalsIgnoreCase("clearall")) {
keybinds.clearKeybinds();
saveKeybinds(keybinds);
} else {
if (item != null && item.getType() != Material.AIR) {
// fail
player.sendMessage("not empty");
return PostCastAction.ALREADY_HANDLED;
}
Spell spell = MagicSpells.getSpellbook(player).getSpellByName(args[0]);
if (spell == null) {
// fail
player.sendMessage("no spell");
return PostCastAction.ALREADY_HANDLED;
}
keybinds.setKeybind(slot, spell);
keybinds.select(slot);
saveKeybinds(keybinds);
}
}
return PostCastAction.HANDLE_NORMALLY;
}
@EventHandler
public void onItemHeldChange(PlayerItemHeldEvent event) {
Keybinds keybinds = playerKeybinds.get(event.getPlayer().getName());
if (keybinds != null) {
keybinds.deselect(event.getPreviousSlot());
keybinds.select(event.getNewSlot());
}
}
@EventHandler
public void onAnimate(PlayerAnimationEvent event) {
Keybinds keybinds = playerKeybinds.get(event.getPlayer().getName());
if (keybinds != null) {
boolean casted = keybinds.castKeybind(event.getPlayer().getInventory().getHeldItemSlot());
if (casted) {
event.setCancelled(true);
}
}
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.isCancelled()) return;
Keybinds keybinds = playerKeybinds.get(event.getPlayer().getName());
if (keybinds != null && keybinds.hasKeybind(event.getPlayer().getInventory().getHeldItemSlot())) {
event.setCancelled(true);
}
}
@EventHandler(priority=EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event) {
loadKeybinds(event.getPlayer());
}
@Override
public boolean castFromConsole(CommandSender sender, String[] args) {
return false;
}
@Override
public List<String> tabComplete(CommandSender sender, String partial) {
return null;
}
protected void sendFakeSlotUpdate(Player player, int slot, ItemStack item) {
MagicSpells.getVolatileCodeHandler().sendFakeSlotUpdate(player, slot, item);
}
private class Keybinds {
private Player player;
private Spell[] keybinds;
public Keybinds(Player player) {
this.player = player;
this.keybinds = new Spell[10];
}
public void deselect(int slot) {
Spell spell = keybinds[slot];
if (spell != null) {
ItemStack spellIcon = spell.getSpellIcon();
if (spellIcon == null) {
spellIcon = defaultSpellIcon;
}
//player.getInventory().setItem(slot, new ItemStack(spellIcon.getType(), 0, spellIcon.getDurability()));
sendFakeSlotUpdate(player, slot, spellIcon);
}
}
public void select(int slot) {
Spell spell = keybinds[slot];
if (spell != null) {
sendFakeSlotUpdate(player, slot, wandItem);
}
}
public boolean hasKeybind(int slot) {
return (keybinds[slot] != null);
}
public boolean castKeybind(int slot) {
Spell spell = keybinds[slot];
if (spell != null) {
spell.cast(player);
return true;
}
return false;
}
public void setKeybind(int slot, Spell spell) {
keybinds[slot] = spell;
}
public void clearKeybind(int slot) {
keybinds[slot] = null;
sendFakeSlotUpdate(player, slot, null);
}
public void clearKeybinds() {
for (int i = 0; i < keybinds.length; i++) {
if (keybinds[i] != null) {
keybinds[i] = null;
sendFakeSlotUpdate(player, i, null);
}
}
}
}
}