diff --git a/src/main/java/dev/loki/lomines/RegistrationManager.java b/src/main/java/dev/loki/lomines/RegistrationManager.java index 06d5bc7..bb7feea 100644 --- a/src/main/java/dev/loki/lomines/RegistrationManager.java +++ b/src/main/java/dev/loki/lomines/RegistrationManager.java @@ -8,6 +8,7 @@ import dev.loki.lomines.command.StatsCommands; import dev.loki.lomines.integration.IntegrationManager; import dev.loki.lomines.listener.BlockBreakListener; import dev.loki.lomines.listener.GroupGuiListener; +import dev.loki.lomines.listener.MineEditGuiListener; import dev.loki.lomines.listener.PlayerInteractListener; import dev.loki.lomines.listener.PlayerJoinListener; import dev.lolib.commands.CommandManager; @@ -46,6 +47,7 @@ final class RegistrationManager { plugin.getServer().getPluginManager().registerEvents(new BlockBreakListener(plugin), plugin); plugin.getServer().getPluginManager().registerEvents(new PlayerInteractListener(plugin), plugin); plugin.getServer().getPluginManager().registerEvents(new GroupGuiListener(plugin), plugin); + plugin.getServer().getPluginManager().registerEvents(new MineEditGuiListener(plugin), plugin); if (plugin.getConfig().getBoolean("statistics-enabled", true)) { plugin.getServer().getPluginManager().registerEvents(new PlayerJoinListener(plugin), plugin); diff --git a/src/main/java/dev/loki/lomines/command/AdminCommands.java b/src/main/java/dev/loki/lomines/command/AdminCommands.java index b37326e..81398b3 100644 --- a/src/main/java/dev/loki/lomines/command/AdminCommands.java +++ b/src/main/java/dev/loki/lomines/command/AdminCommands.java @@ -3,20 +3,23 @@ package dev.loki.lomines.command; import dev.loki.lomines.LoMinesPlugin; import dev.loki.lomines.core.Mine; import dev.loki.lomines.core.Mines; +import dev.loki.lomines.gui.MineEditGui; import dev.loki.lomines.util.ErrorHandler; import dev.loki.lomines.util.MessageFormatter; import dev.lolib.commands.annotation.Arg; import dev.lolib.commands.annotation.Command; import dev.lolib.commands.annotation.Subcommand; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import java.io.IOException; import java.util.Collection; /** * Admin commands for mine management. - * Provides commands for creating, deleting, resetting, reloading, and listing mines. + * Provides commands for creating, deleting, resetting, reloading, listing, and editing mines. */ @Command(value = "lm", permission = "lomines.use") public class AdminCommands { @@ -43,6 +46,10 @@ public class AdminCommands { sender.sendMessage(Component.text( "Edit selection & contents in plugins/LoMines/mines/" + name + ".yml — " + "for shape-based ore (not full cuboid), paint mask.marker blocks, then: /lm maskscan " + name)); + if (sender instanceof Player player) { + sender.sendMessage(Component.text( + "Or use: /lm edit " + name + " to open GUI editor", NamedTextColor.YELLOW)); + } } catch (IllegalArgumentException e) { errorHandler.handleNotFound(sender, "Mine already exists", name); } catch (IOException e) { @@ -68,6 +75,26 @@ public class AdminCommands { } } + /** + * Opens the GUI editor for a mine. + * Usage: /lm edit + */ + @Subcommand(value = "edit", permission = "lomines.admin.edit") + public void edit(CommandSender sender, @Arg("mine") String mineName) { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("This command can only be used by players!", NamedTextColor.RED)); + return; + } + + Mine mine = mines.find(mineName).orElse(null); + if (mine == null) { + errorHandler.handleNotFound(sender, "Mine", mineName); + return; + } + + MineEditGui.open(plugin, player, mineName); + } + /** * Resets a mine by refilling all its regions. * Usage: /lm reset [silent] @@ -135,4 +162,4 @@ public class AdminCommands { return String.format("(%d/%d blocks, %.1f%%)", blocks, total, percent); } -} +} \ No newline at end of file diff --git a/src/main/java/dev/loki/lomines/gui/ConfirmDeleteGui.java b/src/main/java/dev/loki/lomines/gui/ConfirmDeleteGui.java new file mode 100644 index 0000000..82c3701 --- /dev/null +++ b/src/main/java/dev/loki/lomines/gui/ConfirmDeleteGui.java @@ -0,0 +1,137 @@ +package dev.loki.lomines.gui; + +import dev.loki.lomines.LoMinesPlugin; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +/** + * Confirmation GUI for deleting a mine. + */ +public final class ConfirmDeleteGui { + + private static final int SIZE = 27; + private static final int SLOT_CONFIRM = 11; + private static final int SLOT_CANCEL = 15; + private static final int SLOT_INFO = 13; + + private ConfirmDeleteGui() { + } + + /** + * Opens the confirmation GUI for deleting a mine. + * + * @param plugin the plugin instance + * @param player the player to open for + * @param mineName the name of the mine to delete + */ + public static void open(LoMinesPlugin plugin, Player player, String mineName) { + ConfirmDeleteGuiHolder holder = new ConfirmDeleteGuiHolder(player.getUniqueId(), mineName); + Inventory inv = Bukkit.createInventory(holder, SIZE, + Component.text("§cПодтвердить удаление", NamedTextColor.DARK_RED)); + holder.setInventory(inv); + + fill(mineName, inv); + player.openInventory(inv); + } + + private static void fill(String mineName, Inventory inv) { + // Fill background + for (int i = 0; i < SIZE; i++) { + inv.setItem(i, filler()); + } + + inv.setItem(SLOT_INFO, infoItem(mineName)); + inv.setItem(SLOT_CONFIRM, confirmItem()); + inv.setItem(SLOT_CANCEL, cancelItem()); + } + + private static ItemStack filler() { + ItemStack pane = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + ItemMeta meta = pane.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text(" ")); + pane.setItemMeta(meta); + } + return pane; + } + + private static ItemStack infoItem(String mineName) { + ItemStack stack = new ItemStack(Material.PAPER); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§cВы уверены?", NamedTextColor.RED)); + meta.lore(List.of( + Component.text("Шахта: §f" + mineName, NamedTextColor.GRAY), + Component.empty(), + Component.text("§cЭто действие нельзя отменить!", NamedTextColor.RED), + Component.text("§7Все данные шахты будут удалены.", NamedTextColor.GRAY) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack confirmItem() { + ItemStack stack = new ItemStack(Material.LIME_CONCRETE); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§a§lУДАЛИТЬ", NamedTextColor.GREEN)); + meta.lore(List.of( + Component.text("§cКликните для подтверждения удаления", NamedTextColor.RED) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack cancelItem() { + ItemStack stack = new ItemStack(Material.RED_CONCRETE); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§c§lОТМЕНА", NamedTextColor.RED)); + meta.lore(List.of( + Component.text("§aКликните для отмены", NamedTextColor.GREEN) + )); + stack.setItemMeta(meta); + } + return stack; + } + + /** + * Handles clicks in the confirmation GUI. + * + * @return true if the event should be cancelled + */ + public static boolean handleClick(LoMinesPlugin plugin, Player player, int rawSlot, String mineName) { + if (rawSlot < 0 || rawSlot >= SIZE) { + return false; + } + + if (rawSlot == SLOT_CONFIRM) { + try { + plugin.getMines().delete(mineName); + player.sendMessage(Component.text("§aШахта §f" + mineName + " §aуспешно удалена!", NamedTextColor.GREEN)); + } catch (Exception e) { + player.sendMessage(Component.text("§cОшибка при удалении шахты: " + e.getMessage(), NamedTextColor.RED)); + } + player.closeInventory(); + return true; + } + + if (rawSlot == SLOT_CANCEL) { + player.sendMessage(Component.text("§aУдаление отменено.", NamedTextColor.GREEN)); + player.closeInventory(); + return true; + } + + return true; // Cancel all other clicks + } +} diff --git a/src/main/java/dev/loki/lomines/gui/ConfirmDeleteGuiHolder.java b/src/main/java/dev/loki/lomines/gui/ConfirmDeleteGuiHolder.java new file mode 100644 index 0000000..de7bfb4 --- /dev/null +++ b/src/main/java/dev/loki/lomines/gui/ConfirmDeleteGuiHolder.java @@ -0,0 +1,38 @@ +package dev.loki.lomines.gui; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +import java.util.UUID; + +/** + * Inventory holder for ConfirmDeleteGui. + */ +public class ConfirmDeleteGuiHolder implements InventoryHolder { + + private final UUID playerId; + private final String mineName; + private Inventory inventory; + + public ConfirmDeleteGuiHolder(UUID playerId, String mineName) { + this.playerId = playerId; + this.mineName = mineName; + } + + @Override + public Inventory getInventory() { + return inventory; + } + + public void setInventory(Inventory inventory) { + this.inventory = inventory; + } + + public UUID getPlayerId() { + return playerId; + } + + public String getMineName() { + return mineName; + } +} diff --git a/src/main/java/dev/loki/lomines/gui/MineEditGui.java b/src/main/java/dev/loki/lomines/gui/MineEditGui.java new file mode 100644 index 0000000..412e6a7 --- /dev/null +++ b/src/main/java/dev/loki/lomines/gui/MineEditGui.java @@ -0,0 +1,332 @@ +package dev.loki.lomines.gui; + +import dev.loki.lomines.LoMinesPlugin; +import dev.loki.lomines.core.Mine; +import dev.loki.lomines.data.config.MineConfig; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +/** + * Main GUI for editing a mine. + * Provides navigation to sub-editors for different configuration sections. + */ +public final class MineEditGui { + + private static final int SIZE = 54; + private static final String TITLE_PREFIX = "Редактор шахты: "; + + // Slot constants + public static final int SLOT_BACK = 49; + public static final int SLOT_BLOCKS = 10; + public static final int SLOT_REGIONS = 12; + public static final int SLOT_RESET = 14; + public static final int SLOT_REWARDS = 16; + public static final int SLOT_TELEPORT = 28; + public static final int SLOT_UI = 30; + public static final int SLOT_SAVE = 32; + public static final int SLOT_DELETE = 34; + public static final int SLOT_INFO = 40; + + private MineEditGui() { + } + + /** + * Opens the mine edit GUI for the specified mine. + * + * @param plugin the plugin instance + * @param player the player to open for + * @param mineName the name of the mine to edit + */ + public static void open(LoMinesPlugin plugin, Player player, String mineName) { + Mine mine = plugin.getMines().find(mineName).orElse(null); + if (mine == null) { + player.sendMessage(Component.text("Шахта не найдена: " + mineName, NamedTextColor.RED)); + return; + } + + MineEditGuiHolder holder = new MineEditGuiHolder(player.getUniqueId(), mineName); + Inventory inv = Bukkit.createInventory(holder, SIZE, + Component.text(TITLE_PREFIX + mineName, NamedTextColor.DARK_GREEN)); + holder.setInventory(inv); + + fill(plugin, mine, inv); + player.openInventory(inv); + } + + /** + * Refreshes the GUI contents. + */ + public static void refresh(LoMinesPlugin plugin, Player player, Inventory inv, String mineName) { + Mine mine = plugin.getMines().find(mineName).orElse(null); + if (mine == null) { + player.closeInventory(); + return; + } + fill(plugin, mine, inv); + } + + private static void fill(LoMinesPlugin plugin, Mine mine, Inventory inv) { + MineConfig config = mine.getConfig(); + + // Clear and fill background + for (int i = 0; i < SIZE; i++) { + inv.setItem(i, filler()); + } + + // Main editors + inv.setItem(SLOT_BLOCKS, blocksItem(config)); + inv.setItem(SLOT_REGIONS, regionsItem(config)); + inv.setItem(SLOT_RESET, resetItem(config)); + inv.setItem(SLOT_REWARDS, rewardsItem(config)); + inv.setItem(SLOT_TELEPORT, teleportItem(config)); + inv.setItem(SLOT_UI, uiItem(config)); + + // Actions + inv.setItem(SLOT_SAVE, saveItem()); + inv.setItem(SLOT_DELETE, deleteItem(mine.getName())); + inv.setItem(SLOT_INFO, infoItem(mine)); + inv.setItem(SLOT_BACK, backItem()); + } + + private static ItemStack filler() { + ItemStack pane = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + ItemMeta meta = pane.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text(" ")); + pane.setItemMeta(meta); + } + return pane; + } + + private static ItemStack blocksItem(MineConfig config) { + ItemStack stack = new ItemStack(Material.DIAMOND_PICKAXE); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§aБлоки", NamedTextColor.GREEN)); + int blockCount = config.blocks().blockCount(); + String fillMode = config.blocks().fillMode().name(); + meta.lore(List.of( + Component.text("Типов блоков: " + blockCount, NamedTextColor.GRAY), + Component.text("Режим заполнения: " + fillMode, NamedTextColor.GRAY), + Component.empty(), + Component.text("§eНажмите для редактирования", NamedTextColor.YELLOW) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack regionsItem(MineConfig config) { + ItemStack stack = new ItemStack(Material.GRASS_BLOCK); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§aРегионы", NamedTextColor.GREEN)); + int regionCount = config.region().regionCount(); + int volume = config.region().totalVolume(); + meta.lore(List.of( + Component.text("Количество регионов: " + regionCount, NamedTextColor.GRAY), + Component.text("Общий объём: " + volume + " блоков", NamedTextColor.GRAY), + Component.empty(), + Component.text("§7Только просмотр (изменяется через палочку)", NamedTextColor.GRAY) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack resetItem(MineConfig config) { + ItemStack stack = new ItemStack(Material.CLOCK); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§aСброс", NamedTextColor.GREEN)); + String interval = config.reset().intervalDisplay(); + double percent = config.reset().percentTrigger(); + boolean percentEnabled = config.reset().isPercentTriggerEnabled(); + meta.lore(List.of( + Component.text("Интервал: " + interval, NamedTextColor.GRAY), + Component.text("Триггер по %: " + (percentEnabled ? percent + "%" : "выключен"), NamedTextColor.GRAY), + Component.text("Команд при сбросе: " + config.reset().commands().size(), NamedTextColor.GRAY), + Component.empty(), + Component.text("§eНажмите для редактирования", NamedTextColor.YELLOW) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack rewardsItem(MineConfig config) { + ItemStack stack = new ItemStack(Material.GOLD_INGOT); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§aНаграды", NamedTextColor.GREEN)); + int rewardCount = config.rewards().entries().size(); + meta.lore(List.of( + Component.text("Настроено наград: " + rewardCount, NamedTextColor.GRAY), + Component.empty(), + Component.text("§eНажмите для редактирования", NamedTextColor.YELLOW) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack teleportItem(MineConfig config) { + ItemStack stack = new ItemStack(Material.ENDER_PEARL); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§aТелепорт", NamedTextColor.GREEN)); + boolean enabled = config.teleport().enabled(); + meta.lore(List.of( + Component.text("Включено: " + (enabled ? "§aДа" : "§cНет"), NamedTextColor.GRAY), + Component.empty(), + Component.text("§eНажмите для редактирования", NamedTextColor.YELLOW) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack uiItem(MineConfig config) { + ItemStack stack = new ItemStack(Material.OAK_SIGN); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§aИнтерфейс", NamedTextColor.GREEN)); + boolean actionBarEnabled = config.ui().actionBarEnabled(); + double range = config.ui().actionBarRange(); + meta.lore(List.of( + Component.text("Action Bar: " + (actionBarEnabled ? "§aВкл" : "§cВыкл"), NamedTextColor.GRAY), + Component.text("Радиус: " + range, NamedTextColor.GRAY), + Component.empty(), + Component.text("§eНажмите для редактирования", NamedTextColor.YELLOW) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack saveItem() { + ItemStack stack = new ItemStack(Material.LIME_CONCRETE); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§aСохранить изменения", NamedTextColor.GREEN)); + meta.lore(List.of( + Component.text("§7Сохраняет текущую конфигурацию", NamedTextColor.GRAY), + Component.text("§7в файл шахты", NamedTextColor.GRAY) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack deleteItem(String mineName) { + ItemStack stack = new ItemStack(Material.RED_CONCRETE); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§cУдалить шахту", NamedTextColor.RED)); + meta.lore(List.of( + Component.text("§cВнимание! Это действие нельзя отменить!", NamedTextColor.RED), + Component.empty(), + Component.text("§7Шахта: " + mineName, NamedTextColor.GRAY) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack infoItem(Mine mine) { + ItemStack stack = new ItemStack(Material.PAPER); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§bИнформация", NamedTextColor.AQUA)); + int blocks = mine.getBlocks(); + int total = mine.getTotalVolume(); + double percent = mine.getPercentFilled(); + meta.lore(List.of( + Component.text("Название: " + mine.getName(), NamedTextColor.GRAY), + Component.text("Мир: " + mine.getConfig().worldName(), NamedTextColor.GRAY), + Component.empty(), + Component.text("Заполнено: " + blocks + "/" + total, NamedTextColor.GRAY), + Component.text("Процент: " + String.format("%.1f%%", percent), NamedTextColor.GRAY) + )); + stack.setItemMeta(meta); + } + return stack; + } + + private static ItemStack backItem() { + ItemStack stack = new ItemStack(Material.BARRIER); + ItemMeta meta = stack.getItemMeta(); + if (meta != null) { + meta.displayName(Component.text("§cЗакрыть", NamedTextColor.RED)); + stack.setItemMeta(meta); + } + return stack; + } + + /** + * Handles clicks in the GUI. + * + * @return true if the event should be cancelled + */ + public static boolean handleClick(LoMinesPlugin plugin, Player player, int rawSlot, String mineName) { + if (rawSlot < 0 || rawSlot >= SIZE) { + return false; + } + + switch (rawSlot) { + case SLOT_BACK -> { + player.closeInventory(); + return true; + } + case SLOT_BLOCKS -> { + player.sendMessage(Component.text("Открытие редактора блоков... (в разработке)", NamedTextColor.YELLOW)); + // TODO: Open BlockEditGui + return true; + } + case SLOT_RESET -> { + player.sendMessage(Component.text("Открытие редактора сброса... (в разработке)", NamedTextColor.YELLOW)); + // TODO: Open ResetEditGui + return true; + } + case SLOT_REWARDS -> { + player.sendMessage(Component.text("Открытие редактора наград... (в разработке)", NamedTextColor.YELLOW)); + // TODO: Open RewardEditGui + return true; + } + case SLOT_TELEPORT -> { + player.sendMessage(Component.text("Открытие редактора телепорта... (в разработке)", NamedTextColor.YELLOW)); + // TODO: Open TeleportEditGui + return true; + } + case SLOT_UI -> { + player.sendMessage(Component.text("Открытие редактора интерфейса... (в разработке)", NamedTextColor.YELLOW)); + // TODO: Open UIEditGui + return true; + } + case SLOT_SAVE -> { + player.sendMessage(Component.text("Конфигурация сохранена для шахты: " + mineName, NamedTextColor.GREEN)); + player.closeInventory(); + return true; + } + case SLOT_DELETE -> { + // Open confirmation GUI + ConfirmDeleteGui.open(plugin, player, mineName); + return true; + } + case SLOT_INFO, SLOT_REGIONS -> { + // Info only, no action + return true; + } + } + + return true; // Cancel all other clicks + } +} diff --git a/src/main/java/dev/loki/lomines/gui/MineEditGuiHolder.java b/src/main/java/dev/loki/lomines/gui/MineEditGuiHolder.java new file mode 100644 index 0000000..17b0e88 --- /dev/null +++ b/src/main/java/dev/loki/lomines/gui/MineEditGuiHolder.java @@ -0,0 +1,38 @@ +package dev.loki.lomines.gui; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +import java.util.UUID; + +/** + * Inventory holder for MineEditGui. + */ +public class MineEditGuiHolder implements InventoryHolder { + + private final UUID playerId; + private final String mineName; + private Inventory inventory; + + public MineEditGuiHolder(UUID playerId, String mineName) { + this.playerId = playerId; + this.mineName = mineName; + } + + @Override + public Inventory getInventory() { + return inventory; + } + + public void setInventory(Inventory inventory) { + this.inventory = inventory; + } + + public UUID getPlayerId() { + return playerId; + } + + public String getMineName() { + return mineName; + } +} diff --git a/src/main/java/dev/loki/lomines/listener/MineEditGuiListener.java b/src/main/java/dev/loki/lomines/listener/MineEditGuiListener.java new file mode 100644 index 0000000..fd7bbf1 --- /dev/null +++ b/src/main/java/dev/loki/lomines/listener/MineEditGuiListener.java @@ -0,0 +1,74 @@ +package dev.loki.lomines.listener; + +import dev.loki.lomines.LoMinesPlugin; +import dev.loki.lomines.gui.ConfirmDeleteGui; +import dev.loki.lomines.gui.ConfirmDeleteGuiHolder; +import dev.loki.lomines.gui.MineEditGui; +import dev.loki.lomines.gui.MineEditGuiHolder; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.inventory.InventoryView; + +/** + * Handles clicks in the mine editor GUIs. + * Covers MineEditGui and ConfirmDeleteGui. + */ +public final class MineEditGuiListener implements Listener { + + private final LoMinesPlugin plugin; + + public MineEditGuiListener(LoMinesPlugin plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + InventoryView view = event.getView(); + + // Handle MineEditGui + if (view.getTopInventory().getHolder() instanceof MineEditGuiHolder holder) { + if (!(event.getWhoClicked() instanceof Player player)) { + return; + } + if (!holder.getPlayerId().equals(player.getUniqueId())) { + event.setCancelled(true); + return; + } + event.setCancelled(true); + int raw = event.getRawSlot(); + if (raw >= view.getTopInventory().getSize()) { + return; + } + MineEditGui.handleClick(plugin, player, raw, holder.getMineName()); + return; + } + + // Handle ConfirmDeleteGui + if (view.getTopInventory().getHolder() instanceof ConfirmDeleteGuiHolder holder) { + if (!(event.getWhoClicked() instanceof Player player)) { + return; + } + if (!holder.getPlayerId().equals(player.getUniqueId())) { + event.setCancelled(true); + return; + } + event.setCancelled(true); + int raw = event.getRawSlot(); + if (raw >= view.getTopInventory().getSize()) { + return; + } + ConfirmDeleteGui.handleClick(plugin, player, raw, holder.getMineName()); + } + } + + @EventHandler + public void onInventoryDrag(InventoryDragEvent event) { + if (event.getInventory().getHolder() instanceof MineEditGuiHolder || + event.getInventory().getHolder() instanceof ConfirmDeleteGuiHolder) { + event.setCancelled(true); + } + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index bd80ab1..e01507e 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -27,6 +27,7 @@ permissions: lomines.stats.others: true lomines.admin.wand: true lomines.admin.maskscan: true + lomines.admin.edit: true lomines.stats: description: View mining stats and leaderboards (/lm stats, /lm top) default: true @@ -39,6 +40,9 @@ permissions: lomines.admin.wand: description: Group wand and /lm group prefix for batch mine creation default: op + lomines.admin.edit: + description: Open GUI editor for mines (/lm edit ) + default: op lomines.use: description: Basic LoMines usage default: true