feat(gui): add mine editor GUI system

New GUI classes:
- MineEditGui.java - main editor with navigation to sub-editors
- MineEditGuiHolder.java - inventory holder for editor
- ConfirmDeleteGui.java - confirmation dialog for mine deletion
- ConfirmDeleteGuiHolder.java - inventory holder for confirmation
- MineEditGuiListener.java - handles clicks in editor GUIs

Updated:
- AdminCommands.java - add /lm edit <mine> command
- RegistrationManager.java - register MineEditGuiListener
- plugin.yml - add lomines.admin.edit permission

Features:
- Visual editor showing mine configuration sections
- Blocks, Regions, Reset, Rewards, Teleport, UI sections
- Save and Delete actions with confirmation
- Info panel showing mine status (blocks, volume, percent)

Sub-editors (placeholder, to be implemented):
- BlockEditGui - edit block types and weights
- ResetEditGui - edit reset interval and triggers
- RewardEditGui - edit mining rewards
- TeleportEditGui - edit teleport on reset
- UIEditGui - edit action bar settings
This commit is contained in:
loki5512344 2026-05-31 22:23:46 +02:00
parent 56249f47cf
commit a9c8a0c323
8 changed files with 654 additions and 2 deletions

View file

@ -8,6 +8,7 @@ import dev.loki.lomines.command.StatsCommands;
import dev.loki.lomines.integration.IntegrationManager; import dev.loki.lomines.integration.IntegrationManager;
import dev.loki.lomines.listener.BlockBreakListener; import dev.loki.lomines.listener.BlockBreakListener;
import dev.loki.lomines.listener.GroupGuiListener; import dev.loki.lomines.listener.GroupGuiListener;
import dev.loki.lomines.listener.MineEditGuiListener;
import dev.loki.lomines.listener.PlayerInteractListener; import dev.loki.lomines.listener.PlayerInteractListener;
import dev.loki.lomines.listener.PlayerJoinListener; import dev.loki.lomines.listener.PlayerJoinListener;
import dev.lolib.commands.CommandManager; 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 BlockBreakListener(plugin), plugin);
plugin.getServer().getPluginManager().registerEvents(new PlayerInteractListener(plugin), plugin); plugin.getServer().getPluginManager().registerEvents(new PlayerInteractListener(plugin), plugin);
plugin.getServer().getPluginManager().registerEvents(new GroupGuiListener(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)) { if (plugin.getConfig().getBoolean("statistics-enabled", true)) {
plugin.getServer().getPluginManager().registerEvents(new PlayerJoinListener(plugin), plugin); plugin.getServer().getPluginManager().registerEvents(new PlayerJoinListener(plugin), plugin);

View file

@ -3,20 +3,23 @@ package dev.loki.lomines.command;
import dev.loki.lomines.LoMinesPlugin; import dev.loki.lomines.LoMinesPlugin;
import dev.loki.lomines.core.Mine; import dev.loki.lomines.core.Mine;
import dev.loki.lomines.core.Mines; import dev.loki.lomines.core.Mines;
import dev.loki.lomines.gui.MineEditGui;
import dev.loki.lomines.util.ErrorHandler; import dev.loki.lomines.util.ErrorHandler;
import dev.loki.lomines.util.MessageFormatter; import dev.loki.lomines.util.MessageFormatter;
import dev.lolib.commands.annotation.Arg; import dev.lolib.commands.annotation.Arg;
import dev.lolib.commands.annotation.Command; import dev.lolib.commands.annotation.Command;
import dev.lolib.commands.annotation.Subcommand; import dev.lolib.commands.annotation.Subcommand;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
/** /**
* Admin commands for mine management. * 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") @Command(value = "lm", permission = "lomines.use")
public class AdminCommands { public class AdminCommands {
@ -43,6 +46,10 @@ public class AdminCommands {
sender.sendMessage(Component.text( sender.sendMessage(Component.text(
"Edit selection & contents in plugins/LoMines/mines/" + name + ".yml — " "Edit selection & contents in plugins/LoMines/mines/" + name + ".yml — "
+ "for shape-based ore (not full cuboid), paint mask.marker blocks, then: /lm maskscan " + name)); + "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) { } catch (IllegalArgumentException e) {
errorHandler.handleNotFound(sender, "Mine already exists", name); errorHandler.handleNotFound(sender, "Mine already exists", name);
} catch (IOException e) { } catch (IOException e) {
@ -68,6 +75,26 @@ public class AdminCommands {
} }
} }
/**
* Opens the GUI editor for a mine.
* Usage: /lm edit <mine>
*/
@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. * Resets a mine by refilling all its regions.
* Usage: /lm reset <mine> [silent] * Usage: /lm reset <mine> [silent]

View file

@ -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
}
}

View file

@ -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;
}
}

View file

@ -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
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -27,6 +27,7 @@ permissions:
lomines.stats.others: true lomines.stats.others: true
lomines.admin.wand: true lomines.admin.wand: true
lomines.admin.maskscan: true lomines.admin.maskscan: true
lomines.admin.edit: true
lomines.stats: lomines.stats:
description: View mining stats and leaderboards (/lm stats, /lm top) description: View mining stats and leaderboards (/lm stats, /lm top)
default: true default: true
@ -39,6 +40,9 @@ permissions:
lomines.admin.wand: lomines.admin.wand:
description: Group wand and /lm group prefix for batch mine creation description: Group wand and /lm group prefix for batch mine creation
default: op default: op
lomines.admin.edit:
description: Open GUI editor for mines (/lm edit <mine>)
default: op
lomines.use: lomines.use:
description: Basic LoMines usage description: Basic LoMines usage
default: true default: true