feat: add multiple region support for mines
This commit is contained in:
parent
957468b6b6
commit
0f2735f171
8 changed files with 403 additions and 33 deletions
|
|
@ -5,6 +5,7 @@ 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.RegionCommands;
|
||||
import dev.loki.lomines.command.admin.StatsCommands;
|
||||
import dev.loki.lomines.command.common.LoMinesTabCompleter;
|
||||
import dev.loki.lomines.command.player.PlayerCommands;
|
||||
|
|
@ -37,6 +38,7 @@ final class RegistrationManager {
|
|||
commandManager.register(new InfoCommand(plugin));
|
||||
commandManager.register(new TeleportCommand(plugin));
|
||||
commandManager.register(new CopyCommand(plugin));
|
||||
commandManager.register(new RegionCommands(plugin));
|
||||
|
||||
plugin.loLogger().info("Commands registered");
|
||||
}
|
||||
|
|
|
|||
161
src/main/java/dev/loki/lomines/command/admin/RegionCommands.java
Normal file
161
src/main/java/dev/loki/lomines/command/admin/RegionCommands.java
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
package dev.loki.lomines.command.admin;
|
||||
|
||||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.Mine;
|
||||
import dev.loki.lomines.data.config.MineConfig;
|
||||
import dev.loki.lomines.data.config.region.RegionConfig;
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Commands for managing mine regions (multiple spawn areas).
|
||||
*/
|
||||
public class RegionCommands {
|
||||
|
||||
private final LoMinesPlugin plugin;
|
||||
|
||||
public RegionCommands(LoMinesPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all regions in a mine.
|
||||
* Usage: /lm regions <mine>
|
||||
*/
|
||||
@Subcommand(value = "regions", permission = "lomines.admin.regions")
|
||||
void listRegions(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;
|
||||
}
|
||||
|
||||
List<Cuboid> regions = mine.getRegions();
|
||||
sender.sendMessage(Component.text("§8§m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
||||
sender.sendMessage(Component.text("§6§lРегионы шахты §f" + mine.getName()));
|
||||
sender.sendMessage(Component.text("§7Всего регионов: §f" + regions.size()));
|
||||
sender.sendMessage(Component.text(""));
|
||||
|
||||
for (int i = 0; i < regions.size(); i++) {
|
||||
Cuboid r = regions.get(i);
|
||||
sender.sendMessage(Component.text("§e#" + (i + 1) + " §7(§f" + r.getVolume() + " §7блоков)"));
|
||||
sender.sendMessage(Component.text(" §7Мир: §f" + r.getWorld().getName()));
|
||||
sender.sendMessage(Component.text(" §7От: §f" + r.getMinX() + ", " + r.getMinY() + ", " + r.getMinZ()));
|
||||
sender.sendMessage(Component.text(" §7До: §f" + r.getMaxX() + ", " + r.getMaxY() + ", " + r.getMaxZ()));
|
||||
}
|
||||
sender.sendMessage(Component.text("§8§m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new region to a mine using current wand selection.
|
||||
* Usage: /lm addregion <mine>
|
||||
*/
|
||||
@Subcommand(value = "addregion", permission = "lomines.admin.regions")
|
||||
void addRegion(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 wandManager = plugin.getGroupWandManager();
|
||||
var session = wandManager.getSession(player);
|
||||
|
||||
if (!session.isComplete()) {
|
||||
player.sendMessage(Component.text("§cВыделите регион палочкой! ЛКМ - 1-я точка, ПКМ - 2-я точка"));
|
||||
return;
|
||||
}
|
||||
|
||||
Cuboid newRegion = session.toCuboid();
|
||||
String mineWorld = mine.getConfig().region().worldName();
|
||||
String regionWorld = newRegion.getWorld().getName();
|
||||
|
||||
if (!mineWorld.equals(regionWorld)) {
|
||||
player.sendMessage(Component.text("§cРегион должен быть в мире §f" + mineWorld + "§c, а не §f" + regionWorld));
|
||||
return;
|
||||
}
|
||||
|
||||
// Add new region to existing regions
|
||||
List<Cuboid> currentRegions = new ArrayList<>(mine.getRegions());
|
||||
currentRegions.add(newRegion);
|
||||
|
||||
// Update config
|
||||
var newRegionConfig = new RegionConfig(currentRegions);
|
||||
updateMineRegions(mine, newRegionConfig);
|
||||
|
||||
player.sendMessage(Component.text("§aДобавлен регион #" + currentRegions.size()));
|
||||
player.sendMessage(Component.text("§7От: §f" + newRegion.getMinX() + ", " + newRegion.getMinY() + ", " + newRegion.getMinZ()));
|
||||
player.sendMessage(Component.text("§7До: §f" + newRegion.getMaxX() + ", " + newRegion.getMaxY() + ", " + newRegion.getMaxZ()));
|
||||
player.sendMessage(Component.text("§7Объём: §f" + newRegion.getVolume() + " §7блоков"));
|
||||
|
||||
session.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a region by index.
|
||||
* Usage: /lm removeregion <mine> <index>
|
||||
*/
|
||||
@Subcommand(value = "removeregion", permission = "lomines.admin.regions")
|
||||
void removeRegion(CommandSender sender,
|
||||
@Arg("mine") String mineName,
|
||||
@Arg("index") int index) {
|
||||
Mine mine = plugin.getMines().find(mineName).orElse(null);
|
||||
if (mine == null) {
|
||||
sender.sendMessage(Component.text("Шахта не найдена: " + mineName, NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
List<Cuboid> currentRegions = new ArrayList<>(mine.getRegions());
|
||||
|
||||
if (currentRegions.size() <= 1) {
|
||||
sender.sendMessage(Component.text("§cНельзя удалить последний регион! Удалите всю шахту."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 1 || index > currentRegions.size()) {
|
||||
sender.sendMessage(Component.text("§cНеверный номер региона. Доступны: 1-" + currentRegions.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
Cuboid removed = currentRegions.remove(index - 1);
|
||||
var newRegionConfig = new RegionConfig(currentRegions);
|
||||
updateMineRegions(mine, newRegionConfig);
|
||||
|
||||
sender.sendMessage(Component.text("§aУдалён регион #" + index));
|
||||
sender.sendMessage(Component.text("§7Был: §f" + removed.getMinX() + ", " + removed.getMinY() + ", " + removed.getMinZ() +
|
||||
" §7-> §f" + removed.getMaxX() + ", " + removed.getMaxY() + ", " + removed.getMaxZ()));
|
||||
sender.sendMessage(Component.text("§7Осталось регионов: §f" + currentRegions.size()));
|
||||
}
|
||||
|
||||
private void updateMineRegions(Mine mine, RegionConfig newConfig) {
|
||||
var oldConfig = mine.getConfig();
|
||||
var newMineConfig = new MineConfig(
|
||||
newConfig,
|
||||
oldConfig.blocks(),
|
||||
oldConfig.reset(),
|
||||
oldConfig.teleport(),
|
||||
oldConfig.playerSpawn(),
|
||||
oldConfig.rewards(),
|
||||
oldConfig.ui(),
|
||||
oldConfig.worldGuard()
|
||||
);
|
||||
|
||||
// Update and save
|
||||
plugin.getMines().updateMineConfig(mine.getName(), newMineConfig);
|
||||
mine.save();
|
||||
}
|
||||
}
|
||||
|
|
@ -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", "info", "tp", "copy", "help"
|
||||
"clearspawn", "info", "tp", "copy", "regions", "addregion", "removeregion", "help"
|
||||
);
|
||||
|
||||
private static final List<String> BOOLEAN_VALUES = List.of("true", "false");
|
||||
|
|
@ -67,13 +67,15 @@ 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", "info" ->
|
||||
case "delete", "maskscan", "edit", "setteleport", "setspawn", "clearspawn", "info",
|
||||
"regions", "addregion" ->
|
||||
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);
|
||||
case "removeregion" -> completeRemoveRegion(sender, partial);
|
||||
default -> new ArrayList<>();
|
||||
};
|
||||
}
|
||||
|
|
@ -83,10 +85,24 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
case "reset" -> filterStartsWith(BOOLEAN_VALUES, partial);
|
||||
case "top" -> completeTopSecondArg(arg2, partial);
|
||||
case "copy" -> filterStartsWith(getMineNames(), partial);
|
||||
case "removeregion" -> completeRegionIndex(arg2, partial);
|
||||
default -> new ArrayList<>();
|
||||
};
|
||||
}
|
||||
|
||||
private List<String> completeRegionIndex(String mineName, String partial) {
|
||||
var mine = plugin.getMines().find(mineName);
|
||||
if (mine.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
int regionCount = mine.get().getRegions().size();
|
||||
List<String> indices = new ArrayList<>();
|
||||
for (int i = 1; i <= regionCount; i++) {
|
||||
indices.add(String.valueOf(i));
|
||||
}
|
||||
return filterStartsWith(indices, partial);
|
||||
}
|
||||
|
||||
private List<String> completeCreate(String partial) {
|
||||
if (partial.isEmpty()) {
|
||||
return new ArrayList<>(List.of("<name>"));
|
||||
|
|
@ -146,6 +162,13 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
return filterStartsWith(getMineNames(), partial);
|
||||
}
|
||||
|
||||
private List<String> completeRemoveRegion(CommandSender sender, String partial) {
|
||||
if (!sender.hasPermission("lomines.admin.regions")) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return filterStartsWith(getMineNames(), partial);
|
||||
}
|
||||
|
||||
private boolean isNumericPartial(String partial) {
|
||||
return partial.isEmpty() || partial.matches("\\d*");
|
||||
}
|
||||
|
|
@ -179,6 +202,7 @@ public class LoMinesTabCompleter implements TabCompleter {
|
|||
case "stats", "top" -> sender.hasPermission("lomines.stats");
|
||||
case "tp" -> sender.hasPermission("lomines.teleport");
|
||||
case "copy" -> sender.hasPermission("lomines.admin.copy");
|
||||
case "regions", "addregion", "removeregion" -> sender.hasPermission("lomines.admin.regions");
|
||||
case "help" -> sender.hasPermission("lomines.use");
|
||||
default -> true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -112,6 +112,34 @@ public final class Mines {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates mine configuration and saves to disk.
|
||||
* Used for modifying regions, blocks, etc.
|
||||
*/
|
||||
public void updateMineConfig(String name, MineConfig newConfig) throws IOException {
|
||||
if (!repository.exists(name)) {
|
||||
throw new IllegalArgumentException("Mine not found: " + name);
|
||||
}
|
||||
|
||||
// Save new config to file
|
||||
fileManager.saveConfig(name, newConfig);
|
||||
|
||||
// Reload to apply changes
|
||||
try {
|
||||
Mine oldMine = repository.find(name).orElse(null);
|
||||
repository.reload(name);
|
||||
|
||||
if (oldMine != null) {
|
||||
Mine newMine = repository.find(name).orElse(null);
|
||||
if (newMine != null) {
|
||||
worldGuardService.updateRegion(name, newMine.getConfig());
|
||||
}
|
||||
}
|
||||
} catch (ConfigLoader.ConfigLoadException e) {
|
||||
throw new IOException("Failed to reload mine after config update: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public WorldGuardRegionService getWorldGuardService() {
|
||||
return worldGuardService;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,6 +144,22 @@ public record MineFileManager(Path minesFolder, ConfigLoader configLoader) {
|
|||
configLoader.save(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a mine configuration to file by name.
|
||||
*
|
||||
* @param name the mine name
|
||||
* @param config the configuration to save
|
||||
* @throws ConfigLoader.ConfigLoadException if saving fails
|
||||
*/
|
||||
public void saveConfig(String name, MineConfig config) throws ConfigLoader.ConfigLoadException {
|
||||
// Ensure the config has the correct name
|
||||
MineConfig configToSave = config;
|
||||
if (!name.equals(config.region().worldName())) {
|
||||
// Config name doesn't matter internally, just save as-is
|
||||
}
|
||||
configLoader.save(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves mask positions for mask fill mode.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,33 +2,65 @@ package dev.loki.lomines.data.config.spawn;
|
|||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Configuration for player spawn location when stuck in blocks.
|
||||
* Configuration for player spawn locations when stuck in blocks.
|
||||
* Supports multiple spawn points for a single mine.
|
||||
* Used to teleport players out when they are suffocating after mine reset.
|
||||
*/
|
||||
public record PlayerSpawnConfig(
|
||||
boolean enabled,
|
||||
Location location
|
||||
) {
|
||||
public final class PlayerSpawnConfig {
|
||||
|
||||
public PlayerSpawnConfig {
|
||||
if (!enabled) {
|
||||
location = null;
|
||||
} else if (location != null) {
|
||||
// Defensive copy
|
||||
location = location.clone();
|
||||
Objects.requireNonNull(location.getWorld(), "Spawn world cannot be null");
|
||||
private final boolean enabled;
|
||||
private final List<Location> locations;
|
||||
|
||||
public PlayerSpawnConfig(boolean enabled, List<Location> locations) {
|
||||
this.enabled = enabled;
|
||||
if (!enabled || locations == null) {
|
||||
this.locations = List.of();
|
||||
} else {
|
||||
// Defensive copy with validation
|
||||
List<Location> copy = new ArrayList<>();
|
||||
for (Location loc : locations) {
|
||||
if (loc != null) {
|
||||
Location cloned = loc.clone();
|
||||
Objects.requireNonNull(cloned.getWorld(), "Spawn world cannot be null");
|
||||
copy.add(cloned);
|
||||
}
|
||||
}
|
||||
this.locations = List.copyOf(copy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the spawn location if enabled.
|
||||
* Returns the primary spawn location (first in list) if enabled.
|
||||
*/
|
||||
public Optional<Location> getLocation() {
|
||||
return Optional.ofNullable(enabled ? location : null);
|
||||
return locations.isEmpty() ? Optional.empty() : Optional.of(locations.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all spawn locations.
|
||||
*/
|
||||
public List<Location> getLocations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if spawn is enabled and has at least one location.
|
||||
*/
|
||||
public boolean enabled() {
|
||||
return enabled && !locations.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of configured spawn locations.
|
||||
*/
|
||||
public int count() {
|
||||
return locations.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -39,9 +71,44 @@ public record PlayerSpawnConfig(
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates enabled config with location.
|
||||
* Creates enabled config with single location.
|
||||
*/
|
||||
public static PlayerSpawnConfig at(Location location) {
|
||||
return new PlayerSpawnConfig(true, location);
|
||||
return new PlayerSpawnConfig(true, List.of(location));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates enabled config with multiple locations.
|
||||
*/
|
||||
public static PlayerSpawnConfig at(List<Location> locations) {
|
||||
return new PlayerSpawnConfig(true, locations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new config with an additional location.
|
||||
*/
|
||||
public PlayerSpawnConfig addLocation(Location location) {
|
||||
List<Location> newList = new ArrayList<>(locations);
|
||||
newList.add(location);
|
||||
return new PlayerSpawnConfig(true, newList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new config without the location at given index.
|
||||
*/
|
||||
public PlayerSpawnConfig removeLocation(int index) {
|
||||
if (index < 0 || index >= locations.size()) {
|
||||
return this;
|
||||
}
|
||||
List<Location> newList = new ArrayList<>(locations);
|
||||
newList.remove(index);
|
||||
return new PlayerSpawnConfig(!newList.isEmpty(), newList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all locations (disables spawn).
|
||||
*/
|
||||
public PlayerSpawnConfig clear() {
|
||||
return disabled();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,32 +2,65 @@ package dev.loki.lomines.data.config.teleport;
|
|||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Configuration for mine teleportation on reset.
|
||||
* Supports multiple teleport locations for a single mine.
|
||||
*/
|
||||
public record TeleportConfig(
|
||||
boolean enabled,
|
||||
Location location
|
||||
) {
|
||||
public final class TeleportConfig {
|
||||
|
||||
public TeleportConfig {
|
||||
if (!enabled) {
|
||||
location = null;
|
||||
} else if (location != null) {
|
||||
// Defensive copy
|
||||
location = location.clone();
|
||||
Objects.requireNonNull(location.getWorld(), "Teleport world cannot be null");
|
||||
private final boolean enabled;
|
||||
private final List<Location> locations;
|
||||
|
||||
public TeleportConfig(boolean enabled, List<Location> locations) {
|
||||
this.enabled = enabled;
|
||||
if (!enabled || locations == null) {
|
||||
this.locations = List.of();
|
||||
} else {
|
||||
// Defensive copy with validation
|
||||
List<Location> copy = new ArrayList<>();
|
||||
for (Location loc : locations) {
|
||||
if (loc != null) {
|
||||
Location cloned = loc.clone();
|
||||
Objects.requireNonNull(cloned.getWorld(), "Teleport world cannot be null");
|
||||
copy.add(cloned);
|
||||
}
|
||||
}
|
||||
this.locations = List.copyOf(copy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the teleport location if enabled.
|
||||
* Returns the primary teleport location (first in list) if enabled.
|
||||
*/
|
||||
public Optional<Location> getLocation() {
|
||||
return Optional.ofNullable(enabled ? location : null);
|
||||
return locations.isEmpty() ? Optional.empty() : Optional.of(locations.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all teleport locations.
|
||||
*/
|
||||
public List<Location> getLocations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if teleport is enabled and has at least one location.
|
||||
*/
|
||||
public boolean enabled() {
|
||||
return enabled && !locations.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of configured teleport locations.
|
||||
*/
|
||||
public int count() {
|
||||
return locations.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,9 +71,44 @@ public record TeleportConfig(
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates enabled config with location.
|
||||
* Creates enabled config with single location.
|
||||
*/
|
||||
public static TeleportConfig at(Location location) {
|
||||
return new TeleportConfig(true, location);
|
||||
return new TeleportConfig(true, List.of(location));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates enabled config with multiple locations.
|
||||
*/
|
||||
public static TeleportConfig at(List<Location> locations) {
|
||||
return new TeleportConfig(true, locations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new config with an additional location.
|
||||
*/
|
||||
public TeleportConfig addLocation(Location location) {
|
||||
List<Location> newList = new ArrayList<>(locations);
|
||||
newList.add(location);
|
||||
return new TeleportConfig(true, newList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new config without the location at given index.
|
||||
*/
|
||||
public TeleportConfig removeLocation(int index) {
|
||||
if (index < 0 || index >= locations.size()) {
|
||||
return this;
|
||||
}
|
||||
List<Location> newList = new ArrayList<>(locations);
|
||||
newList.remove(index);
|
||||
return new TeleportConfig(!newList.isEmpty(), newList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all locations (disables teleport).
|
||||
*/
|
||||
public TeleportConfig clear() {
|
||||
return disabled();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
todo.md
4
todo.md
|
|
@ -450,6 +450,10 @@ dev.loki.lomines/
|
|||
- [x] Добавить `/lm tp <mine>` — телепортация ✅
|
||||
- [x] Добавить `/lm copy <from> <to>` — копирование ✅
|
||||
- [x] Разбить большие GUI файлы (>200 строк) ✅
|
||||
- [x] Множественные регионы в одной шахте ✅
|
||||
- `/lm regions <mine>` — список регионов
|
||||
- `/lm addregion <mine>` — добавить регион
|
||||
- `/lm removeregion <mine> <index>` — удалить регион
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue