diff --git a/pom.xml b/pom.xml index 910dc7c..35284df 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ de.iani.cubeside PlayerUUIDCache - 1.4.0 + 1.5.1-SNAPSHOT provided diff --git a/src/main/java/de/iani/treasurechest/ChestInventoryListener.java b/src/main/java/de/iani/treasurechest/ChestInventoryListener.java index 4f3aa1b..958daef 100644 --- a/src/main/java/de/iani/treasurechest/ChestInventoryListener.java +++ b/src/main/java/de/iani/treasurechest/ChestInventoryListener.java @@ -1,8 +1,10 @@ package de.iani.treasurechest; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -24,6 +26,8 @@ import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; +import de.iani.treasurechest.database.DatabaseTreasureChestItem; + public class ChestInventoryListener implements Listener { private TreasureChest plugin; @@ -58,7 +62,7 @@ OpenInventoryData openInventory = new OpenInventoryData(b.getLocation(), inventory); int pos = 0; - for (TreasureChestItem item : content.getItems()) { + for (DatabaseTreasureChestItem item : content.getItems()) { if (pos < 9 * 6) { ItemStack di = item.getDisplayItem().clone(); ItemMeta meta = di.getItemMeta(); @@ -90,7 +94,7 @@ meta.setLore(lore); di.setItemMeta(meta); inventory.setItem(pos, di); - openInventory.setItemAtPosition(pos, pos); + openInventory.setItemAtPosition(pos, item.getId()); } pos += 1; } @@ -124,7 +128,10 @@ clonedPlayerInventory.setContents(playerInv); PlayerTreasureChestContent content = plugin.getData().getChestContent(player.getUniqueId()); - int entryId = openInventory.getEntryAtPosition(event.getRawSlot()); + Integer entryId = openInventory.getEntryAtPosition(event.getRawSlot()); + if (entryId == null) { + return; + } TreasureChestItem selectedItem = content.getItem(entryId); if (selectedItem != null) { ItemStack[] priceList = selectedItem.getPriceItems(); @@ -136,10 +143,18 @@ } if (!clonedPlayerInventory.addItem(temp).isEmpty()) { plugin.sendMessage(player, "Du hast nicht genügend Platz in deinem Inventar!", true); - player.updateInventory(); return; } } + try { + if (!plugin.getDatabase().deleteItem(player.getUniqueId(), entryId)) { + return; + } + } catch (SQLException e) { + plugin.sendMessage(player, ChatColor.DARK_RED + "Datenbankfehler"); + plugin.getLogger().log(Level.SEVERE, "Could not delete item " + entryId + " for " + player.getUniqueId() + ": " + e.getMessage(), e); + return; + } plugin.sendMessage(player, ChatColor.GRAY + "Du hast folgende Items erhalten:"); if (priceCount > 0) { ItemStack[] temp = new ItemStack[priceCount]; @@ -174,7 +189,7 @@ player.playSound(event.getWhoClicked().getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1f, 1f); content.removeItem(entryId); openInventory.getInventory().setItem(event.getRawSlot(), null); - openInventory.removeEntryAtPositionAndShift(event.getRawSlot()); + openInventory.removeEntryAtPosition(event.getRawSlot()); player.updateInventory(); } } diff --git a/src/main/java/de/iani/treasurechest/ListedItemsData.java b/src/main/java/de/iani/treasurechest/ListedItemsData.java new file mode 100644 index 0000000..ef60208 --- /dev/null +++ b/src/main/java/de/iani/treasurechest/ListedItemsData.java @@ -0,0 +1,26 @@ +package de.iani.treasurechest; + +import java.util.HashMap; +import java.util.UUID; + +public class ListedItemsData { + private UUID owner; + private HashMap items; + + public ListedItemsData(UUID owner) { + this.owner = owner; + this.items = new HashMap<>(); + } + + public void addItem(int listPos, int databaseKey) { + items.put(listPos, databaseKey); + } + + public Integer getItemDatabaseKey(int listPos) { + return items.get(listPos); + } + + public UUID getOwner() { + return owner; + } +} diff --git a/src/main/java/de/iani/treasurechest/OpenInventoryData.java b/src/main/java/de/iani/treasurechest/OpenInventoryData.java index 2574f61..03fb34b 100644 --- a/src/main/java/de/iani/treasurechest/OpenInventoryData.java +++ b/src/main/java/de/iani/treasurechest/OpenInventoryData.java @@ -1,59 +1,50 @@ -package de.iani.treasurechest; - -import org.bukkit.Location; -import org.bukkit.inventory.Inventory; - -public class OpenInventoryData { - private Location location; - - private Inventory inventory; - - private int[] itemAtLocation; - - public OpenInventoryData(Location location, Inventory inventory) { - this.location = location; - this.inventory = inventory; - } - - public Inventory getInventory() { - return inventory; - } - - public Location getLocation() { - return location; - } - - public void setItemAtPosition(int inventoryPosition, int itemListPosition) { - if (itemAtLocation == null) { - itemAtLocation = new int[inventoryPosition + 1]; - } else if (itemAtLocation.length <= inventoryPosition) { - int[] temp = itemAtLocation; - itemAtLocation = new int[inventoryPosition + 1]; - System.arraycopy(temp, 0, itemAtLocation, 0, temp.length); - } - itemAtLocation[inventoryPosition] = itemListPosition + 1; - } - - public int getEntryAtPosition(int inventoryPosition) { - if (itemAtLocation == null || itemAtLocation.length <= inventoryPosition || inventoryPosition < 0) { - return -1; - } - return itemAtLocation[inventoryPosition] - 1; - } - - public void removeEntryAtPositionAndShift(int inventoryPosition) { - if (itemAtLocation == null || itemAtLocation.length <= inventoryPosition || inventoryPosition < 0) { - return; - } - int old = itemAtLocation[inventoryPosition]; - if (old >= 0) { - itemAtLocation[inventoryPosition] = -1; - for (int i = 0; i < itemAtLocation.length; i++) { - int oldHere = itemAtLocation[i]; - if (oldHere > old) { - itemAtLocation[i] = oldHere - 1; - } - } - } - } -} +package de.iani.treasurechest; + +import java.util.Arrays; + +import org.bukkit.Location; +import org.bukkit.inventory.Inventory; + +public class OpenInventoryData { + private Location location; + + private Inventory inventory; + + private Integer[] itemAtLocation; + + public OpenInventoryData(Location location, Inventory inventory) { + this.location = location; + this.inventory = inventory; + } + + public Inventory getInventory() { + return inventory; + } + + public Location getLocation() { + return location; + } + + public void setItemAtPosition(int inventoryPosition, int itemListPosition) { + if (itemAtLocation == null) { + itemAtLocation = new Integer[inventoryPosition + 1]; + } else if (itemAtLocation.length <= inventoryPosition) { + itemAtLocation = Arrays.copyOf(itemAtLocation, inventoryPosition + 1); + } + itemAtLocation[inventoryPosition] = itemListPosition; + } + + public Integer getEntryAtPosition(int inventoryPosition) { + if (itemAtLocation == null || itemAtLocation.length <= inventoryPosition || inventoryPosition < 0) { + return null; + } + return itemAtLocation[inventoryPosition]; + } + + public void removeEntryAtPosition(int inventoryPosition) { + if (itemAtLocation == null || itemAtLocation.length <= inventoryPosition || inventoryPosition < 0) { + return; + } + itemAtLocation[inventoryPosition] = null; + } +} diff --git a/src/main/java/de/iani/treasurechest/PlayerEventListener.java b/src/main/java/de/iani/treasurechest/PlayerEventListener.java index c4a6be1..36beaec 100644 --- a/src/main/java/de/iani/treasurechest/PlayerEventListener.java +++ b/src/main/java/de/iani/treasurechest/PlayerEventListener.java @@ -1,19 +1,27 @@ -package de.iani.treasurechest; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerQuitEvent; - -public class PlayerEventListener implements Listener { - private TreasureChest plugin; - - public PlayerEventListener(TreasureChest plugin) { - this.plugin = plugin; - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent event) { - plugin.getData().removeActiveItem(event.getPlayer().getUniqueId()); - } - -} +package de.iani.treasurechest; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class PlayerEventListener implements Listener { + private TreasureChest plugin; + + public PlayerEventListener(TreasureChest plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + plugin.getData().loadTreasureChest(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + plugin.getData().removeActiveItem(event.getPlayer().getUniqueId()); + plugin.getData().unloadTreasureChest(event.getPlayer().getUniqueId()); + plugin.getData().removeListedItems(event.getPlayer().getUniqueId()); + } + +} diff --git a/src/main/java/de/iani/treasurechest/PlayerTreasureChestContent.java b/src/main/java/de/iani/treasurechest/PlayerTreasureChestContent.java index 15d892a..769ed37 100644 --- a/src/main/java/de/iani/treasurechest/PlayerTreasureChestContent.java +++ b/src/main/java/de/iani/treasurechest/PlayerTreasureChestContent.java @@ -1,114 +1,170 @@ package de.iani.treasurechest; -import java.io.File; -import java.io.IOException; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.UUID; import java.util.logging.Level; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.scheduler.BukkitRunnable; + +import de.iani.treasurechest.database.DatabaseTreasureChestItem; +import de.iani.treasurechest.database.TreasureChestDatabase; +import de.iani.treasurechest.worker.WorkEntry; public class PlayerTreasureChestContent { - private TreasureChest plugin; + private final TreasureChest plugin; + private final UUID owner; - private File file; + private LoadState loadState = LoadState.NOT_LOADED; - private ArrayList items; + private ArrayList items; + private HashMap itemsById; + private ArrayList loadCallbacks; - private long online; - - public PlayerTreasureChestContent(TreasureChest plugin, File file) { + public PlayerTreasureChestContent(UUID owner, TreasureChest plugin) { this.plugin = plugin; - this.file = file; - try { - if (file.exists()) { - YamlConfiguration conf = YamlConfiguration.loadConfiguration(file); + this.owner = owner; + } - ConfigurationSection prices = conf.getConfigurationSection("prices"); - if (prices != null) { - for (String e : prices.getKeys(false)) { - ConfigurationSection price = prices.getConfigurationSection(e); - if (price != null) { - ItemStack display = price.getItemStack("displayItem"); - if (display == null) { - display = new ItemStack(Material.BEDROCK); - ItemMeta meta = display.getItemMeta(); - meta.setDisplayName("Unset displayitem"); - display.setItemMeta(meta); + public void loadAsync(Runnable loadCallback) { + if (loadCallback != null) { + if (loadState == LoadState.LOADED) { + loadCallback.run(); + return; + } + if (loadCallbacks == null) { + loadCallbacks = new ArrayList<>(); + } + loadCallbacks.add(loadCallback); + } + loadAsync(); + } + + public void loadAsync() { + if (loadState != LoadState.NOT_LOADED) { + return; + } + loadState = LoadState.LOADING; + plugin.getWorkerThread().addWork(new WorkEntry() { + @Override + public void process(TreasureChestDatabase database) { + try { + ArrayList loadedItems = plugin.getDatabase().getPlayerItems(owner); + new BukkitRunnable() { + @Override + public void run() { + items = loadedItems; + itemsById = new HashMap<>(); + for (DatabaseTreasureChestItem i : items) { + itemsById.put(i.getId(), i); } - int priceMoney = price.getInt("priceMoney"); - ArrayList priceItems = new ArrayList<>(); - ConfigurationSection itemPricesSection = price.getConfigurationSection("itemPrices"); - if (itemPricesSection != null) { - for (String pricee : itemPricesSection.getKeys(false)) { - ItemStack priceItem = itemPricesSection.getItemStack(pricee); - if (priceItem != null) { - priceItems.add(priceItem); - } + loadState = LoadState.LOADED; + + if (loadCallbacks != null) { + for (Runnable r : loadCallbacks) { + r.run(); } + loadCallbacks = null; } - if (items == null) { - items = new ArrayList<>(); - } - items.add(new TreasureChestItem(display, priceItems.toArray(new ItemStack[priceItems.size()]), priceMoney)); } - } + }.runTask(plugin); + } catch (SQLException e) { + plugin.getLogger().log(Level.SEVERE, "Could not load treasure chest data for " + owner + ": " + e, e); } } - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Could not load user chest file: " + file.getName(), e); - } + }); } - private void save() { - file.getParentFile().mkdirs(); - YamlConfiguration conf = new YamlConfiguration(); - ConfigurationSection prices = conf.createSection("prices"); - if (items != null) { - int nr = 0; - for (TreasureChestItem i : items) { - ConfigurationSection price = prices.createSection(Integer.toString(nr++)); - price.set("displayItem", i.getDisplayItem().clone()); - price.set("priceMoney", i.getPriceMoney()); - ConfigurationSection itemsSec = price.createSection("itemPrices"); - if (i.getPriceItems() != null) { - int nr2 = 0; - for (ItemStack st : i.getPriceItems()) { - itemsSec.set(Integer.toString(nr2++), st.clone()); - } - } - } - } - try { - conf.save(file); - } catch (IOException e) { - plugin.getLogger().log(Level.SEVERE, "Could not save user chest file: " + file.getName(), e); - } - } + // public PlayerTreasureChestContent(UUID owner, TreasureChest plugin, File file) { + // this.plugin = plugin; + // this.file = file; + // try { + // if (file.exists()) { + // YamlConfiguration conf = YamlConfiguration.loadConfiguration(file); + // + // ConfigurationSection prices = conf.getConfigurationSection("prices"); + // if (prices != null) { + // for (String e : prices.getKeys(false)) { + // ConfigurationSection price = prices.getConfigurationSection(e); + // if (price != null) { + // ItemStack display = price.getItemStack("displayItem"); + // if (display == null) { + // display = new ItemStack(Material.BEDROCK); + // ItemMeta meta = display.getItemMeta(); + // meta.setDisplayName("Unset displayitem"); + // display.setItemMeta(meta); + // } + // int priceMoney = price.getInt("priceMoney"); + // ArrayList priceItems = new ArrayList<>(); + // ConfigurationSection itemPricesSection = price.getConfigurationSection("itemPrices"); + // if (itemPricesSection != null) { + // for (String pricee : itemPricesSection.getKeys(false)) { + // ItemStack priceItem = itemPricesSection.getItemStack(pricee); + // if (priceItem != null) { + // priceItems.add(priceItem); + // } + // } + // } + // if (items == null) { + // items = new ArrayList<>(); + // } + // items.add(new TreasureChestItem(display, priceItems.toArray(new ItemStack[priceItems.size()]), priceMoney)); + // } + // } + // } + // } + // } catch (Exception e) { + // plugin.getLogger().log(Level.SEVERE, "Could not load user chest file: " + file.getName(), e); + // } + // } - public void addItem(TreasureChestItem item) { + // private void save() { + // file.getParentFile().mkdirs(); + // YamlConfiguration conf = new YamlConfiguration(); + // ConfigurationSection prices = conf.createSection("prices"); + // if (items != null) { + // int nr = 0; + // for (TreasureChestItem i : items) { + // ConfigurationSection price = prices.createSection(Integer.toString(nr++)); + // price.set("displayItem", i.getDisplayItem().clone()); + // price.set("priceMoney", i.getPriceMoney()); + // ConfigurationSection itemsSec = price.createSection("itemPrices"); + // if (i.getPriceItems() != null) { + // int nr2 = 0; + // for (ItemStack st : i.getPriceItems()) { + // itemsSec.set(Integer.toString(nr2++), st.clone()); + // } + // } + // } + // } + // try { + // conf.save(file); + // } catch (IOException e) { + // plugin.getLogger().log(Level.SEVERE, "Could not save user chest file: " + file.getName(), e); + // } + // } + + void addItem(DatabaseTreasureChestItem item) { item = item.clone(); if (items == null) { items = new ArrayList<>(); + itemsById = new HashMap<>(); } - items.add(item); - save(); + items.add(0, item); + itemsById.put(item.getId(), item); } - public boolean removeItem(int pos) { - if (items == null || items.size() <= pos || pos < 0) { + public boolean removeItem(int id) { + if (itemsById == null) { return false; } - items.remove(pos); - if (items.size() == 0) { - items = null; + DatabaseTreasureChestItem removed = itemsById.remove(id); + if (removed != null) { + items.remove(removed); } - save(); return true; } @@ -116,22 +172,23 @@ return items == null || items.isEmpty(); } - public List getItems() { + public List getItems() { return items == null ? Collections.emptyList() : Collections.unmodifiableList(items); } - public TreasureChestItem getItem(int pos) { - if (items == null || items.size() <= pos || pos < 0) { - return null; - } - return items.get(pos); + public DatabaseTreasureChestItem getItem(int id) { + return itemsById.get(id); } - public void setOnline(long t) { - online = t; + public LoadState getLoadState() { + return loadState; } - public boolean isOnline(long t) { - return online == t; + public UUID getOwner() { + return owner; + } + + public enum LoadState { + NOT_LOADED, LOADING, LOADED } } diff --git a/src/main/java/de/iani/treasurechest/TreasureChest.java b/src/main/java/de/iani/treasurechest/TreasureChest.java index ddcaeff..4b69993 100644 --- a/src/main/java/de/iani/treasurechest/TreasureChest.java +++ b/src/main/java/de/iani/treasurechest/TreasureChest.java @@ -1,5 +1,6 @@ package de.iani.treasurechest; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Random; import java.util.UUID; @@ -18,10 +19,16 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; import de.iani.playerUUIDCache.CachedPlayer; import de.iani.playerUUIDCache.PlayerUUIDCache; -import de.iani.playerUUIDCache.SQLConfig; +import de.iani.treasurechest.PlayerTreasureChestContent.LoadState; +import de.iani.treasurechest.database.DatabaseTreasureChestItem; +import de.iani.treasurechest.database.SQLConfig; +import de.iani.treasurechest.database.TreasureChestDatabase; +import de.iani.treasurechest.worker.WorkEntry; +import de.iani.treasurechest.worker.WorkerThread; import net.milkbowl.vault.economy.Economy; public class TreasureChest extends JavaPlugin implements TreasureChestAPI { @@ -31,8 +38,6 @@ private Random random; - // private PlayerUUIDTools uuidTools; - private boolean hasEconomy; private Economy economy; @@ -41,17 +46,28 @@ private SQLConfig sqlConfig; + private TreasureChestDatabase database; + private WorkerThread workerThread; + @Override public void onEnable() { saveDefaultConfig(); random = new Random(); setupEconomy(); - // uuidTools = new PlayerUUIDTools(this); playerUUIDCache = (PlayerUUIDCache) getServer().getPluginManager().getPlugin("PlayerUUIDCache"); readConfig(); - // chestLocation = new Location(getServer().getWorlds().get(0), 308, 127, -879); + try { + database = new TreasureChestDatabase(sqlConfig); + } catch (SQLException e) { + getLogger().log(Level.SEVERE, "Could not connect to database: " + e.getMessage(), e); + setEnabled(false); + return; + } + + workerThread = new WorkerThread(this); data = new TreasureChestData(this); + getCommand("treasurechest").setExecutor(new TreasureChestCommandExecutor(this)); getServer().getPluginManager().registerEvents(new ChestInventoryListener(this), this); @@ -66,7 +82,7 @@ getServer().getScheduler().runTaskTimer(this, new Runnable() { @Override public void run() { - doGC(); + data.doGC(); } }, 8456, 140000); } @@ -107,15 +123,31 @@ } items = copied.toArray(new ItemStack[copied.size()]); - PlayerTreasureChestContent content = getData().getChestContent(player); - content.addItem(new TreasureChestItem(displayItem, items, money)); + TreasureChestItem item = new TreasureChestItem(displayItem, items, money); + workerThread.addWork(new WorkEntry() { + @Override + public void process(TreasureChestDatabase database) { + try { + DatabaseTreasureChestItem added = database.addItem(player, item); + if (added != null) { + new BukkitRunnable() { + @Override + public void run() { + PlayerTreasureChestContent cc = getData().getChestContent(player); + if (cc != null && cc.getLoadState() == LoadState.LOADED) { + cc.addItem(added); + } + } + }; + } + } catch (SQLException e) { + getLogger().log(Level.SEVERE, "Could not add treasure chest item to database: " + e.getMessage(), e); + } + } + }); return true; } - protected void doGC() { - data.doGC(); - } - private void readConfig() { // saveDefaultConfig(); FileConfiguration config = getConfig(); @@ -153,11 +185,6 @@ super.saveConfig(); } - // public PlayerUUIDTools getUUIDTools() - // { - // return uuidTools; - // } - public TreasureChestData getData() { return data; } @@ -177,8 +204,12 @@ double dz = playerLocation.getZ() - chestLocation.getZ(); double dsquared = dx * dx + dy * dy + dz * dz; if (dsquared < 16 * 16) { - if (!data.getChestContent(player.getUniqueId()).isEmpty()) { - player.playEffect(chestLocation, Effect.MOBSPAWNER_FLAMES, null); + PlayerTreasureChestContent playerData = data.getChestContent(player.getUniqueId()); + if (playerData != null) { + playerData.loadAsync(); + if (!playerData.isEmpty()) { + player.playEffect(chestLocation, Effect.MOBSPAWNER_FLAMES, null); + } } } } @@ -265,4 +296,11 @@ return new String(cap); } + public TreasureChestDatabase getDatabase() { + return database; + } + + public WorkerThread getWorkerThread() { + return workerThread; + } } diff --git a/src/main/java/de/iani/treasurechest/TreasureChestCommandExecutor.java b/src/main/java/de/iani/treasurechest/TreasureChestCommandExecutor.java index 08c10d4..368e210 100644 --- a/src/main/java/de/iani/treasurechest/TreasureChestCommandExecutor.java +++ b/src/main/java/de/iani/treasurechest/TreasureChestCommandExecutor.java @@ -1,265 +1,294 @@ -package de.iani.treasurechest; - -import java.util.List; -import java.util.Set; -import java.util.UUID; - -import org.bukkit.ChatColor; -import org.bukkit.Effect; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import de.iani.playerUUIDCache.CachedPlayer; - -public class TreasureChestCommandExecutor implements CommandExecutor { - private TreasureChest plugin; - - public TreasureChestCommandExecutor(TreasureChest plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (args.length == 0) { - displayHelp(sender, label); - } else { - String subcommand = args[0].toLowerCase(); - if (subcommand.equals("setchest")) { - if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.setchest")) { - return true; - } - Player player = ((Player) sender); - Block target = player.getTargetBlock((Set) null, 5); - plugin.setChestLocation(target == null ? null : target.getLocation()); - if (target != null) { - player.playEffect(target.getLocation(), Effect.MOBSPAWNER_FLAMES, null); - player.playEffect(target.getLocation(), Effect.MOBSPAWNER_FLAMES, null); - player.playEffect(target.getLocation(), Effect.MOBSPAWNER_FLAMES, null); - plugin.sendMessage(sender, "Treasurechest location set!"); - } else { - plugin.sendMessage(sender, "Treasurechest location removed!"); - } - } else if (subcommand.equals("create")) { - if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.create")) { - return true; - } - Player player = ((Player) sender); - ItemStack inHand = player.getInventory().getItemInMainHand(); - if (inHand == null || inHand.getType() == Material.AIR || inHand.getAmount() == 0) { - plugin.sendMessage(sender, "You have to hold the display item in hand!", true); - return true; - } - TreasureChestItem newItem = new TreasureChestItem(inHand.clone(), null, 0); - plugin.getData().setActiveItem(player.getUniqueId(), newItem); - plugin.sendMessage(sender, "Created a new Treasurechest item!"); - } else if (subcommand.equals("addmoney")) { - if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.create")) { - return true; - } - if (args.length < 2) { - plugin.sendMessage(sender, "/" + label + " addmoney ", true); - return true; - } - int amount = getIntArgument(args[1], 0); - Player player = ((Player) sender); - TreasureChestItem activeItem = plugin.getData().getActiveItem(player.getUniqueId()); - if (activeItem == null) { - plugin.sendMessage(sender, "You have no active item!", true); - return true; - } - activeItem.setPriceMoney(activeItem.getPriceMoney() + amount); - plugin.sendMessage(sender, "Set the money to " + activeItem.getPriceMoney()); - } else if (subcommand.equals("additem")) { - if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.create")) { - return true; - } - Player player = ((Player) sender); - ItemStack inHand = player.getInventory().getItemInMainHand(); - if (inHand == null || inHand.getType() == Material.AIR || inHand.getAmount() == 0) { - plugin.sendMessage(sender, "You have to hold the item in hand!", true); - return true; - } - TreasureChestItem activeItem = plugin.getData().getActiveItem(player.getUniqueId()); - if (activeItem == null) { - plugin.sendMessage(sender, "You have no active item!", true); - return true; - } - activeItem.addPriceItem(inHand.clone()); - plugin.sendMessage(sender, "Item added: " + inHand.getAmount() + " " + TreasureChest.capitalize(inHand.getType().name(), true)); - } else if (subcommand.equals("give")) { - if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.give")) { - return true; - } - if (args.length < 2) { - plugin.sendMessage(sender, "/" + label + " give ", true); - return true; - } - Player player = ((Player) sender); - TreasureChestItem activeItem = plugin.getData().getActiveItem(player.getUniqueId()); - if (activeItem == null) { - plugin.sendMessage(sender, "You have no active item!", true); - return true; - } - - for (int arg = 1; arg < args.length; arg++) { - String nameOrId = args[arg].replace(",", "").trim(); - UUID targetuuid = null; - try { - targetuuid = UUID.fromString(nameOrId); - } catch (Exception e) { - CachedPlayer target = plugin.getPlayerUUIDCache().getPlayerFromNameOrUUID(nameOrId, true); - if (target != null) { - targetuuid = target.getUUID(); - nameOrId = target.getName(); - } - } - if (targetuuid == null) { - plugin.sendMessage(sender, "Unknown player!", true); - } else { - PlayerTreasureChestContent content = plugin.getData().getChestContent(targetuuid); - content.addItem(activeItem); - plugin.sendMessage(sender, "Item given to: " + nameOrId + " (" + targetuuid.toString() + ")"); - } - } - return true; - } else if (subcommand.equals("list")) { - if (!checkPermission(sender, "treasurechest.list")) { - return true; - } - if (args.length < 2) { - plugin.sendMessage(sender, "/" + label + " list ", true); - return true; - } - String nameOrId = args[1]; - UUID targetuuid = null; - try { - targetuuid = UUID.fromString(nameOrId); - } catch (Exception e) { - CachedPlayer target = plugin.getPlayerUUIDCache().getPlayerFromNameOrUUID(nameOrId, true); - if (target != null) { - targetuuid = target.getUUID(); - nameOrId = target.getName(); - } - } - if (targetuuid == null) { - plugin.sendMessage(sender, "Unknown player!", true); - return true; - } - - PlayerTreasureChestContent content = plugin.getData().getChestContent(targetuuid); - plugin.sendMessage(sender, ChatColor.GRAY + "Preise von " + nameOrId + " (" + targetuuid.toString() + "):"); - List items = content.getItems(); - if (items.isEmpty()) { - plugin.sendMessage(sender, "keine Preise vorhanden"); - } else { - int nr = 1; - for (TreasureChestItem i : items) { - plugin.sendMessage(sender, nr + ": " + i.getDisplayItem().getItemMeta().getDisplayName()); - nr++; - } - } - } else if (subcommand.equals("remove")) { - if (!checkPermission(sender, "treasurechest.remove")) { - return true; - } - if (args.length < 3) { - plugin.sendMessage(sender, "/" + label + " remove ", true); - return true; - } - - String nameOrId = args[1]; - UUID targetuuid = null; - try { - targetuuid = UUID.fromString(nameOrId); - } catch (Exception e) { - CachedPlayer target = plugin.getPlayerUUIDCache().getPlayerFromNameOrUUID(nameOrId, true); - if (target != null) { - targetuuid = target.getUUID(); - nameOrId = target.getName(); - } - } - if (targetuuid == null) { - plugin.sendMessage(sender, "Unknown player!", true); - return true; - } - int nr = getIntArgument(args[2], -1); - PlayerTreasureChestContent content = plugin.getData().getChestContent(targetuuid); - if (!content.removeItem(nr - 1)) { - plugin.sendMessage(sender, "Ungültige ID", true); - return true; - } - plugin.sendMessage(sender, "Der Preis wurde entfernt!"); - } else { - plugin.sendMessage(sender, "Unknown subcommand!", true); - return true; - } - } - return true; - } - - private void displayHelp(CommandSender sender, String label) { - plugin.sendMessage(sender, ChatColor.GREEN + "Commands"); - if (checkPlayer(sender, true) && checkPermission(sender, "treasurechest.setchest", true)) { - plugin.sendMessage(sender, "/" + label + " setchest"); - plugin.sendMessage(sender, ChatColor.GREEN + " Set the treasure chest location to the location you are looking at."); - } - if (checkPlayer(sender, true) && checkPermission(sender, "treasurechest.create", true)) { - plugin.sendMessage(sender, "/" + label + " create"); - plugin.sendMessage(sender, ChatColor.GREEN + " Creates a price with the item in hand as display item."); - plugin.sendMessage(sender, "/" + label + " additem"); - plugin.sendMessage(sender, ChatColor.GREEN + " Adds the item in hand to the price."); - plugin.sendMessage(sender, "/" + label + " addmoney "); - plugin.sendMessage(sender, ChatColor.GREEN + " Adds money to a price."); - } - if (checkPlayer(sender, true) && checkPermission(sender, "treasurechest.give", true)) { - plugin.sendMessage(sender, "/" + label + " give "); - plugin.sendMessage(sender, ChatColor.GREEN + " Gives a price to a player."); - } - if (checkPermission(sender, "treasurechest.list")) { - plugin.sendMessage(sender, "/" + label + " list "); - plugin.sendMessage(sender, ChatColor.GREEN + " Gives price for a player."); - } - if (checkPermission(sender, "treasurechest.remove")) { - plugin.sendMessage(sender, "/" + label + " remove "); - plugin.sendMessage(sender, ChatColor.GREEN + " Removes a price from a players chest."); - } - } - - private int getIntArgument(String value, int defaultValue) { - try { - return Integer.parseInt(value); - } catch (Exception e) { - // ignore - return default - } - return defaultValue; - } - - private boolean checkPermission(CommandSender sender, String perm) { - return checkPermission(sender, perm, false); - } - - private boolean checkPermission(CommandSender sender, String perm, boolean silent) { - boolean hasPermission = sender.hasPermission(perm); - if (!silent && !hasPermission) { - plugin.sendMessage(sender, "No permission!", true); - } - return hasPermission; - } - - private boolean checkPlayer(CommandSender sender) { - return checkPlayer(sender, false); - } - - private boolean checkPlayer(CommandSender sender, boolean silent) { - boolean isPlayer = sender instanceof Player; - if (!isPlayer && !silent) { - plugin.sendMessage(sender, "You must be a player!", true); - } - return isPlayer; - } -} +package de.iani.treasurechest; + +import java.sql.SQLException; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.logging.Level; + +import org.bukkit.ChatColor; +import org.bukkit.Effect; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import de.iani.playerUUIDCache.CachedPlayer; +import de.iani.treasurechest.PlayerTreasureChestContent.LoadState; +import de.iani.treasurechest.database.DatabaseTreasureChestItem; + +public class TreasureChestCommandExecutor implements CommandExecutor { + private TreasureChest plugin; + + public TreasureChestCommandExecutor(TreasureChest plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 0) { + displayHelp(sender, label); + } else { + String subcommand = args[0].toLowerCase(); + if (subcommand.equals("setchest")) { + if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.setchest")) { + return true; + } + Player player = ((Player) sender); + Block target = player.getTargetBlock((Set) null, 5); + plugin.setChestLocation(target == null ? null : target.getLocation()); + if (target != null) { + player.playEffect(target.getLocation(), Effect.MOBSPAWNER_FLAMES, null); + player.playEffect(target.getLocation(), Effect.MOBSPAWNER_FLAMES, null); + player.playEffect(target.getLocation(), Effect.MOBSPAWNER_FLAMES, null); + plugin.sendMessage(sender, "Treasurechest location set!"); + } else { + plugin.sendMessage(sender, "Treasurechest location removed!"); + } + } else if (subcommand.equals("create")) { + if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.create")) { + return true; + } + Player player = ((Player) sender); + ItemStack inHand = player.getInventory().getItemInMainHand(); + if (inHand == null || inHand.getType() == Material.AIR || inHand.getAmount() == 0) { + plugin.sendMessage(sender, "You have to hold the display item in hand!", true); + return true; + } + TreasureChestItem newItem = new TreasureChestItem(inHand.clone(), null, 0); + plugin.getData().setActiveItem(player.getUniqueId(), newItem); + plugin.sendMessage(sender, "Created a new Treasurechest item!"); + } else if (subcommand.equals("addmoney")) { + if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.create")) { + return true; + } + if (args.length < 2) { + plugin.sendMessage(sender, "/" + label + " addmoney ", true); + return true; + } + int amount = getIntArgument(args[1], 0); + Player player = ((Player) sender); + TreasureChestItem activeItem = plugin.getData().getActiveItem(player.getUniqueId()); + if (activeItem == null) { + plugin.sendMessage(sender, "You have no active item!", true); + return true; + } + activeItem.setPriceMoney(activeItem.getPriceMoney() + amount); + plugin.sendMessage(sender, "Set the money to " + activeItem.getPriceMoney()); + } else if (subcommand.equals("additem")) { + if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.create")) { + return true; + } + Player player = ((Player) sender); + ItemStack inHand = player.getInventory().getItemInMainHand(); + if (inHand == null || inHand.getType() == Material.AIR || inHand.getAmount() == 0) { + plugin.sendMessage(sender, "You have to hold the item in hand!", true); + return true; + } + TreasureChestItem activeItem = plugin.getData().getActiveItem(player.getUniqueId()); + if (activeItem == null) { + plugin.sendMessage(sender, "You have no active item!", true); + return true; + } + activeItem.addPriceItem(inHand.clone()); + plugin.sendMessage(sender, "Item added: " + inHand.getAmount() + " " + TreasureChest.capitalize(inHand.getType().name(), true)); + } else if (subcommand.equals("give")) { + if (!checkPlayer(sender) || !checkPermission(sender, "treasurechest.give")) { + return true; + } + if (args.length < 2) { + plugin.sendMessage(sender, "/" + label + " give ", true); + return true; + } + Player player = ((Player) sender); + TreasureChestItem activeItem = plugin.getData().getActiveItem(player.getUniqueId()); + if (activeItem == null) { + plugin.sendMessage(sender, "You have no active item!", true); + return true; + } + + for (int arg = 1; arg < args.length; arg++) { + String nameOrId = args[arg].replace(",", "").trim(); + CachedPlayer target = plugin.getPlayerUUIDCache().getPlayerFromNameOrUUID(nameOrId); + if (target == null) { + plugin.sendMessage(sender, "Unknown player!", true); + } else { + plugin.addItem(target, activeItem.getDisplayItem(), activeItem.getPriceItems(), activeItem.getPriceMoney()); + plugin.sendMessage(sender, "Item given to: " + target.getName() + " (" + target.getUUID() + ")"); + } + } + return true; + } else if (subcommand.equals("list")) { + if (!checkPermission(sender, "treasurechest.list")) { + return true; + } + if (args.length < 2) { + plugin.sendMessage(sender, "/" + label + " list ", true); + return true; + } + String nameOrId = args[1]; + UUID targetuuid = null; + try { + targetuuid = UUID.fromString(nameOrId); + } catch (Exception e) { + CachedPlayer target = plugin.getPlayerUUIDCache().getPlayerFromNameOrUUID(nameOrId, true); + if (target != null) { + targetuuid = target.getUUID(); + nameOrId = target.getName(); + } + } + if (targetuuid == null) { + plugin.sendMessage(sender, "Unknown player!", true); + return true; + } + + PlayerTreasureChestContent content = plugin.getData().getChestContent(targetuuid); + plugin.sendMessage(sender, ChatColor.GRAY + "Preise von " + nameOrId + " (" + targetuuid.toString() + "):"); + List items = content.getItems(); + if (items.isEmpty()) { + plugin.sendMessage(sender, "keine Preise vorhanden"); + } else { + ListedItemsData lid = new ListedItemsData(targetuuid); + int nr = 1; + for (DatabaseTreasureChestItem i : items) { + plugin.sendMessage(sender, nr + ": " + i.getDisplayItem().getItemMeta().getDisplayName()); + lid.addItem(nr, i.getId()); + nr++; + } + if (sender instanceof Player) { + Player player = ((Player) sender); + plugin.getData().setListedItems(player.getUniqueId(), lid); + } else { + plugin.getData().setListedItems(null, lid); + } + } + } else if (subcommand.equals("remove")) { + if (!checkPermission(sender, "treasurechest.remove")) { + return true; + } + if (args.length < 3) { + plugin.sendMessage(sender, "/" + label + " remove ", true); + return true; + } + + String nameOrId = args[1]; + UUID targetuuid = null; + try { + targetuuid = UUID.fromString(nameOrId); + } catch (Exception e) { + CachedPlayer target = plugin.getPlayerUUIDCache().getPlayerFromNameOrUUID(nameOrId, true); + if (target != null) { + targetuuid = target.getUUID(); + nameOrId = target.getName(); + } + } + if (targetuuid == null) { + plugin.sendMessage(sender, "Unknown player!", true); + return true; + } + int nr = getIntArgument(args[2], -1); + + ListedItemsData lid; + if (sender instanceof Player) { + Player player = ((Player) sender); + lid = plugin.getData().getListedItems(player.getUniqueId()); + } else { + lid = plugin.getData().getListedItems(null); + } + if (lid == null || !lid.getOwner().equals(targetuuid)) { + plugin.sendMessage(sender, "Nicht der gelistete Spieler", true); + return true; + } + Integer key = lid.getItemDatabaseKey(nr); + if (key == null) { + plugin.sendMessage(sender, "Ungültige ID", true); + return true; + } + try { + if (plugin.getDatabase().deleteItem(targetuuid, key)) { + PlayerTreasureChestContent content = plugin.getData().getChestContent(targetuuid); + if (content != null && content.getLoadState() == LoadState.LOADED) { + content.removeItem(key); + } + } else { + plugin.sendMessage(sender, "Ungültige ID", true); + return true; + } + } catch (SQLException e) { + plugin.sendMessage(sender, ChatColor.DARK_RED + "Datenbankfehler"); + plugin.getLogger().log(Level.SEVERE, "Could not delete item " + key + " for " + targetuuid + ": " + e.getMessage(), e); + return true; + } + plugin.sendMessage(sender, "Der Preis wurde entfernt!"); + } else { + plugin.sendMessage(sender, "Unknown subcommand!", true); + return true; + } + } + return true; + } + + private void displayHelp(CommandSender sender, String label) { + plugin.sendMessage(sender, ChatColor.GREEN + "Commands"); + if (checkPlayer(sender, true) && checkPermission(sender, "treasurechest.setchest", true)) { + plugin.sendMessage(sender, "/" + label + " setchest"); + plugin.sendMessage(sender, ChatColor.GREEN + " Set the treasure chest location to the location you are looking at."); + } + if (checkPlayer(sender, true) && checkPermission(sender, "treasurechest.create", true)) { + plugin.sendMessage(sender, "/" + label + " create"); + plugin.sendMessage(sender, ChatColor.GREEN + " Creates a price with the item in hand as display item."); + plugin.sendMessage(sender, "/" + label + " additem"); + plugin.sendMessage(sender, ChatColor.GREEN + " Adds the item in hand to the price."); + plugin.sendMessage(sender, "/" + label + " addmoney "); + plugin.sendMessage(sender, ChatColor.GREEN + " Adds money to a price."); + } + if (checkPlayer(sender, true) && checkPermission(sender, "treasurechest.give", true)) { + plugin.sendMessage(sender, "/" + label + " give "); + plugin.sendMessage(sender, ChatColor.GREEN + " Gives a price to a player."); + } + if (checkPermission(sender, "treasurechest.list")) { + plugin.sendMessage(sender, "/" + label + " list "); + plugin.sendMessage(sender, ChatColor.GREEN + " Gives price for a player."); + } + if (checkPermission(sender, "treasurechest.remove")) { + plugin.sendMessage(sender, "/" + label + " remove "); + plugin.sendMessage(sender, ChatColor.GREEN + " Removes a price from a players chest."); + } + } + + private int getIntArgument(String value, int defaultValue) { + try { + return Integer.parseInt(value); + } catch (Exception e) { + // ignore - return default + } + return defaultValue; + } + + private boolean checkPermission(CommandSender sender, String perm) { + return checkPermission(sender, perm, false); + } + + private boolean checkPermission(CommandSender sender, String perm, boolean silent) { + boolean hasPermission = sender.hasPermission(perm); + if (!silent && !hasPermission) { + plugin.sendMessage(sender, "No permission!", true); + } + return hasPermission; + } + + private boolean checkPlayer(CommandSender sender) { + return checkPlayer(sender, false); + } + + private boolean checkPlayer(CommandSender sender, boolean silent) { + boolean isPlayer = sender instanceof Player; + if (!isPlayer && !silent) { + plugin.sendMessage(sender, "You must be a player!", true); + } + return isPlayer; + } +} diff --git a/src/main/java/de/iani/treasurechest/TreasureChestData.java b/src/main/java/de/iani/treasurechest/TreasureChestData.java index c38e0ff..3c5cc6a 100644 --- a/src/main/java/de/iani/treasurechest/TreasureChestData.java +++ b/src/main/java/de/iani/treasurechest/TreasureChestData.java @@ -1,84 +1,77 @@ -package de.iani.treasurechest; - -import java.io.File; -import java.util.HashMap; -import java.util.Iterator; -import java.util.UUID; - -import org.bukkit.entity.Player; - -public class TreasureChestData { - private HashMap namedItems; - - private HashMap activeItems; - - private HashMap loadedChests; - - private TreasureChest plugin; - - private File chestContentFolder; - - public TreasureChestData(TreasureChest plugin) { - namedItems = new HashMap<>(); - activeItems = new HashMap<>(); - loadedChests = new HashMap<>(); - - this.plugin = plugin; - chestContentFolder = new File(this.plugin.getDataFolder(), "content"); - chestContentFolder.mkdirs(); - } - - public TreasureChestItem getNamedItem(String name) { - return namedItems.get(name.toLowerCase().trim()); - } - - public TreasureChestItem getActiveItem(UUID playerUUID) { - return activeItems.get(playerUUID); - } - - public TreasureChestItem setActiveItem(UUID playerUUID, TreasureChestItem item) { - if (item == null) { - return removeActiveItem(playerUUID); - } - return activeItems.put(playerUUID, item); - } - - public TreasureChestItem removeActiveItem(UUID playerUUID) { - return activeItems.remove(playerUUID); - } - - public PlayerTreasureChestContent getChestContentIfLoaded(UUID playerUUID) { - return loadedChests.get(playerUUID); - } - - public PlayerTreasureChestContent getChestContent(UUID playerUUID) { - PlayerTreasureChestContent loaded = getChestContentIfLoaded(playerUUID); - if (loaded != null) { - return loaded; - } - return loadOrCreateChestContent(playerUUID); - } - - private PlayerTreasureChestContent loadOrCreateChestContent(UUID playerUUID) { - File playerData = new File(chestContentFolder, playerUUID.toString() + ".yml"); - PlayerTreasureChestContent content = new PlayerTreasureChestContent(plugin, playerData); - loadedChests.put(playerUUID, content); - return content; - } - - public void doGC() { - long t = System.currentTimeMillis(); - for (Player player : plugin.getServer().getOnlinePlayers()) { - PlayerTreasureChestContent content = loadedChests.get(player.getUniqueId()); - if (content != null) { - content.setOnline(t); - } - } - Iterator it = loadedChests.values().iterator(); - while (it.hasNext()) { - if (!it.next().isOnline(t)) { - it.remove(); - } - } - } -} +package de.iani.treasurechest; + +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.UUID; + +public class TreasureChestData { + private HashMap activeItems; + + private HashMap loadedChests; + + private HashMap listedItems; + + private TreasureChest plugin; + + private File chestContentFolder; + + public TreasureChestData(TreasureChest plugin) { + activeItems = new HashMap<>(); + loadedChests = new HashMap<>(); + listedItems = new HashMap<>(); + + this.plugin = plugin; + chestContentFolder = new File(this.plugin.getDataFolder(), "content"); + chestContentFolder.mkdirs(); + } + + public TreasureChestItem getActiveItem(UUID playerUUID) { + return activeItems.get(playerUUID); + } + + public TreasureChestItem setActiveItem(UUID playerUUID, TreasureChestItem item) { + if (item == null) { + return removeActiveItem(playerUUID); + } + return activeItems.put(playerUUID, item); + } + + public TreasureChestItem removeActiveItem(UUID playerUUID) { + return activeItems.remove(playerUUID); + } + + public PlayerTreasureChestContent getChestContent(UUID playerUUID) { + return loadedChests.get(playerUUID); + } + + public void loadTreasureChest(UUID owner) { + loadedChests.put(owner, new PlayerTreasureChestContent(owner, plugin)); + } + + public void unloadTreasureChest(UUID owner) { + loadedChests.remove(owner); + } + + public ListedItemsData getListedItems(UUID owner) { + return listedItems.get(owner); + } + + public void setListedItems(UUID owner, ListedItemsData data) { + listedItems.put(owner, data); + } + + public void removeListedItems(UUID owner) { + listedItems.remove(owner); + } + + public void doGC() { + Iterator it = loadedChests.values().iterator(); + while (it.hasNext()) { + PlayerTreasureChestContent c = it.next(); + if (plugin.getServer().getPlayer(c.getOwner()) == null) { + it.remove(); + } + } + } +} diff --git a/src/main/java/de/iani/treasurechest/database/DatabaseTreasureChestItem.java b/src/main/java/de/iani/treasurechest/database/DatabaseTreasureChestItem.java new file mode 100644 index 0000000..b36ebfd --- /dev/null +++ b/src/main/java/de/iani/treasurechest/database/DatabaseTreasureChestItem.java @@ -0,0 +1,30 @@ +package de.iani.treasurechest.database; + +import org.bukkit.inventory.ItemStack; + +import de.iani.treasurechest.TreasureChestItem; + +public class DatabaseTreasureChestItem extends TreasureChestItem { + + private final long time; + private final int id; + + public DatabaseTreasureChestItem(ItemStack displayItem, ItemStack[] priceItems, int priceMoney, long time, int id) { + super(displayItem, priceItems, priceMoney); + this.time = time; + this.id = id; + } + + public long getTime() { + return time; + } + + public int getId() { + return id; + } + + @Override + public DatabaseTreasureChestItem clone() { + return (DatabaseTreasureChestItem) super.clone(); + } +} diff --git a/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java b/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java index 23b056f..94a5b99 100644 --- a/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java +++ b/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java @@ -8,8 +8,12 @@ import java.util.ArrayList; import java.util.UUID; -import de.iani.playerUUIDCache.CachedPlayer; -import de.iani.playerUUIDCache.PlayerUUIDCache; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; + import de.iani.treasurechest.TreasureChestItem; import de.iani.treasurechest.util.sql.MySQLConnection; import de.iani.treasurechest.util.sql.SQLConnection; @@ -21,20 +25,17 @@ private final String tableName; private final String insertContent; - private final String selectContent; - private final String removeContent; - private final String removeOldContent; public TreasureChestDatabase(SQLConfig config) throws SQLException { connection = new MySQLConnection(config.getHost(), config.getDatabase(), config.getUser(), config.getPassword()); this.tableName = config.getTablePrefix() + "_content"; - insertContent = "INSERT INTO " + tableName + " (uuid, time, displayItem, content) VALUES (?, ?, ?, ?)"; + insertContent = "INSERT INTO " + tableName + " (uuid, time, content) VALUES (?, ?, ?)"; - selectContent = "SELECT id, uuid, time, displayItem, content FROM " + tableName + " WHERE uuid = ?"; + selectContent = "SELECT id, uuid, time, content FROM " + tableName + " WHERE uuid = ? ORDER BY time DESC"; removeContent = "DELETE FROM " + tableName + " WHERE id = ? AND uuid = ?"; @@ -46,12 +47,11 @@ if (!sqlConnection.hasTable(tableName)) { Statement smt = connection.createStatement(); smt.executeUpdate("CREATE TABLE `" + tableName + "` ("// - + "`id` INT NOT NULL,"// + + "`id` INT NOT NULL AUTO_INCREMENT,"// + "`uuid` CHAR( 36 ) NOT NULL,"// + "`time` BIGINT NOT NULL,"// - + "`displayItem` MEDIUMTEXT ,"// - + "`content` MEDIUMTEXT ,"// - + "PRIMARY KEY ( `id` ), INDEX ( `uuid` ) ) ENGINE = innodb"); + + "`content` LONGTEXT,"// + + "PRIMARY KEY ( `id` ), INDEX ( `uuid`, `time` ) ) ENGINE = innodb"); smt.close(); } return null; @@ -63,79 +63,105 @@ connection.disconnect(); } - public void addItem(final UUID owner, final String displayItem, final String content) throws SQLException { - this.connection.runCommands(new SQLRunnable() { + public DatabaseTreasureChestItem addItem(UUID owner, TreasureChestItem item) throws SQLException { + return this.connection.runCommands(new SQLRunnable() { @Override - public Void execute(Connection connection, SQLConnection sqlConnection) throws SQLException { - PreparedStatement smt = sqlConnection.getOrCreateStatement(insertContent); + public DatabaseTreasureChestItem execute(Connection connection, SQLConnection sqlConnection) throws SQLException { + PreparedStatement smt = sqlConnection.getOrCreateStatement(insertContent, Statement.RETURN_GENERATED_KEYS); smt.setString(1, owner.toString()); - smt.setLong(2, System.currentTimeMillis()); - smt.setString(3, displayItem); - smt.setString(4, content); - smt.executeUpdate(); - return null; - } - }); - - } - - public ArrayList getPlayerItems(final UUID uuid) throws SQLException { - return this.connection.runCommands(new SQLRunnable>() { - @Override - public ArrayList execute(Connection connection, SQLConnection sqlConnection) throws SQLException { - PreparedStatement smt = sqlConnection.getOrCreateStatement(selectContent); - smt.setString(1, uuid.toString()); - ResultSet rs = smt.executeQuery(); - while (rs.next()) { - // TODO - } - rs.close(); - return null; - } - }); - } - - public CachedPlayer getPlayer(final String name) throws SQLException { - return this.connection.runCommands(new SQLRunnable() { - @Override - public CachedPlayer execute(Connection connection, SQLConnection sqlConnection) throws SQLException { - String realName = name; - PreparedStatement smt = sqlConnection.getOrCreateStatement(selectPlayerByName); - smt.setString(1, name); - ResultSet rs = smt.executeQuery(); - - UUID uuid = null; - long time = Long.MIN_VALUE; - while (rs.next()) { - long thisTime = rs.getLong(3); - if (thisTime > time) { - try { - uuid = UUID.fromString(rs.getString(1)); - realName = rs.getString(2); - time = thisTime; - } catch (IllegalArgumentException e) { - // ignore invalid uuid - } + long time = System.currentTimeMillis(); + smt.setLong(2, time); + YamlConfiguration conf = new YamlConfiguration(); + conf.set("display", item.getDisplayItem()); + ConfigurationSection itemsSection = conf.createSection("items"); + ItemStack[] items = item.getPriceItems(); + if (items != null) { + for (int i = 0; i < items.length; i++) { + ItemStack stack = items[i]; + itemsSection.set(Integer.toString(i), stack); } } - rs.close(); - if (uuid != null) { - return new CachedPlayer(uuid, realName, time, System.currentTimeMillis()); + conf.set("money", item.getPriceMoney()); + smt.setString(3, conf.saveToString()); + smt.executeUpdate(); + ResultSet genKeys = smt.getGeneratedKeys(); + Integer id = null; + if (genKeys.next()) { + id = genKeys.getInt(1); } - return null; + genKeys.close(); + if (id == null) { + throw new SQLException("No id was generated!"); + } + return new DatabaseTreasureChestItem(item.getDisplayItem(), item.getPriceItems(), item.getPriceMoney(), time, id); + } + }); + + } + + public ArrayList getPlayerItems(UUID owner) throws SQLException { + return this.connection.runCommands(new SQLRunnable>() { + @Override + public ArrayList execute(Connection connection, SQLConnection sqlConnection) throws SQLException { + ArrayList result = new ArrayList<>(); + PreparedStatement smt = sqlConnection.getOrCreateStatement(selectContent); + smt.setString(1, owner.toString()); + ResultSet rs = smt.executeQuery(); + while (rs.next()) { + int id = rs.getInt("id"); + long time = rs.getLong("time"); + String content = rs.getString("content"); + YamlConfiguration conf = new YamlConfiguration(); + try { + conf.loadFromString(content); + } catch (InvalidConfigurationException e) { + e.printStackTrace(); + } + ItemStack displayItem = conf.getItemStack("display"); + if (displayItem == null || displayItem.getAmount() == 0 || displayItem.getType() == Material.AIR) { + displayItem = new ItemStack(Material.BEDROCK); + } + ArrayList stacks = new ArrayList<>(); + ConfigurationSection itemsSection = conf.getConfigurationSection("items"); + for (String key : itemsSection.getKeys(false)) { + ItemStack stack = itemsSection.getItemStack(key); + if (stack != null && stack.getAmount() > 0 && stack.getType() != Material.AIR) { + stacks.add(stack); + } + } + ItemStack[] priceItems = stacks.toArray(new ItemStack[stacks.size()]); + int priceMoney = conf.getInt("money"); + result.add(new DatabaseTreasureChestItem(displayItem, priceItems, priceMoney, time, id)); + } + rs.close(); + return result; } }); } - public void deleteOldPlayerProfiles() throws SQLException { - this.connection.runCommands(new SQLRunnable() { + public boolean deleteItem(UUID owner, int id) throws SQLException { + return this.connection.runCommands(new SQLRunnable() { @Override - public Void execute(Connection connection, SQLConnection sqlConnection) throws SQLException { - PreparedStatement smt = sqlConnection.getOrCreateStatement(deleteOldPlayerProfiles); - smt.setLong(1, System.currentTimeMillis() - PlayerUUIDCache.PROFILE_PROPERTIES_CACHE_EXPIRATION_TIME); - smt.executeUpdate(); - return null; + public Boolean execute(Connection connection, SQLConnection sqlConnection) throws SQLException { + PreparedStatement smt = sqlConnection.getOrCreateStatement(removeContent); + smt.setInt(1, id); + smt.setString(2, owner.toString()); + boolean updated = smt.executeUpdate() > 0; + return updated; + } + }); + } + + public int deleteOldItems(long days) throws SQLException { + return this.connection.runCommands(new SQLRunnable() { + @Override + public Integer execute(Connection connection, SQLConnection sqlConnection) throws SQLException { + PreparedStatement smt = sqlConnection.getOrCreateStatement(removeOldContent); + long minTime = System.currentTimeMillis() - days * 24 * 60 * 60 * 1000; + smt.setLong(1, minTime); + int updated = smt.executeUpdate(); + return updated; } }); } diff --git a/src/main/java/de/iani/treasurechest/worker/WorkEntry.java b/src/main/java/de/iani/treasurechest/worker/WorkEntry.java new file mode 100644 index 0000000..7c1566a --- /dev/null +++ b/src/main/java/de/iani/treasurechest/worker/WorkEntry.java @@ -0,0 +1,7 @@ +package de.iani.treasurechest.worker; + +import de.iani.treasurechest.database.TreasureChestDatabase; + +public interface WorkEntry { + void process(TreasureChestDatabase database); +} \ No newline at end of file diff --git a/src/main/java/de/iani/treasurechest/worker/WorkerThread.java b/src/main/java/de/iani/treasurechest/worker/WorkerThread.java new file mode 100644 index 0000000..5504eaf --- /dev/null +++ b/src/main/java/de/iani/treasurechest/worker/WorkerThread.java @@ -0,0 +1,79 @@ +package de.iani.treasurechest.worker; + +import java.util.ArrayDeque; +import java.util.logging.Level; + +import de.iani.treasurechest.TreasureChest; +import de.iani.treasurechest.database.TreasureChestDatabase; + +public class WorkerThread extends Thread { + + private TreasureChest plugin; + private TreasureChestDatabase database; + private boolean stopping; + private ArrayDeque work; + + public WorkerThread(TreasureChest plugin) { + this.plugin = plugin; + this.work = new ArrayDeque(); + this.database = plugin.getDatabase(); + setName("TreasureChest worker"); + start(); + } + + public void addWork(WorkEntry e) { + synchronized (work) { + work.addLast(e); + work.notify(); + } + } + + public void shutdown() { + synchronized (work) { + stopping = true; + work.notify(); + } + boolean interrupt = false; + while (isAlive()) { + try { + join(); + } catch (InterruptedException e) { + interrupt = true; + } + } + if (interrupt) { + Thread.currentThread().interrupt(); + } + if (database != null) { + database.disconnect(); + database = null; + } + } + + @Override + public void run() { + WorkEntry e; + while (true) { + synchronized (work) { + e = work.pollFirst(); + if (e == null) { + if (stopping) { + return; + } + try { + work.wait(); + } catch (InterruptedException e1) { + Thread.currentThread().interrupt(); + } + } + } + if (e != null && database != null) { + try { + e.process(database); + } catch (Exception er) { + plugin.getLogger().log(Level.SEVERE, "Error in TreasureChest worker thread", er); + } + } + } + } +}