diff --git a/build.gradle b/build.gradle index 85d1028..5b9e362 100644 --- a/build.gradle +++ b/build.gradle @@ -15,18 +15,18 @@ repositories { } dependencies { - compileOnly paper('1.18.2-R0.1-SNAPSHOT') + compileOnly paper('1.19.2-R0.1-SNAPSHOT') implementation 'co.aikar:acf-paper:0.5.1-SNAPSHOT' // implementation 'co.aikar:taskchain-bukkit:3.7.2' } group = 'eu.zhincore.chestnetworks' -version = '1.0-SNAPSHOT' +version = '1.1-SNAPSHOT' description = 'chestnetworks' spigot { authors 'Zhincore' - apiVersion '1.18' + apiVersion '1.19' excludeLibraries('acf-paper') } @@ -43,7 +43,7 @@ compileJava { } java { - toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + toolchain.languageVersion.set(JavaLanguageVersion.of(18)) } build.dependsOn shadowJar diff --git a/old/ChestNetController.java b/old/ChestNetController.java new file mode 100644 index 0000000..ddeda85 --- /dev/null +++ b/old/ChestNetController.java @@ -0,0 +1,273 @@ +package eu.zhincore.chestnetworks; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import eu.zhincore.chestnetworks.network.Database; + +public class ChestNetController { + private HashMap playerSelectQueue = new HashMap<>(); + private ChestNetworksPlugin plugin; + private Database database; + private ChestNetSorter sorter; + private JsonObject players; + + public ChestNetController(ChestNetworksPlugin plugin) { + this.plugin = plugin; + database = new Database(plugin); + sorter = new ChestNetSorter(plugin); + players = (JsonObject) database.data; + } + + public Boolean isPlayerSelectQueue(Player player) { + String playerId = player.getUniqueId().toString(); + return playerSelectQueue.has(playerId); + } + + public void cancelPlayerSelect(Player player) { + String playerId = player.getUniqueId().toString(); + if (playerSelectQueue.has(playerId)) { + playerSelectQueue.remove(playerId); + plugin.messenger.send("selrmvd", player); + return; + } + plugin.messenger.send("selrmnt", player); + } + + public void list(Player player) { + List nets = listNets(player); + if (nets != null && nets.size() > 0) { + plugin.messenger.send("netlist", player, String.join(", ", nets)); + } else { + plugin.messenger.send("nlistnt", player); + } + } + + public List listNets(Player player) { + String playerId = player.getUniqueId().toString(); + return listNets(playerId); + } + + @SuppressWarnings("unchecked") + public List listNets(String playerId) { + if (players.has(playerId)) { + return new ArrayList(((JsonObject) players.get(playerId)).keySet()); + } + return null; + } + + public List listChests(Player player, String name) { + String playerId = player.getUniqueId().toString(); + return listChests(playerId, name); + } + + @SuppressWarnings("unchecked") + public List listChests(String playerId, String netName) { + if (players.has(playerId)) { + JsonObject network = (JsonObject) players.get(playerId); + if (network.has(netName)) { + var chests = network.getAsJsonArray(netName); + + // Add info to each chest, used when referencing the network + for (var chest : chests) { + chest.addProperty("owner", playerId); + chest.addProperty("network", netName); + } + return chests; + } + } + return null; + } + + @SuppressWarnings("unchecked") + public List listGlobalChests() { + List playerIds = new ArrayList<>(players.keySet()); + List outaddProperty = new ArrayList<>(); + for (String playerId : playerIds) { + for (String networkName : listNets(playerId)) { + outaddProperty.addAll(listChests(playerId, networkName)); + } + } + return outaddProperty; + } + + @SuppressWarnings("unchecked") + public List listGlobalChestLocations() { + List playerIds = new ArrayList<>(players.keySet()); + List outaddProperty = new ArrayList<>(); + for (String playerId : playerIds) { + for (String networkName : listNets(playerId)) { + outaddProperty.addAll(listChests(playerId, networkName).stream() + .map(v -> ((Location) Database.jsonToLoc((JsonObject) v.get("location")))).collect(Collectors.toList())); + } + } + return outaddProperty; + } + + public void delete(Player player, String name) { + String playerId = player.getUniqueId().toString(); + if (players.has(playerId)) { + JsonObject networks = (JsonObject) players.get(playerId); + if (networks.has(name)) { + networks.remove(name); + plugin.messenger.send("cnetdel", player, name); + database.save(); + return; + } + } + } + + @SuppressWarnings("unchecked") + public void create(Player player, String name) { + String playerId = player.getUniqueId().toString(); + if (!players.has(playerId)) { + players.addProperty(playerId, new JsonObject()); + } + JsonObject networks = (JsonObject) players.get(playerId); + if (networks.has(name)) { + plugin.messenger.send("cnet409", player, name); + return; + } + + networks.addProperty(name, new JsonArray()); + if (database.save()) { + plugin.messenger.send("created", player, name); + } else { + plugin.messenger.send("dberror", player); + } + + } + + public void startAddChest(Player player, String name, String type, List content) { + String playerId = player.getUniqueId().toString(); + if (!players.has(playerId)) { + plugin.messenger.send("cnet404", player, name); + return; + } + JsonObject networks = (JsonObject) players.get(playerId); + if (!networks.has(name)) { + plugin.messenger.send("cnet404", player, name); + return; + } + + if (playerSelectQueue.has(playerId)) { + // Already selecting a chest + plugin.messenger.send("cnet425", player); + return; + } + + startPlayerSelect(player, new String[] { "add", name, type, String.join(",", content) }); + } + + public void startCheckChest(Player player) { + startPlayerSelect(player, new String[] { "check" }); + } + + private void startPlayerSelect(Player player, String[] data) { + String playerId = player.getUniqueId().toString(); + playerSelectQueue.add(playerId, data); + plugin.messenger.send("selectc", player); + } + + public void onPlayerSelected(Player player, Location loc) { + String playerId = player.getUniqueId().toString(); + if (!playerSelectQueue.has(playerId)) return; + String[] playerData = playerSelectQueue.remove(playerId); + switch (playerData[0]) { + case "add": + addChest(player, loc, playerData); + break; + case "check": + checkChest(player, loc); + break; + } + } + + @SuppressWarnings("unchecked") + private void addChest(Player player, Location loc, String[] playerData) { + String playerId = player.getUniqueId().toString(); + JsonObject jsonLoc = (JsonObject) Database.locToJson(loc); + JsonArray network = (JsonArray) ((JsonObject) players.get(playerId)).get(playerData[1]); + Inventory inv = getChestByLoc(loc).getInventory(); + + // Detect is this chest is already registered + Chest registeredChest = getRegisteredChest(inv); + if (registeredChest != null) { + JsonObject chestData = getChestData(registeredChest.getLocation()); + network.remove(chestData); + } + + JsonObject chest = new JsonObject(); + chest.add("location", jsonLoc); + chest.addProperty("type", playerData[2]); + JsonArray content = new JsonArray(); + content.addAll((List) Arrays.asList(playerData[3].toUpperCase().split(","))); + content.removeIf(v -> v.equals("")); + chest.addProperty("content", content); + network.add(chest); + database.save(); + plugin.messenger.send("chadded", player, playerData[1]); + update(inv); + } + + @SuppressWarnings("unchecked") + private void checkChest(Player player, Location loc) { + Chest registeredChest = getRegisteredChest(getChestByLoc(loc).getInventory()); + if (registeredChest == null) { + plugin.messenger.send("ccecknt", player); + return; + } + JsonObject chestData = getChestData(registeredChest.getLocation()); + String type = (String) chestData.get("type"); + JsonArray content = (JsonArray) chestData.get("content"); + plugin.messenger.send("chcheck", player, (String) chestData.get("network"), (String) chestData.get("owner"), type, + type.equals("inaddProperty") ? "N/A" + : content.size() == 0 ? "§oEverything§r" : (String) String.join(", ", content)); + } + + public JsonObject getChestData(Location loc) { + for (Object chest : listGlobalChests()) { + if (Database.jsonToLoc((JsonObject) ((JsonObject) chest).get("location")).equals(loc)) { + return (JsonObject) chest; + } + } + return null; + } + + public void removeChest(Location loc, Player player) { + JsonObject chest = getChestData(loc); + if (chest == null) return; + ((JsonArray) ((JsonObject) players.get(chest.get("owner"))).get(chest.get("network"))).remove(chest); + if (player != null) { + plugin.messenger.send("chesrem", (CommandSender) player, (String) chest.get("network")); + } + database.save(); + } + + public void setSorting(String playerId, String netName, boolean enabled) { + JsonArray network = (JsonArray) ((JsonObject) players.get(playerId)).get(netName); + for (Object chestDatai : network) { + JsonObject chestData = (JsonObject) chestDatai; + if (enabled) chestData.addProperty("sort", true); + else chestData.remove("sort"); + } + database.save(); + // update() + } + +} diff --git a/old/ChestNetListener.java b/old/ChestNetListener.java new file mode 100644 index 0000000..d842c26 --- /dev/null +++ b/old/ChestNetListener.java @@ -0,0 +1,65 @@ +package eu.zhincore.chestnetworks; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.Event; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryMoveItemEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; + +public class ChestNetListener implements Listener { + private ChestNetController networkController; + + public ChestNetListener(ChestNetController networkController) { + this.networkController = networkController; + } + + @EventHandler + public void onInteract(PlayerInteractEvent ev) { + Block block = ev.getClickedBlock(); + Player player = ev.getPlayer(); + + if (ev.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (block.getType() == Material.CHEST) { + if (networkController.isPlayerSelectQueue(player)) { + ev.setUseInteractedBlock(Event.Result.DENY); + networkController.onPlayerSelected(player, block.getLocation()); + } + } + } + } + + @EventHandler + public void onBlockBreakEvent(BlockBreakEvent ev) { + Block block = ev.getBlock(); + Player player = ev instanceof BlockBreakEvent ? ((BlockBreakEvent) ev).getPlayer() : null; + if (block.getType() == Material.CHEST) { + networkController.removeChest(block.getLocation(), player); + } + } + + @EventHandler + public void onInventoryCloseEvent(InventoryCloseEvent ev) { + onInventoryUpdate(ev.getInventory()); + } + + @EventHandler + public void onInventoryMoveItemEvent(InventoryMoveItemEvent ev) { + onInventoryUpdate(ev.getDestination()); + } + + private void onInventoryUpdate(Inventory inv) { + if (inv.getViewers().size() != 1 || inv.getType() != InventoryType.CHEST) { + return; + } + + networkController.update(inv); + } +} diff --git a/old/ChestNetMessenger.java b/old/ChestNetMessenger.java new file mode 100644 index 0000000..8b58be1 --- /dev/null +++ b/old/ChestNetMessenger.java @@ -0,0 +1,41 @@ +package eu.zhincore.chestnetworks; + +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; +import org.bukkit.command.CommandSender; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +public class ChestNetMessenger { + private static final String prefix = "§b[§2ChestNetworks§b]§r "; + private JSONObject messages; + private JSONParser parser = new JSONParser(); + + public ChestNetMessenger(Reader messagesRaw) throws IOException, ParseException { + messages = (JSONObject) parser.parse(messagesRaw); + } + + String[] getMessage(String key, String... params) { + JSONArray jsonmessages = ((JSONArray) this.messages.get(key)); + List messages = new ArrayList<>(); + // fill place-holders + for (Object jsonmessage : jsonmessages) { + String message = (String) jsonmessage; + for (String param : params) { + message = message.replaceFirst("%s", param); + } + messages.add(message); + } + return messages.toArray(String[]::new); + } + + void send(String key, CommandSender target, String... params) { + var message = getMessage(key, params); + + target.sendMessage(prefix + String.join("\n", message)); + } +} diff --git a/old/ChestNetSorter.java b/old/ChestNetSorter.java new file mode 100644 index 0000000..03ced29 --- /dev/null +++ b/old/ChestNetSorter.java @@ -0,0 +1,49 @@ +package eu.zhincore.chestnetworks; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class ChestNetSorter { + private static final Comparator defaultComparator = new Comparator<>() { + public int compare(ItemStack stack1, ItemStack stack2) { + int materialOrder = stack1.getType().compareTo(stack2.getType()); + return materialOrder == 0 ? stack1.getAmount() - stack2.getAmount() : materialOrder; + } + }; + + public static void sortInventories(Inventory... inventories) { + var contents = new ArrayList(); + for (var inventory : inventories) { + for (var stack : inventory.getContents()) { + if (stack != null) contents.add(stack); + } + inventory.clear(); + } + + Collections.sort(contents, defaultComparator); + + int i = 0; + int leftItems = contents.size(); + + for (var inventory : inventories) { + int size = inventory.getSize(); + if (leftItems < size) size = leftItems; + + inventory.addItem(contents.subList(i, size).toArray(new ItemStack[0])); + + leftItems -= size; + if (leftItems <= 0) break; + } + } + + // private void sortInventoriesAsync(Inventory... inventories) { + + // taskChain.newChain().async(() -> Collections.sort(contents, + // defaultComparator)).sync(() -> { + + // }); + // } +} diff --git a/old/ChestNetUtils.java b/old/ChestNetUtils.java new file mode 100644 index 0000000..24c9ba9 --- /dev/null +++ b/old/ChestNetUtils.java @@ -0,0 +1,31 @@ +package eu.zhincore.chestnetworks; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +public class ChestNetUtils { + public static Chest getChestByLocation(Location location) { + Block target = location.getBlock(); + if (target.getType() == Material.CHEST) { + return (Chest) target.getState(); + } + return null; + } + + public static Chest[] getChests(Inventory inventory) { + InventoryHolder holder = inventory.getHolder(); + if (holder instanceof DoubleChest) { + DoubleChest doubleChest = ((DoubleChest) holder); + return new Chest[] { (Chest) doubleChest.getLeftSide(), (Chest) doubleChest.getRightSide() }; + } else if (holder instanceof Chest) { + return new Chest[] { (Chest) holder }; + } + return null; + } + +} diff --git a/old/ChestNetworksPlugin.java b/old/ChestNetworksPlugin.java new file mode 100644 index 0000000..bdd6f49 --- /dev/null +++ b/old/ChestNetworksPlugin.java @@ -0,0 +1,30 @@ +package eu.zhincore.chestnetworks; + +import java.io.IOException; +import org.bukkit.plugin.java.JavaPlugin; +import org.json.simple.parser.ParseException; + +public class ChestNetworksPlugin extends JavaPlugin { + public ChestNetMessenger messenger; + private ChestNetController networksController; + + @Override + public void onEnable() { + try { + messenger = new ChestNetMessenger(getTextResource("messages.json")); + } catch (IOException | ParseException e) { + e.printStackTrace(); + getServer().getPluginManager().disablePlugin(this); + return; + } + networksController = new ChestNetController(this); + getCommand("chestnet").setExecutor(new CommandChestNet(this, networksController)); + getCommand("chestnet").setTabCompleter(new CommandChestNetTabCompleter(networksController)); + getServer().getPluginManager().registerEvents(new ChestNetListener(networksController), this); + } + + @Override + public void onDisable() { + networksController = null; + } +} diff --git a/old/CommandChestNet.java b/old/CommandChestNet.java new file mode 100644 index 0000000..fb2246d --- /dev/null +++ b/old/CommandChestNet.java @@ -0,0 +1,106 @@ +package eu.zhincore.chestnetworks; + +import java.util.Arrays; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class CommandChestNet implements CommandExecutor { + private ChestNetController networksController; + private ChestNetworksPlugin plugin; + + public CommandChestNet(ChestNetworksPlugin plugin, ChestNetController networksController) { + this.networksController = networksController; + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(String.format("[%s] This command can be only used by player.", label)); + return true; + } + + if (args.length < 1) return false; + + // Sanitize arguments + for (int i = args.length - 1; i != 0; i--) { + args[i] = args[i].replace("\\", "\\\\"); + } + + // Sub-commands + switch (args[0]) { + case "h": + case "help": + plugin.messenger.send("helpmsg", (Player) sender, command.getName(), String.join(", ", command.getAliases())); + break; + + case "c": + case "create": + if (args.length < 2) { + sender.sendMessage(ChatColor.GOLD + "Use: " + ChatColor.RED + "/" + label + " create "); + return true; + } + networksController.create((Player) sender, args[1]); + break; + + case "deleteNetwork": + if (args.length < 2) { + sender.sendMessage(ChatColor.GOLD + "Use: " + ChatColor.RED + "/" + label + " delete "); + return true; + } + networksController.delete((Player) sender, args[1]); + break; + + case "setChest": + case "addChest": + if (args.length < 3 || !(args[2].equals("storage") || args[2].equals("input"))) { + sender.sendMessage(ChatColor.GOLD + "Use: " + ChatColor.RED + "/" + label + + " addChest [contents...]"); + return true; + } + networksController.startAddChest((Player) sender, args[1], args[2], + Arrays.asList(args).subList(3, args.length)); + break; + + case "list": + case "listNets": + case "listNetworks": + networksController.list((Player) sender); + break; + + case "listChests": + // TODO + break; + + case "sorting": + if (args.length < 3) { + sender.sendMessage( + ChatColor.GOLD + "Use: " + ChatColor.RED + "/" + label + " sorting "); + return true; + } + var enabled = args[2].equalsIgnoreCase("on"); + networksController.setSorting(((Player) sender).getUniqueId().toString(), args[1], enabled); + sender.sendMessage("Sorting changed"); + break; + + case "check": + case "checkChest": + networksController.startCheckChest((Player) sender); + break; + + case "cancel": + case "cancelSelect": + networksController.cancelPlayerSelect((Player) sender); + break; + + default: + return false; + } + + return true; + } + +} diff --git a/old/CommandChestNetTabCompleter.java b/old/CommandChestNetTabCompleter.java new file mode 100644 index 0000000..d0553e6 --- /dev/null +++ b/old/CommandChestNetTabCompleter.java @@ -0,0 +1,67 @@ +package eu.zhincore.chestnetworks; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +public class CommandChestNetTabCompleter implements TabCompleter { + private ChestNetController networksController; + + public CommandChestNetTabCompleter(ChestNetController networksController) { + this.networksController = networksController; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + if (networksController.isPlayerSelectQueue((Player) sender)) { + return Arrays.asList(new String[] { "cancelSelect" }); + } else if (args.length == 1) { + return Arrays.asList( + new String[] { "help", "create", "deleteNetwork", "addChest", "setChest", "list", "checkChest", "sorting" }); + } else { + switch (args[0]) { + case "create": + case "deleteNetwork": + if (args.length == 2) { + return Arrays.asList(new String[] { "" }); + } + return new ArrayList<>(); + case "sorting": + if (args.length == 2) return getNets((Player) sender); + if (args.length == 3) return Arrays.asList(new String[] { "on", "off" }); + return new ArrayList<>(); + case "setChest": + case "addChest": + if (args.length == 2) { + return getNets((Player) sender); + } else if (args.length == 3) { + return Arrays.asList(new String[] { "input", "storage" }); + } else if (args[2].equals("storage")) { + return getMaterials(args[3]); + } + return new ArrayList<>(); + default: + return new ArrayList<>(); + } + } + } + + private List getNets(Player sender) { + return networksController.listNets((Player) sender); + } + + private List getMaterials(String query) { + List names = new ArrayList<>(); + for (Material material : Material.values()) { + if (material.name().toUpperCase().startsWith(query.toUpperCase())) { + names.add(material.name()); + } + } + return names; + } +} diff --git a/src/main/resources/messages.json b/old/messages.json similarity index 100% rename from src/main/resources/messages.json rename to old/messages.json diff --git a/src/main/java/eu/zhincore/chestnetworks/ChestNetCommand.java b/src/main/java/eu/zhincore/chestnetworks/ChestNetCommand.java index ecc6ac6..7f7c13b 100644 --- a/src/main/java/eu/zhincore/chestnetworks/ChestNetCommand.java +++ b/src/main/java/eu/zhincore/chestnetworks/ChestNetCommand.java @@ -6,7 +6,7 @@ import co.aikar.commands.PaperCommandManager; import co.aikar.commands.annotation.*; import co.aikar.locales.MessageKey; -import eu.zhincore.chestnetworks.networks.ChestNetworkManager; +import eu.zhincore.chestnetworks.networks.ChestNetworksManager; @CommandAlias("cnet|chestnet|chestnetworks") @CommandPermission("chestnetworks.command") @@ -15,14 +15,14 @@ public class ChestNetCommand extends BaseCommand { private PaperCommandManager cmdManager; @Dependency - private ChestNetworkManager networkManager; + private ChestNetworksManager networkManager; @Subcommand("list") public void list(Player player) { var networks = networkManager.listNetworks(player.getUniqueId()); if (networks.isEmpty()) { - cmdManager.sendMessage(player, MessageType.ERROR, MessageKey.of("chestnet.no_networks")); + cmdManager.sendMessage(player, MessageType.INFO, MessageKey.of("chestnet.no_networks")); } else { var replacements = new String[] { "{networks}", String.join(", ", networks) }; cmdManager.sendMessage(player, MessageType.INFO, MessageKey.of("chestnet.list"), replacements); diff --git a/src/main/java/eu/zhincore/chestnetworks/ChestNetListener.java b/src/main/java/eu/zhincore/chestnetworks/ChestNetListener.java index 8fdba13..6866bb5 100644 --- a/src/main/java/eu/zhincore/chestnetworks/ChestNetListener.java +++ b/src/main/java/eu/zhincore/chestnetworks/ChestNetListener.java @@ -1,8 +1,9 @@ package eu.zhincore.chestnetworks; +import java.util.ArrayList; import java.util.HashMap; import java.util.UUID; -import org.bukkit.Location; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerInteractEvent; @@ -68,7 +69,24 @@ public void onPlayerInteract(PlayerInteractEvent ev) { cmdManager.sendMessage(player, MessageType.ERROR, MessageKey.of("chestnet.chest_not_exists")); return; } - cmdManager.sendMessage(player, MessageType.ERROR, MessageKey.of("chestnet.chest_info"), "network"); + + var replacements = new ArrayList(); + + replacements.add("network"); + replacements.add(chestData.network.name); + + var owner = Bukkit.getOfflinePlayer(chestData.network.owner); + replacements.add("owner"); + replacements.add(owner == null ? "unknown" : owner.getName()); + + replacements.add("type"); + replacements.add(chestData.type.toString()); + + replacements.add("content"); + replacements.add(chestData.content.toString()); + + cmdManager.sendMessage(player, MessageType.ERROR, MessageKey.of("chestnet.chest_info"), + replacements.toArray(new String[0])); break; } } diff --git a/src/main/java/eu/zhincore/chestnetworks/ChestNetworksPlugin.java b/src/main/java/eu/zhincore/chestnetworks/ChestNetworksPlugin.java index 44d9026..e9d568b 100644 --- a/src/main/java/eu/zhincore/chestnetworks/ChestNetworksPlugin.java +++ b/src/main/java/eu/zhincore/chestnetworks/ChestNetworksPlugin.java @@ -10,7 +10,7 @@ import com.google.common.collect.Lists; import co.aikar.commands.MessageType; import co.aikar.commands.PaperCommandManager; -import eu.zhincore.chestnetworks.networks.ChestNetworkManager; +import eu.zhincore.chestnetworks.networks.ChestNetworksManager; public class ChestNetworksPlugin extends JavaPlugin { public Database database; @@ -24,12 +24,12 @@ public void onEnable() { // Initialize ACF commandManager = new PaperCommandManager(this); - commandManager.enableUnstableAPI("help"); + // commandManager.enableUnstableAPI("help"); commandManager.usePerIssuerLocale(false); commandManager.setFormat(MessageType.INFO, 1, ChatColor.GREEN); commandManager.registerDependency(PaperCommandManager.class, commandManager); - commandManager.registerDependency(ChestNetworkManager.class, database.networkManager); + commandManager.registerDependency(ChestNetworksManager.class, database.networkManager); // Initialize ACF locales var locales = commandManager.getLocales(); @@ -62,5 +62,7 @@ public boolean loadInternalYamlLanguageFile(String name, Locale locale) @Override public void onDisable() { + database = null; + commandManager = null; } } diff --git a/src/main/java/eu/zhincore/chestnetworks/Database.java b/src/main/java/eu/zhincore/chestnetworks/Database.java index d08f4d4..bbe0ca3 100644 --- a/src/main/java/eu/zhincore/chestnetworks/Database.java +++ b/src/main/java/eu/zhincore/chestnetworks/Database.java @@ -6,20 +6,18 @@ import java.io.InputStreamReader; import java.io.Reader; import org.bukkit.Location; -import com.google.common.collect.HashBasedTable; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import eu.zhincore.chestnetworks.networks.ChestNetworkManager; +import eu.zhincore.chestnetworks.networks.ChestNetworksManager; import eu.zhincore.chestnetworks.util.BukkitLocationSerializer; -import eu.zhincore.chestnetworks.util.ChestNetworksPluginSerializer; -import eu.zhincore.chestnetworks.util.HashBasedTableSerializer; +import eu.zhincore.chestnetworks.util.ChestNetworksManagerSerializer; import eu.zhincore.chestnetworks.util.SchedulableTask; public class Database { private File file; private Gson gson; public ChestNetworksPlugin plugin; - public ChestNetworkManager networkManager; + public ChestNetworksManager networkManager; private SchedulableTask saveTask; public Database(ChestNetworksPlugin plugin) { @@ -27,24 +25,23 @@ public Database(ChestNetworksPlugin plugin) { saveTask = new SchedulableTask(plugin, () -> this.save()); file = new File(plugin.getDataFolder(), "data.json"); gson = new GsonBuilder().enableComplexMapKeySerialization() - .registerTypeAdapter(ChestNetworksPlugin.class, new ChestNetworksPluginSerializer(plugin)) - .registerTypeAdapter(HashBasedTable.class, new HashBasedTableSerializer()) + .registerTypeAdapter(ChestNetworksManager.class, new ChestNetworksManagerSerializer(plugin)) .registerTypeAdapter(Location.class, new BukkitLocationSerializer()).create(); } - public ChestNetworkManager load() { + public ChestNetworksManager load() { try { if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } if (file.exists()) { Reader reader = new InputStreamReader(new FileInputStream(file), "UTF-8"); - return networkManager = gson.fromJson(reader, ChestNetworkManager.class); + return networkManager = gson.fromJson(reader, ChestNetworksManager.class); } } catch (Exception ex) { ex.printStackTrace(); } - return networkManager = new ChestNetworkManager(plugin); + return networkManager = new ChestNetworksManager(plugin); } public void scheduleSave() { diff --git a/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetwork.java b/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetwork.java index 668b87f..b340fee 100644 --- a/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetwork.java +++ b/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetwork.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.UUID; import org.bukkit.inventory.ItemStack; import com.google.common.collect.ArrayListMultimap; import eu.zhincore.chestnetworks.ChestNetworksPlugin; @@ -11,6 +12,8 @@ import eu.zhincore.chestnetworks.util.SchedulableTask; public class ChestNetwork { + public transient String name; + public transient UUID owner; public boolean sort = true; public List chests = new ArrayList<>(); private ChestNetworksPlugin plugin; @@ -18,6 +21,10 @@ public class ChestNetwork { private transient ArrayListMultimap, NetworkChest> indexByContent = ArrayListMultimap.create(); private transient SchedulableTask indexingTask = new SchedulableTask(plugin, () -> this.rebuildIndex(), true); + public ChestNetwork(ChestNetworksPlugin plugin) { + this.plugin = plugin; + } + public void addChest(NetworkChest chest) { chests.add(chest); indexingTask.schedule(); diff --git a/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetworkManager.java b/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetworksManager.java similarity index 87% rename from src/main/java/eu/zhincore/chestnetworks/networks/ChestNetworkManager.java rename to src/main/java/eu/zhincore/chestnetworks/networks/ChestNetworksManager.java index 20adee5..697219f 100644 --- a/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetworkManager.java +++ b/src/main/java/eu/zhincore/chestnetworks/networks/ChestNetworksManager.java @@ -10,11 +10,11 @@ import com.google.common.collect.ImmutableSet; import eu.zhincore.chestnetworks.ChestNetworksPlugin; -public class ChestNetworkManager { - private HashBasedTable networks = HashBasedTable.create(); +public class ChestNetworksManager { + public HashBasedTable networks = HashBasedTable.create(); private ChestNetworksPlugin plugin; - public ChestNetworkManager(ChestNetworksPlugin plugin) { + public ChestNetworksManager(ChestNetworksPlugin plugin) { this.plugin = plugin; } @@ -30,7 +30,12 @@ public Set listNetworks(UUID playerId) { public boolean create(UUID playerId, String netName) { var playerNets = networks.row(playerId.toString()); if (playerNets.containsKey(netName)) return false; - playerNets.put(netName, new ChestNetwork()); + + var net = new ChestNetwork(plugin); + net.name = netName; + net.owner = playerId; + playerNets.put(netName, net); + plugin.database.scheduleSave(); return true; } diff --git a/src/main/java/eu/zhincore/chestnetworks/util/ChestNetworksManagerSerializer.java b/src/main/java/eu/zhincore/chestnetworks/util/ChestNetworksManagerSerializer.java new file mode 100644 index 0000000..c4d3689 --- /dev/null +++ b/src/main/java/eu/zhincore/chestnetworks/util/ChestNetworksManagerSerializer.java @@ -0,0 +1,45 @@ +package eu.zhincore.chestnetworks.util; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.UUID; +import com.google.common.collect.HashBasedTable; +import com.google.gson.*; +import eu.zhincore.chestnetworks.ChestNetworksPlugin; +import eu.zhincore.chestnetworks.networks.ChestNetwork; +import eu.zhincore.chestnetworks.networks.ChestNetworksManager; + +public class ChestNetworksManagerSerializer + implements JsonSerializer, JsonDeserializer { + ChestNetworksPlugin plugin; + + public ChestNetworksManagerSerializer(ChestNetworksPlugin plugin) { + this.plugin = plugin; + } + + @Override + public JsonElement serialize(ChestNetworksManager manager, Type typeOfSrc, JsonSerializationContext context) { + return context.serialize(manager.networks.rowMap()); + } + + @Override + public ChestNetworksManager deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { + HashMap> map = context.deserialize(json, HashMap.class); + HashBasedTable networks = HashBasedTable.create(); + + for (var playerRow : map.entrySet()) { + for (var networkCell : playerRow.getValue().entrySet()) { + var owner = playerRow.getKey(); + var name = networkCell.getKey(); + + var net = networks.put(owner, name, context.deserialize(networkCell.getValue(), ChestNetwork.class)); + net.name = name; + net.owner = UUID.fromString(owner); + } + } + + var manager = new ChestNetworksManager(plugin); + manager.networks = networks; + return manager; + } +} diff --git a/src/main/java/eu/zhincore/chestnetworks/util/ChestNetworksPluginSerializer.java b/src/main/java/eu/zhincore/chestnetworks/util/ChestNetworksPluginSerializer.java deleted file mode 100644 index d2f25c8..0000000 --- a/src/main/java/eu/zhincore/chestnetworks/util/ChestNetworksPluginSerializer.java +++ /dev/null @@ -1,24 +0,0 @@ -package eu.zhincore.chestnetworks.util; - -import java.lang.reflect.Type; -import com.google.gson.*; -import eu.zhincore.chestnetworks.ChestNetworksPlugin; - -public class ChestNetworksPluginSerializer - implements JsonSerializer, JsonDeserializer { - ChestNetworksPlugin plugin; - - public ChestNetworksPluginSerializer(ChestNetworksPlugin plugin) { - this.plugin = plugin; - } - - @Override - public JsonElement serialize(ChestNetworksPlugin plugin, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive("ChestNetworks"); - } - - @Override - public ChestNetworksPlugin deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { - return plugin; - } -} diff --git a/src/main/java/eu/zhincore/chestnetworks/util/HashBasedTableSerializer.java b/src/main/java/eu/zhincore/chestnetworks/util/HashBasedTableSerializer.java deleted file mode 100644 index 71d6c81..0000000 --- a/src/main/java/eu/zhincore/chestnetworks/util/HashBasedTableSerializer.java +++ /dev/null @@ -1,28 +0,0 @@ -package eu.zhincore.chestnetworks.util; - -import java.lang.reflect.Type; -import java.util.HashMap; -import com.google.common.collect.HashBasedTable; -import com.google.gson.*; - -public class HashBasedTableSerializer implements JsonSerializer>, - JsonDeserializer> { - @Override - public JsonElement serialize(HashBasedTable table, Type typeOfSrc, - JsonSerializationContext context) { - return context.serialize(table.rowMap()); - } - - @Override - public HashBasedTable deserialize(JsonElement json, Type typeOfT, - JsonDeserializationContext context) { - HashMap> map = context.deserialize(json, HashMap.class); - var table = HashBasedTable.create(); - - for (var row : map.entrySet()) { - table.row(row.getKey()).putAll(row.getValue()); - } - - return table; - } -} diff --git a/src/main/resources/lang_en.yml b/src/main/resources/lang_en.yml index ba0c900..783fe84 100644 --- a/src/main/resources/lang_en.yml +++ b/src/main/resources/lang_en.yml @@ -1,17 +1,12 @@ chestnet: - no_networks: You haven't created any networks yet. + no_networks: "You haven't created any networks yet." list: "You have created these networks: {networks}." - created: Network '{name}' created. - exists: Network '{name}' already exists. - not_exists: Network '{name}' doesn't exists! - deleted: Network '{name}' deleted. - not_chest: The selected block is not a chest! - chest_added: Chest has been successfully added to the network! - chest_exists: This chest is already registered in a network! - chest_not_exists: This chest isn't registered in any network! - chest_info: - "Chest info:" - " Network: {network}" - " Owner: {owner}" - " Type: {type}" - " Content: {content}" + created: "Network '{name}' created." + exists: "Network '{name}' already exists." + not_exists: "Network '{name}' doesn't exists!" + deleted: "Network '{name}' deleted." + not_chest: "The selected block is not a chest!" + chest_added: "Chest has been successfully added to the network!" + chest_exists: "This chest is already registered in a network!" + chest_not_exists: "This chest isn't registered in any network!" + chest_info: "Chest info:\n Network: {network}\n Owner: {owner}\n Type: {type}\n Content: {content}"