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:
parent
56249f47cf
commit
a9c8a0c323
8 changed files with 654 additions and 2 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
137
src/main/java/dev/loki/lomines/gui/ConfirmDeleteGui.java
Normal file
137
src/main/java/dev/loki/lomines/gui/ConfirmDeleteGui.java
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
332
src/main/java/dev/loki/lomines/gui/MineEditGui.java
Normal file
332
src/main/java/dev/loki/lomines/gui/MineEditGui.java
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/main/java/dev/loki/lomines/gui/MineEditGuiHolder.java
Normal file
38
src/main/java/dev/loki/lomines/gui/MineEditGuiHolder.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue