/** * bNpcStore 1.2-SNAPSHOT Copyright (C) 2013 CodingBadgers * <plugins@mcbadgercraft.com> * * This program 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. * * This program 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 * this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.codingbadgers.bnpcstore; import uk.codingbadgers.bnpcstore.database.DatabaseManager; import java.io.File; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.npc.NPC; import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; import static org.bukkit.Bukkit.getServer; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.RegisteredServiceProvider; import uk.codingbadgers.bFundamentals.bFundamentals; import uk.codingbadgers.bFundamentals.gui.GuiCallback; import uk.codingbadgers.bFundamentals.gui.GuiInventory; import uk.codingbadgers.bFundamentals.gui.GuiInventorySubMenu; import uk.codingbadgers.bFundamentals.module.Module; import uk.codingbadgers.bnpcstore.commands.NpcStoreCommand; import uk.codingbadgers.bnpcstore.gui.callbacks.GuiBuySellCallback; import uk.codingbadgers.bnpcstore.npc.NpcStoreListener; import uk.codingbadgers.bnpcstore.npc.StoreNPC; import uk.thecodingbadgers.bDatabaseManager.DatabaseTable.DatabaseTable; public class bNpcStore extends Module { /** * Static plugin module instance */ static bNpcStore instance; /** * A map of inventories and their names */ private Map<String, GuiInventory> stores; /** * A map of npcs and their stores */ private Map<NPC, StoreNPC> npcStores; /** * The vault economy item */ private Economy economy; /** * The database manager * */ private DatabaseManager databasemanager; private Map<GuiInventory, List<String>> m_subMenuNames; private Map<GuiInventory, List<String>> m_itemNames; /** * Called when the module is disabled. */ @Override public void onDisable() { stores.clear(); bNpcStore.instance = null; } /** * Called when the module is loaded. */ @Override public void onEnable() { bNpcStore.instance = this; m_subMenuNames = new HashMap<GuiInventory, List<String>>(); m_itemNames = new HashMap<GuiInventory, List<String>>(); this.databasemanager = new DatabaseManager(this.m_plugin); // listeners register(new NpcStoreListener()); // commands registerCommand(new NpcStoreCommand()); // Load store guis loadStoreGuis(); // Load store npcs loadStoreNPCs(); } /** * Output a message to someone * * @param destination The thing to send the message to * @param message The message to send */ public void output(CommandSender destination, String message) { Module.sendMessage(this.getName(), destination, message); } /** * Access to the module instance * * @return */ public static bNpcStore getInstance() { return bNpcStore.instance; } /** * Access to the vault economy * * @return The vault economy */ public Economy getEconomy() { if (this.economy == null) { // Get the economy instance RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class); if (economyProvider != null) { this.economy = economyProvider.getProvider(); } if (this.economy == null) { bFundamentals.log(Level.SEVERE, "Failed to find an economy plugin to use!"); } } return this.economy; } /** * Load all store gui configs */ private void loadStoreGuis() { this.stores = new HashMap<String, GuiInventory>(); File storeFolder = new File(this.getDataFolder() + File.separator + "stores"); if (!storeFolder.exists()) { storeFolder.mkdirs(); createDefaultStore(storeFolder); } for (File folder : storeFolder.listFiles()) { if (!folder.isDirectory()) { continue; } FileConfiguration storeConfig = createConfigFile(folder + File.separator + "store.yml"); FileConfiguration subMenuConfig = createConfigFile(folder + File.separator + "submenus.yml"); FileConfiguration itemConfig = createConfigFile(folder + File.separator + "items.yml"); GuiInventory inventory = new GuiInventory(m_plugin); loadStoreConfig(storeConfig, inventory); loadSubMenuConfig(subMenuConfig, itemConfig, inventory); this.stores.put(inventory.getTitle(), inventory); bFundamentals.log(Level.INFO, "Loaded store - " + inventory.getTitle()); } } /** * */ private void loadStoreNPCs() { this.npcStores = new HashMap<NPC, StoreNPC>(); DatabaseTable storeNpcTable = this.databasemanager.getNpcStoreTable(); ResultSet result = this.databasemanager.getDatabase().queryResult("SELECT * FROM `bNpcStore-Npcs`"); try { while (result.next()) { int ID = result.getInt("npcID"); String storeName = result.getString("storeName"); Bukkit.getLogger().log(Level.INFO, "Loading: " + ID + ", " + storeName); for (NPC npc : CitizensAPI.getNPCRegistry()) { if (npc.getId() == ID) { Bukkit.getLogger().log(Level.INFO, "Found NPC for " + ID); StoreNPC storeNPC = new StoreNPC(npc, false); storeNPC.setStore(storeName); this.registerNewNPC(storeNPC, npc); break; } } } result.close(); } catch (SQLException e) { e.printStackTrace(); } } /** * * @return */ public DatabaseManager getDatabaseManager() { return this.databasemanager; } /** * Create a default store as an example */ private void createDefaultStore(File storeFolder) { storeFolder = new File(storeFolder + File.separator + "default"); FileConfiguration storeConfig = createConfigFile(storeFolder + File.separator + "store.yml"); FileConfiguration subMenuConfig = createConfigFile(storeFolder + File.separator + "submenus.yml"); FileConfiguration itemConfig = createConfigFile(storeFolder + File.separator + "items.yml"); // Setup the default store storeConfig.set("store.name", "Default Store"); storeConfig.set("store.rows", 1); storeConfig.set("store.submenus", new String[]{"Example1", "Example2", "Example3"}); storeConfig.set("store.items", new String[]{"TestItem"}); // Setup the submenus for (int exampleIndex = 1; exampleIndex <= 3; ++exampleIndex) { String nodePath = "submenu.Example" + exampleIndex; subMenuConfig.set(nodePath + ".name", "Example " + exampleIndex); subMenuConfig.set(nodePath + ".icon", Material.GOLDEN_APPLE.name()); subMenuConfig.set(nodePath + ".rows", exampleIndex + 1); subMenuConfig.set(nodePath + ".details", new String[]{"This is", "an example", "submenu"}); subMenuConfig.set(nodePath + ".submenus", new String[]{}); subMenuConfig.set(nodePath + ".items", new String[]{"Apple", "Potato", "Carrot"}); } // Setup the items String[] items = new String[]{"Apple", "Potato", "Carrot", "TestItem"}; Material[] icons = new Material[]{Material.APPLE, Material.POTATO_ITEM, Material.CARROT_ITEM, Material.DIAMOND}; for (int exampleIndex = 0; exampleIndex < 4; ++exampleIndex) { String nodePath = "item." + items[exampleIndex]; itemConfig.set(nodePath + ".name", items[exampleIndex]); itemConfig.set(nodePath + ".icon", icons[exampleIndex].name()); itemConfig.set(nodePath + ".row", 0); itemConfig.set(nodePath + ".column", exampleIndex); itemConfig.set(nodePath + ".cost", exampleIndex * 17); itemConfig.set(nodePath + ".details", new String[]{"This is", "an example", "item"}); } try { storeConfig.save(new File(storeFolder + File.separator + "store.yml")); subMenuConfig.save(new File(storeFolder + File.separator + "submenus.yml")); itemConfig.save(new File(storeFolder + File.separator + "items.yml")); } catch (Exception ex) { ex.printStackTrace(); } } /** * Create a configuration file at a given path * * @param path The path to the config file. * @return A FileConfiguration for a file at the given path */ private FileConfiguration createConfigFile(String path) { File file = new File(path); try { if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); } } catch (IOException ex) { return null; } return YamlConfiguration.loadConfiguration(file); } /** * * @param storeName * @return */ public GuiInventory getInventory(String storeName) { if (!this.stores.containsKey(storeName)) { Bukkit.getLogger().log(Level.WARNING, "Could not find a store with the name '" + storeName + "'"); return null; } return this.stores.get(storeName); } /** * * @return */ public List<String> getStoreNames() { List<String> names = new ArrayList<String>(); for (String name : this.stores.keySet()) { names.add(name); } return names; } /** * * @param npc * @return */ public StoreNPC findStoreNPC(NPC npc) { if (!this.npcStores.containsKey(npc)) { return null; } return this.npcStores.get(npc); } /** * * @param storeNPC * @param npc */ public void registerNewNPC(StoreNPC storeNPC, NPC npc) { if (this.npcStores.containsKey(npc)) { return; } this.npcStores.put(npc, storeNPC); } /** * * @param npc * @param storeName */ public void updateNpcStore(NPC npc, String storeName) { if (!this.npcStores.containsKey(npc)) { return; } StoreNPC storeNPC = this.npcStores.get(npc); this.npcStores.remove(npc); npc.setName(storeName); this.registerNewNPC(storeNPC, npc); } /** * * @param npc */ public void removeNPCStore(NPC npc) { if (!this.npcStores.containsKey(npc)) { return; } final String query = "DELETE FROM `bNpcStore-Npcs` WHERE `npcID`=" + npc.getId(); this.databasemanager.getDatabase().query(query, true); this.npcStores.remove(npc); } /** * Load the main store config * * @param storeConfig Config to load from */ private void loadStoreConfig(FileConfiguration storeConfig, GuiInventory inventory) { String title = storeConfig.getString("store.name"); int rowCount = storeConfig.getInt("store.rows"); List<String> submenus = storeConfig.getStringList("store.submenus"); m_subMenuNames.put(inventory, submenus); List<String> items = storeConfig.getStringList("store.items"); m_itemNames.put(inventory, items); inventory.createInventory(title, rowCount); } /** * Load the sub menu config * * @param subMenuConfig The sub menu config to load */ protected void loadSubMenuConfig(FileConfiguration subMenuConfig, FileConfiguration itemConfig, GuiInventory inventory) { if (this.m_subMenuNames.isEmpty()) { loadItemConfig(itemConfig, inventory); return; } List<String> subMenuNames = m_subMenuNames.get(inventory); if (!subMenuNames.isEmpty()) { int subMenuIndex = 0; String subMenu = subMenuNames.get(subMenuIndex); while (inventory.getSubMenu(subMenu) == null) { String nodePath = "submenu." + subMenu; String name = subMenuConfig.getString(nodePath + ".name"); Material icon = Material.valueOf(subMenuConfig.getString(nodePath + ".icon")); int rows = subMenuConfig.getInt(nodePath + ".rows"); List<String> details = subMenuConfig.getStringList(nodePath + ".details"); details = parseColorCodes(details); List<String> submenus = subMenuConfig.getStringList(nodePath + ".submenus"); List<String> items = subMenuConfig.getStringList(nodePath + ".items"); GuiInventorySubMenu subMenuInventory = new GuiInventorySubMenu(inventory, inventory.getTitle() + " - " + name, rows); addSubmenus(subMenuInventory, submenus); addItems(subMenuInventory, items); loadSubMenuConfig(subMenuConfig, itemConfig, subMenuInventory); inventory.addSubMenuItem(name, icon, details, subMenuInventory); subMenuIndex++; if (subMenuIndex >= subMenuNames.size()) { break; } subMenu = subMenuNames.get(subMenuIndex); } } loadItemConfig(itemConfig, inventory); } private void loadItemConfig(FileConfiguration itemConfig, GuiInventory inventory) { if (this.m_itemNames.isEmpty()) { return; } List<String> items = m_itemNames.get(inventory); if (!items.isEmpty()) { int itemIndex = 0; String item = items.get(itemIndex); while (inventory.getItem(item) == null) { String nodePath = "item." + item; try { String name = itemConfig.getString(nodePath + ".name"); int row = itemConfig.getInt(nodePath + ".row"); int column = itemConfig.getInt(nodePath + ".column"); List<String> details = itemConfig.getStringList(nodePath + ".details"); details = parseColorCodes(details); String rawIcon = itemConfig.getString(nodePath + ".icon"); String iconName = rawIcon; Byte dataValue = -1; if (rawIcon.contains(":")) { String[] iconParts = rawIcon.split(":"); iconName = iconParts[0]; dataValue = Byte.parseByte(iconParts[1]); } ItemStack itemStack = null; if (dataValue != -1) { itemStack = new ItemStack(Material.valueOf(iconName), 1, dataValue); } else { itemStack = new ItemStack(Material.valueOf(iconName)); } GuiCallback onClickCallback = null; if (itemConfig.contains(nodePath + ".onclick")) { // BuySellCallback if (itemConfig.contains(nodePath + ".onclick.buysell")) { double buyPrice = itemConfig.getDouble(nodePath + ".onclick.buysell.buyprice", 100.0); double sellPrice = itemConfig.getDouble(nodePath + ".onclick.buysell.sellprice", 100.0); details.add(" "); details.add("Buy for £" + buyPrice + " each."); details.add("Sell for £" + sellPrice + " each."); onClickCallback = new GuiBuySellCallback(inventory, name, itemStack, buyPrice, sellPrice); } } String[] detailsArray = new String[details.size()]; details.toArray(detailsArray); inventory.addMenuItem(name, itemStack, detailsArray, (row * 9) + column, onClickCallback); } catch (Exception ex) { Bukkit.getLogger().log(Level.WARNING, "Failed to load item - " + item, ex); } itemIndex++; if (itemIndex >= items.size()) { break; } item = items.get(itemIndex); } } } /** * * @param details * @return */ private List<String> parseColorCodes(List<String> details) { List<String> parsedDetails = new ArrayList<String>(); for (String line : details) { parsedDetails.add(ChatColor.translateAlternateColorCodes('&', line)); } return parsedDetails; } /** * * @param subMenus */ private void addSubmenus(GuiInventory subMenuInventory, List<String> subMenus) { m_subMenuNames.put(subMenuInventory, subMenus); } /** * * @param items */ private void addItems(GuiInventory subMenuInventory, List<String> items) { m_itemNames.put(subMenuInventory, items); } }