package net.aufdemrand.denizen.scripts.commands.item;
import net.aufdemrand.denizen.BukkitScriptEntryData;
import net.aufdemrand.denizen.objects.dItem;
import net.aufdemrand.denizen.objects.dLocation;
import net.aufdemrand.denizen.scripts.containers.core.BookScriptContainer;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.exceptions.CommandExecutionException;
import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException;
import net.aufdemrand.denizencore.objects.aH;
import net.aufdemrand.denizencore.objects.dScript;
import net.aufdemrand.denizencore.scripts.ScriptEntry;
import net.aufdemrand.denizencore.scripts.commands.AbstractCommand;
import net.aufdemrand.denizencore.tags.ReplaceableTagEvent;
import net.aufdemrand.denizencore.tags.TagManager;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class ScribeCommand extends AbstractCommand implements Listener {
private enum BookAction {GIVE, DROP, EQUIP, NONE}
@Override
public void onEnable() {
DenizenAPI.getCurrentInstance().getServer().getPluginManager().registerEvents(this, DenizenAPI.getCurrentInstance());
TagManager.registerTagEvents(this);
}
@Override
public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) {
if (arg.matchesEnum(BookAction.values())
&& !scriptEntry.hasObject("action")) {
scriptEntry.addObject("action", BookAction.valueOf(arg.getValue().toUpperCase()));
}
else if (!scriptEntry.hasObject("script")
&& arg.matchesArgumentType(dScript.class)) {
scriptEntry.addObject("script", arg.asType(dScript.class));
}
else if (!scriptEntry.hasObject("location")
&& arg.matchesArgumentType(dLocation.class)) {
scriptEntry.addObject("location", arg.asType(dLocation.class));
scriptEntry.addObject("action", BookAction.DROP);
}
else if (!scriptEntry.hasObject("item")
&& arg.matchesArgumentType(dItem.class)) {
scriptEntry.addObject("item", arg.asType(dItem.class));
}
else {
arg.reportUnhandled();
}
}
scriptEntry.defaultObject("action", BookAction.GIVE);
scriptEntry.defaultObject("item", new dItem(Material.WRITTEN_BOOK));
// Must contain a book script
if (!scriptEntry.hasObject("script")) {
throw new InvalidArgumentsException("Missing SCRIPT argument!");
}
}
@Override
public void execute(ScriptEntry scriptEntry) throws CommandExecutionException {
// Retrieve objects from ScriptEntry
BookAction action = (BookAction) scriptEntry.getObject("action");
dItem book = (dItem) scriptEntry.getObject("item");
dScript script = (dScript) scriptEntry.getObject("script");
dLocation location = (dLocation) scriptEntry.getObject("location");
BookScriptContainer bookScript = (BookScriptContainer) script.getContainer();
book = bookScript.writeBookTo(book, ((BukkitScriptEntryData) scriptEntry.entryData).getPlayer(), ((BukkitScriptEntryData) scriptEntry.entryData).getNPC());
// Post-write action? Can be NONE.
switch (action) {
case DROP:
dropBook(location, book.getItemStack());
break;
case GIVE:
giveBook(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getPlayerEntity(), book.getItemStack());
// Update player's inventory
((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getPlayerEntity().updateInventory();
break;
case EQUIP:
equipBook(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getPlayerEntity(), book.getItemStack());
// Update player's inventory
((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getPlayerEntity().updateInventory();
break;
case NONE:
break;
}
}
private void giveBook(Player player, ItemStack book) {
Inventory inv = player.getInventory();
int emptySpot = inv.firstEmpty();
if (emptySpot != -1) {
player.getInventory().addItem(book);
}
else {
player.getWorld().dropItem(player.getLocation(), book);
dB.log("Player's inventory is full, dropped book.");
}
}
private void equipBook(Player player, ItemStack book) {
ItemStack currItem = player.getItemInHand();
Inventory inv = player.getInventory();
int emptySpot = inv.firstEmpty();
// if player isn't holding anything
if (currItem == null || currItem.getType() == Material.AIR) {
player.setItemInHand(book);
return;
}
// drop it if inventory has no empty slots
emptySpot = inv.firstEmpty();
dB.log("emptySpot: " + emptySpot);
if (emptySpot == -1) {
player.getWorld().dropItem(player.getLocation(), book);
dB.log("Player's inventory is full, dropped book.");
}
// move current held item to empty spot, set item in hand to the book
else {
inv.setItem(emptySpot, currItem);
player.setItemInHand(book);
dB.log("...added book to player hand, moved original item");
}
}
private void dropBook(Location location, ItemStack book) {
location.getWorld().dropItem(location, book);
}
/**
* Catches a replaceable tag event for '<P>' and replaces it with
* a book-friendly 'newline'.
*
* @param e ReplaceableTagEvent
*/
@TagManager.TagEvents
public void paragraph(ReplaceableTagEvent e) {
// <--[tag]
// @attribute <P>
// @returns Element
// @description
// Returns a paragraph, for use in books.
// -->
if (e.matches("P")) {
e.setReplaced("\n \u00A7r \n");
// <--[tag]
// @attribute <N>
// @returns Element
// @description
// Returns a newline symbol, for use in books.
// -->
}
else if (e.matches("N")) {
e.setReplaced("\n");
}
}
}