/* * Copyright (C) 2013-2016 Gonçalo Baltazar <me@goncalomb.com> * * This file is part of NBTEditor. * * NBTEditor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NBTEditor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NBTEditor. If not, see <http://www.gnu.org/licenses/>. */ package com.goncalomb.bukkit.nbteditor.bos; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Random; import java.util.logging.Level; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.Plugin; import com.goncalomb.bukkit.customitems.api.CustomItem; import com.goncalomb.bukkit.customitems.api.CustomItemManager; import com.goncalomb.bukkit.mylib.namemaps.EntityTypeMap; import com.goncalomb.bukkit.mylib.reflect.NBTTagCompound; import com.goncalomb.bukkit.mylib.utils.BookSerialize; import com.goncalomb.bukkit.nbteditor.nbt.DroppedItemNBT; import com.goncalomb.bukkit.nbteditor.nbt.EntityNBT; import com.goncalomb.bukkit.nbteditor.nbt.EquippableNBT; import com.goncalomb.bukkit.nbteditor.nbt.FallingBlockNBT; import com.goncalomb.bukkit.nbteditor.nbt.FireworkNBT; import com.goncalomb.bukkit.nbteditor.nbt.MinecartContainerNBT; import com.goncalomb.bukkit.nbteditor.nbt.MinecartSpawnerNBT; import com.goncalomb.bukkit.nbteditor.nbt.MobNBT; import com.goncalomb.bukkit.nbteditor.nbt.ThrownPotionNBT; import com.goncalomb.bukkit.nbteditor.nbt.VillagerNBT; import com.goncalomb.bukkit.nbteditor.nbt.attributes.Attribute; import com.goncalomb.bukkit.nbteditor.nbt.attributes.Modifier; import com.goncalomb.bukkit.nbteditor.nbt.variable.NBTVariable; import com.goncalomb.bukkit.nbteditor.nbt.variable.NBTVariableContainer; import net.iharder.Base64; public class BookOfSouls { private static final String _author = ChatColor.GOLD + "The Creator"; private static final String _dataTitle = "" + ChatColor.DARK_PURPLE + ChatColor.BOLD + "Soul Data v0.2" + ChatColor.BLACK + "\n"; private static final String _dataTitleOLD = "" + ChatColor.DARK_PURPLE + ChatColor.BOLD + "Soul Data v0.1" + ChatColor.BLACK + "\n"; private static CustomItem _bosEmptyCustomItem; private static CustomItem _bosCustomItem; private static Plugin _plugin = null; private static final String[] _mobEquipSlotName = new String[] { "Head Equipment", "Chest Equipment", "Legs Equipment", "Feet Equipment", "Main Hand Item", "Off Hand Item" }; private ItemStack _book; private EntityNBT _entityNbt; public static void initialize(Plugin plugin) { if (_plugin != null) return; _plugin = plugin; _bosEmptyCustomItem = new BookOfSoulsEmptyCI(); CustomItemManager.register(_bosEmptyCustomItem, plugin, _plugin.getName()); _bosCustomItem = new BookOfSoulsCI(); CustomItemManager.register(_bosCustomItem, plugin, _plugin.getName()); } static EntityNBT bookToEntityNBT(ItemStack book) { if (isValidBook(book)) { try { String data = BookSerialize.loadData((BookMeta) book.getItemMeta(), _dataTitle); if (data == null) { // This is not a BoS v0.2, is BoS v0.1? data = BookSerialize.loadData((BookMeta) book.getItemMeta(), _dataTitleOLD); if (data != null) { // Yes, it is v0.1, do a dirty conversion. int i = data.indexOf(','); NBTTagCompound nbtData = NBTTagCompound.unserialize(Base64.decode(data.substring(i + 1))); nbtData.setString("id", data.substring(0, i)); data = Base64.encodeBytes(nbtData.serialize(), Base64.GZIP); } } if (data != null) { if (data.startsWith("§k")) { // Dirty fix, for some reason 'data' can sometimes start with §k. // Remove it!!! data = data.substring(2); } return EntityNBT.unserialize(data); } } catch (Exception e) { _plugin.getLogger().log(Level.WARNING, "Corrupt Book of Souls.", e); return null; } } return null; } public static BookOfSouls getFromBook(ItemStack book) { EntityNBT entityNbt = bookToEntityNBT(book); if (entityNbt != null) { return new BookOfSouls(book, entityNbt); } return null; } public static ItemStack getEmpty() { return _bosEmptyCustomItem.getItem(); } public BookOfSouls(EntityNBT entityNBT) { this(null, entityNBT); } private BookOfSouls(ItemStack book, EntityNBT entityNBT) { _book = book; _entityNbt = entityNBT; } public static boolean isValidBook(ItemStack book) { if (book != null && book.getType() == Material.WRITTEN_BOOK) { ItemMeta meta = book.getItemMeta(); String title = ((BookMeta) meta).getTitle(); if (meta != null && title != null && title.equals(_bosCustomItem.getName())) { return true; } } return false; } public boolean openInventory(Player player) { if (_entityNbt instanceof MobNBT) { (new InventoryForMobs(this, player)).openInventory(player, _plugin); return true; } else if (_entityNbt.getEntityType() == EntityType.ARMOR_STAND) { (new InventoryForEquippable<EquippableNBT>(this, player)).openInventory(player, _plugin); return true; } else if (_entityNbt instanceof DroppedItemNBT) { (new InventoryForDroppedItems(this, player)).openInventory(player, _plugin); return true; } else if (_entityNbt instanceof ThrownPotionNBT) { (new InventoryForThownPotion(this, player)).openInventory(player, _plugin); return true; } else if (_entityNbt instanceof FireworkNBT) { (new InventoryForFirework(this, player)).openInventory(player, _plugin); return true; } else if (_entityNbt instanceof MinecartContainerNBT) { (new InventoryForMinecartContainer(this, player)).openInventory(player, _plugin); return true; } return false; } public boolean openOffersInventory(Player player, int page) { if (_entityNbt instanceof VillagerNBT) { (new InventoryForVillagers(this, page, player)).openInventory(player, _plugin); return true; } return false; } public void openRidingInventory(Player player) { (new InventoryForRiding(this, player)).openInventory(player, _plugin); } public EntityNBT getEntityNBT() { return _entityNbt; } public ItemStack getBook() { if (_book == null) { _book = new ItemStack(Material.WRITTEN_BOOK); saveBook(true); } return _book; } public void saveBook() { saveBook(false); } public void saveBook(boolean resetName) { BookMeta meta = (BookMeta) _book.getItemMeta(); String entityName = EntityTypeMap.getName(_entityNbt.getEntityType()); if (resetName) { meta.setDisplayName(_bosCustomItem.getName() + ChatColor.RESET + " - " + ChatColor.RED + entityName); meta.setTitle(_bosCustomItem.getName()); meta.setAuthor(_author); } meta.setPages(new ArrayList<String>()); StringBuilder sb = new StringBuilder(); sb.append("This book contains the soul of a " + ChatColor.RED + ChatColor.BOLD + entityName + "\n\n"); int x = 7; if (_entityNbt instanceof MinecartSpawnerNBT) { sb.append(ChatColor.BLACK + "Left-click a existing spawner to copy the entities and variables from the spawner, left-click while sneaking to copy them back to the spawner."); meta.addPage(sb.toString()); sb = new StringBuilder(); x = 11; } else if (_entityNbt instanceof FallingBlockNBT) { sb.append(ChatColor.BLACK + "Left-click a block while sneaking to copy block data.\n\n"); x = 5; } for (NBTVariableContainer vc : _entityNbt.getAllVariables()) { if (x == 1) { meta.addPage(sb.toString()); sb = new StringBuilder(); x = 11; } sb.append("" + ChatColor.DARK_PURPLE + ChatColor.ITALIC + vc.getName() + ":\n"); for (NBTVariable var : vc) { if (--x == 0) { meta.addPage(sb.toString()); sb = new StringBuilder(); x = 10; } String value = var.getValue(); sb.append(" " + ChatColor.DARK_BLUE + var.getName() + ": " + ChatColor.BLACK + (value != null ? value : ChatColor.ITALIC + "-") + "\n"); } } meta.addPage(sb.toString()); if (_entityNbt instanceof EquippableNBT) { sb = new StringBuilder(); sb.append("" + ChatColor.DARK_PURPLE + ChatColor.BOLD + "Armor Items:\n"); ItemStack[] items = ((EquippableNBT) _entityNbt).getArmorItems(); for (int i = 0; i < 4; ++i) { sb.append(ChatColor.DARK_BLUE + _mobEquipSlotName[i] + ":\n"); if (items[3 - i] != null) { sb.append(" " + ChatColor.BLACK + items[3 - i].getType().name() + ":" + items[3 - i].getDurability() + "(" + items[3 - i].getAmount() + ")" + "\n"); } else { sb.append(" " + ChatColor.BLACK + ChatColor.ITALIC +"none\n"); } } meta.addPage(sb.toString()); sb = new StringBuilder(); sb.append("" + ChatColor.DARK_PURPLE + ChatColor.BOLD + "Hand Items:\n"); items = ((EquippableNBT) _entityNbt).getHandItems(); for (int i = 0; i < 2; ++i) { sb.append(ChatColor.DARK_BLUE + _mobEquipSlotName[4 + i] + ":\n"); if (items[i] != null) { sb.append(" " + ChatColor.BLACK + items[i].getType().name() + ":" + items[i].getDurability() + "(" + items[i].getAmount() + ")" + "\n"); } else { sb.append(" " + ChatColor.BLACK + ChatColor.ITALIC +"none\n"); } } meta.addPage(sb.toString()); } if (_entityNbt instanceof MobNBT) { MobNBT mob = (MobNBT) _entityNbt; sb = new StringBuilder(); sb.append("" + ChatColor.DARK_PURPLE + ChatColor.BOLD + "Attributes:\n"); Collection<Attribute> attributes = mob.getAttributes().values(); if (attributes.size() == 0) { sb.append(" " + ChatColor.BLACK + ChatColor.ITALIC +"none\n"); } else { x = 11; for (Attribute attribute : attributes) { if (x <= 3) { meta.addPage(sb.toString()); sb = new StringBuilder(); x = 11; } sb.append("" + ChatColor.DARK_PURPLE + ChatColor.ITALIC + attribute.getType().getName() + ":\n"); sb.append(" " + ChatColor.DARK_BLUE + "Base: " + ChatColor.BLACK + attribute.getBase() + "\n"); sb.append(" " + ChatColor.DARK_BLUE + "Modifiers:\n"); x -= 3; List<Modifier> modifiers = attribute.getModifiers(); if (modifiers.size() == 0) { sb.append(" " + ChatColor.BLACK + ChatColor.ITALIC +"none\n"); } else { for (Modifier modifier : modifiers) { if (x <= 3) { meta.addPage(sb.toString()); sb = new StringBuilder(); x = 11; } sb.append(" " + ChatColor.RED + modifier.getName() + ChatColor.DARK_GREEN + " Op: " + ChatColor.BLACK + modifier.getOperation() + "\n"); sb.append(" " + ChatColor.DARK_GREEN + "Amount: " + ChatColor.BLACK + modifier.getAmount() + "\n"); x -= 3; } } sb.append("\n"); --x; } } meta.addPage(sb.toString()); } BookSerialize.saveToBook(meta, _entityNbt.serialize(), _dataTitle); meta.addPage("RandomId: " + Integer.toHexString((new Random()).nextInt()) + "\n\n\n" + ChatColor.DARK_BLUE + ChatColor.BOLD + " The END."); _book.setItemMeta(meta); } }