chore: rewrite ARCHITECTURE, enable tests via MockBukkit, checkstyle for tests, cleanup bin/libs
This commit is contained in:
parent
a0c1ab8ca1
commit
e8d516020c
53 changed files with 1093 additions and 1410 deletions
966
ARCHITECTURE.md
966
ARCHITECTURE.md
File diff suppressed because it is too large
Load diff
|
|
@ -41,9 +41,13 @@ dependencies {
|
|||
testImplementation("io.kotest:kotest-property:5.9.1")
|
||||
testImplementation("org.mockito:mockito-core:5.14.2")
|
||||
testImplementation("org.mockito:mockito-inline:5.2.0")
|
||||
testImplementation("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT")
|
||||
testImplementation("org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.110.0") {
|
||||
exclude(group = "org.junit.jupiter", module = "junit-jupiter-api")
|
||||
}
|
||||
testImplementation("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
|
||||
testImplementation("net.kyori:adventure-api:4.17.0")
|
||||
testImplementation("net.kyori:adventure-text-minimessage:4.17.0")
|
||||
testImplementation("com.sk89q.worldguard:worldguard-bukkit:7.0.13")
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,6 @@
|
|||
<property name="severity" value="error"/>
|
||||
<property name="fileExtensions" value="java"/>
|
||||
|
||||
<module name="BeforeExecutionExclusionFileFilter">
|
||||
<property name="fileNamePattern" value=".*[\\/]src[\\/]test[\\/].*"/>
|
||||
</module>
|
||||
|
||||
<module name="SuppressWarningsFilter"/>
|
||||
|
||||
<module name="LineLength">
|
||||
|
|
@ -24,7 +20,7 @@
|
|||
<module name="SuppressWarningsHolder"/>
|
||||
|
||||
<module name="MethodLength">
|
||||
<property name="max" value="80"/>
|
||||
<property name="max" value="30"/>
|
||||
<property name="countEmpty" value="false"/>
|
||||
</module>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package dev.loki.lomines.command.admin.info;
|
|||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.model.Mine;
|
||||
import dev.loki.lomines.data.config.block.BlockKey;
|
||||
import dev.loki.lomines.data.config.model.MineConfig;
|
||||
import dev.loki.lomines.util.location.geo.Cuboid;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
|
@ -40,8 +41,16 @@ public class InfoCommand {
|
|||
sender.sendMessage(Component.text("§7Блоков: §f" + mine.getBlocks() + "§7/§f" + mine.getTotalVolume() +
|
||||
" §7(§f" + String.format("%.1f", mine.getPercentFilled()) + "%§7)"));
|
||||
|
||||
printRegions(sender, mine.getRegions());
|
||||
printBlocks(sender, config.blocks().weights());
|
||||
printResetAndTeleport(sender, config);
|
||||
|
||||
sender.sendMessage(Component.text("§6§lНаграды: §f" + config.rewards().entries().size() + " записей"));
|
||||
sender.sendMessage(Component.text("§8§m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
||||
}
|
||||
|
||||
private void printRegions(CommandSender sender, List<Cuboid> 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" +
|
||||
|
|
@ -50,8 +59,10 @@ public class InfoCommand {
|
|||
" §7(§f" + r.getVolume() + " §7блоков)"));
|
||||
}
|
||||
sender.sendMessage(Component.text(""));
|
||||
}
|
||||
|
||||
private void printBlocks(CommandSender sender, Map<BlockKey, Double> weights) {
|
||||
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)
|
||||
|
|
@ -60,7 +71,9 @@ public class InfoCommand {
|
|||
if (weights.size() > 10) {
|
||||
sender.sendMessage(Component.text("§7 ... и ещё " + (weights.size() - 10) + " блоков"));
|
||||
}
|
||||
}
|
||||
|
||||
private void printResetAndTeleport(CommandSender sender, MineConfig config) {
|
||||
sender.sendMessage(Component.text("§6§lНастройки сброса:"));
|
||||
sender.sendMessage(Component.text("§7 Интервал: §f" + config.reset().intervalDisplay()));
|
||||
sender.sendMessage(Component.text("§7 Триггер по %: §f" +
|
||||
|
|
@ -71,9 +84,6 @@ public class InfoCommand {
|
|||
(config.teleport().enabled() ? "§aустановлена" : "§7не задана")));
|
||||
sender.sendMessage(Component.text("§7 Точка спавна: §f" +
|
||||
(config.playerSpawn().enabled() ? "§aустановлена" : "§7используется точка телепорта")));
|
||||
|
||||
sender.sendMessage(Component.text("§6§lНаграды: §f" + config.rewards().entries().size() + " записей"));
|
||||
sender.sendMessage(Component.text("§8§m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
||||
}
|
||||
|
||||
private String formatBlockKey(BlockKey key) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,20 @@ public final class RegionActionHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
Cuboid newRegion = resolveNewRegion(player, mine);
|
||||
if (newRegion == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Cuboid> currentRegions = new ArrayList<>(mine.getRegions());
|
||||
currentRegions.add(newRegion);
|
||||
|
||||
updateMineRegions(mine, new RegionConfig(currentRegions));
|
||||
|
||||
sendRegionAdded(player, newRegion, currentRegions.size());
|
||||
}
|
||||
|
||||
private Cuboid resolveNewRegion(Player player, Mine mine) {
|
||||
var wandManager = plugin.getGroupWandManager();
|
||||
var session = wandManager.getSession(player.getUniqueId());
|
||||
int slot = session.getActiveSlot();
|
||||
|
|
@ -40,7 +54,7 @@ public final class RegionActionHandler {
|
|||
var pos2 = session.getPos2(slot);
|
||||
if (pos1 == null || pos2 == null) {
|
||||
player.sendMessage(Component.text("§cВыделите регион палочкой! ЛКМ - 1-я точка, ПКМ - 2-я точка"));
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
Cuboid newRegion = new Cuboid(pos1, pos2);
|
||||
String mineWorld = mine.getConfig().region().worldName();
|
||||
|
|
@ -48,21 +62,17 @@ public final class RegionActionHandler {
|
|||
|
||||
if (!mineWorld.equals(regionWorld)) {
|
||||
player.sendMessage(Component.text("§cРегион должен быть в мире §f" + mineWorld + "§c, а не §f" + regionWorld));
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
session.clearCorners(slot);
|
||||
return newRegion;
|
||||
}
|
||||
|
||||
List<Cuboid> currentRegions = new ArrayList<>(mine.getRegions());
|
||||
currentRegions.add(newRegion);
|
||||
|
||||
var newRegionConfig = new RegionConfig(currentRegions);
|
||||
updateMineRegions(mine, newRegionConfig);
|
||||
|
||||
player.sendMessage(Component.text("§aДобавлен регион #" + currentRegions.size()));
|
||||
private void sendRegionAdded(Player player, Cuboid newRegion, int count) {
|
||||
player.sendMessage(Component.text("§aДобавлен регион #" + count));
|
||||
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.clearCorners(slot);
|
||||
}
|
||||
|
||||
public void removeRegion(CommandSender sender, String mineName, int index) {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,14 @@ public class RegionCommands {
|
|||
|
||||
public void handle(CommandSender sender, String subcommand, String[] args) {
|
||||
switch (subcommand.toLowerCase()) {
|
||||
case "regions" -> {
|
||||
case "regions" -> handleRegions(sender, args);
|
||||
case "addregion" -> handleAddRegion(sender, args);
|
||||
case "removeregion" -> handleRemoveRegion(sender, args);
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRegions(CommandSender sender, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(Component.text("Usage: /lm regions <mine>", NamedTextColor.RED));
|
||||
return;
|
||||
|
|
@ -48,14 +55,16 @@ public class RegionCommands {
|
|||
}
|
||||
sender.sendMessage(Component.text("§8§m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
||||
}
|
||||
case "addregion" -> {
|
||||
|
||||
private void handleAddRegion(CommandSender sender, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(Component.text("Usage: /lm addregion <mine>", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
actionHandler.addRegion(sender, args[0]);
|
||||
}
|
||||
case "removeregion" -> {
|
||||
|
||||
private void handleRemoveRegion(CommandSender sender, String[] args) {
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(Component.text("Usage: /lm removeregion <mine> <index>", NamedTextColor.RED));
|
||||
return;
|
||||
|
|
@ -67,7 +76,4 @@ public class RegionCommands {
|
|||
sender.sendMessage(Component.text("Индекс должен быть числом: " + args[1], NamedTextColor.RED));
|
||||
}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,28 +25,41 @@ public class AdminCommands {
|
|||
|
||||
public void handle(CommandSender sender, String subcommand, String[] args) {
|
||||
switch (subcommand.toLowerCase()) {
|
||||
case "create" -> {
|
||||
case "create" -> handleCreate(sender, args);
|
||||
case "delete" -> handleDelete(sender, args);
|
||||
case "edit" -> handleEdit(sender, args);
|
||||
case "reset" -> handleReset(sender, args);
|
||||
case "reload" -> actionHandler.reload(sender);
|
||||
case "list" -> handleList(sender);
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCreate(CommandSender sender, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(Component.text("Usage: /lm create <name>"));
|
||||
return;
|
||||
}
|
||||
actionHandler.create(sender, args[0]);
|
||||
}
|
||||
case "delete" -> {
|
||||
|
||||
private void handleDelete(CommandSender sender, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(Component.text("Usage: /lm delete <name>"));
|
||||
return;
|
||||
}
|
||||
actionHandler.delete(sender, args[0]);
|
||||
}
|
||||
case "edit" -> {
|
||||
|
||||
private void handleEdit(CommandSender sender, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(Component.text("Usage: /lm edit <mine>"));
|
||||
return;
|
||||
}
|
||||
actionHandler.edit(sender, args[0]);
|
||||
}
|
||||
case "reset" -> {
|
||||
|
||||
private void handleReset(CommandSender sender, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(Component.text("Usage: /lm reset <mine> [silent]"));
|
||||
return;
|
||||
|
|
@ -54,8 +67,8 @@ public class AdminCommands {
|
|||
boolean silent = args.length > 1 && (args[1].equalsIgnoreCase("true") || args[1].equalsIgnoreCase("silent"));
|
||||
actionHandler.reset(sender, args[0], silent);
|
||||
}
|
||||
case "reload" -> actionHandler.reload(sender);
|
||||
case "list" -> {
|
||||
|
||||
private void handleList(CommandSender sender) {
|
||||
Collection<Mine> allMines = mines.getAll();
|
||||
if (allMines.isEmpty()) {
|
||||
sender.sendMessage(Component.text("No mines found"));
|
||||
|
|
@ -67,9 +80,6 @@ public class AdminCommands {
|
|||
sender.sendMessage(Component.text("- " + mine.getName() + " " + status));
|
||||
}
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private String formatMineStatus(Mine mine) {
|
||||
int blocks = mine.getBlocks();
|
||||
|
|
|
|||
|
|
@ -23,27 +23,51 @@ public class CopyCommand {
|
|||
String fromMineName = args[0];
|
||||
String toMineName = args[1];
|
||||
|
||||
MinePair pair = resolveMines(sender, fromMineName, toMineName);
|
||||
if (pair == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceConfig = pair.fromMine().getConfig();
|
||||
|
||||
MineConfig newTargetConfig = buildCopiedConfig(pair.toMine(), sourceConfig);
|
||||
|
||||
try {
|
||||
plugin.getMines().updateMineConfig(pair.toMine().getName(), newTargetConfig);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage(Component.text("Ошибка сохранения: " + e.getMessage(), NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
sendCopySummary(sender, pair.fromMine(), pair.toMine(), sourceConfig);
|
||||
}
|
||||
|
||||
private record MinePair(Mine fromMine, Mine toMine) {
|
||||
}
|
||||
|
||||
private MinePair resolveMines(CommandSender sender, String fromMineName, String toMineName) {
|
||||
Mine fromMine = plugin.getMines().find(fromMineName).orElse(null);
|
||||
if (fromMine == null) {
|
||||
sender.sendMessage(Component.text("Исходная шахта не найдена: " + fromMineName, NamedTextColor.RED));
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
Mine toMine = plugin.getMines().find(toMineName).orElse(null);
|
||||
if (toMine == null) {
|
||||
sender.sendMessage(Component.text("Целевая шахта не найдена: " + toMineName, NamedTextColor.RED));
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (fromMine.getName().equalsIgnoreCase(toMine.getName())) {
|
||||
sender.sendMessage(Component.text("Нельзя копировать шахту саму в себя!", NamedTextColor.RED));
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
return new MinePair(fromMine, toMine);
|
||||
}
|
||||
|
||||
var sourceConfig = fromMine.getConfig();
|
||||
private MineConfig buildCopiedConfig(Mine toMine, MineConfig sourceConfig) {
|
||||
var targetConfig = toMine.getConfig();
|
||||
|
||||
MineConfig newTargetConfig = MineConfig.builder(toMine.getName())
|
||||
return MineConfig.builder(toMine.getName())
|
||||
.region(targetConfig.region())
|
||||
.blocks(sourceConfig.blocks())
|
||||
.reset(sourceConfig.reset())
|
||||
|
|
@ -53,14 +77,9 @@ public class CopyCommand {
|
|||
.worldGuard(sourceConfig.worldGuard())
|
||||
.playerSpawn(sourceConfig.playerSpawn())
|
||||
.build();
|
||||
|
||||
try {
|
||||
plugin.getMines().updateMineConfig(toMine.getName(), newTargetConfig);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage(Component.text("Ошибка сохранения: " + e.getMessage(), NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
private void sendCopySummary(CommandSender sender, Mine fromMine, Mine toMine, MineConfig sourceConfig) {
|
||||
sender.sendMessage(Component.text("§aКонфигурация скопирована из §f" + fromMine.getName() +
|
||||
" §aв §f" + toMine.getName()));
|
||||
sender.sendMessage(Component.text("§7Скопировано:"));
|
||||
|
|
|
|||
|
|
@ -40,18 +40,7 @@ public final class TeleportActionHandler {
|
|||
}
|
||||
|
||||
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();
|
||||
var updatedConfig = withTeleport(config, TeleportConfig.at(player.getLocation()));
|
||||
|
||||
plugin.getMines().getFileManager().saveConfig(updatedConfig);
|
||||
sender.sendMessage(MessageFormatter.success("Teleport location for mine '" + mineName + "' set to your current position"));
|
||||
|
|
@ -76,18 +65,7 @@ public final class TeleportActionHandler {
|
|||
}
|
||||
|
||||
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();
|
||||
var updatedConfig = withPlayerSpawn(config, PlayerSpawnConfig.at(player.getLocation()));
|
||||
|
||||
plugin.getMines().getFileManager().saveConfig(updatedConfig);
|
||||
sender.sendMessage(MessageFormatter.success("Safe spawn location for mine '" + mineName + "' set to your current position"));
|
||||
|
|
@ -108,16 +86,7 @@ public final class TeleportActionHandler {
|
|||
}
|
||||
|
||||
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();
|
||||
var updatedConfig = withPlayerSpawn(config, PlayerSpawnConfig.disabled());
|
||||
|
||||
plugin.getMines().getFileManager().saveConfig(updatedConfig);
|
||||
sender.sendMessage(MessageFormatter.success("Spawn location for mine '" + mineName + "' cleared"));
|
||||
|
|
@ -128,6 +97,32 @@ public final class TeleportActionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private MineConfig withTeleport(MineConfig config, TeleportConfig teleport) {
|
||||
return MineConfig.builder(config.name())
|
||||
.region(config.region())
|
||||
.blocks(config.blocks())
|
||||
.reset(config.reset())
|
||||
.rewards(config.rewards())
|
||||
.teleport(teleport)
|
||||
.ui(config.ui())
|
||||
.worldGuard(config.worldGuard())
|
||||
.playerSpawn(config.playerSpawn())
|
||||
.build();
|
||||
}
|
||||
|
||||
private MineConfig withPlayerSpawn(MineConfig config, PlayerSpawnConfig spawn) {
|
||||
return MineConfig.builder(config.name())
|
||||
.region(config.region())
|
||||
.blocks(config.blocks())
|
||||
.reset(config.reset())
|
||||
.rewards(config.rewards())
|
||||
.teleport(config.teleport())
|
||||
.ui(config.ui())
|
||||
.worldGuard(config.worldGuard())
|
||||
.playerSpawn(spawn)
|
||||
.build();
|
||||
}
|
||||
|
||||
public String formatLocation(Location loc) {
|
||||
return String.format("%.1f, %.1f, %.1f in %s",
|
||||
loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName());
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package dev.loki.lomines.command.admin.stats;
|
|||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.model.Mine;
|
||||
import dev.loki.lomines.core.mine.registry.Mines;
|
||||
import dev.loki.lomines.data.stats.model.Leaderboard;
|
||||
import dev.loki.lomines.data.stats.model.LeaderboardEntry;
|
||||
import dev.loki.lomines.util.ErrorHandler;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
|
@ -77,29 +76,37 @@ public final class LeaderboardRenderer {
|
|||
}
|
||||
|
||||
public static void renderTopCommand(CommandSender sender, String arg1, String arg2, Mines mines, LoMinesPlugin plugin) {
|
||||
TopRequest req = parseTopRequest(arg1, arg2);
|
||||
if (req.mineName() != null) {
|
||||
renderMineTop(sender, req.mineName(), req.limit(), mines, plugin);
|
||||
return;
|
||||
}
|
||||
List<LeaderboardEntry> rows = plugin.getStatsManager().getLeaderboard().getTopTotal(req.limit());
|
||||
sender.sendMessage(Component.text("=== Общий топ ===", NamedTextColor.GOLD));
|
||||
sendTopRows(sender, rows);
|
||||
}
|
||||
|
||||
private record TopRequest(int limit, String mineName) {
|
||||
}
|
||||
|
||||
private static TopRequest parseTopRequest(String arg1, String arg2) {
|
||||
String a = arg1 == null ? "" : arg1.trim();
|
||||
String b = arg2 == null ? "" : arg2.trim();
|
||||
int limit;
|
||||
String mineName;
|
||||
if (a.isEmpty()) {
|
||||
limit = clampLimit(10);
|
||||
mineName = null;
|
||||
} else if (b.isEmpty()) {
|
||||
return new TopRequest(clampLimit(10), null);
|
||||
}
|
||||
if (b.isEmpty()) {
|
||||
Integer asLimit = tryParsePositiveInt(a);
|
||||
if (asLimit != null) {
|
||||
limit = clampLimit(asLimit);
|
||||
mineName = null;
|
||||
} else {
|
||||
limit = clampLimit(10);
|
||||
mineName = a;
|
||||
return new TopRequest(clampLimit(asLimit), null);
|
||||
}
|
||||
return new TopRequest(clampLimit(10), a);
|
||||
}
|
||||
} else {
|
||||
mineName = a;
|
||||
Integer limParsed = tryParsePositiveInt(b);
|
||||
limit = clampLimit(limParsed != null ? limParsed : 10);
|
||||
return new TopRequest(clampLimit(limParsed != null ? limParsed : 10), a);
|
||||
}
|
||||
Leaderboard lb = plugin.getStatsManager().getLeaderboard();
|
||||
if (mineName != null) {
|
||||
|
||||
private static void renderMineTop(CommandSender sender, String mineName, int limit, Mines mines, LoMinesPlugin plugin) {
|
||||
var found = mines.find(mineName);
|
||||
if (found.isEmpty()) {
|
||||
sender.sendMessage(Component.text("Шахта не найдена: " + mineName, NamedTextColor.RED));
|
||||
|
|
@ -107,13 +114,8 @@ public final class LeaderboardRenderer {
|
|||
}
|
||||
Mine m = found.get();
|
||||
String key = m.getName();
|
||||
List<LeaderboardEntry> rows = lb.getTopByMine(key, limit);
|
||||
List<LeaderboardEntry> rows = plugin.getStatsManager().getLeaderboard().getTopByMine(key, limit);
|
||||
sender.sendMessage(Component.text("=== Топ по шахте \u00ab" + key + "\u00bb ===", NamedTextColor.GOLD));
|
||||
sendTopRows(sender, rows);
|
||||
return;
|
||||
}
|
||||
List<LeaderboardEntry> rows = lb.getTopTotal(limit);
|
||||
sender.sendMessage(Component.text("=== Общий топ ===", NamedTextColor.GOLD));
|
||||
sendTopRows(sender, rows);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,20 @@ public class StatsCommands {
|
|||
|
||||
public void handle(CommandSender sender, String subcommand, String[] args) {
|
||||
switch (subcommand.toLowerCase()) {
|
||||
case "stats" -> {
|
||||
case "stats" -> handleStats(sender, args);
|
||||
case "top" -> {
|
||||
if (isStatsDisabled(sender)) {
|
||||
return;
|
||||
}
|
||||
String arg1 = args.length > 0 ? args[0] : "";
|
||||
String arg2 = args.length > 1 ? args[1] : "";
|
||||
LeaderboardRenderer.renderTopCommand(sender, arg1, arg2, mines, plugin);
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStats(CommandSender sender, String[] args) {
|
||||
if (isStatsDisabled(sender)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -56,17 +69,6 @@ public class StatsCommands {
|
|||
.forEach(e -> sender.sendMessage(Component.text(
|
||||
" " + e.getKey() + ": " + e.getValue(), NamedTextColor.DARK_AQUA)));
|
||||
}
|
||||
case "top" -> {
|
||||
if (isStatsDisabled(sender)) {
|
||||
return;
|
||||
}
|
||||
String arg1 = args.length > 0 ? args[0] : "";
|
||||
String arg2 = args.length > 1 ? args[1] : "";
|
||||
LeaderboardRenderer.renderTopCommand(sender, arg1, arg2, mines, plugin);
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isStatsDisabled(CommandSender sender) {
|
||||
if (!plugin.getConfig().getBoolean("statistics-enabled", true)) {
|
||||
|
|
|
|||
|
|
@ -35,19 +35,8 @@ public class TeleportCommand {
|
|||
return;
|
||||
}
|
||||
|
||||
var config = mine.getConfig();
|
||||
Location target;
|
||||
|
||||
if (config.teleport().enabled() && config.teleport().getLocation().isPresent()) {
|
||||
target = config.teleport().getLocation().get();
|
||||
} else if (!mine.getRegions().isEmpty()) {
|
||||
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));
|
||||
Location target = resolveTarget(player, mine);
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -55,4 +44,20 @@ public class TeleportCommand {
|
|||
player.sendMessage(Component.text("§aТелепортировано к шахте §f" + mine.getName() +
|
||||
" §a(§f" + String.format("%.0f, %.0f, %.0f", target.getX(), target.getY(), target.getZ()) + "§a)"));
|
||||
}
|
||||
|
||||
private Location resolveTarget(Player player, Mine mine) {
|
||||
var config = mine.getConfig();
|
||||
if (config.teleport().enabled() && config.teleport().getLocation().isPresent()) {
|
||||
return config.teleport().getLocation().get();
|
||||
}
|
||||
if (!mine.getRegions().isEmpty()) {
|
||||
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;
|
||||
return new Location(region.getWorld(), centerX, centerY, centerZ);
|
||||
}
|
||||
player.sendMessage(Component.text("У шахты нет настроенной точки телепорта!", NamedTextColor.RED));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
/**
|
||||
* Core components of the LoMines plugin.
|
||||
* <p>
|
||||
* This package contains the main plugin class and core system classes:
|
||||
* <ul>
|
||||
* <li>{@code LoMinesPlugin} - Main plugin class extending LoPlugin</li>
|
||||
* <li>{@code Mines} - Registry for managing all active mines</li>
|
||||
* <li>{@code Mine} - Representation of a single mine with its configuration and state</li>
|
||||
* </ul>
|
||||
*/
|
||||
package dev.loki.lomines.core.common;
|
||||
|
|
@ -44,6 +44,7 @@ public final class Mines {
|
|||
}
|
||||
|
||||
public void create(String name, Location corner1, Location corner2) throws IOException {
|
||||
name = name.toLowerCase().trim();
|
||||
if (repository.exists(name)) {
|
||||
throw new IllegalArgumentException("Mine already exists: " + name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,9 +42,13 @@ public final class BlockConfigLoader {
|
|||
yaml.getString("blocks.fill-mode", "CUBOID").toUpperCase()
|
||||
);
|
||||
|
||||
// Parse mask config if applicable
|
||||
BlockConfig.MaskConfig mask = null;
|
||||
if (fillMode == FillMode.MASK) {
|
||||
return new BlockConfig(weights, fillMode, parseMaskConfig(yaml, fillMode));
|
||||
}
|
||||
|
||||
private BlockConfig.MaskConfig parseMaskConfig(YamlConfiguration yaml, FillMode fillMode) {
|
||||
if (fillMode != FillMode.MASK) {
|
||||
return null;
|
||||
}
|
||||
String markerStr = yaml.getString("blocks.mask.marker", "pink_concrete");
|
||||
BlockKey marker = BlockKey.deserialize(markerStr);
|
||||
|
||||
|
|
@ -54,10 +58,7 @@ public final class BlockConfigLoader {
|
|||
positions.put(pos, true);
|
||||
}
|
||||
|
||||
mask = new BlockConfig.MaskConfig(marker, positions);
|
||||
}
|
||||
|
||||
return new BlockConfig(weights, fillMode, mask);
|
||||
return new BlockConfig.MaskConfig(marker, positions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,44 +22,14 @@ public final class WorldGuardConfigLoader {
|
|||
* Supports any WorldGuard flags. Default: block-break=allow.
|
||||
*/
|
||||
public WorldGuardConfig parse(YamlConfiguration yaml) {
|
||||
ConfigurationSection wgSection = yaml.getConfigurationSection("worldguard");
|
||||
if (wgSection == null) {
|
||||
// Check defaults
|
||||
boolean defaultEnabled = defaults.getBoolean("worldguard.enabled", false);
|
||||
if (!defaultEnabled) {
|
||||
return WorldGuardConfig.disabled();
|
||||
}
|
||||
}
|
||||
|
||||
boolean enabled = yaml.getBoolean("worldguard.enabled",
|
||||
defaults.getBoolean("worldguard.enabled", false));
|
||||
|
||||
if (!enabled) {
|
||||
if (!isEnabled(yaml)) {
|
||||
return WorldGuardConfig.disabled();
|
||||
}
|
||||
|
||||
List<String> owners = yaml.getStringList("worldguard.owners");
|
||||
if (owners.isEmpty()) {
|
||||
owners = defaults.getStringList("worldguard.owners");
|
||||
}
|
||||
|
||||
List<String> members = yaml.getStringList("worldguard.members");
|
||||
if (members.isEmpty()) {
|
||||
members = defaults.getStringList("worldguard.members");
|
||||
}
|
||||
|
||||
// Support any WorldGuard flags. Default: only block-break=allow
|
||||
List<String> flags = yaml.getStringList("worldguard.flags");
|
||||
if (flags.isEmpty()) {
|
||||
flags = defaults.getStringList("worldguard.flags");
|
||||
}
|
||||
if (flags.isEmpty()) {
|
||||
flags = List.of("block-break=allow");
|
||||
}
|
||||
|
||||
boolean protect = yaml.getBoolean("worldguard.protect-on-create",
|
||||
defaults.getBoolean("worldguard.protect-on-create", true));
|
||||
|
||||
List<String> owners = resolveOwners(yaml);
|
||||
List<String> members = resolveMembers(yaml);
|
||||
List<String> flags = resolveFlags(yaml);
|
||||
boolean protect = resolveProtect(yaml);
|
||||
String tmpl = yaml.getString("worldguard.region-template",
|
||||
defaults.getString("worldguard.region-template", "{mine_name}_{random_4}"));
|
||||
|
||||
|
|
@ -73,6 +43,50 @@ public final class WorldGuardConfigLoader {
|
|||
.build();
|
||||
}
|
||||
|
||||
private boolean isEnabled(YamlConfiguration yaml) {
|
||||
ConfigurationSection wgSection = yaml.getConfigurationSection("worldguard");
|
||||
if (wgSection == null) {
|
||||
boolean defaultEnabled = defaults.getBoolean("worldguard.enabled", false);
|
||||
if (!defaultEnabled) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return yaml.getBoolean("worldguard.enabled", defaults.getBoolean("worldguard.enabled", false));
|
||||
}
|
||||
|
||||
private List<String> resolveOwners(YamlConfiguration yaml) {
|
||||
List<String> owners = yaml.getStringList("worldguard.owners");
|
||||
if (owners.isEmpty()) {
|
||||
owners = defaults.getStringList("worldguard.owners");
|
||||
}
|
||||
return owners;
|
||||
}
|
||||
|
||||
private List<String> resolveMembers(YamlConfiguration yaml) {
|
||||
List<String> members = yaml.getStringList("worldguard.members");
|
||||
if (members.isEmpty()) {
|
||||
members = defaults.getStringList("worldguard.members");
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
private List<String> resolveFlags(YamlConfiguration yaml) {
|
||||
// Support any WorldGuard flags. Default: only block-break=allow
|
||||
List<String> flags = yaml.getStringList("worldguard.flags");
|
||||
if (flags.isEmpty()) {
|
||||
flags = defaults.getStringList("worldguard.flags");
|
||||
}
|
||||
if (flags.isEmpty()) {
|
||||
flags = List.of("block-break=allow");
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
private boolean resolveProtect(YamlConfiguration yaml) {
|
||||
return yaml.getBoolean("worldguard.protect-on-create",
|
||||
defaults.getBoolean("worldguard.protect-on-create", true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves WorldGuard configuration to YAML.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -36,16 +36,31 @@ public final class RewardConfigLoader {
|
|||
}
|
||||
|
||||
private RewardEntry parseRewardEntry(Map<?, ?> map) {
|
||||
List<BlockKey> blocks = parseBlocks(map.get("blocks"));
|
||||
List<ItemReward> items = parseItems(map.get("items"));
|
||||
List<String> commands = parseCommands(map.get("commands"));
|
||||
Object preventDropsObj = map.get("prevent-drops");
|
||||
boolean preventDrops = preventDropsObj instanceof Boolean b && b;
|
||||
|
||||
Object chanceObj = map.get("chance");
|
||||
double chance = chanceObj instanceof Number n ? n.doubleValue() : 0.0;
|
||||
return new RewardEntry(blocks, chance, items, commands, preventDrops);
|
||||
}
|
||||
|
||||
private List<BlockKey> parseBlocks(Object rawBlocks) {
|
||||
List<BlockKey> blocks = new ArrayList<>();
|
||||
List<?> blockList = (List<?>) map.get("blocks");
|
||||
List<?> blockList = (List<?>) rawBlocks;
|
||||
if (blockList != null) {
|
||||
for (Object b : blockList) {
|
||||
blocks.add(BlockKey.deserialize(b.toString()));
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private List<ItemReward> parseItems(Object rawItems) {
|
||||
List<ItemReward> items = new ArrayList<>();
|
||||
List<?> itemList = (List<?>) map.get("items");
|
||||
List<?> itemList = (List<?>) rawItems;
|
||||
if (itemList != null) {
|
||||
for (Object i : itemList) {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
@ -53,9 +68,11 @@ public final class RewardConfigLoader {
|
|||
items.add(parseItemReward(itemMap));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private List<String> parseCommands(Object commandsObj) {
|
||||
List<String> commands = new ArrayList<>();
|
||||
Object commandsObj = map.get("commands");
|
||||
if (commandsObj instanceof List<?> list) {
|
||||
for (Object obj : list) {
|
||||
if (obj != null) {
|
||||
|
|
@ -63,12 +80,7 @@ public final class RewardConfigLoader {
|
|||
}
|
||||
}
|
||||
}
|
||||
Object preventDropsObj = map.get("prevent-drops");
|
||||
boolean preventDrops = preventDropsObj instanceof Boolean b && b;
|
||||
|
||||
Object chanceObj = map.get("chance");
|
||||
double chance = chanceObj instanceof Number n ? n.doubleValue() : 0.0;
|
||||
return new RewardEntry(blocks, chance, items, commands, preventDrops);
|
||||
return commands;
|
||||
}
|
||||
|
||||
private ItemReward parseItemReward(Map<String, Object> map) {
|
||||
|
|
|
|||
|
|
@ -29,8 +29,13 @@ public final class RewardParser {
|
|||
}
|
||||
|
||||
for (int i = 0; i < rewardsList.size(); i++) {
|
||||
Object rewardObj = rewardsList.get(i);
|
||||
rewards.add(parseRewardAt(rewardsList.get(i), i));
|
||||
}
|
||||
|
||||
return rewards;
|
||||
}
|
||||
|
||||
private Reward parseRewardAt(Object rewardObj, int i) throws ConfigParseException {
|
||||
if (!(rewardObj instanceof Map)) {
|
||||
throw new ConfigParseException(
|
||||
"Invalid reward at index " + i + ": expected map, got " +
|
||||
|
|
@ -42,8 +47,7 @@ public final class RewardParser {
|
|||
Map<String, Object> rewardMap = (Map<String, Object>) rewardObj;
|
||||
|
||||
try {
|
||||
Reward reward = entryParser.parseReward(rewardMap);
|
||||
rewards.add(reward);
|
||||
return entryParser.parseReward(rewardMap);
|
||||
} catch (ConfigParseException e) {
|
||||
throw new ConfigParseException(
|
||||
"Error parsing reward at index " + i + ": " + e.getMessage(),
|
||||
|
|
@ -51,7 +55,4 @@ public final class RewardParser {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rewards;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,12 +43,19 @@ public final class StatsPersistence {
|
|||
}
|
||||
|
||||
for (String uuidString : playersSection.getKeys(false)) {
|
||||
loadPlayer(stats, uuidString, playersSection);
|
||||
}
|
||||
|
||||
plugin.getLogger().info("Loaded statistics for " + stats.size() + " player(s)");
|
||||
}
|
||||
|
||||
private void loadPlayer(Map<UUID, PlayerStats> stats, String uuidString, ConfigurationSection playersSection) {
|
||||
try {
|
||||
UUID playerId = UUID.fromString(uuidString);
|
||||
ConfigurationSection playerSection = playersSection.getConfigurationSection(uuidString);
|
||||
|
||||
if (playerSection == null) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerStats playerStats = stats.computeIfAbsent(playerId, PlayerStats::new);
|
||||
|
|
@ -68,9 +75,6 @@ public final class StatsPersistence {
|
|||
}
|
||||
}
|
||||
|
||||
plugin.getLogger().info("Loaded statistics for " + stats.size() + " player(s)");
|
||||
}
|
||||
|
||||
public void save(Map<UUID, PlayerStats> stats) throws IOException {
|
||||
YamlConfiguration yaml = new YamlConfiguration();
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,20 @@ public final class GroupCreateGui {
|
|||
return;
|
||||
}
|
||||
|
||||
CreationResult result = createSlots(plugin, player, session, base);
|
||||
if (result.created() == 0) {
|
||||
player.sendMessage(Component.text("Нет готовых слотов (2 точки в каждом).", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
player.sendMessage(Component.text(
|
||||
"Создано шахт: " + result.created() + (result.skipped() > 0 ? " (пропущено: " + result.skipped() + ")" : ""),
|
||||
NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
private record CreationResult(int created, int skipped) {
|
||||
}
|
||||
|
||||
private static CreationResult createSlots(LoMinesPlugin plugin, Player player, GroupWandSession session, String base) {
|
||||
Mines mines = plugin.getMines();
|
||||
int created = 0;
|
||||
int skipped = 0;
|
||||
|
|
@ -115,13 +129,6 @@ public final class GroupCreateGui {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (created == 0) {
|
||||
player.sendMessage(Component.text("Нет готовых слотов (2 точки в каждом).", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
player.sendMessage(Component.text(
|
||||
"Создано шахт: " + created + (skipped > 0 ? " (пропущено: " + skipped + ")" : ""),
|
||||
NamedTextColor.GREEN));
|
||||
return new CreationResult(created, skipped);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,19 +30,32 @@ public final class BlockWeightEditor {
|
|||
Map<BlockKey, Double> weights = new java.util.HashMap<>(config.weights());
|
||||
double currentWeight = weights.getOrDefault(blockKey, 0.0) * 100.0;
|
||||
|
||||
double delta = 0;
|
||||
if (leftClick && shiftClick) {
|
||||
delta = 1.0;
|
||||
} else if (rightClick && shiftClick) {
|
||||
delta = -1.0;
|
||||
} else if (leftClick) {
|
||||
delta = 5.0;
|
||||
} else if (rightClick) {
|
||||
delta = -5.0;
|
||||
double newWeight = Math.max(0, Math.min(100,
|
||||
currentWeight + computeDelta(leftClick, shiftClick, rightClick)));
|
||||
|
||||
applyWeightChange(player, blockKey, weights, newWeight, rightClick, shiftClick);
|
||||
|
||||
BlocksGui.refresh(player, player.getOpenInventory().getTopInventory(), mineName, plugin);
|
||||
}
|
||||
|
||||
double newWeight = Math.max(0, Math.min(100, currentWeight + delta));
|
||||
private static double computeDelta(boolean leftClick, boolean shiftClick, boolean rightClick) {
|
||||
if (leftClick && shiftClick) {
|
||||
return 1.0;
|
||||
}
|
||||
if (rightClick && shiftClick) {
|
||||
return -1.0;
|
||||
}
|
||||
if (leftClick) {
|
||||
return 5.0;
|
||||
}
|
||||
if (rightClick) {
|
||||
return -5.0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void applyWeightChange(Player player, BlockKey blockKey, Map<BlockKey, Double> weights,
|
||||
double newWeight, boolean rightClick, boolean shiftClick) {
|
||||
if (rightClick && shiftClick && newWeight <= 0.1) {
|
||||
weights.remove(blockKey);
|
||||
player.sendMessage(Component.text(
|
||||
|
|
@ -53,8 +66,6 @@ public final class BlockWeightEditor {
|
|||
"\u00a7a\u0412\u0435\u0441 \u00a7f" + blockKey.serialize() + " \u00a7a\u0438\u0437\u043c\u0435\u043d\u0435\u043d: \u00a7f"
|
||||
+ String.format("%.1f%%", newWeight)));
|
||||
}
|
||||
|
||||
BlocksGui.refresh(player, player.getOpenInventory().getTopInventory(), mineName, plugin);
|
||||
}
|
||||
|
||||
public static BlockKey getBlockAtSlot(Inventory inv, int slot, LoMinesPlugin plugin, String mineName) {
|
||||
|
|
|
|||
|
|
@ -87,14 +87,7 @@ public final class ResetGui {
|
|||
}
|
||||
|
||||
if (rawSlot == SLOT_MESSAGE) {
|
||||
if (leftClick) {
|
||||
player.sendMessage(Component.text("§eВведите сообщение в чат (или 'cancel' для отмены):"));
|
||||
player.closeInventory();
|
||||
} else if (rightClick) {
|
||||
player.sendMessage(Component.text("§cСообщение очищено."));
|
||||
refresh(player, player.getOpenInventory().getTopInventory(), mineName, plugin);
|
||||
}
|
||||
return true;
|
||||
return handleMessageSlot(plugin, player, mineName, leftClick, rightClick);
|
||||
}
|
||||
|
||||
if (rawSlot == SLOT_COMMANDS && leftClick) {
|
||||
|
|
@ -105,6 +98,18 @@ public final class ResetGui {
|
|||
return true;
|
||||
}
|
||||
|
||||
private static boolean handleMessageSlot(LoMinesPlugin plugin, Player player, String mineName,
|
||||
boolean leftClick, boolean rightClick) {
|
||||
if (leftClick) {
|
||||
player.sendMessage(Component.text("§eВведите сообщение в чат (или 'cancel' для отмены):"));
|
||||
player.closeInventory();
|
||||
} else if (rightClick) {
|
||||
player.sendMessage(Component.text("§cСообщение очищено."));
|
||||
refresh(player, player.getOpenInventory().getTopInventory(), mineName, plugin);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void adjustInterval(LoMinesPlugin plugin, Player player, String mineName,
|
||||
boolean leftClick, boolean rightClick, boolean shiftClick) {
|
||||
int delta = 0;
|
||||
|
|
|
|||
|
|
@ -81,11 +81,11 @@ public final class MineEditGui {
|
|||
if (rawSlot < 0 || rawSlot >= SIZE) {
|
||||
return false;
|
||||
}
|
||||
switch (rawSlot) {
|
||||
case SLOT_BACK -> {
|
||||
player.closeInventory();
|
||||
return true;
|
||||
return handleNavigationSlot(plugin, player, mineName, rawSlot);
|
||||
}
|
||||
|
||||
private static boolean handleNavigationSlot(LoMinesPlugin plugin, Player player, String mineName, int rawSlot) {
|
||||
switch (rawSlot) {
|
||||
case SLOT_BLOCKS -> {
|
||||
BlocksGui.open(plugin, player, mineName);
|
||||
return true;
|
||||
|
|
@ -98,6 +98,22 @@ public final class MineEditGui {
|
|||
RewardsGui.open(plugin, player, mineName);
|
||||
return true;
|
||||
}
|
||||
case SLOT_DELETE -> {
|
||||
ConfirmDeleteGui.open(plugin, player, mineName);
|
||||
return true;
|
||||
}
|
||||
default -> {
|
||||
return handleInfoSlot(player, mineName, rawSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean handleInfoSlot(Player player, String mineName, int rawSlot) {
|
||||
switch (rawSlot) {
|
||||
case SLOT_BACK -> {
|
||||
player.closeInventory();
|
||||
return true;
|
||||
}
|
||||
case SLOT_TELEPORT -> {
|
||||
player.sendMessage(Component.text("Используйте команды /lm setteleport и /lm setspawn", NamedTextColor.YELLOW));
|
||||
return true;
|
||||
|
|
@ -111,10 +127,6 @@ public final class MineEditGui {
|
|||
player.closeInventory();
|
||||
return true;
|
||||
}
|
||||
case SLOT_DELETE -> {
|
||||
ConfirmDeleteGui.open(plugin, player, mineName);
|
||||
return true;
|
||||
}
|
||||
case SLOT_INFO, SLOT_REGIONS -> {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ public final class WorldGuardRegionService {
|
|||
}
|
||||
String regionName = wgConfig.generateRegionName(mineName);
|
||||
try {
|
||||
return createRegionInManager(mineName, config, regionName, wgConfig);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe("Failed to create WorldGuard region for mine " + mineName + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String createRegionInManager(String mineName, MineConfig config, String regionName, WorldGuardConfig wgConfig) {
|
||||
RegionManager regionManager = getRegionManager(config.worldName());
|
||||
if (regionManager == null) {
|
||||
return null;
|
||||
|
|
@ -63,10 +71,6 @@ public final class WorldGuardRegionService {
|
|||
regionManager.addRegion(region);
|
||||
plugin.getLogger().info("Created WorldGuard region '" + regionName + "' for mine " + mineName);
|
||||
return regionName;
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe("Failed to create WorldGuard region for mine " + mineName + ": " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateRegion(String mineName, MineConfig config) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,17 @@ public final class PlayerInteractListener implements Listener {
|
|||
|
||||
if (action == Action.LEFT_CLICK_BLOCK && event.hasBlock()) {
|
||||
event.setCancelled(true);
|
||||
Block block = event.getClickedBlock();
|
||||
handleLeftClick(player, event.getClickedBlock());
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == Action.RIGHT_CLICK_BLOCK && !player.isSneaking()) {
|
||||
event.setCancelled(true);
|
||||
handleRightClick(player, event.getClickedBlock());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLeftClick(Player player, Block block) {
|
||||
if (block == null) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -60,12 +70,9 @@ public final class PlayerInteractListener implements Listener {
|
|||
|
||||
// Start showing particles when selection is made
|
||||
plugin.getWandParticleService().startShowingParticles(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == Action.RIGHT_CLICK_BLOCK && !player.isSneaking()) {
|
||||
event.setCancelled(true);
|
||||
Block block = event.getClickedBlock();
|
||||
private void handleRightClick(Player player, Block block) {
|
||||
if (block == null) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -78,7 +85,6 @@ public final class PlayerInteractListener implements Listener {
|
|||
// Start showing particles when selection is made
|
||||
plugin.getWandParticleService().startShowingParticles(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts/stops particle visualization when player switches items.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ public final class LocationParser {
|
|||
);
|
||||
}
|
||||
|
||||
return buildLocation(matcher, locationString);
|
||||
}
|
||||
|
||||
private static Location buildLocation(Matcher matcher, String locationString) throws ConfigParseException {
|
||||
try {
|
||||
String worldName = matcher.group(1);
|
||||
double x = Double.parseDouble(matcher.group(2));
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ public final class SafeTeleportUtil {
|
|||
return destination;
|
||||
}
|
||||
|
||||
return findFallbackSafe(world, x, y, z, yaw, pitch, maxUpOffset);
|
||||
}
|
||||
|
||||
private static Location findFallbackSafe(World world, int x, int y, int z, float yaw, float pitch, int maxUpOffset) {
|
||||
Location result = findNearbySafe(world, x, y, z, yaw, pitch);
|
||||
if (result != null) {
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ import org.mockito.Mock;
|
|||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
|
|
|
|||
|
|
@ -10,41 +10,47 @@ import dev.loki.lomines.util.location.geo.Cuboid;
|
|||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for Mine class, specifically testing BlockSetter creation logic.
|
||||
*/
|
||||
@Disabled("Paper API RegistryAccess not available in unit tests")
|
||||
class MineTest {
|
||||
|
||||
@Mock
|
||||
private LoMinesPlugin plugin;
|
||||
|
||||
@Mock
|
||||
private ServerMock server;
|
||||
private World world;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
when(world.getName()).thenReturn("world");
|
||||
server = MockBukkit.mock();
|
||||
server.addSimpleWorld("world");
|
||||
world = server.getWorld("world");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateBlockSetter_WithOraxenPrefix_CreatesBukkitBlockSetter() {
|
||||
void testCreateBlockSetterWithOraxenPrefixCreatesBukkitBlockSetter() {
|
||||
// Oraxen integration is disabled — constructor throws IllegalArgumentException
|
||||
Map<BlockKey, Double> blocks = new HashMap<>();
|
||||
blocks.put(new BlockKey.Oraxen("custom_ore"), 50.0);
|
||||
|
|
@ -59,7 +65,7 @@ class MineTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testCreateBlockSetter_WithItemsAdderPrefix_CreatesBukkitBlockSetter() {
|
||||
void testCreateBlockSetterWithItemsAdderPrefixCreatesBukkitBlockSetter() {
|
||||
// ItemsAdder integration is disabled — constructor throws IllegalArgumentException
|
||||
Map<BlockKey, Double> blocks = new HashMap<>();
|
||||
blocks.put(new BlockKey.ItemsAdder("custom_block"), 60.0);
|
||||
|
|
@ -73,7 +79,7 @@ class MineTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testCreateBlockSetter_WithoutPrefix_CreatesBukkitBlockSetter() {
|
||||
void testCreateBlockSetterWithoutPrefixCreatesBukkitBlockSetter() {
|
||||
Map<BlockKey, Double> blocks = new HashMap<>();
|
||||
blocks.put(new BlockKey.Vanilla(Material.STONE), 50.0);
|
||||
blocks.put(new BlockKey.Vanilla(Material.COAL_ORE), 30.0);
|
||||
|
|
@ -89,7 +95,7 @@ class MineTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testCreateBlockSetter_WithEmptyBlocks_ThrowsException() {
|
||||
void testCreateBlockSetterWithEmptyBlocksThrowsException() {
|
||||
Map<BlockKey, Double> blocks = new HashMap<>();
|
||||
|
||||
assertThrows(
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ class MineTickerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testConstruction_WithValidParameters_DoesNotThrow() {
|
||||
void testConstructionWithValidParametersDoesNotThrow() {
|
||||
// Act & Assert
|
||||
assertDoesNotThrow(() -> new MineTicker(mines, plugin));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStop_WhenNotRunning_DoesNotThrow() {
|
||||
void testStopWhenNotRunningDoesNotThrow() {
|
||||
// Arrange
|
||||
MineTicker ticker = new MineTicker(mines, plugin);
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class MineTickerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testMultipleStops_DoNotThrow() {
|
||||
void testMultipleStopsDoNotThrow() {
|
||||
// Arrange
|
||||
MineTicker ticker = new MineTicker(mines, plugin);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,19 +3,12 @@ package dev.loki.lomines.core;
|
|||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.model.Mine;
|
||||
import dev.loki.lomines.core.mine.registry.Mines;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
|
@ -23,19 +16,13 @@ import java.nio.file.Path;
|
|||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Disabled("WorldGuard dependency not available in unit tests")
|
||||
class MinesLifecycleTest {
|
||||
|
||||
@TempDir
|
||||
|
|
@ -43,43 +30,25 @@ class MinesLifecycleTest {
|
|||
|
||||
private Mines mines;
|
||||
private LoMinesPlugin plugin;
|
||||
private BukkitScheduler scheduler;
|
||||
private MockedStatic<Bukkit> globalBukkit;
|
||||
private ServerMock server;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
globalBukkit = mockStatic(Bukkit.class);
|
||||
|
||||
org.bukkit.plugin.PluginManager pluginManager = mock(org.bukkit.plugin.PluginManager.class);
|
||||
Server server = mock(Server.class);
|
||||
World world = mock(World.class);
|
||||
BlockData blockData = mock(BlockData.class);
|
||||
|
||||
globalBukkit.when(Bukkit::getPluginManager).thenReturn(pluginManager);
|
||||
globalBukkit.when(Bukkit::getServer).thenReturn(server);
|
||||
globalBukkit.when(() -> Bukkit.getWorld(anyString())).thenReturn(world);
|
||||
globalBukkit.when(() -> Bukkit.createBlockData(any(Material.class))).thenReturn(blockData);
|
||||
when(world.getName()).thenReturn("world");
|
||||
server = MockBukkit.mock();
|
||||
server.addSimpleWorld("world");
|
||||
|
||||
plugin = mock(LoMinesPlugin.class);
|
||||
Logger logger = mock(Logger.class);
|
||||
scheduler = mock(BukkitScheduler.class);
|
||||
|
||||
when(plugin.getDataFolder()).thenReturn(tempDir.toFile());
|
||||
when(plugin.getLogger()).thenReturn(logger);
|
||||
|
||||
globalBukkit.when(Bukkit::getScheduler).thenReturn(scheduler);
|
||||
BukkitTask task = mock(BukkitTask.class);
|
||||
when(scheduler.runTaskTimer(any(), any(Runnable.class), anyLong(), anyLong())).thenReturn(task);
|
||||
|
||||
mines = new Mines(plugin);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
if (globalBukkit != null) {
|
||||
globalBukkit.close();
|
||||
}
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -97,9 +66,9 @@ class MinesLifecycleTest {
|
|||
|
||||
@Test
|
||||
void testCreateMineCreatesFolder() throws IOException {
|
||||
assertFalse(Files.exists(tempDir.resolve("mines")));
|
||||
mines.create("testmine");
|
||||
assertTrue(Files.isDirectory(tempDir.resolve("mines")));
|
||||
mines.create("testmine");
|
||||
assertTrue(Files.exists(tempDir.resolve("mines/testmine.yml")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -3,19 +3,12 @@ package dev.loki.lomines.core;
|
|||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.model.Mine;
|
||||
import dev.loki.lomines.core.mine.registry.Mines;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
|
@ -25,15 +18,9 @@ import java.util.logging.Logger;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Disabled("WorldGuard dependency not available in unit tests")
|
||||
class MinesLoadingTest {
|
||||
|
||||
private static final String FULL_YAML = """
|
||||
|
|
@ -61,43 +48,25 @@ class MinesLoadingTest {
|
|||
|
||||
private Mines mines;
|
||||
private LoMinesPlugin plugin;
|
||||
private BukkitScheduler scheduler;
|
||||
private MockedStatic<Bukkit> globalBukkit;
|
||||
private ServerMock server;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
globalBukkit = mockStatic(Bukkit.class);
|
||||
|
||||
org.bukkit.plugin.PluginManager pluginManager = mock(org.bukkit.plugin.PluginManager.class);
|
||||
Server server = mock(Server.class);
|
||||
World world = mock(World.class);
|
||||
BlockData blockData = mock(BlockData.class);
|
||||
|
||||
globalBukkit.when(Bukkit::getPluginManager).thenReturn(pluginManager);
|
||||
globalBukkit.when(Bukkit::getServer).thenReturn(server);
|
||||
globalBukkit.when(() -> Bukkit.getWorld(anyString())).thenReturn(world);
|
||||
globalBukkit.when(() -> Bukkit.createBlockData(any(Material.class))).thenReturn(blockData);
|
||||
when(world.getName()).thenReturn("world");
|
||||
server = MockBukkit.mock();
|
||||
server.addSimpleWorld("world");
|
||||
|
||||
plugin = mock(LoMinesPlugin.class);
|
||||
Logger logger = mock(Logger.class);
|
||||
scheduler = mock(BukkitScheduler.class);
|
||||
|
||||
when(plugin.getDataFolder()).thenReturn(tempDir.toFile());
|
||||
when(plugin.getLogger()).thenReturn(logger);
|
||||
|
||||
globalBukkit.when(Bukkit::getScheduler).thenReturn(scheduler);
|
||||
BukkitTask task = mock(BukkitTask.class);
|
||||
when(scheduler.runTaskTimer(any(), any(Runnable.class), anyLong(), anyLong())).thenReturn(task);
|
||||
|
||||
mines = new Mines(plugin);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
if (globalBukkit != null) {
|
||||
globalBukkit.close();
|
||||
}
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,22 +1,13 @@
|
|||
package dev.loki.lomines.core;
|
||||
|
||||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.core.mine.model.Mine;
|
||||
import dev.loki.lomines.core.mine.registry.Mines;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
|
@ -25,19 +16,15 @@ import java.util.logging.Logger;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for Mines registry.
|
||||
*/
|
||||
@Disabled("WorldGuard dependency not available in unit tests")
|
||||
class MinesTest {
|
||||
|
||||
@TempDir
|
||||
|
|
@ -45,43 +32,25 @@ class MinesTest {
|
|||
|
||||
private Mines mines;
|
||||
private LoMinesPlugin plugin;
|
||||
private BukkitScheduler scheduler;
|
||||
private MockedStatic<Bukkit> globalBukkit;
|
||||
private ServerMock server;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
globalBukkit = mockStatic(Bukkit.class);
|
||||
|
||||
PluginManager pluginManager = mock(PluginManager.class);
|
||||
Server server = mock(Server.class);
|
||||
World world = mock(World.class);
|
||||
BlockData blockData = mock(BlockData.class);
|
||||
|
||||
globalBukkit.when(Bukkit::getPluginManager).thenReturn(pluginManager);
|
||||
globalBukkit.when(Bukkit::getServer).thenReturn(server);
|
||||
globalBukkit.when(() -> Bukkit.getWorld(anyString())).thenReturn(world);
|
||||
globalBukkit.when(() -> Bukkit.createBlockData(any(Material.class))).thenReturn(blockData);
|
||||
when(world.getName()).thenReturn("world");
|
||||
server = MockBukkit.mock();
|
||||
server.addSimpleWorld("world");
|
||||
|
||||
plugin = mock(LoMinesPlugin.class);
|
||||
Logger logger = mock(Logger.class);
|
||||
scheduler = mock(BukkitScheduler.class);
|
||||
|
||||
when(plugin.getDataFolder()).thenReturn(tempDir.toFile());
|
||||
when(plugin.getLogger()).thenReturn(logger);
|
||||
|
||||
globalBukkit.when(Bukkit::getScheduler).thenReturn(scheduler);
|
||||
BukkitTask task = mock(BukkitTask.class);
|
||||
when(scheduler.runTaskTimer(any(), any(Runnable.class), anyLong(), anyLong())).thenReturn(task);
|
||||
|
||||
mines = new Mines(plugin);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
if (globalBukkit != null) {
|
||||
globalBukkit.close();
|
||||
}
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class LeaderboardPositionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetPosition_ReturnsCorrectPosition() {
|
||||
void testGetPositionReturnsCorrectPosition() {
|
||||
UUID player1 = UUID.randomUUID();
|
||||
UUID player2 = UUID.randomUUID();
|
||||
UUID player3 = UUID.randomUUID();
|
||||
|
|
@ -45,13 +45,13 @@ class LeaderboardPositionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetPosition_ReturnsMinusOneForNonExistentPlayer() {
|
||||
void testGetPositionReturnsMinusOneForNonExistentPlayer() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
assertEquals(-1, leaderboard.getPosition(playerId), "Should return -1 for non-existent player");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPosition_ReturnsMinusOneForZeroBlocks() {
|
||||
void testGetPositionReturnsMinusOneForZeroBlocks() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
statsManager.getOrCreate(playerId).setTotalBlocks(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class LeaderboardQueryTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopByMine_SortedDescending() {
|
||||
void testGetTopByMineSortedDescending() {
|
||||
UUID player1 = UUID.randomUUID();
|
||||
UUID player2 = UUID.randomUUID();
|
||||
UUID player3 = UUID.randomUUID();
|
||||
|
|
@ -49,7 +49,7 @@ class LeaderboardQueryTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopByMine_FiltersZeroBlocks() {
|
||||
void testGetTopByMineFiltersZeroBlocks() {
|
||||
UUID player1 = UUID.randomUUID();
|
||||
UUID player2 = UUID.randomUUID();
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ class LeaderboardQueryTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopByMine_OnlyIncludesSpecificMine() {
|
||||
void testGetTopByMineOnlyIncludesSpecificMine() {
|
||||
UUID player1 = UUID.randomUUID();
|
||||
UUID player2 = UUID.randomUUID();
|
||||
|
||||
|
|
|
|||
|
|
@ -39,13 +39,13 @@ class LeaderboardTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopTotal_EmptyStats() {
|
||||
void testGetTopTotalEmptyStats() {
|
||||
List<LeaderboardEntry> top = leaderboard.getTopTotal(10);
|
||||
assertTrue(top.isEmpty(), "Top list should be empty when no stats exist");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetTopTotal_SinglePlayer() {
|
||||
void testGetTopTotalSinglePlayer() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
PlayerStats stats = statsManager.getOrCreate(playerId);
|
||||
stats.setTotalBlocks(100);
|
||||
|
|
@ -57,7 +57,7 @@ class LeaderboardTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopTotal_SortedDescending() {
|
||||
void testGetTopTotalSortedDescending() {
|
||||
UUID player1 = UUID.randomUUID();
|
||||
UUID player2 = UUID.randomUUID();
|
||||
UUID player3 = UUID.randomUUID();
|
||||
|
|
@ -74,7 +74,7 @@ class LeaderboardTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopTotal_LimitRespected() {
|
||||
void testGetTopTotalLimitRespected() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
statsManager.getOrCreate(playerId).setTotalBlocks(i + 1);
|
||||
|
|
@ -85,7 +85,7 @@ class LeaderboardTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopTotal_FiltersZeroBlocks() {
|
||||
void testGetTopTotalFiltersZeroBlocks() {
|
||||
UUID player1 = UUID.randomUUID();
|
||||
UUID player2 = UUID.randomUUID();
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ class LeaderboardTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetTopTotal_CachingWorks() {
|
||||
void testGetTopTotalCachingWorks() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
statsManager.getOrCreate(playerId).setTotalBlocks(100);
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ class LeaderboardTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testInvalidateCache_ClearsCache() {
|
||||
void testInvalidateCacheClearsCache() {
|
||||
UUID playerId = UUID.randomUUID();
|
||||
statsManager.getOrCreate(playerId).setTotalBlocks(100);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package dev.loki.lomines.data;
|
||||
|
||||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.data.stats.model.PlayerStats;
|
||||
import dev.loki.lomines.data.stats.service.StatsManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
|
@ -11,7 +10,6 @@ import org.junit.jupiter.api.Test;
|
|||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package dev.loki.lomines.data;
|
|||
import dev.loki.lomines.LoMinesPlugin;
|
||||
import dev.loki.lomines.data.stats.model.PlayerStats;
|
||||
import dev.loki.lomines.data.stats.service.StatsManager;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ import dev.loki.lomines.data.config.reset.ResetConfig;
|
|||
import dev.loki.lomines.data.config.reward.RewardConfig;
|
||||
import dev.loki.lomines.data.config.teleport.TeleportConfig;
|
||||
import dev.loki.lomines.data.config.ui.UIConfig;
|
||||
import dev.loki.lomines.util.location.geo.Cuboid;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -25,26 +25,40 @@ import java.util.Map;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@Disabled("Paper API RegistryAccess not available in unit tests")
|
||||
class MineConfigTest {
|
||||
|
||||
private ServerMock server;
|
||||
private World world;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server = MockBukkit.mock();
|
||||
server.addSimpleWorld("world");
|
||||
world = server.getWorld("world");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
private RegionConfig testRegion() {
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
return RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
}
|
||||
|
||||
private BlockConfig testBlocks() {
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
return new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuilder() {
|
||||
try (MockedStatic<org.bukkit.Bukkit> bukkit = Mockito.mockStatic(org.bukkit.Bukkit.class)) {
|
||||
World world = mock(World.class);
|
||||
when(world.getName()).thenReturn("world");
|
||||
bukkit.when(() -> org.bukkit.Bukkit.getWorld("world")).thenReturn(world);
|
||||
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
RegionConfig region = RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
BlockConfig blocks = new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
RegionConfig region = testRegion();
|
||||
BlockConfig blocks = testBlocks();
|
||||
|
||||
MineConfig config = MineConfig.builder("testmine")
|
||||
.region(region)
|
||||
|
|
@ -59,22 +73,11 @@ class MineConfigTest {
|
|||
assertEquals(1, config.region().regionCount());
|
||||
assertEquals(1, config.blocks().blockCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultsFactory() {
|
||||
try (MockedStatic<org.bukkit.Bukkit> bukkit = Mockito.mockStatic(org.bukkit.Bukkit.class)) {
|
||||
World world = mock(World.class);
|
||||
when(world.getName()).thenReturn("world");
|
||||
bukkit.when(() -> org.bukkit.Bukkit.getWorld("world")).thenReturn(world);
|
||||
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
RegionConfig region = RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
BlockConfig blocks = new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
RegionConfig region = testRegion();
|
||||
BlockConfig blocks = testBlocks();
|
||||
|
||||
MineConfig config = MineConfigDefaults.defaults("mymine", region, blocks);
|
||||
|
||||
|
|
@ -84,22 +87,11 @@ class MineConfigTest {
|
|||
assertNotNull(config.teleport());
|
||||
assertNotNull(config.ui());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNameNormalized() {
|
||||
try (MockedStatic<org.bukkit.Bukkit> bukkit = Mockito.mockStatic(org.bukkit.Bukkit.class)) {
|
||||
World world = mock(World.class);
|
||||
when(world.getName()).thenReturn("world");
|
||||
bukkit.when(() -> org.bukkit.Bukkit.getWorld("world")).thenReturn(world);
|
||||
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
RegionConfig region = RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
BlockConfig blocks = new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
RegionConfig region = testRegion();
|
||||
BlockConfig blocks = testBlocks();
|
||||
|
||||
MineConfig config = MineConfig.builder("TestMine_123 ")
|
||||
.region(region)
|
||||
|
|
@ -108,22 +100,15 @@ class MineConfigTest {
|
|||
|
||||
assertEquals("testmine_123", config.name());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWorldNameDelegation() {
|
||||
try (MockedStatic<org.bukkit.Bukkit> bukkit = Mockito.mockStatic(org.bukkit.Bukkit.class)) {
|
||||
World world = mock(World.class);
|
||||
when(world.getName()).thenReturn("nether");
|
||||
bukkit.when(() -> org.bukkit.Bukkit.getWorld("nether")).thenReturn(world);
|
||||
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
server.addSimpleWorld("nether");
|
||||
World nether = server.getWorld("nether");
|
||||
Location loc1 = new Location(nether, 0, 64, 0);
|
||||
Location loc2 = new Location(nether, 10, 74, 10);
|
||||
RegionConfig region = RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
BlockConfig blocks = new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
BlockConfig blocks = testBlocks();
|
||||
|
||||
MineConfig config = MineConfig.builder("test")
|
||||
.region(region)
|
||||
|
|
@ -132,5 +117,4 @@ class MineConfigTest {
|
|||
|
||||
assertEquals("nether", config.worldName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,21 +8,47 @@ import dev.loki.lomines.data.config.region.RegionConfig;
|
|||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class MineConfigValidationTest {
|
||||
|
||||
private ServerMock server;
|
||||
private World world;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server = MockBukkit.mock();
|
||||
server.addSimpleWorld("world");
|
||||
world = server.getWorld("world");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
private RegionConfig testRegion() {
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
return RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
}
|
||||
|
||||
private BlockConfig testBlocks() {
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
return new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullNameThrows() {
|
||||
assertThrows(NullPointerException.class, () ->
|
||||
|
|
@ -30,20 +56,9 @@ class MineConfigValidationTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Paper API RegistryAccess not available in unit tests")
|
||||
void testBlankNameThrows() {
|
||||
try (MockedStatic<org.bukkit.Bukkit> bukkit = Mockito.mockStatic(org.bukkit.Bukkit.class)) {
|
||||
World world = mock(World.class);
|
||||
when(world.getName()).thenReturn("world");
|
||||
bukkit.when(() -> org.bukkit.Bukkit.getWorld("world")).thenReturn(world);
|
||||
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
RegionConfig region = RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
BlockConfig blocks = new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
RegionConfig region = testRegion();
|
||||
BlockConfig blocks = testBlocks();
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
MineConfig.builder(" ")
|
||||
|
|
@ -51,14 +66,10 @@ class MineConfigValidationTest {
|
|||
.blocks(blocks)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Paper API RegistryAccess not available in unit tests")
|
||||
void testNullRegionThrows() {
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
weights.put(new BlockKey.Vanilla(Material.STONE), 100.0);
|
||||
BlockConfig blocks = new BlockConfig(weights, FillMode.CUBOID, null);
|
||||
BlockConfig blocks = testBlocks();
|
||||
|
||||
assertThrows(NullPointerException.class, () ->
|
||||
MineConfig.builder("test")
|
||||
|
|
@ -69,14 +80,7 @@ class MineConfigValidationTest {
|
|||
|
||||
@Test
|
||||
void testNullBlocksThrows() {
|
||||
try (MockedStatic<org.bukkit.Bukkit> bukkit = Mockito.mockStatic(org.bukkit.Bukkit.class)) {
|
||||
World world = mock(World.class);
|
||||
when(world.getName()).thenReturn("world");
|
||||
bukkit.when(() -> org.bukkit.Bukkit.getWorld("world")).thenReturn(world);
|
||||
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 10, 74, 10);
|
||||
RegionConfig region = RegionConfig.fromSelections(List.of(loc1, loc2));
|
||||
RegionConfig region = testRegion();
|
||||
|
||||
assertThrows(NullPointerException.class, () ->
|
||||
MineConfig.builder("test")
|
||||
|
|
@ -84,5 +88,4 @@ class MineConfigValidationTest {
|
|||
.blocks(null)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package dev.loki.lomines.data.config.block;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -13,9 +16,20 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Disabled("Paper API RegistryAccess not available in unit tests")
|
||||
class BlockConfigTest {
|
||||
|
||||
private ServerMock server;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server = MockBukkit.mock();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidConfig() {
|
||||
Map<BlockKey, Double> weights = new HashMap<>();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,31 @@
|
|||
package dev.loki.lomines.data.config.block;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@Disabled("Paper API RegistryAccess not available in unit tests")
|
||||
class BlockKeyTest {
|
||||
|
||||
private ServerMock server;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
server = MockBukkit.mock();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVanillaSerialization() {
|
||||
BlockKey.Vanilla stone = new BlockKey.Vanilla(Material.STONE);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class UIConfigTest {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import java.util.Collections;
|
|||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
|
@ -38,7 +37,7 @@ class ChunkUtilsRefreshTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUpdateChunks_withLargeRegion() {
|
||||
void testUpdateChunksWithLargeRegion() {
|
||||
Location loc1 = new Location(world, 0, 0, 0);
|
||||
Location loc2 = new Location(world, 100, 100, 100);
|
||||
when(world.getChunkAt(anyInt(), anyInt())).thenReturn(chunk);
|
||||
|
|
@ -52,7 +51,7 @@ class ChunkUtilsRefreshTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUpdateChunks_withNoPlayers() {
|
||||
void testUpdateChunksWithNoPlayers() {
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 5, 70, 5);
|
||||
when(world.getChunkAt(anyInt(), anyInt())).thenReturn(chunk);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
|
@ -43,14 +42,14 @@ class ChunkUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUpdateChunks_withNullRegion_throwsException() {
|
||||
void testUpdateChunksWithNullRegionThrowsException() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
ChunkUtils.updateChunks(null);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateChunks_withSingleChunkRegion() {
|
||||
void testUpdateChunksWithSingleChunkRegion() {
|
||||
// Create a small region within a single chunk
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 5, 70, 5);
|
||||
|
|
@ -69,7 +68,7 @@ class ChunkUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUpdateChunks_withMultipleChunks() {
|
||||
void testUpdateChunksWithMultipleChunks() {
|
||||
// Create a region spanning multiple chunks (16 blocks per chunk)
|
||||
Location loc1 = new Location(world, 0, 64, 0);
|
||||
Location loc2 = new Location(world, 32, 70, 32);
|
||||
|
|
@ -88,7 +87,7 @@ class ChunkUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUpdateChunks_withNegativeCoordinates() {
|
||||
void testUpdateChunksWithNegativeCoordinates() {
|
||||
// Test with negative coordinates
|
||||
Location loc1 = new Location(world, -16, 64, -16);
|
||||
Location loc2 = new Location(world, -1, 70, -1);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ import org.mockito.Mockito;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class LocationParserErrorTest {
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import dev.loki.lomines.util.format.TimeFormatter;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class TimeFormatterTest {
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test;
|
|||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class SelectionManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void getSelection_createsNewSelectionIfNotExists() {
|
||||
void getSelectionCreatesNewSelectionIfNotExists() {
|
||||
Selection selection = manager.getSelection(playerId);
|
||||
|
||||
assertNotNull(selection);
|
||||
|
|
@ -34,7 +34,7 @@ class SelectionManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void getSelection_returnsSameInstanceOnMultipleCalls() {
|
||||
void getSelectionReturnsSameInstanceOnMultipleCalls() {
|
||||
Selection first = manager.getSelection(playerId);
|
||||
Selection second = manager.getSelection(playerId);
|
||||
|
||||
|
|
@ -42,21 +42,21 @@ class SelectionManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void getSelection_throwsExceptionForNullPlayerId() {
|
||||
void getSelectionThrowsExceptionForNullPlayerId() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
manager.getSelection(null);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void findSelection_returnsEmptyWhenNotExists() {
|
||||
void findSelectionReturnsEmptyWhenNotExists() {
|
||||
Optional<Selection> result = manager.findSelection(playerId);
|
||||
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void findSelection_returnsSelectionWhenExists() {
|
||||
void findSelectionReturnsSelectionWhenExists() {
|
||||
Selection created = manager.getSelection(playerId);
|
||||
Optional<Selection> found = manager.findSelection(playerId);
|
||||
|
||||
|
|
@ -65,33 +65,33 @@ class SelectionManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void findSelection_throwsExceptionForNullPlayerId() {
|
||||
void findSelectionThrowsExceptionForNullPlayerId() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
manager.findSelection(null);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasSelection_returnsFalseWhenNotExists() {
|
||||
void hasSelectionReturnsFalseWhenNotExists() {
|
||||
assertFalse(manager.hasSelection(playerId));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasSelection_returnsTrueWhenExists() {
|
||||
void hasSelectionReturnsTrueWhenExists() {
|
||||
manager.getSelection(playerId);
|
||||
|
||||
assertTrue(manager.hasSelection(playerId));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasSelection_throwsExceptionForNullPlayerId() {
|
||||
void hasSelectionThrowsExceptionForNullPlayerId() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
manager.hasSelection(null);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void clearSelection_removesSelection() {
|
||||
void clearSelectionRemovesSelection() {
|
||||
manager.getSelection(playerId);
|
||||
assertTrue(manager.hasSelection(playerId));
|
||||
|
||||
|
|
@ -101,14 +101,14 @@ class SelectionManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void clearSelection_doesNothingWhenSelectionNotExists() {
|
||||
void clearSelectionDoesNothingWhenSelectionNotExists() {
|
||||
assertDoesNotThrow(() -> {
|
||||
manager.clearSelection(playerId);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void clearSelection_throwsExceptionForNullPlayerId() {
|
||||
void clearSelectionThrowsExceptionForNullPlayerId() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
manager.clearSelection(null);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
package dev.loki.lomines.util.selection;
|
||||
|
||||
import dev.loki.lomines.util.location.geo.Cuboid;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
|
|
|||
29
todo.md
29
todo.md
|
|
@ -1,7 +1,7 @@
|
|||
# LoMines — План реструктуризации и улучшения качества
|
||||
|
||||
> **Обновлено:** 2026-07-06
|
||||
> **Цели:** Разбивка на подпапки (≤3 файла), лимит 150 строк/файл, Checkstyle
|
||||
> **Обновлено:** 2026-08-12
|
||||
> **Цели:** Разбивка на подпапки (≤3 файла), лимит 150 строк/файл, Checkstyle, тестовое покрытие
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -574,3 +574,28 @@ dev.loki.lomines/
|
|||
- **0 файлов >150 строк**
|
||||
- **0 папок >3 файлов**
|
||||
- **145 main + 31 test = 176 файлов**
|
||||
|
||||
---
|
||||
|
||||
## ✅ Постреструктуризационные задачи завершены (2026-08-12)
|
||||
|
||||
### Docs
|
||||
- `ARCHITECTURE.md` полностью переписан под реальный код: `dev.loki.lomines`, `extends JavaPlugin`, без lolib/LoAPI (ранее описывал Kotlin-версию)
|
||||
- Удалён устаревший `core/common/package-info.java` (ссылался на `LoPlugin`, `Mines`/`Mine` в `core.common`) — пакет был пустым
|
||||
|
||||
### Checkstyle
|
||||
- `BeforeExecutionExclusionFileFilter` (исключавший `src/test`) убран — тесты теперь проверяются
|
||||
- `MethodLength` 80 → 30
|
||||
- Исправлены нарушения: 23 в main (выделение private-методов) + 60 в test (unused imports, camelCase для тестов)
|
||||
|
||||
### Тесты: MockBukkit
|
||||
- Подключён `org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.110.0` (testImplementation)
|
||||
- `testImplementation` paper-api приведён к `1.21.11-R0.1-SNAPSHOT` (требование MockBukkit), `compileOnly` остаётся `1.21.4`
|
||||
- Включены все 48 ранее отключённых тестов: `BlockKeyTest`, `BlockConfigTest`, `MineTest`, `MineConfigTest`, `MineConfigValidationTest`, `MinesTest`, `MinesLoadingTest`, `MinesLifecycleTest`
|
||||
- **Итог: 184 теста, 0 skipped, 0 failures**
|
||||
|
||||
### Багфикс
|
||||
- `Mines.create("TestMine")` сохранял `testmine.yml` (record нормализует имя в lowercase), но загружал `TestMine.yml` → `IOException`. Исправлено нормализацией имени в `Mines.create` (`name.toLowerCase().trim()`)
|
||||
|
||||
### Cleanup
|
||||
- Удалены `bin/` (Eclipse output, был gitignored) и `libs/` (содержал только `.gitkeep`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue