diff --git a/src/main/java/dev/loki/lomines/command/AdminCommands.java b/src/main/java/dev/loki/lomines/command/AdminCommands.java index 81398b3..cf61e41 100644 --- a/src/main/java/dev/loki/lomines/command/AdminCommands.java +++ b/src/main/java/dev/loki/lomines/command/AdminCommands.java @@ -3,6 +3,9 @@ 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.data.config.MineConfig; +import dev.loki.lomines.data.config.spawn.PlayerSpawnConfig; +import dev.loki.lomines.data.config.teleport.TeleportConfig; import dev.loki.lomines.gui.MineEditGui; import dev.loki.lomines.util.ErrorHandler; import dev.loki.lomines.util.MessageFormatter; @@ -11,6 +14,7 @@ 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.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -152,6 +156,133 @@ public class AdminCommands { } } + /** + * Sets the teleport location for players when mine resets. + * Usage: /lm setteleport + */ + @Subcommand(value = "setteleport", permission = "lomines.admin.setteleport") + public void setTeleport(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; + } + + try { + Mine mine = mines.find(mineName).orElse(null); + if (mine == null) { + errorHandler.handleNotFound(sender, "Mine", mineName); + return; + } + + // Get current player location and update config + var config = mine.getConfig(); + var newTeleport = TeleportConfig.at(player.getLocation()); + + var updatedConfig = MineConfig.builder(mineName) + .region(config.region()) + .blocks(config.blocks()) + .reset(config.reset()) + .rewards(config.rewards()) + .teleport(newTeleport) + .ui(config.ui()) + .worldGuard(config.worldGuard()) + .playerSpawn(config.playerSpawn()) + .build(); + + plugin.getMines().getFileManager().saveConfig(updatedConfig); + sender.sendMessage(MessageFormatter.success("Teleport location for mine '" + mineName + "' set to your current position")); + sender.sendMessage(Component.text("Location: " + formatLocation(player.getLocation()), NamedTextColor.GRAY)); + } catch (Exception e) { + errorHandler.handleError(sender, "Failed to set teleport: " + e.getMessage(), + "Failed to set teleport for " + mineName, e); + } + } + + /** + * Sets the safe spawn location for stuck players after mine reset. + * Usage: /lm setspawn + */ + @Subcommand(value = "setspawn", permission = "lomines.admin.setspawn") + public void setSpawn(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; + } + + try { + Mine mine = mines.find(mineName).orElse(null); + if (mine == null) { + errorHandler.handleNotFound(sender, "Mine", mineName); + return; + } + + // Get current player location and update config + var config = mine.getConfig(); + var newSpawn = PlayerSpawnConfig.at(player.getLocation()); + + var updatedConfig = MineConfig.builder(mineName) + .region(config.region()) + .blocks(config.blocks()) + .reset(config.reset()) + .rewards(config.rewards()) + .teleport(config.teleport()) + .ui(config.ui()) + .worldGuard(config.worldGuard()) + .playerSpawn(newSpawn) + .build(); + + plugin.getMines().getFileManager().saveConfig(updatedConfig); + sender.sendMessage(MessageFormatter.success("Safe spawn location for mine '" + mineName + "' set to your current position")); + sender.sendMessage(Component.text("Location: " + formatLocation(player.getLocation()), NamedTextColor.GRAY)); + sender.sendMessage(Component.text("Players stuck in blocks will be teleported here after reset", NamedTextColor.YELLOW)); + } catch (Exception e) { + errorHandler.handleError(sender, "Failed to set spawn: " + e.getMessage(), + "Failed to set spawn for " + mineName, e); + } + } + + /** + * Clears the spawn location for stuck players. + * Usage: /lm clearspawn + */ + @Subcommand(value = "clearspawn", permission = "lomines.admin.setspawn") + public void clearSpawn(CommandSender sender, @Arg("mine") String mineName) { + try { + Mine mine = mines.find(mineName).orElse(null); + if (mine == null) { + errorHandler.handleNotFound(sender, "Mine", mineName); + return; + } + + var config = mine.getConfig(); + var updatedConfig = MineConfig.builder(mineName) + .region(config.region()) + .blocks(config.blocks()) + .reset(config.reset()) + .rewards(config.rewards()) + .teleport(config.teleport()) + .ui(config.ui()) + .worldGuard(config.worldGuard()) + .playerSpawn(PlayerSpawnConfig.disabled()) + .build(); + + plugin.getMines().getFileManager().saveConfig(updatedConfig); + sender.sendMessage(MessageFormatter.success("Spawn location for mine '" + mineName + "' cleared")); + sender.sendMessage(Component.text("Players will use teleport location instead", NamedTextColor.GRAY)); + } catch (Exception e) { + errorHandler.handleError(sender, "Failed to clear spawn: " + e.getMessage(), + "Failed to clear spawn for " + mineName, e); + } + } + + /** + * Formats location for display. + */ + private String formatLocation(Location loc) { + return String.format("%.1f, %.1f, %.1f in %s", + loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName()); + } + /** * Formats mine status information for display. */ diff --git a/src/main/java/dev/loki/lomines/command/LoMinesTabCompleter.java b/src/main/java/dev/loki/lomines/command/LoMinesTabCompleter.java index 3477874..8204ee1 100644 --- a/src/main/java/dev/loki/lomines/command/LoMinesTabCompleter.java +++ b/src/main/java/dev/loki/lomines/command/LoMinesTabCompleter.java @@ -20,7 +20,8 @@ public class LoMinesTabCompleter implements TabCompleter { // Static command lists for fast lookup private static final List ADMIN_COMMANDS = List.of( - "create", "delete", "reset", "reload", "list", "maskscan" + "create", "delete", "reset", "reload", "list", "maskscan", + "edit", "setteleport", "setspawn", "clearspawn" ); private static final List PLAYER_COMMANDS = List.of( @@ -29,7 +30,8 @@ public class LoMinesTabCompleter implements TabCompleter { private static final List ALL_COMMANDS = List.of( "create", "delete", "reset", "reload", "list", "wand", "group", - "stats", "top", "maskscan", "help" + "stats", "top", "maskscan", "edit", "setteleport", "setspawn", + "clearspawn", "help" ); public LoMinesTabCompleter(LoMinesPlugin plugin) { @@ -65,7 +67,7 @@ public class LoMinesTabCompleter implements TabCompleter { String partial = args[1].toLowerCase(); switch (subcommand) { - case "delete", "reset", "maskscan" -> + case "delete", "reset", "maskscan", "edit", "setteleport", "setspawn", "clearspawn" -> completions.addAll(getMineNames(partial)); case "create" -> { if (partial.isEmpty()) { @@ -106,8 +108,10 @@ public class LoMinesTabCompleter implements TabCompleter { private boolean hasPermission(CommandSender sender, String command) { return switch (command) { - case "create", "delete", "reset", "reload", "list", "maskscan" -> + case "create", "delete", "reset", "reload", "list", "maskscan", "edit" -> sender.hasPermission("lomines.admin"); + case "setteleport" -> sender.hasPermission("lomines.admin.setteleport"); + case "setspawn", "clearspawn" -> sender.hasPermission("lomines.admin.setspawn"); case "wand", "group" -> sender.hasPermission("lomines.admin.wand"); case "stats" -> sender.hasPermission("lomines.stats"); case "top" -> sender.hasPermission("lomines.stats"); diff --git a/src/main/java/dev/loki/lomines/core/Mines.java b/src/main/java/dev/loki/lomines/core/Mines.java index b6413c2..49832be 100644 --- a/src/main/java/dev/loki/lomines/core/Mines.java +++ b/src/main/java/dev/loki/lomines/core/Mines.java @@ -198,4 +198,11 @@ public final class Mines { public WorldGuardRegionService getWorldGuardService() { return worldGuardService; } + + /** + * Returns the file manager for saving mine configurations. + */ + public MineFileManager getFileManager() { + return fileManager; + } } diff --git a/src/main/java/dev/loki/lomines/core/service/MineFileManager.java b/src/main/java/dev/loki/lomines/core/service/MineFileManager.java index 2e4a109..4abe321 100644 --- a/src/main/java/dev/loki/lomines/core/service/MineFileManager.java +++ b/src/main/java/dev/loki/lomines/core/service/MineFileManager.java @@ -134,6 +134,16 @@ public record MineFileManager(Path minesFolder, ConfigLoader configLoader) { } } + /** + * Saves a mine configuration to file. + * + * @param config the configuration to save + * @throws ConfigLoader.ConfigLoadException if saving fails + */ + public void saveConfig(MineConfig config) throws ConfigLoader.ConfigLoadException { + configLoader.save(config); + } + /** * Saves mask positions for mask fill mode. */ diff --git a/src/main/java/dev/loki/lomines/gui/MineEditGui.java b/src/main/java/dev/loki/lomines/gui/MineEditGui.java index 412e6a7..b8e4e9e 100644 --- a/src/main/java/dev/loki/lomines/gui/MineEditGui.java +++ b/src/main/java/dev/loki/lomines/gui/MineEditGui.java @@ -184,10 +184,17 @@ public final class MineEditGui { if (meta != null) { meta.displayName(Component.text("§aТелепорт", NamedTextColor.GREEN)); boolean enabled = config.teleport().enabled(); + boolean spawnEnabled = config.playerSpawn().enabled(); meta.lore(List.of( Component.text("Включено: " + (enabled ? "§aДа" : "§cНет"), NamedTextColor.GRAY), + Component.text("Точка спавна (застрявших): " + (spawnEnabled ? "§aДа" : "§7Нет"), NamedTextColor.GRAY), Component.empty(), - Component.text("§eНажмите для редактирования", NamedTextColor.YELLOW) + Component.text("§eНажмите для редактирования", NamedTextColor.YELLOW), + Component.empty(), + Component.text("§7Команды:", NamedTextColor.DARK_GRAY), + Component.text("§7/lm setteleport ", NamedTextColor.GRAY), + Component.text("§7/lm setspawn ", NamedTextColor.GRAY), + Component.text("§7/lm clearspawn ", NamedTextColor.GRAY) )); stack.setItemMeta(meta); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e01507e..3495af0 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -28,6 +28,8 @@ permissions: lomines.admin.wand: true lomines.admin.maskscan: true lomines.admin.edit: true + lomines.admin.setteleport: true + lomines.admin.setspawn: true lomines.stats: description: View mining stats and leaderboards (/lm stats, /lm top) default: true @@ -46,3 +48,9 @@ permissions: lomines.use: description: Basic LoMines usage default: true + lomines.admin.setteleport: + description: Set teleport location for mine reset (/lm setteleport ) + default: op + lomines.admin.setspawn: + description: Set safe spawn location for stuck players (/lm setspawn , /lm clearspawn ) + default: op