diff --git a/src/main/java/net/countercraft/movecraft/repair/MovecraftRepair.java b/src/main/java/net/countercraft/movecraft/repair/MovecraftRepair.java index b2f4c63..906ab7a 100644 --- a/src/main/java/net/countercraft/movecraft/repair/MovecraftRepair.java +++ b/src/main/java/net/countercraft/movecraft/repair/MovecraftRepair.java @@ -15,6 +15,13 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin; import net.countercraft.movecraft.craft.type.TypeData.InvalidValueException; +import net.countercraft.movecraft.repair.commands.RepairInventoryCommand; +import net.countercraft.movecraft.repair.bar.RepairBarManager; +import net.countercraft.movecraft.repair.bar.config.PlayerManager; +import net.countercraft.movecraft.repair.commands.RepairBarCommand; +import net.countercraft.movecraft.repair.commands.RepairCancelCommand; +import net.countercraft.movecraft.repair.commands.RepairListCommand; +import net.countercraft.movecraft.repair.commands.RepairReportCommand; import net.countercraft.movecraft.repair.config.Config; import net.countercraft.movecraft.repair.localisation.I18nSupport; import net.countercraft.movecraft.repair.types.blobs.ListBlob; @@ -39,8 +46,15 @@ public static MovecraftRepair getInstance() { public void onEnable() { instance = this; + // Save default config, create default userdata and language if needed saveDefaultConfig(); + File folder = new File(getDataFolder(), "userdata"); + if (!folder.exists()) { + getLogger().info("Created userdata directory"); + folder.mkdirs(); + } + String[] languages = { "en" }; for (String s : languages) { if (!new File(getDataFolder() + "/localisation/mc-repairlang_" + s + ".properties").exists()) { @@ -82,14 +96,21 @@ public void onEnable() { protoRepairCache = new ProtoRepairCache(); protoRepairCache.runTaskTimerAsynchronously(this, 10, 200); + var playerManager = new PlayerManager(); + getServer().getPluginManager().registerEvents(playerManager, this); + // Startup repair bar manager (every second) - RepairBarManager repairBarManager = new RepairBarManager(); + RepairBarManager repairBarManager = new RepairBarManager(playerManager); repairBarManager.runTaskTimerAsynchronously(this, 15, 20); getServer().getPluginManager().registerEvents(repairBarManager, this); getServer().getPluginManager().registerEvents(new RepairSign(), this); + getCommand("repairbar").setExecutor(new RepairBarCommand(playerManager)); + getCommand("repaircancel").setExecutor(new RepairCancelCommand()); + getCommand("repairinventory").setExecutor(new RepairInventoryCommand()); getCommand("repairlist").setExecutor(new RepairListCommand()); + getCommand("repairreport").setExecutor(new RepairReportCommand()); } private static void loadConfig(FileConfiguration config) { @@ -102,6 +123,7 @@ private static void loadConfig(FileConfiguration config) { Config.RepairMaxBlocksPerTick = config.getInt("RepairMaxBlocksPerTick", 2); Config.RepairMoneyPerBlock = config.getDouble("RepairMoneyPerBlock", 0.0); Config.RepairMaxPercent = config.getDouble("RepairMaxPercent", 50); + Config.DisableDoubleClick = config.getBoolean("DisableDoubleClick", false); Config.RepairTool = Material.valueOf(config.getString("RepairTool", "firework_rocket").toUpperCase()); Object entry = config.get("RepairBlobs"); if (!(entry instanceof List)) { diff --git a/src/main/java/net/countercraft/movecraft/repair/RepairManager.java b/src/main/java/net/countercraft/movecraft/repair/RepairManager.java index fa6f4d1..9fe61e6 100644 --- a/src/main/java/net/countercraft/movecraft/repair/RepairManager.java +++ b/src/main/java/net/countercraft/movecraft/repair/RepairManager.java @@ -8,6 +8,7 @@ import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; import net.countercraft.movecraft.repair.config.Config; +import net.countercraft.movecraft.repair.events.RepairCancelledEvent; import net.countercraft.movecraft.repair.events.RepairFinishedEvent; import net.countercraft.movecraft.repair.events.RepairStartedEvent; import net.countercraft.movecraft.repair.types.Repair; @@ -55,6 +56,13 @@ public void start(Repair repair) { repairs.add(repair); } + public void cancel(Repair repair) { + Bukkit.getPluginManager().callEvent(new RepairCancelledEvent(repair)); + + MovecraftRepair.getInstance().getLogger().info(() -> String.format("%s has cancelled repair %s with the cost of %.2f", repair.getPlayerUUID(), repair.getName(), repair.getCost())); + repairs.remove(repair); + } + private void end(Repair repair) { Bukkit.getPluginManager().callEvent(new RepairFinishedEvent(repair)); diff --git a/src/main/java/net/countercraft/movecraft/repair/RepairSign.java b/src/main/java/net/countercraft/movecraft/repair/RepairSign.java index db4fa1e..40a13fb 100644 --- a/src/main/java/net/countercraft/movecraft/repair/RepairSign.java +++ b/src/main/java/net/countercraft/movecraft/repair/RepairSign.java @@ -64,7 +64,8 @@ public void onSignClick(PlayerInteractEvent event) { event.setCancelled(true); Player player = event.getPlayer(); if (Config.RepairTicksPerBlock == 0) { - player.sendMessage(I18nSupport.getInternationalisedString("Repair functionality is disabled or WorldEdit was not detected")); + player.sendMessage(I18nSupport + .getInternationalisedString("Repair functionality is disabled or WorldEdit was not detected")); return; } @@ -78,7 +79,7 @@ public void onSignClick(PlayerInteractEvent event) { player.sendMessage(I18nSupport.getInternationalisedString("Insufficient Permissions")); return; } - + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { onRightClick(sign, player, craft); } else if (event.getAction() == Action.LEFT_CLICK_BLOCK) { @@ -103,39 +104,38 @@ public void onRightClick(Sign sign, Player player, PlayerCraft craft) { Repair repair = null; try { repair = protoRepair.execute(craft, sign); - } - catch (ProtoRepair.NotEnoughMoneyException e) { + } catch (ProtoRepair.NotEnoughMoneyException e) { // Not enough money, tell the player player.sendMessage(I18nSupport.getInternationalisedString("Economy - Not Enough Money")); - } - catch (ProtoRepair.NotEnoughItemsException e) { + } catch (ProtoRepair.NotEnoughItemsException e) { // Not enough items, tell the player for (RepairBlob blob : e.getRemaining().getKeySet()) { player.sendMessage( - I18nSupport.getInternationalisedString("Repair - Need more of material") - + String.format( - ": %s - %d", - blob.getName(), - (int) Math.ceil(e.getRemaining().get(blob)) - ) - ); + I18nSupport.getInternationalisedString("Repair - Need more of material") + + String.format( + ": %s - %d", + blob.getName(), + (int) Math.ceil(e.getRemaining().get(blob)))); } return; - } - catch (ProtoRepair.ProtoRepairExpiredException | ProtoRepair.ProtoRepairLocationException e) { + } catch (ProtoRepair.ProtoRepairExpiredException | ProtoRepair.ProtoRepairLocationException e) { // Expired or wrong location, go back to first click // ItemRemovalException shouldn't happen, but go back to first click regardless createProtoRepair(sign, uuid, player, craft); return; - } - catch (Exception e) { + } catch (Exception e) { // Something weird went wrong, let it fail silently e.printStackTrace(); return; } // Release the craft, and start the repair - CraftManager.getInstance().release(craft, CraftReleaseEvent.Reason.REPAIR, true); // Note: This change is "temporary" and means that repairs allow the player to repilot and could have damaging effects on combat releases + CraftManager.getInstance().release(craft, CraftReleaseEvent.Reason.REPAIR, true); // Note: This change is + // "temporary" and means that + // repairs allow the player to + // repilot and could have + // damaging effects on combat + // releases MovecraftRepair.getInstance().getRepairManager().start(repair); } @@ -146,8 +146,7 @@ private void createProtoRepair(Sign sign, UUID uuid, Player player, PlayerCraft RepairState state; try { state = new RepairState(uuid, stateName); - } - catch (IOException e) { + } catch (IOException e) { player.sendMessage(I18nSupport.getInternationalisedString("Repair - State not found")); return; } @@ -156,8 +155,7 @@ private void createProtoRepair(Sign sign, UUID uuid, Player player, PlayerCraft ProtoRepair protoRepair; try { protoRepair = state.execute(sign); - } - catch (WorldEditException e) { + } catch (WorldEditException e) { player.sendMessage(I18nSupport.getInternationalisedString("Repair - State not found")); return; } @@ -166,9 +164,11 @@ private void createProtoRepair(Sign sign, UUID uuid, Player player, PlayerCraft return; } - player.sendMessage(I18nSupport.getInternationalisedString("Repair - Total damaged blocks") + ": " + protoRepair.getDamagedBlockCount()); + player.sendMessage(I18nSupport.getInternationalisedString("Repair - Total damaged blocks") + ": " + + protoRepair.getDamagedBlockCount()); double percent = 100.0 * protoRepair.getDamagedBlockCount() / craft.getHitBox().size(); - player.sendMessage(I18nSupport.getInternationalisedString("Repair - Percentage of craft") + String.format(": %.2f", percent)); + player.sendMessage(I18nSupport.getInternationalisedString("Repair - Percentage of craft") + + String.format(": %.2f", percent)); if (percent > Config.RepairMaxPercent) { player.sendMessage(I18nSupport.getInternationalisedString("Repair - Failed Craft Too Damaged")); return; @@ -176,16 +176,17 @@ private void createProtoRepair(Sign sign, UUID uuid, Player player, PlayerCraft for (RepairBlob blob : protoRepair.getMaterials().getKeySet()) { player.sendMessage(String.format( - "%s : %d", - blob.getName(), - (int) Math.ceil(protoRepair.getMaterials().get(blob)) - )); + "%s : %d", + blob.getName(), + (int) Math.ceil(protoRepair.getMaterials().get(blob)))); } long duration = (long) Math.ceil(protoRepair.getQueue().size() * Config.RepairTicksPerBlock / 20.0); - player.sendMessage(I18nSupport.getInternationalisedString("Repair - Seconds to complete repair") + String.format(": %d", duration)); + player.sendMessage(I18nSupport.getInternationalisedString("Repair - Seconds to complete repair") + + String.format(": %d", duration)); - player.sendMessage(I18nSupport.getInternationalisedString("Repair - Money to complete repair") + String.format(": %.2f", protoRepair.getQueue().size() * Config.RepairMoneyPerBlock)); + player.sendMessage(I18nSupport.getInternationalisedString("Repair - Money to complete repair") + + String.format(": %.2f", protoRepair.getQueue().size() * Config.RepairMoneyPerBlock)); // Add to cache only if not empty if (!protoRepair.getQueue().isEmpty()) @@ -193,11 +194,13 @@ private void createProtoRepair(Sign sign, UUID uuid, Player player, PlayerCraft } public void onLeftClick(Sign sign, Player player, PlayerCraft craft) { - Long lastLeftClick = leftClickCache.get(player.getUniqueId()); - if (lastLeftClick == null || (System.currentTimeMillis() - lastLeftClick.longValue() > 5000)) { - // First click, just add to the map - leftClickCache.put(player.getUniqueId(), System.currentTimeMillis()); - return; + if (!Config.DisableDoubleClick) { + Long lastLeftClick = leftClickCache.get(player.getUniqueId()); + if (lastLeftClick == null || (System.currentTimeMillis() - lastLeftClick.longValue() > 5000)) { + // First click, just add to the map + leftClickCache.put(player.getUniqueId(), System.currentTimeMillis()); + return; + } } if (!WEUtils.saveCraftSchematic(craft, sign)) { diff --git a/src/main/java/net/countercraft/movecraft/repair/RepairBarManager.java b/src/main/java/net/countercraft/movecraft/repair/bar/RepairBarManager.java similarity index 61% rename from src/main/java/net/countercraft/movecraft/repair/RepairBarManager.java rename to src/main/java/net/countercraft/movecraft/repair/bar/RepairBarManager.java index b5b7214..a1fff0e 100644 --- a/src/main/java/net/countercraft/movecraft/repair/RepairBarManager.java +++ b/src/main/java/net/countercraft/movecraft/repair/bar/RepairBarManager.java @@ -1,4 +1,4 @@ -package net.countercraft.movecraft.repair; +package net.countercraft.movecraft.repair.bar; import java.util.HashMap; import java.util.Map; @@ -13,23 +13,43 @@ import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; +import net.countercraft.movecraft.repair.bar.config.PlayerManager; +import net.countercraft.movecraft.repair.events.RepairCancelledEvent; import net.countercraft.movecraft.repair.events.RepairFinishedEvent; import net.countercraft.movecraft.repair.events.RepairStartedEvent; import net.countercraft.movecraft.repair.localisation.I18nSupport; import net.countercraft.movecraft.repair.types.Repair; public class RepairBarManager extends BukkitRunnable implements Listener { + @NotNull + private final PlayerManager manager; private Map bossBars = new HashMap<>(); + public RepairBarManager(@NotNull PlayerManager manager) { + this.manager = manager; + } + @Override public void run() { + if (bossBars.get(null) != null) { + // If we have a null key, remove the bossbar + BossBar bossBar = bossBars.get(null); + bossBars.remove(null); + bossBar.setVisible(false); + bossBar.removeAll(); + } + for (Map.Entry entry : bossBars.entrySet()) { Repair repair = entry.getKey(); BossBar bossBar = entry.getValue(); Player player = Bukkit.getPlayer(repair.getPlayerUUID()); if (player != null) { - bossBar.addPlayer(player); + if (manager.getBarSetting(player)) { + bossBar.addPlayer(player); + } else { + bossBar.removePlayer(player); + } } int remaining = repair.remaining(); @@ -45,28 +65,42 @@ public void run() { public void onRepairStart(@NotNull RepairStartedEvent event) { Repair repair = event.getRepair(); - BossBar bossBar = Bukkit.createBossBar(null, BarColor.WHITE, BarStyle.SOLID); + BossBar bossBar = Bukkit.createBossBar(repair.getName(), BarColor.WHITE, BarStyle.SOLID); + bossBar.setProgress(0.0); bossBars.put(repair, bossBar); Player player = Bukkit.getPlayer(repair.getPlayerUUID()); if (player != null) { - bossBar.addPlayer(player); player.sendMessage(I18nSupport.getInternationalisedString("Repair - Repairs underway")); + if (manager.getBarSetting(player)) { + bossBar.addPlayer(player); + } else { + bossBar.removePlayer(player); + } } } @EventHandler public void onRepairFinished(@NotNull RepairFinishedEvent event) { - Repair repair = event.getRepair(); - BossBar bossBar = bossBars.get(repair); - - bossBars.remove(repair); - bossBar.setVisible(false); + remove(event.getRepair()); - Player player = Bukkit.getPlayer(repair.getPlayerUUID()); + Player player = Bukkit.getPlayer(event.getRepair().getPlayerUUID()); if (player == null) return; player.sendMessage(I18nSupport.getInternationalisedString("Repair - Repairs complete")); } + + @EventHandler + public void onRepairCancelled(@NotNull RepairCancelledEvent event) { + remove(event.getRepair()); + } + + private void remove(Repair repair) { + BossBar bossBar = bossBars.get(repair); + + bossBars.remove(repair); + bossBar.setVisible(false); + bossBar.removeAll(); + } } diff --git a/src/main/java/net/countercraft/movecraft/repair/bar/config/PlayerConfig.java b/src/main/java/net/countercraft/movecraft/repair/bar/config/PlayerConfig.java new file mode 100644 index 0000000..8386c9f --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/repair/bar/config/PlayerConfig.java @@ -0,0 +1,31 @@ +package net.countercraft.movecraft.repair.bar.config; + +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public class PlayerConfig { + @Nullable + private UUID owner; + private boolean barSetting = true; + + public PlayerConfig() { + } + + public PlayerConfig(UUID owner) { + this.owner = owner; + } + + @Nullable + public UUID getOwner() { + return owner; + } + + public boolean getBarSetting() { + return barSetting; + } + + public void toggleBarSetting() { + barSetting = !barSetting; + } +} diff --git a/src/main/java/net/countercraft/movecraft/repair/bar/config/PlayerManager.java b/src/main/java/net/countercraft/movecraft/repair/bar/config/PlayerManager.java new file mode 100644 index 0000000..c8ca24a --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/repair/bar/config/PlayerManager.java @@ -0,0 +1,132 @@ +package net.countercraft.movecraft.repair.bar.config; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; + +import net.countercraft.movecraft.repair.MovecraftRepair; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Map; +import java.util.UUID; +import java.util.WeakHashMap; + +public class PlayerManager implements Listener { + private final Map cache = new WeakHashMap<>(); + + @Nullable + public boolean getBarSetting(Player player) { + var config = cache.get(player); + if (config == null) + return true; + + return config.getBarSetting(); + } + + public void toggleBarSetting(Player player) { + var config = cache.get(player); + if (config == null) { + config = loadPlayer(player); + cache.put(player, config); + } + + config.toggleBarSetting(); + } + + private void savePlayer(Player player) { + var config = cache.get(player); + if (config == null) + return; + + Gson gson = buildGson(); + String str = null; + try { + str = gson.toJson(config); + } catch (JsonIOException e) { + e.printStackTrace(); + return; + } + + File file = getFile(player.getUniqueId()); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + writer.write(str); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + return; + } + } + + @NotNull + private PlayerConfig loadPlayer(@NotNull Player player) { + File file = getFile(player.getUniqueId()); + if (!file.exists() || !file.isFile() || !file.canRead()) + return new PlayerConfig(player.getUniqueId()); + + Gson gson = buildGson(); + PlayerConfig config = null; + try { + config = gson.fromJson(new FileReader(file), new TypeToken() { + }.getType()); + } catch (FileNotFoundException ignored) { + return new PlayerConfig(player.getUniqueId()); + } catch (JsonSyntaxException | JsonIOException e) { + e.printStackTrace(); + } + return config; + } + + private File getFile(UUID owner) { + return new File( + MovecraftRepair.getInstance().getDataFolder().getAbsolutePath() + "/userdata/" + owner + ".json"); + } + + private static Gson buildGson() { + GsonBuilder builder = new GsonBuilder(); + builder.setPrettyPrinting(); + builder.serializeNulls(); + return builder.create(); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerJoin(@NotNull PlayerJoinEvent e) { + Player player = e.getPlayer(); + var config = loadPlayer(player); + cache.put(player, config); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerQuit(@NotNull PlayerQuitEvent e) { + Player player = e.getPlayer(); + savePlayer(player); + cache.remove(player); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPluginDisable(@NotNull PluginDisableEvent e) { + if (e.getPlugin() != MovecraftRepair.getInstance()) + return; + + for (Player p : cache.keySet()) { + savePlayer(p); + } + cache.clear(); + } +} diff --git a/src/main/java/net/countercraft/movecraft/repair/commands/RepairBarCommand.java b/src/main/java/net/countercraft/movecraft/repair/commands/RepairBarCommand.java new file mode 100644 index 0000000..d3feeac --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/repair/commands/RepairBarCommand.java @@ -0,0 +1,42 @@ +package net.countercraft.movecraft.repair.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import net.countercraft.movecraft.localisation.I18nSupport; +import net.countercraft.movecraft.repair.bar.config.PlayerManager; + +import static net.countercraft.movecraft.util.ChatUtils.MOVECRAFT_COMMAND_PREFIX; + +public class RepairBarCommand implements CommandExecutor { + @NotNull + private final PlayerManager manager; + + public RepairBarCommand(@NotNull PlayerManager manager) { + this.manager = manager; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, + @NotNull String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Must Be Player")); + return true; + } + Player player = (Player) sender; + + if (!player.hasPermission("movecraft.repair.repairbar")) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Insufficient Permissions")); + return true; + } + + manager.toggleBarSetting(player); + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Command - Bar set") + ": " + manager.getBarSetting(player)); + return true; + } +} diff --git a/src/main/java/net/countercraft/movecraft/repair/commands/RepairCancelCommand.java b/src/main/java/net/countercraft/movecraft/repair/commands/RepairCancelCommand.java new file mode 100644 index 0000000..2bc2506 --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/repair/commands/RepairCancelCommand.java @@ -0,0 +1,56 @@ +package net.countercraft.movecraft.repair.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import net.countercraft.movecraft.repair.MovecraftRepair; +import net.countercraft.movecraft.repair.localisation.I18nSupport; +import net.countercraft.movecraft.repair.types.Repair; + +import static net.countercraft.movecraft.util.ChatUtils.MOVECRAFT_COMMAND_PREFIX; + +public class RepairCancelCommand implements CommandExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, + @NotNull String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Must Be Player")); + return true; + } + Player player = (Player) sender; + + if (!player.hasPermission("movecraft.repair.repaircancel")) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Insufficient Permissions")); + return true; + } + + // Find player's newest repair + Repair newest = null; + for (Repair repair : MovecraftRepair.getInstance().getRepairManager().get()) { + if (repair.getPlayerUUID() != player.getUniqueId()) + continue; + + if (newest == null || repair.getStart() < newest.getStart()) { + newest = repair; + } + } + + // No repairs + if (newest == null) { + player.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - No Repairs")); + return true; + } + + // Cancel + MovecraftRepair.getInstance().getRepairManager().cancel(newest); + player.sendMessage(I18nSupport.getInternationalisedString("Repair - Repair cancelled")); + + return true; + } +} diff --git a/src/main/java/net/countercraft/movecraft/repair/commands/RepairInventoryCommand.java b/src/main/java/net/countercraft/movecraft/repair/commands/RepairInventoryCommand.java new file mode 100644 index 0000000..cf00a52 --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/repair/commands/RepairInventoryCommand.java @@ -0,0 +1,112 @@ +package net.countercraft.movecraft.repair.commands; + +import java.util.LinkedList; +import java.util.List; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Container; +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 org.jetbrains.annotations.NotNull; + +import net.countercraft.movecraft.MovecraftLocation; +import net.countercraft.movecraft.craft.Craft; +import net.countercraft.movecraft.craft.CraftManager; +import net.countercraft.movecraft.craft.PlayerCraft; +import net.countercraft.movecraft.repair.RepairBlobManager; +import net.countercraft.movecraft.repair.localisation.I18nSupport; +import net.countercraft.movecraft.repair.types.RepairCounter; +import net.countercraft.movecraft.repair.types.blobs.RepairBlob; +import net.countercraft.movecraft.util.Tags; +import net.countercraft.movecraft.util.TopicPaginator; + +import static net.countercraft.movecraft.util.ChatUtils.MOVECRAFT_COMMAND_PREFIX; + +public class RepairInventoryCommand implements CommandExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Must Be Player")); + return true; + } + Player player = (Player) sender; + + if (!player.hasPermission("movecraft.repair.repaircancel")) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Insufficient Permissions")); + return true; + } + + PlayerCraft craft = CraftManager.getInstance().getCraftByPlayer(player); + if (craft == null) { + player.sendMessage(I18nSupport.getInternationalisedString("You must be piloting a craft")); + return true; + } + + int page = 1; // Default page + if (args.length > 0) { + try { + page = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Paginator - Invalid Page") + " \"" + args[0] + "\""); + return true; + } + } + + RepairCounter inventory = sumInventory(craft); + List keys = new LinkedList<>(inventory.getKeySet()); + keys.sort((key1, key2) -> ((int) (inventory.get(key2) - inventory.get(key1)))); + + TopicPaginator paginator = new TopicPaginator(I18nSupport.getInternationalisedString("Inventory - Inventory Header"), false); + for (RepairBlob key : keys) { + paginator.addLine(buildLine(key, inventory.get(key))); + } + + if (paginator.isEmpty()) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Inventory - Empty Craft")); + return true; + } + + if (!paginator.isInBounds(page)) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport.getInternationalisedString("Paginator - Page Number") + " " + page + " " + net.countercraft.movecraft.localisation.I18nSupport.getInternationalisedString("Paginator - Exceeds Bounds")); + return true; + } + + for (String line : paginator.getPage(page)) { + player.sendMessage(line); + } + return true; + } + + private String buildLine(RepairBlob key, double count) { + return key.getName() + ": " + String.format("%,.0f", count); + } + + private RepairCounter sumInventory(Craft craft) { + RepairCounter result = new RepairCounter(); + World world = craft.getWorld(); + for (MovecraftLocation location : craft.getHitBox()) { + Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ()); + if (!Tags.CHESTS.contains(block.getType())) + continue; + + BlockState state = block.getState(); + if (!(state instanceof Container)) + continue; + + for (ItemStack item : ((Container) state).getInventory().getContents()) { + if (item == null) + continue; + + result.add(RepairBlobManager.get(item.getType()), item.getAmount()); + } + } + return result; + } +} diff --git a/src/main/java/net/countercraft/movecraft/repair/RepairListCommand.java b/src/main/java/net/countercraft/movecraft/repair/commands/RepairListCommand.java similarity index 68% rename from src/main/java/net/countercraft/movecraft/repair/RepairListCommand.java rename to src/main/java/net/countercraft/movecraft/repair/commands/RepairListCommand.java index 3b1eb5a..cc6ad6b 100644 --- a/src/main/java/net/countercraft/movecraft/repair/RepairListCommand.java +++ b/src/main/java/net/countercraft/movecraft/repair/commands/RepairListCommand.java @@ -1,5 +1,6 @@ -package net.countercraft.movecraft.repair; +package net.countercraft.movecraft.repair.commands; +import net.countercraft.movecraft.repair.MovecraftRepair; import net.countercraft.movecraft.repair.localisation.I18nSupport; import net.countercraft.movecraft.util.TopicPaginator; import org.bukkit.command.Command; @@ -15,22 +16,26 @@ public class RepairListCommand implements CommandExecutor { @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, + @NotNull String[] args) { if (!(sender instanceof Player)) { - sender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Must Be Player")); + sender.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Must Be Player")); return true; } Player player = (Player) sender; if (!player.hasPermission("movecraft.repair.repairlist")) { - player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport.getInternationalisedString("Insufficient Permissions")); + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Insufficient Permissions")); return true; } File repairDirectory = new File(MovecraftRepair.getInstance().getDataFolder(), "RepairStates"); File playerDirectory = new File(repairDirectory, player.getUniqueId().toString()); if (!playerDirectory.exists()) { - player.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Empty Directory")); + player.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Empty Directory")); return true; } @@ -42,7 +47,8 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command try { page = Integer.parseInt(args[0]); } catch (NumberFormatException e) { - player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport.getInternationalisedString("Paginator - Invalid Page") +" \"" + args[0] + "\""); + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Paginator - Invalid Page") + " \"" + args[0] + "\""); return true; } } @@ -56,19 +62,22 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } if (pageinator.isEmpty()) { - player.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Empty Directory")); + player.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Empty Directory")); return true; } if (!pageinator.isInBounds(page)) { player.sendMessage(MOVECRAFT_COMMAND_PREFIX + - net.countercraft.movecraft.localisation.I18nSupport.getInternationalisedString("Paginator - Page Number") + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Paginator - Page Number") + " " + page + " " + - net.countercraft.movecraft.localisation.I18nSupport.getInternationalisedString("Paginator - Exceeds Bounds")); + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Paginator - Exceeds Bounds")); return true; } - for(String line : pageinator.getPage(page)) { + for (String line : pageinator.getPage(page)) { player.sendMessage(line); } diff --git a/src/main/java/net/countercraft/movecraft/repair/commands/RepairReportCommand.java b/src/main/java/net/countercraft/movecraft/repair/commands/RepairReportCommand.java new file mode 100644 index 0000000..29d34ec --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/repair/commands/RepairReportCommand.java @@ -0,0 +1,76 @@ +package net.countercraft.movecraft.repair.commands; + +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import net.countercraft.movecraft.repair.MovecraftRepair; +import net.countercraft.movecraft.repair.localisation.I18nSupport; +import net.countercraft.movecraft.repair.types.Repair; +import net.countercraft.movecraft.util.TopicPaginator; + +import static net.countercraft.movecraft.util.ChatUtils.MOVECRAFT_COMMAND_PREFIX; + +public class RepairReportCommand implements CommandExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, + @NotNull String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - Must Be Player")); + return true; + } + Player player = (Player) sender; + + if (!player.hasPermission("movecraft.repair.repairreport")) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Insufficient Permissions")); + return true; + } + + TopicPaginator pageinator = new TopicPaginator( + I18nSupport.getInternationalisedString("Repair - Ongoing Repairs")); + + int page = 1; // Default page + if (args.length > 0) { + try { + page = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Paginator - Invalid Page") + " \"" + args[0] + "\""); + return true; + } + } + + for (Repair repair : MovecraftRepair.getInstance().getRepairManager().get()) { + Player p = Bukkit.getPlayer(repair.getPlayerUUID()); + pageinator.addLine(repair.getName() + " " + (p == null ? "None" : p.getName()) + " @ " + repair.remaining() + + ", " + (repair.size() - repair.remaining()) + " / " + repair.size()); + } + + if (pageinator.isEmpty()) { + player.sendMessage( + MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Repair - No Repairs")); + return true; + } + + if (!pageinator.isInBounds(page)) { + player.sendMessage(MOVECRAFT_COMMAND_PREFIX + + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Paginator - Page Number") + + " " + page + " " + + net.countercraft.movecraft.localisation.I18nSupport + .getInternationalisedString("Paginator - Exceeds Bounds")); + return true; + } + + for (String line : pageinator.getPage(page)) { + player.sendMessage(line); + } + + return true; + } +} diff --git a/src/main/java/net/countercraft/movecraft/repair/config/Config.java b/src/main/java/net/countercraft/movecraft/repair/config/Config.java index 481cf63..72dc606 100644 --- a/src/main/java/net/countercraft/movecraft/repair/config/Config.java +++ b/src/main/java/net/countercraft/movecraft/repair/config/Config.java @@ -17,6 +17,7 @@ public class Config { public static double RepairMoneyPerBlock = 0.0; public static double RepairMaxPercent = 50.0; public static Material RepairTool = Material.FIREWORK_ROCKET; + public static boolean DisableDoubleClick = false; public static Set RepairDispenserItems = EnumSet.noneOf(Material.class); public static Set RepairFurnaceItems = EnumSet.noneOf(Material.class); public static Set RepairDropperItems = EnumSet.noneOf(Material.class); diff --git a/src/main/java/net/countercraft/movecraft/repair/events/RepairCancelledEvent.java b/src/main/java/net/countercraft/movecraft/repair/events/RepairCancelledEvent.java new file mode 100644 index 0000000..b642c25 --- /dev/null +++ b/src/main/java/net/countercraft/movecraft/repair/events/RepairCancelledEvent.java @@ -0,0 +1,9 @@ +package net.countercraft.movecraft.repair.events; + +import net.countercraft.movecraft.repair.types.Repair; + +public class RepairCancelledEvent extends RepairEvent { + public RepairCancelledEvent(Repair repair) { + super(repair); + } +} diff --git a/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java b/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java index 368c3c5..bc0e9bf 100644 --- a/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java +++ b/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java @@ -48,11 +48,11 @@ public class RepairState { private BlockVector3 schematicSignOffset; private BlockVector3 size; - public RepairState(UUID plauerUUID, String name) throws IOException, IllegalStateException { - this.playerUUID = plauerUUID; + public RepairState(UUID playerUUID, String name) throws IOException, IllegalStateException { + this.playerUUID = playerUUID; this.name = name; File dataDirectory = new File(MovecraftRepair.getInstance().getDataFolder(), "RepairStates"); - File playerDirectory = new File(dataDirectory, plauerUUID.toString()); + File playerDirectory = new File(dataDirectory, playerUUID.toString()); if (!playerDirectory.exists() && !playerDirectory.mkdirs()) throw new IllegalStateException("Unable to create player directory"); diff --git a/src/main/java/net/countercraft/movecraft/repair/util/WEUtils.java b/src/main/java/net/countercraft/movecraft/repair/util/WEUtils.java index 4ef43f2..8b27fdc 100644 --- a/src/main/java/net/countercraft/movecraft/repair/util/WEUtils.java +++ b/src/main/java/net/countercraft/movecraft/repair/util/WEUtils.java @@ -57,15 +57,15 @@ public class WEUtils { /** * Load a schematic from disk - * + * * @param directory Directory for the schematic file * @param name Name of the schematic file (without the extension) * @return A clipboard containing the schematic * @throws FileNotFoundException Schematic file not found - * @throws IOException + * @throws IOException Other I/O exception */ @Nullable - public static Clipboard loadSchematic(File directory, String name) throws IOException { + public static Clipboard loadSchematic(File directory, String name) throws FileNotFoundException, IOException { name += "." + SCHEMATIC_FORMAT.getPrimaryFileExtension(); File file = new File(directory, name); Clipboard clipboard; @@ -82,7 +82,7 @@ public static Clipboard loadSchematic(File directory, String name) throws IOExce /** * Save a schematic from a craft - * + * * @param craft The craft to save * @return true on success */ @@ -147,7 +147,7 @@ private static Set getWorldEditBlocks(@NotNull HitBox hitbox, @NotNul /** * Get the contents of a WorldEdit block - * + * * @param block block to check * @return Counter of the materials in the block */ @@ -193,7 +193,7 @@ private static Material getMaterial(String str) { /** * Get the sign contents of a WorldEdit block - * + * * @param block block to check * @return Array of sign lines in the block */ @@ -211,33 +211,43 @@ public static String[] getBlockSignLines(BaseBlock block) { return result; } - private static String[] TEXT_STYLES = { "bold", "italic", "underline", "strikethrough" }; + private static final String[] TEXT_STYLES = {"bold", "italic", "underline", "strikethrough"}; private static String getSignTextFromJSON(String json) { - Gson gson = new Gson(); - Map lineData = gson.fromJson(json, Map.class); - String result = ""; - result += getSignTextFromMap(lineData); - if (!lineData.containsKey("extra")) - return result; + try { + Gson gson = new Gson(); + Map lineData = gson.fromJson(json, Map.class); + String result = ""; + if (lineData == null) + return result; - Object extrasObject = lineData.get("extra"); - if (!(extrasObject instanceof List)) - return result; + result += getSignTextFromMap(lineData); + if (!lineData.containsKey("extra")) + return result; - List extras = (List) extrasObject; - StringBuilder builder = new StringBuilder(); - for (Object componentObject : extras) { - if (!(componentObject instanceof Map)) - continue; + Object extrasObject = lineData.get("extra"); + if (!(extrasObject instanceof List)) + return result; + + List extras = (List) extrasObject; + StringBuilder builder = new StringBuilder(); + for (Object componentObject : extras) { + if (!(componentObject instanceof Map)) + continue; - builder.append(getSignTextFromMap((Map) componentObject)); + builder.append(getSignTextFromMap((Map) componentObject)); + } + result += builder.toString(); + + return result; + } catch (Exception e) { + MovecraftRepair.getInstance().getLogger().severe("Got exception when parsing '" + json + "'"); + e.printStackTrace(); + return ""; } - result += builder.toString(); - return result; } - private static String getSignTextFromMap(Map component) { + private static @NotNull String getSignTextFromMap(@NotNull Map component) { StringBuilder builder = new StringBuilder(); if (component.containsKey("color")) { builder.append(ChatColor.valueOf(((String) component.get("color")).toUpperCase())); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b73ecf4..128d064 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -5,7 +5,9 @@ RepairMaxTickTime: 5000000 # Maximum time spent per tick, in nanoseconds RepairMoneyPerBlock: 10 RepairMaxPercent: 50 RepairTool: "firework_rocket" -RepairBlobs: # "Blobs" of materials which can be used interchangably to repair +DisableDoubleClick: false # Disable a double click being required to save a repair +RepairBlobs: # "Blobs" of materials which can be used interchangeably to repair + - ["cauldron", "water_cauldron"] - "#chests" - "#concrete" - "#concrete_powder" diff --git a/src/main/resources/localisation/mc-repairlang_en.properties b/src/main/resources/localisation/mc-repairlang_en.properties index 73cde91..aab30aa 100644 --- a/src/main/resources/localisation/mc-repairlang_en.properties +++ b/src/main/resources/localisation/mc-repairlang_en.properties @@ -1,4 +1,5 @@ Repair\ -\ Repairs\ underway=Repairs underway +Repair\ -\ Repair\ cancelled=Repair cancelled Repair\ -\ Could\ not\ save\ file=Could not save file Repair\ -\ State\ saved=State saved Repair\ -\ State\ not\ found=REPAIR STATE NOT FOUND @@ -12,6 +13,11 @@ Repair\ -\ Seconds\ to\ complete\ repair=Seconds to complete repair Repair\ -\ Money\ to\ complete\ repair=Money to complete repair Repair\ -\ Empty\ Directory=You currently have no saved states. Repair\ -\ Saved\ States=Saved States +Repair\ -\ Ongoing\ Repairs=Ongoing repairs +Repair\ -\ No\ Repairs=None found Repair\ -\ Must\ Be\ Player=You must be a player to check the list of saved states. +Command\ -\ Bar\ Set=Repair Bar now set to Economy\ -\ Not\ Enough\ Money=You do not have enough money -You\ must\ be\ piloting\ a\ craft=You must be piloting a craft +Inventory\ -\ Inventory\ Header=Inventory +Inventory\ -\ Empty\ Craft=Your craft has no items in it's inventory. +You\ must\ be\ piloting\ a\ craft=You must be piloting a craft \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index caa1aa5..086a72f 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -7,6 +7,18 @@ authors: [TylerS1066, cccm5, BaccaYarro] website: https://github.com/APDevTeam/Movecraft-Repair main: net.countercraft.movecraft.repair.MovecraftRepair commands: + repairbar: + description: Toggle the repair bar feature + permission: movecraft.repair.repairbar + repaircancel: + description: Cancel an ongoing repair state + permission: movecraft.repair.repaircancel + repairinventory: + description: Check the inventory of your craft + permission: movecraft.repair.repairinventory repairlist: description: List saved repair states - permission: movecraft.repair.repairlist \ No newline at end of file + permission: movecraft.repair.repairlist + repairreport: + description: List ongoing repair states + permission: movecraft.repair.repairreport