diff --git a/src/main/java/de/iani/treasurechest/Permissions.java b/src/main/java/de/iani/treasurechest/Permissions.java index b154d9c..5dbe0c2 100644 --- a/src/main/java/de/iani/treasurechest/Permissions.java +++ b/src/main/java/de/iani/treasurechest/Permissions.java @@ -6,4 +6,5 @@ public static final String GIVE = "treasurechest.give"; public static final String LIST = "treasurechest.list"; public static final String REMOVE = "treasurechest.remove"; + public static final String UPDATEALL = "treasurechest.updateall"; } diff --git a/src/main/java/de/iani/treasurechest/TreasureChest.java b/src/main/java/de/iani/treasurechest/TreasureChest.java index ac68daf..38e3557 100644 --- a/src/main/java/de/iani/treasurechest/TreasureChest.java +++ b/src/main/java/de/iani/treasurechest/TreasureChest.java @@ -12,6 +12,7 @@ import de.iani.treasurechest.commands.ListCommand; import de.iani.treasurechest.commands.RemoveCommand; import de.iani.treasurechest.commands.SetChestCommand; +import de.iani.treasurechest.commands.UpdateAllCommand; import de.iani.treasurechest.database.DatabaseTreasureChestItem; import de.iani.treasurechest.database.SQLConfig; import de.iani.treasurechest.database.TreasureChestDatabase; @@ -86,6 +87,7 @@ treasurechestCommand.addCommandMapping(new GiveCommand(this), "give"); treasurechestCommand.addCommandMapping(new ListCommand(this), "list"); treasurechestCommand.addCommandMapping(new RemoveCommand(this), "remove"); + treasurechestCommand.addCommandMapping(new UpdateAllCommand(this), "updateall"); getServer().getPluginManager().registerEvents(new ChestInventoryListener(this), this); getServer().getPluginManager().registerEvents(new PlayerEventListener(this), this); diff --git a/src/main/java/de/iani/treasurechest/TreasureChestItem.java b/src/main/java/de/iani/treasurechest/TreasureChestItem.java index 04bb03c..ea8a78b 100644 --- a/src/main/java/de/iani/treasurechest/TreasureChestItem.java +++ b/src/main/java/de/iani/treasurechest/TreasureChestItem.java @@ -23,6 +23,10 @@ return displayItem; } + public void setDisplayItem(ItemStack displayItem) { + this.displayItem = displayItem; + } + public ItemStack[] getPriceItems() { return priceItems; } diff --git a/src/main/java/de/iani/treasurechest/commands/UpdateAllCommand.java b/src/main/java/de/iani/treasurechest/commands/UpdateAllCommand.java new file mode 100644 index 0000000..61911d2 --- /dev/null +++ b/src/main/java/de/iani/treasurechest/commands/UpdateAllCommand.java @@ -0,0 +1,129 @@ +package de.iani.treasurechest.commands; + +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.bukkit.commands.exceptions.DisallowsCommandBlockException; +import de.iani.cubesideutils.bukkit.commands.exceptions.IllegalSyntaxException; +import de.iani.cubesideutils.bukkit.commands.exceptions.InternalCommandException; +import de.iani.cubesideutils.bukkit.commands.exceptions.NoPermissionException; +import de.iani.cubesideutils.bukkit.commands.exceptions.RequiresPlayerException; +import de.iani.cubesideutils.bukkit.updater.DataUpdater; +import de.iani.cubesideutils.commands.ArgsParser; +import de.iani.treasurechest.Permissions; +import de.iani.treasurechest.TreasureChest; +import de.iani.treasurechest.database.DatabaseTreasureChestItem; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.logging.Level; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +public class UpdateAllCommand extends SubCommand { + private TreasureChest plugin; + + public UpdateAllCommand(TreasureChest plugin) { + this.plugin = plugin; + } + + @Override + public String getRequiredPermission() { + return Permissions.UPDATEALL; + } + + @Override + public boolean requiresPlayer() { + return false; + } + + @Override + public String getUsage() { + return "CONFIRM|FORCEALL"; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) throws DisallowsCommandBlockException, RequiresPlayerException, NoPermissionException, IllegalSyntaxException, InternalCommandException { + if (args.remaining() != 1) { + plugin.sendMessage(sender, commandString + getUsage(), true); + return true; + } + String arg = args.getNext(""); + if (!arg.equals("CONFIRM") && !arg.equals("FORCEALL")) { + plugin.sendMessage(sender, commandString + getUsage(), true); + return true; + } + boolean forceAll = arg.equals("FORCEALL"); + ArrayList allHeads; + try { + sender.sendMessage(ChatColor.DARK_RED + "Lade Schatztruheninhalte!"); + allHeads = plugin.getDatabase().getAllItems(); + sender.sendMessage(ChatColor.DARK_RED + "Laden abgeschlossen (" + allHeads.size() + ") - Beginne Update!"); + } catch (SQLException e) { + sender.sendMessage("Exception while loading"); + plugin.getLogger().log(Level.SEVERE, "Exception while loading", e); + return true; + } + new BukkitRunnable() { + int total = allHeads.size(); + int checked = 0; + int converted = 0; + + @Override + public void run() { + for (int k = 0; k < 100; k++) { + if (checked >= total) { + sender.sendMessage(ChatColor.DARK_RED + "Update: " + checked + "/" + total + " (" + converted + " updated)"); + sender.sendMessage(ChatColor.DARK_RED + "Update abgeschlossen!"); + this.cancel(); + return; + } + DatabaseTreasureChestItem i = allHeads.get(checked); + checked++; + + boolean changed = false; + + ItemStack oldStack = i.getDisplayItem(); + ItemStack newStack = DataUpdater.updateItemStack(oldStack); + if (!Objects.equals(newStack, oldStack)) { + i.setDisplayItem(newStack); + changed = true; + } + + ItemStack[] priceItems = i.getPriceItems(); + if (priceItems != null) { + for (int j = 0; j < priceItems.length; j++) { + oldStack = priceItems[j]; + newStack = DataUpdater.updateItemStack(oldStack); + if (!Objects.equals(newStack, oldStack)) { + priceItems[j] = newStack; + changed = true; + } + } + } + if (forceAll || changed) { + try { + plugin.getDatabase().updateItem(i); + } catch (SQLException e) { + sender.sendMessage("Exception while updating: " + i.getId()); + plugin.getLogger().log(Level.SEVERE, "Exception while updating: " + i.getId(), e); + } + converted++; + } + if (checked % 100 == 0) { + sender.sendMessage(ChatColor.DARK_RED + "Update: " + checked + "/" + total + " (" + converted + " updated)"); + } + } + } + }.runTaskTimer(plugin, 1, 1); + return true; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + return List.of(); + } +} diff --git a/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java b/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java index 95e7625..9e82f9e 100644 --- a/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java +++ b/src/main/java/de/iani/treasurechest/database/TreasureChestDatabase.java @@ -27,6 +27,8 @@ private final String selectContent; private final String removeContent; private final String removeOldContent; + private final String selectAllContent; + private final String updateContent; public TreasureChestDatabase(TreasureChest plugin, SQLConfig config) throws SQLException { this.plugin = plugin; @@ -41,6 +43,10 @@ removeOldContent = "DELETE FROM " + tableName + " WHERE time < ?"; + selectAllContent = "SELECT id, uuid, time, content FROM " + tableName + " ORDER BY id DESC"; + + updateContent = "UPDATE " + tableName + " SET content = ? WHERE id = ?"; + this.connection.runCommands((connection, sqlConnection) -> { if (!sqlConnection.hasTable(tableName)) { Statement smt = connection.createStatement(); @@ -93,6 +99,28 @@ }); } + public boolean updateItem(DatabaseTreasureChestItem item) throws SQLException { + return this.connection.runCommands((connection, sqlConnection) -> { + PreparedStatement smt = sqlConnection.getOrCreateStatement(updateContent); + + 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); + } + } + conf.set("money", item.getPriceMoney()); + smt.setString(1, conf.saveToString()); + smt.setInt(2, item.getId()); + int count = smt.executeUpdate(); + return count > 0; + }); + } + public ArrayList getPlayerItems(UUID owner) throws SQLException { return this.connection.runCommands((connection, sqlConnection) -> { ArrayList result = new ArrayList<>(); @@ -132,6 +160,44 @@ }); } + public ArrayList getAllItems() throws SQLException { + return this.connection.runCommands((connection, sqlConnection) -> { + ArrayList result = new ArrayList<>(); + PreparedStatement smt = sqlConnection.getOrCreateStatement(selectAllContent); + 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) { + plugin.getLogger().log(Level.WARNING, "Could not load treasure chest item " + id, e); + continue; + } + ItemStack displayItem = conf.getItemStack("display"); + if (displayItem == null || displayItem.getAmount() == 0 || displayItem.getType() == Material.AIR) { + plugin.getLogger().log(Level.WARNING, "No display item for item " + id); + continue; + } + 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 boolean deleteItem(UUID owner, int id) throws SQLException { return this.connection.runCommands((connection, sqlConnection) -> { PreparedStatement smt = sqlConnection.getOrCreateStatement(removeContent);