From acc7f076e0946b93df1b29f8a21853e7e85c4bfe Mon Sep 17 00:00:00 2001 From: unurled Date: Mon, 8 Apr 2024 22:45:46 +0200 Subject: [PATCH] treasure chests --- .../sr/commands/CommandManager.java | 1 + .../sr/commands/admin/TreasureCommand.java | 157 ++++++++++++++++++ .../sr/components/treasure/Treasure.java | 14 +- .../components/treasure/TreasureManager.java | 26 +++ .../sr/gui/treasure/TreasureGUI.java | 59 +++++++ .../unurled/sacredrealms/sr/utils/Items.java | 1 - src/main/resources/plugin.yml | 7 +- 7 files changed, 262 insertions(+), 3 deletions(-) create mode 100644 src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java create mode 100644 src/main/java/me/unurled/sacredrealms/sr/gui/treasure/TreasureGUI.java diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java index b5c883e..a2190dc 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java @@ -42,6 +42,7 @@ public class CommandManager extends Manager { registerCommand("level", LevelCommand.class); registerCommand("entitytype", EntityTypeCommand.class); registerCommand("item", ItemCommand.class); + registerCommand("treasure", ItemCommand.class); registerCommand("resetadventure", ResetAdventureCommand.class); } diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java new file mode 100644 index 0000000..5b9d4e1 --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/TreasureCommand.java @@ -0,0 +1,157 @@ +package me.unurled.sacredrealms.sr.commands.admin; + +import static me.unurled.sacredrealms.sr.utils.Component.textComp; + +import java.util.List; +import java.util.Set; +import me.unurled.sacredrealms.sr.components.treasure.Treasure; +import me.unurled.sacredrealms.sr.components.treasure.TreasureManager; +import me.unurled.sacredrealms.sr.gui.treasure.TreasureGUI; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.xenondevs.invui.window.Window; + +public class TreasureCommand implements TabExecutor { + + public static final Set TRANSPARENT = + Set.of(Material.AIR, Material.CAVE_AIR, Material.VOID_AIR, Material.WATER, Material.LAVA); + + /** + * Executes the given command, returning its success.
+ * If false is returned, then the "usage" plugin.yml entry for this command (if defined) will be + * sent to the player. + * + * @param sender Source of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return true if a valid command, otherwise false + */ + @Override + public boolean onCommand( + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String[] args) { + // create, modify, list, get, delete + if (args.length == 0) { + sender.sendMessage("Usage: /treasure "); + return true; + } + Block block; + switch (args[0]) { + case "create" -> { + if (!(sender instanceof Player p)) { + sender.sendMessage("You must be a player to use this command."); + return true; + } + block = p.getTargetBlock(TRANSPARENT, 3); + if (block.getBlockData().getMaterial().equals(Material.CHEST)) { + // create a new treasure chest + Treasure treasure; + if (args.length == 2) { + treasure = new Treasure(block.getLocation(), args[1]); + } else { + treasure = new Treasure(block.getLocation()); + } + TreasureManager.getInstance(TreasureManager.class).addTreasure(treasure); + } + } + case "modify" -> { + if (!(sender instanceof Player p)) { + sender.sendMessage("You must be a player to use this command."); + return true; + } + block = p.getTargetBlock(TRANSPARENT, 3); + if (block.getBlockData().getMaterial().equals(Material.CHEST)) { + // find the treasure chest + Treasure treasure = + TreasureManager.getInstance(TreasureManager.class) + .findByLocation(block.getLocation()); + if (treasure == null) { + sender.sendMessage("No treasure chest found at this location."); + return true; + } + // open the GUI + Window window = + Window.single() + .setViewer(p) + .setTitle("Attributes") + .setGui(TreasureGUI.createGui(treasure)) + .build(); + window.open(); + } + } + case "list" -> { + sender.sendMessage("Treasures:"); + for (Treasure treasure : + TreasureManager.getInstance(TreasureManager.class).getTreasures()) { + String s = + String.format( + "%sx: %s, y: %s, z: %s", + treasure.getLocation().getBlockX(), + treasure.getLocation().getBlockY(), + treasure.getLocation().getBlockZ(), + treasure.getLocation().toString(), + treasure.getLocation().getBlockX(), + treasure.getLocation().getBlockY(), + treasure.getLocation().getBlockZ()); + Component text = textComp(s); + sender.sendMessage(text); + } + } + case "delete" -> { + if (!(sender instanceof Player p)) { + sender.sendMessage("You must be a player to use this command."); + return true; + } + block = p.getTargetBlock(TRANSPARENT, 3); + if (block.getBlockData().getMaterial().equals(Material.CHEST)) { + // find the treasure chest + Treasure treasure = + TreasureManager.getInstance(TreasureManager.class) + .findByLocation(block.getLocation()); + if (treasure == null) { + sender.sendMessage("No treasure chest found at this location."); + return true; + } + // remove the treasure chest + TreasureManager.getInstance(TreasureManager.class).removeTreasure(treasure); + } + } + default -> { + sender.sendMessage("Usage: /treasure "); + return true; + } + } + return true; + } + + /** + * Requests a list of possible completions for a command argument. + * + * @param sender Source of the command. For players tab-completing a command inside of a command + * block, this will be the player, not the command block. + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args The arguments passed to the command, including final partial argument to be + * completed + * @return A List of possible completions for the final argument, or null to default to the + * command executor + */ + @Override + public @Nullable List onTabComplete( + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String[] args) { + return List.of(); + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java index 9a6057f..0ee6ae4 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/Treasure.java @@ -18,6 +18,18 @@ public class Treasure { public Treasure() {} + public Treasure(Location location) { + this.location = location; + this.items = new HashMap<>(); + this.permission = ""; + } + + public Treasure(Location location, String permission) { + this.location = location; + this.items = new HashMap<>(); + this.permission = permission; + } + public Treasure(Location location, Map items, String permission) { this.location = location; this.items = items; @@ -46,7 +58,7 @@ public class Treasure { return items; } - public void setItems(HashMap items) { + public void setItems(Map items) { this.items = items; } diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java index ac00db0..713eee3 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java +++ b/src/main/java/me/unurled/sacredrealms/sr/components/treasure/TreasureManager.java @@ -4,9 +4,12 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nullable; import me.unurled.sacredrealms.sr.data.DataHandler; import me.unurled.sacredrealms.sr.data.DataManager; import me.unurled.sacredrealms.sr.managers.Manager; +import org.bukkit.Location; +import org.jetbrains.annotations.NotNull; public class TreasureManager extends Manager { private final List treasures = new ArrayList<>(); @@ -36,4 +39,27 @@ public class TreasureManager extends Manager { treasures.add(gson.fromJson(dh.get("treasures." + key), Treasure.class)); } } + + public void addTreasure(Treasure treasure) { + treasures.add(treasure); + } + + @Nullable + public Treasure findByLocation(@NotNull Location loc) { + for (Treasure treasure : treasures) { + if (treasure.getLocation().equals(loc)) { + return treasure; + } + } + return null; + } + + @NotNull + public List getTreasures() { + return treasures; + } + + public void removeTreasure(@NotNull Treasure treasure) { + treasures.remove(treasure); + } } diff --git a/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/TreasureGUI.java b/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/TreasureGUI.java new file mode 100644 index 0000000..54f965b --- /dev/null +++ b/src/main/java/me/unurled/sacredrealms/sr/gui/treasure/TreasureGUI.java @@ -0,0 +1,59 @@ +package me.unurled.sacredrealms.sr.gui.treasure; + +import static me.unurled.sacredrealms.sr.utils.Component.textComp; + +import me.unurled.sacredrealms.sr.components.treasure.Treasure; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.gui.Gui; +import xyz.xenondevs.invui.gui.Gui.Builder.Normal; +import xyz.xenondevs.invui.item.Item; +import xyz.xenondevs.invui.item.impl.SimpleItem; + +public class TreasureGUI { + + @NotNull + public static Gui createGui(@NotNull Treasure treasure) { + ItemStack itemStack = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(textComp("")); + itemStack.setItemMeta(itemMeta); + Item pane = new SimpleItem(itemStack); + Normal gui = + Gui.normal() + .setStructure(".........", "abcdefghi", "jklmnopqr", "stuvwxyz$", "...123...") + .addIngredient('.', pane); + if (!treasure.getItems().isEmpty()) { + for (int i = 0; i < treasure.getItems().size(); i++) { + Item item = new SimpleItem(treasure.getItems().get(i)); + if (i == 28) { + gui.addIngredient('$', item); + } else { + gui.addIngredient((char) (i + 'a'), item); + } + } + } + + ItemStack cancel = new ItemStack(Material.BARRIER); + ItemMeta cancelMeta = cancel.getItemMeta(); + cancelMeta.displayName(textComp("Cancel")); + cancel.setItemMeta(cancelMeta); + + ItemStack confirm = new ItemStack(Material.GREEN_STAINED_GLASS_PANE); + ItemMeta confirmMeta = confirm.getItemMeta(); + confirmMeta.displayName(textComp("Confirm")); + confirm.setItemMeta(confirmMeta); + + ItemStack delete = new ItemStack(Material.RED_STAINED_GLASS_PANE); + ItemMeta deleteMeta = delete.getItemMeta(); + deleteMeta.displayName(textComp("Delete")); + delete.setItemMeta(deleteMeta); + + gui.addIngredient('1', new SimpleItem(delete)); + gui.addIngredient('2', new SimpleItem(cancel)); + gui.addIngredient('3', new SimpleItem(confirm)); + return gui.build(); + } +} diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java b/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java index 3bc1e63..05da40e 100644 --- a/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java +++ b/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java @@ -74,7 +74,6 @@ public class Items { * @return the itemstack with lore */ public static ItemStack lore(ItemStack stack) { - ItemManager im = Manager.getInstance(ItemManager.class); if (im == null) return stack; if (stack == null) return stack; diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 8efb3c4..598e5f9 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -32,6 +32,9 @@ permissions: sr.resetadventure: default: op description: When the player has permission for the command /resetadventure + sr.treasure.manage: + default: op + description: When the player has permission for the command /treasure create commands: attributes: @@ -45,4 +48,6 @@ commands: item: description: Create/modify an item. resetadventure: - description: Reset the adventure of the player \ No newline at end of file + description: Reset the adventure of the player + treasure: + description: Create a treasure chest.