feat: add info, teleport, and copy commands
This commit is contained in:
parent
f6cccbcd33
commit
957468b6b6
6 changed files with 305 additions and 6 deletions
|
|
@ -1,11 +1,14 @@
|
|||
package dev.loki.lomines;
|
||||
|
||||
import dev.loki.lomines.command.admin.AdminCommands;
|
||||
import dev.loki.lomines.command.admin.CopyCommand;
|
||||
import dev.loki.lomines.command.admin.HologramCommands;
|
||||
import dev.loki.lomines.command.admin.InfoCommand;
|
||||
import dev.loki.lomines.command.admin.MaskCommands;
|
||||
import dev.loki.lomines.command.admin.StatsCommands;
|
||||
import dev.loki.lomines.command.common.LoMinesTabCompleter;
|
||||
import dev.loki.lomines.command.player.PlayerCommands;
|
||||
import dev.loki.lomines.command.player.TeleportCommand;
|
||||
import dev.loki.lomines.integration.IntegrationManager;
|
||||
import dev.loki.lomines.listener.BlockBreakListener;
|
||||
import dev.loki.lomines.listener.GroupGuiListener;
|
||||
|
|
@ -31,6 +34,9 @@ final class RegistrationManager {
|
|||
commandManager.register(new StatsCommands(plugin));
|
||||
commandManager.register(new MaskCommands(plugin));
|
||||
commandManager.register(new HologramCommands(plugin));
|
||||
commandManager.register(new InfoCommand(plugin));
|
||||
commandManager.register(new TeleportCommand(plugin));
|
||||
commandManager.register(new CopyCommand(plugin));
|
||||
|
||||
plugin.loLogger().info("Commands registered");
|
||||
}
|
||||
|
|
|
|||
108
src/main/java/dev/loki/lomines/command/admin/CopyCommand.java
Normal file
108
src/main/java/dev/loki/lomines/command/admin/CopyCommand.java
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
package dev.loki.lomines.command.admin;
|
||||
|
||||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.Mine;
|
||||
import dev.loki.lomines.core.mine.MineConfig;
|
||||
import dev.lolilb.commands.annotation.Arg;
|
||||
import dev.lolilb.commands.annotation.Subcommand;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Command to copy mine configuration from one mine to another.
|
||||
*/
|
||||
public class CopyCommand {
|
||||
|
||||
private final LoMinesPlugin plugin;
|
||||
|
||||
public CopyCommand(LoMinesPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies mine configuration (blocks, reset settings, rewards, etc.)
|
||||
* from source mine to target mine. Regions and positions are NOT copied.
|
||||
* Usage: /lm copy <from> <to>
|
||||
*/
|
||||
@Subcommand(value = "copy", permission = "lomines.admin.copy")
|
||||
void copy(CommandSender sender,
|
||||
@Arg("from-mine") String fromMineName,
|
||||
@Arg("to-mine") String toMineName) {
|
||||
|
||||
Mine fromMine = plugin.getMines().find(fromMineName).orElse(null);
|
||||
if (fromMine == null) {
|
||||
sender.sendMessage(Component.text("Исходная шахта не найдена: " + fromMineName, NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
Mine toMine = plugin.getMines().find(toMineName).orElse(null);
|
||||
if (toMine == null) {
|
||||
sender.sendMessage(Component.text("Целевая шахта не найдена: " + toMineName, NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fromMine.getName().equalsIgnoreCase(toMine.getName())) {
|
||||
sender.sendMessage(Component.text("Нельзя копировать шахту саму в себя!", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceConfig = fromMine.getConfig();
|
||||
var targetConfig = toMine.getConfig();
|
||||
|
||||
// Copy blocks configuration
|
||||
targetConfig.blocks().weights().clear();
|
||||
targetConfig.blocks().weights().putAll(sourceConfig.blocks().weights());
|
||||
|
||||
// Copy reset settings
|
||||
var targetReset = targetConfig.reset();
|
||||
var sourceReset = sourceConfig.reset();
|
||||
targetReset.intervalSeconds(sourceReset.intervalSeconds());
|
||||
targetReset.percentTrigger(sourceReset.percentTrigger());
|
||||
targetReset.percentTriggerEnabled(sourceReset.isPercentTriggerEnabled());
|
||||
targetReset.intervalDisplay(sourceReset.intervalDisplay());
|
||||
|
||||
// Copy teleport and spawn settings
|
||||
var targetTeleport = targetConfig.teleport();
|
||||
var sourceTeleport = sourceConfig.teleport();
|
||||
targetTeleport.enabled(sourceTeleport.enabled());
|
||||
if (sourceTeleport.getLocation().isPresent()) {
|
||||
targetTeleport.setLocation(sourceTeleport.getLocation().get());
|
||||
} else {
|
||||
targetTeleport.setLocation(null);
|
||||
}
|
||||
|
||||
var targetSpawn = targetConfig.playerSpawn();
|
||||
var sourceSpawn = sourceConfig.playerSpawn();
|
||||
targetSpawn.enabled(sourceSpawn.enabled());
|
||||
if (sourceSpawn.getLocation().isPresent()) {
|
||||
targetSpawn.setLocation(sourceSpawn.getLocation().get());
|
||||
} else {
|
||||
targetSpawn.setLocation(null);
|
||||
}
|
||||
|
||||
// Copy rewards
|
||||
targetConfig.rewards().entries().clear();
|
||||
targetConfig.rewards().entries().addAll(sourceConfig.rewards().entries());
|
||||
|
||||
// Copy other settings
|
||||
targetConfig.blockPhysics(sourceConfig.isBlockPhysicsEnabled());
|
||||
targetConfig.entitySpawning(sourceConfig.isEntitySpawningEnabled());
|
||||
targetConfig.liquidFlow(sourceConfig.isLiquidFlowEnabled());
|
||||
|
||||
// Save target mine
|
||||
toMine.save();
|
||||
|
||||
sender.sendMessage(Component.text("§aКонфигурация скопирована из §f" + fromMine.getName() +
|
||||
" §aв §f" + toMine.getName()));
|
||||
sender.sendMessage(Component.text("§7Скопировано:"));
|
||||
sender.sendMessage(Component.text(" §7• Блоки: §f" + sourceConfig.blocks().weights().size() + " типов"));
|
||||
sender.sendMessage(Component.text(" §7• Настройки сброса"));
|
||||
sender.sendMessage(Component.text(" §7• Точки телепорта/спавна"));
|
||||
sender.sendMessage(Component.text(" §7• Награды: §f" + sourceConfig.rewards().entries().size() + " записей"));
|
||||
sender.sendMessage(Component.text("§7§oПримечание: регионы и позиции не скопированы"));
|
||||
}
|
||||
}
|
||||
105
src/main/java/dev/loki/lomines/command/admin/InfoCommand.java
Normal file
105
src/main/java/dev/loki/lomines/command/admin/InfoCommand.java
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
package dev.loki.lomines.command.admin;
|
||||
|
||||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.Mine;
|
||||
import dev.loki.lomines.data.config.block.BlockKey;
|
||||
import dev.loki.lomines.util.location.Cuboid;
|
||||
import dev.lolilb.commands.annotation.Arg;
|
||||
import dev.lolilb.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.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Command to display detailed information about a mine.
|
||||
*/
|
||||
public class InfoCommand {
|
||||
|
||||
private final LoMinesPlugin plugin;
|
||||
|
||||
public InfoCommand(LoMinesPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows detailed information about a mine.
|
||||
* Usage: /lm info <mine>
|
||||
*/
|
||||
@Subcommand(value = "info", permission = "lomines.admin.info")
|
||||
void info(CommandSender sender, @Arg("mine") String mineName) {
|
||||
Mine mine = plugin.getMines().find(mineName).orElse(null);
|
||||
if (mine == null) {
|
||||
sender.sendMessage(Component.text("Шахта не найдена: " + mineName, NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
var config = mine.getConfig();
|
||||
|
||||
sender.sendMessage(Component.text("§8§m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
||||
sender.sendMessage(Component.text("§6§lИнформация о шахте: §f" + mine.getName()));
|
||||
sender.sendMessage(Component.text(""));
|
||||
|
||||
// Basic info
|
||||
sender.sendMessage(Component.text("§7Мир: §f" + config.worldName()));
|
||||
sender.sendMessage(Component.text("§7Блоков: §f" + mine.getBlocks() + "§7/§f" + mine.getTotalVolume() +
|
||||
" §7(§f" + String.format("%.1f", mine.getPercentFilled()) + "%§7)"));
|
||||
sender.sendMessage(Component.text(""));
|
||||
|
||||
// Regions
|
||||
sender.sendMessage(Component.text("§6§lРегионы:"));
|
||||
List<Cuboid> regions = mine.getRegions();
|
||||
for (int i = 0; i < regions.size(); i++) {
|
||||
Cuboid r = regions.get(i);
|
||||
sender.sendMessage(Component.text("§7 #" + (i + 1) + ": §f" +
|
||||
r.getMinX() + "," + r.getMinY() + "," + r.getMinZ() + " §7-> §f" +
|
||||
r.getMaxX() + "," + r.getMaxY() + "," + r.getMaxZ() +
|
||||
" §7(§f" + r.getVolume() + " §7блоков)"));
|
||||
}
|
||||
sender.sendMessage(Component.text(""));
|
||||
|
||||
// Blocks
|
||||
sender.sendMessage(Component.text("§6§lБлоки:"));
|
||||
Map<BlockKey, Double> weights = config.blocks().weights();
|
||||
weights.entrySet().stream()
|
||||
.sorted((a, b) -> Double.compare(b.getValue(), a.getValue()))
|
||||
.limit(10)
|
||||
.forEach(e -> sender.sendMessage(Component.text(
|
||||
"§7 " + formatBlockKey(e.getKey()) + ": §f" + String.format("%.1f", e.getValue() * 100) + "%")));
|
||||
if (weights.size() > 10) {
|
||||
sender.sendMessage(Component.text("§7 ... и ещё " + (weights.size() - 10) + " блоков"));
|
||||
}
|
||||
sender.sendMessage(Component.text(""));
|
||||
|
||||
// Reset settings
|
||||
sender.sendMessage(Component.text("§6§lНастройки сброса:"));
|
||||
sender.sendMessage(Component.text("§7 Интервал: §f" + config.reset().intervalDisplay()));
|
||||
sender.sendMessage(Component.text("§7 Триггер по %: §f" +
|
||||
(config.reset().isPercentTriggerEnabled() ? config.reset().percentTrigger() + "%" : "выкл")));
|
||||
sender.sendMessage(Component.text(""));
|
||||
|
||||
// Teleport/Spawn
|
||||
sender.sendMessage(Component.text("§6§lТелепортация:"));
|
||||
sender.sendMessage(Component.text("§7 Точка телепорта: §f" +
|
||||
(config.teleport().enabled() ? "§aустановлена" : "§7не задана")));
|
||||
sender.sendMessage(Component.text("§7 Точка спавна: §f" +
|
||||
(config.playerSpawn().enabled() ? "§aустановлена" : "§7используется точка телепорта")));
|
||||
sender.sendMessage(Component.text(""));
|
||||
|
||||
// Rewards
|
||||
sender.sendMessage(Component.text("§6§lНаграды: §f" + config.rewards().entries().size() + " записей"));
|
||||
|
||||
sender.sendMessage(Component.text("§8§m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
||||
}
|
||||
|
||||
private String formatBlockKey(BlockKey key) {
|
||||
return switch (key) {
|
||||
case BlockKey.Vanilla v -> v.material().name().toLowerCase();
|
||||
case BlockKey.Oraxen o -> "oraxen:" + o.id();
|
||||
case BlockKey.ItemsAdder i -> "ia:" + i.id();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
private static final List<String> ALL_COMMANDS = List.of(
|
||||
"create", "delete", "reset", "reload", "list", "wand", "group",
|
||||
"stats", "top", "maskscan", "edit", "setteleport", "setspawn",
|
||||
"clearspawn", "help"
|
||||
"clearspawn", "info", "tp", "copy", "help"
|
||||
);
|
||||
|
||||
private static final List<String> BOOLEAN_VALUES = List.of("true", "false");
|
||||
|
|
@ -67,11 +67,13 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
private List<String> completeSecondArg(CommandSender sender, String subcommand, String partial) {
|
||||
return switch (subcommand) {
|
||||
case "create" -> completeCreate(partial);
|
||||
case "delete", "maskscan", "edit", "setteleport", "setspawn", "clearspawn" ->
|
||||
case "delete", "maskscan", "edit", "setteleport", "setspawn", "clearspawn", "info" ->
|
||||
filterStartsWith(getMineNames(), partial);
|
||||
case "reset" -> completeReset(partial);
|
||||
case "stats" -> completeStats(sender, partial);
|
||||
case "top" -> completeTopFirstArg(partial);
|
||||
case "tp" -> completeTeleport(sender, partial);
|
||||
case "copy" -> completeCopyFirstArg(partial);
|
||||
default -> new ArrayList<>();
|
||||
};
|
||||
}
|
||||
|
|
@ -80,6 +82,7 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
return switch (subcommand) {
|
||||
case "reset" -> filterStartsWith(BOOLEAN_VALUES, partial);
|
||||
case "top" -> completeTopSecondArg(arg2, partial);
|
||||
case "copy" -> filterStartsWith(getMineNames(), partial);
|
||||
default -> new ArrayList<>();
|
||||
};
|
||||
}
|
||||
|
|
@ -132,6 +135,17 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private List<String> completeTeleport(CommandSender sender, String partial) {
|
||||
if (!sender.hasPermission("lomines.teleport")) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return filterStartsWith(getMineNames(), partial);
|
||||
}
|
||||
|
||||
private List<String> completeCopyFirstArg(String partial) {
|
||||
return filterStartsWith(getMineNames(), partial);
|
||||
}
|
||||
|
||||
private boolean isNumericPartial(String partial) {
|
||||
return partial.isEmpty() || partial.matches("\\d*");
|
||||
}
|
||||
|
|
@ -156,13 +170,15 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
|
||||
private boolean hasPermission(CommandSender sender, String cmd) {
|
||||
return switch (cmd) {
|
||||
case "create", "delete", "reload", "list", "maskscan", "edit" ->
|
||||
case "create", "delete", "reload", "list", "maskscan", "edit", "info" ->
|
||||
sender.hasPermission("lomines.admin");
|
||||
case "reset" -> sender.hasPermission("lomines.admin.reset");
|
||||
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", "top" -> sender.hasPermission("lomines.stats");
|
||||
case "tp" -> sender.hasPermission("lomines.teleport");
|
||||
case "copy" -> sender.hasPermission("lomines.admin.copy");
|
||||
case "help" -> sender.hasPermission("lomines.use");
|
||||
default -> true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
package dev.loki.lomines.command.player;
|
||||
|
||||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.Mine;
|
||||
import dev.loki.lomines.util.location.Cuboid;
|
||||
import dev.lolilb.commands.annotation.Arg;
|
||||
import dev.lolilb.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;
|
||||
|
||||
/**
|
||||
* Command to teleport to a mine.
|
||||
*/
|
||||
public class TeleportCommand {
|
||||
|
||||
private final LoMinesPlugin plugin;
|
||||
|
||||
public TeleportCommand(LoMinesPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teleports player to the mine's location.
|
||||
* Usage: /lm tp <mine>
|
||||
*/
|
||||
@Subcommand(value = "tp", permission = "lomines.teleport")
|
||||
void teleport(CommandSender sender, @Arg("mine") String mineName) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(Component.text("Эта команда только для игроков!", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
Mine mine = plugin.getMines().find(mineName).orElse(null);
|
||||
if (mine == null) {
|
||||
player.sendMessage(Component.text("Шахта не найдена: " + mineName, NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
var config = mine.getConfig();
|
||||
Location target;
|
||||
|
||||
// Try teleport location first
|
||||
if (config.teleport().enabled() && config.teleport().getLocation().isPresent()) {
|
||||
target = config.teleport().getLocation().get();
|
||||
} else if (!mine.getRegions().isEmpty()) {
|
||||
// Use center of first region
|
||||
Cuboid region = mine.getRegions().get(0);
|
||||
double centerX = (region.getMinX() + region.getMaxX()) / 2.0 + 0.5;
|
||||
double centerZ = (region.getMinZ() + region.getMaxZ()) / 2.0 + 0.5;
|
||||
double centerY = region.getMaxY() + 1;
|
||||
target = new Location(region.getWorld(), centerX, centerY, centerZ);
|
||||
} else {
|
||||
player.sendMessage(Component.text("У шахты нет настроенной точки телепорта!", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
player.teleport(target);
|
||||
player.sendMessage(Component.text("§aТелепортировано к шахте §f" + mine.getName() +
|
||||
" §a(§f" + String.format("%.0f, %.0f, %.0f", target.getX(), target.getY(), target.getZ()) + "§a)"));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue