diff --git a/src/main/java/dev/marcospaulo/canalhandia/BlueMapBridge.java b/src/main/java/dev/marcospaulo/canalhandia/BlueMapBridge.java index 02f4961..2d65cc0 100644 --- a/src/main/java/dev/marcospaulo/canalhandia/BlueMapBridge.java +++ b/src/main/java/dev/marcospaulo/canalhandia/BlueMapBridge.java @@ -127,9 +127,13 @@ final class BlueMapBridge { if (!mapMatchesWorld(map, loader.world())) { continue; } + String statusHtml = loader.enabled() + ? "Ativo" + : "Pausado"; var marker = de.bluecolored.bluemap.api.markers.POIMarker.builder() - .label("Âncora #" + loader.id() + " (" + loader.ownerName() + ")") - .detail("Âncora de Chunk #" + loader.id() + "
Dono: " + .label(loader.simpleName() + " (" + loader.ownerName() + ")" + (loader.enabled() ? "" : " [Pausado]")) + .detail("" + escape(loader.displayName()) + "
Status: " + + statusHtml + "
Dono: " + escape(loader.ownerName()) + "
Chunk: " + loader.chunkCoords()) .position(loader.x(), loader.y(), loader.z()) .build(); diff --git a/src/main/java/dev/marcospaulo/canalhandia/CanalhandiaCommand.java b/src/main/java/dev/marcospaulo/canalhandia/CanalhandiaCommand.java index 5e7f3ae..af32693 100644 --- a/src/main/java/dev/marcospaulo/canalhandia/CanalhandiaCommand.java +++ b/src/main/java/dev/marcospaulo/canalhandia/CanalhandiaCommand.java @@ -1823,6 +1823,9 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { case "remover", "remove", "del" -> chunkloaderRemove(sender, rest); case "receita", "craft" -> chunkloaderRecipe(sender); case "limite", "limit" -> chunkloaderLimit(sender, rest); + case "nome", "renomear", "rename" -> chunkloaderRename(sender, rest); + case "ativar", "enable" -> chunkloaderSetEnabled(sender, rest, true); + case "desativar", "pausar", "disable", "pause" -> chunkloaderSetEnabled(sender, rest, false); case "admin" -> chunkloaderAdmin(sender, rest); case "dar", "give" -> { if (admin(sender)) { @@ -1855,13 +1858,30 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { boolean bedrock = isBedrock(sender); for (ChunkLoader loader : mine) { - Component line = Component.text(" #" + loader.id() + " ", NamedTextColor.AQUA) - .append(Component.text(loader.place() + " " + loader.chunkCoords(), NamedTextColor.WHITE)); + String statusText = loader.enabled() ? "[Ativa]" : "[Pausada]"; + NamedTextColor statusColor = loader.enabled() ? NamedTextColor.GREEN : NamedTextColor.RED; + + Component line = Component.text(" " + loader.displayName() + " ", NamedTextColor.AQUA) + .append(Component.text(loader.place() + " " + loader.chunkCoords() + " ", NamedTextColor.WHITE)) + .append(Component.text(statusText + " ", statusColor)); if (!bedrock) { - line = line.append(Component.text(" [Remover]", NamedTextColor.RED) + if (loader.enabled()) { + line = line.append(Component.text("[Pausar] ", NamedTextColor.YELLOW) + .hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText( + Component.text("Clique para pausar " + loader.displayName(), NamedTextColor.GRAY))) + .clickEvent(net.kyori.adventure.text.event.ClickEvent.runCommand( + "/chunkloader desativar " + loader.id()))); + } else { + line = line.append(Component.text("[Ativar] ", NamedTextColor.GREEN) + .hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText( + Component.text("Clique para reativar " + loader.displayName(), NamedTextColor.GRAY))) + .clickEvent(net.kyori.adventure.text.event.ClickEvent.runCommand( + "/chunkloader ativar " + loader.id()))); + } + line = line.append(Component.text("[Remover]", NamedTextColor.RED) .hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText( - Component.text("Clique para desativar a âncora #" + loader.id(), NamedTextColor.GRAY))) + Component.text("Clique para recolher " + loader.displayName(), NamedTextColor.GRAY))) .clickEvent(net.kyori.adventure.text.event.ClickEvent.suggestCommand( "/chunkloader remover " + loader.id()))); } @@ -1891,9 +1911,11 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { .append(Component.text(" em " + world, NamedTextColor.WHITE))); if (here != null) { + String status = here.enabled() ? "Ativa" : "Pausada"; + NamedTextColor statusCol = here.enabled() ? NamedTextColor.GREEN : NamedTextColor.RED; sender.sendMessage(Component.text(" Status: ", NamedTextColor.GRAY) - .append(Component.text("Carregada continuamente por Âncora #" + here.id(), NamedTextColor.GREEN)) - .append(Component.text(" (" + here.ownerName() + ")", NamedTextColor.WHITE))); + .append(Component.text(here.displayName() + " (" + status + ")", statusCol)) + .append(Component.text(" de " + here.ownerName(), NamedTextColor.WHITE))); } else { sender.sendMessage(Component.text(" Status: ", NamedTextColor.GRAY) .append(Component.text("Carregamento normal (sem âncora)", NamedTextColor.DARK_GRAY))); @@ -1903,24 +1925,70 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { .append(Component.text(used + "/" + limitStr, NamedTextColor.YELLOW))); } + private void chunkloaderRename(CommandSender sender, String[] args) { + if (args.length < 2) { + Msg.error(sender, "Uso: /chunkloader nome "); + return; + } + ChunkLoader loader = plugin.chunkLoaders().find(args[0]); + if (loader == null) { + Msg.error(sender, "Nenhuma âncora encontrada para '" + args[0] + "'."); + return; + } + boolean isOwner = sender instanceof Player player && player.getUniqueId().toString().equalsIgnoreCase(loader.ownerUuid()); + boolean isAdmin = sender.hasPermission(ADMIN) || sender.hasPermission("canalhandia.chunkloader.admin"); + if (!isOwner && !isAdmin) { + Msg.error(sender, "Esta âncora pertence a " + loader.ownerName() + "."); + return; + } + String newName = String.join(" ", Arrays.copyOfRange(args, 1, args.length)).trim(); + if (newName.length() > 32) { + Msg.error(sender, "Nome muito longo (máximo 32 caracteres)."); + return; + } + plugin.chunkLoaders().rename(loader.id(), newName); + plugin.blueMap().syncChunkLoaders(); + Msg.ok(sender, "Âncora #" + loader.id() + " renomeada para '" + newName + "'."); + } + + private void chunkloaderSetEnabled(CommandSender sender, String[] args, boolean enabled) { + if (args.length < 1) { + Msg.error(sender, "Uso: /chunkloader " + (enabled ? "ativar" : "desativar") + " "); + return; + } + ChunkLoader loader = plugin.chunkLoaders().find(args[0]); + if (loader == null) { + Msg.error(sender, "Nenhuma âncora encontrada para '" + args[0] + "'."); + return; + } + boolean isOwner = sender instanceof Player player && player.getUniqueId().toString().equalsIgnoreCase(loader.ownerUuid()); + boolean isAdmin = sender.hasPermission(ADMIN) || sender.hasPermission("canalhandia.chunkloader.admin"); + if (!isOwner && !isAdmin) { + Msg.error(sender, "Esta âncora pertence a " + loader.ownerName() + "."); + return; + } + if (loader.enabled() == enabled) { + Msg.error(sender, "A âncora " + loader.displayName() + " já está " + (enabled ? "ativa" : "pausada") + "."); + return; + } + plugin.chunkLoaders().setEnabled(loader.id(), enabled); + plugin.blueMap().syncChunkLoaders(); + Msg.ok(sender, "Âncora " + loader.displayName() + " " + (enabled ? "ATIVADA." : "PAUSADA/DESATIVADA.")); + } + private void chunkloaderRemove(CommandSender sender, String[] args) { if (args.length < 1) { - Msg.error(sender, "Uso: /chunkloader remover "); + Msg.error(sender, "Uso: /chunkloader remover "); return; } - long id = parseLong(args[0]); - if (id <= 0) { - Msg.error(sender, "ID inválido."); - return; - } - - ChunkLoader loader = plugin.chunkLoaders().byId(id); + ChunkLoader loader = plugin.chunkLoaders().find(args[0]); if (loader == null) { - Msg.error(sender, "Nenhuma Âncora de Chunk encontrada com o ID #" + id); + Msg.error(sender, "Nenhuma Âncora de Chunk encontrada para '" + args[0] + "'."); return; } + long id = loader.id(); boolean isOwner = sender instanceof Player player && player.getUniqueId().toString().equalsIgnoreCase(loader.ownerUuid()); boolean isAdmin = sender.hasPermission(ADMIN) || sender.hasPermission("canalhandia.chunkloader.admin"); @@ -1948,7 +2016,7 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { for (ItemStack drop : overflow.values()) { player.getWorld().dropItemNaturally(player.getLocation(), drop); } - Msg.ok(sender, "Âncora de Chunk #" + id + " desativada e devolvida ao inventário."); + Msg.ok(sender, "Âncora de Chunk " + loader.displayName() + " desativada e devolvida ao inventário."); } else { try { org.bukkit.World w = Bukkit.getWorld(loader.world()); @@ -1958,7 +2026,7 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { } } catch (Exception ignored) { } - Msg.ok(sender, "Âncora de Chunk #" + id + " desativada e dropada em " + loader.place() + "."); + Msg.ok(sender, "Âncora de Chunk " + loader.displayName() + " desativada e dropada em " + loader.place() + "."); } } @@ -2108,8 +2176,14 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { sender.sendMessage(Component.text(" /chunkloader info", NamedTextColor.AQUA) .append(Component.text(" — Informações sobre a chunk onde você está", NamedTextColor.GRAY))); sender.sendMessage(Component.text(" /chunkloader listar", NamedTextColor.AQUA) - .append(Component.text(" — Lista suas âncoras ativas e coordenadas", NamedTextColor.GRAY))); - sender.sendMessage(Component.text(" /chunkloader remover ", NamedTextColor.AQUA) + .append(Component.text(" — Lista suas âncoras, nomes, status e coordenadas", NamedTextColor.GRAY))); + sender.sendMessage(Component.text(" /chunkloader nome ", NamedTextColor.AQUA) + .append(Component.text(" — Define um nome/rótulo para a âncora", NamedTextColor.GRAY))); + sender.sendMessage(Component.text(" /chunkloader ativar ", NamedTextColor.AQUA) + .append(Component.text(" — Reativa o carregamento contínuo da âncora", NamedTextColor.GRAY))); + sender.sendMessage(Component.text(" /chunkloader desativar ", NamedTextColor.AQUA) + .append(Component.text(" — Pausa o carregamento sem quebrar o bloco", NamedTextColor.GRAY))); + sender.sendMessage(Component.text(" /chunkloader remover ", NamedTextColor.AQUA) .append(Component.text(" — Desativa e recolhe uma de suas âncoras", NamedTextColor.GRAY))); sender.sendMessage(Component.text(" /chunkloader receita", NamedTextColor.AQUA) .append(Component.text(" — Mostra a receita de criação do bloco", NamedTextColor.GRAY))); @@ -2284,19 +2358,25 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter { } if (name.equals("chunkloader") || name.equals("ancora") || name.equals("ancoras")) { if (args.length == 1) { - List options = new ArrayList<>(List.of("info", "listar", "remover", "receita", "limite")); + List options = new ArrayList<>(List.of("info", "listar", "nome", "ativar", "desativar", "remover", "receita", "limite")); if (sender.hasPermission(ADMIN) || sender.hasPermission("canalhandia.chunkloader.admin")) { options.addAll(List.of("admin", "dar")); } return filter(options, args[0]); } - if (args.length == 2 && (args[0].equalsIgnoreCase("remover") || args[0].equalsIgnoreCase("del"))) { + if (args.length == 2 && (args[0].equalsIgnoreCase("remover") || args[0].equalsIgnoreCase("del") + || args[0].equalsIgnoreCase("nome") || args[0].equalsIgnoreCase("renomear") + || args[0].equalsIgnoreCase("ativar") || args[0].equalsIgnoreCase("desativar") + || args[0].equalsIgnoreCase("pausar"))) { if (sender instanceof Player player) { - List ids = new ArrayList<>(); + List identifiers = new ArrayList<>(); for (ChunkLoader loader : plugin.chunkLoaders().byOwner(player.getUniqueId().toString())) { - ids.add(String.valueOf(loader.id())); + identifiers.add(String.valueOf(loader.id())); + if (loader.name() != null && !loader.name().isBlank()) { + identifiers.add(loader.name()); + } } - return filter(ids, args[1]); + return filter(identifiers, args[1]); } } if (args.length == 2 && args[0].equalsIgnoreCase("limite")) { diff --git a/src/main/java/dev/marcospaulo/canalhandia/ChunkLoader.java b/src/main/java/dev/marcospaulo/canalhandia/ChunkLoader.java index 463125c..d80ef1f 100644 --- a/src/main/java/dev/marcospaulo/canalhandia/ChunkLoader.java +++ b/src/main/java/dev/marcospaulo/canalhandia/ChunkLoader.java @@ -8,6 +8,8 @@ package dev.marcospaulo.canalhandia; */ record ChunkLoader( long id, + String name, + boolean enabled, String ownerUuid, String ownerName, String world, @@ -18,6 +20,10 @@ record ChunkLoader( int chunkZ, long createdAt) { + ChunkLoader(long id, String ownerUuid, String ownerName, String world, int x, int y, int z, int chunkX, int chunkZ, long createdAt) { + this(id, "", true, ownerUuid, ownerName, world, x, y, z, chunkX, chunkZ, createdAt); + } + String blockCoords() { return x + ", " + y + ", " + z; } @@ -29,4 +35,20 @@ record ChunkLoader( String place() { return blockCoords() + (world == null || world.isBlank() ? "" : " (" + world + ")"); } + + String displayName() { + return (name != null && !name.isBlank()) ? name + " (#" + id + ")" : "#" + id; + } + + String simpleName() { + return (name != null && !name.isBlank()) ? name : "#" + id; + } + + ChunkLoader withName(String newName) { + return new ChunkLoader(id, newName == null ? "" : newName.trim(), enabled, ownerUuid, ownerName, world, x, y, z, chunkX, chunkZ, createdAt); + } + + ChunkLoader withEnabled(boolean newEnabled) { + return new ChunkLoader(id, name, newEnabled, ownerUuid, ownerName, world, x, y, z, chunkX, chunkZ, createdAt); + } } diff --git a/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaderListener.java b/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaderListener.java index 60f92f6..a4bc90b 100644 --- a/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaderListener.java +++ b/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaderListener.java @@ -78,13 +78,27 @@ final class ChunkLoaderListener implements Listener { return; } + String customName = ""; + var meta = event.getItemInHand().getItemMeta(); + if (meta != null && meta.hasDisplayName()) { + try { + String raw = net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer.plainText() + .serialize(meta.displayName()).trim(); + if (!raw.equalsIgnoreCase("Âncora de Chunk") && !raw.isBlank()) { + customName = raw; + } + } catch (Exception ignored) { + } + } + ChunkLoader loader = plugin.chunkLoaders().add( player.getUniqueId().toString(), player.getName(), world, loc.getBlockX(), loc.getBlockY(), - loc.getBlockZ() + loc.getBlockZ(), + customName ); try { @@ -96,7 +110,7 @@ final class ChunkLoaderListener implements Listener { plugin.blueMap().syncChunkLoaders(); String limitStr = limit == Integer.MAX_VALUE ? "ilimitado" : String.valueOf(limit); - Msg.ok(player, "Âncora de Chunk ativada! Esta chunk [" + chunkX + ", " + chunkZ + "] ficará carregada continuamente (" + Msg.ok(player, "Âncora de Chunk " + loader.displayName() + " ativada! Esta chunk [" + chunkX + ", " + chunkZ + "] ficará carregada continuamente (" + (current + 1) + "/" + limitStr + ")."); } @@ -129,13 +143,13 @@ final class ChunkLoaderListener implements Listener { event.setExpToDrop(0); if (player.getGameMode() == GameMode.CREATIVE) { - Msg.ok(player, "Âncora de Chunk #" + loader.id() + " desativada (Modo Criativo)."); + Msg.ok(player, "Âncora de Chunk " + loader.displayName() + " desativada (Modo Criativo)."); } else { Map overflow = player.getInventory().addItem(ChunkAnchorItem.create(plugin, 1)); for (ItemStack drop : overflow.values()) { player.getWorld().dropItemNaturally(player.getLocation(), drop); } - Msg.ok(player, "Âncora de Chunk #" + loader.id() + " desativada e recolhida para o seu inventário."); + Msg.ok(player, "Âncora de Chunk " + loader.displayName() + " desativada e recolhida para o seu inventário."); } try { @@ -169,10 +183,36 @@ final class ChunkLoaderListener implements Listener { block.getZ() ); if (loader != null) { - // Prevent respawn anchor exploding or depleting charges when used as chunk loader event.setCancelled(true); Player player = event.getPlayer(); - Msg.ok(player, "Âncora de Chunk #" + loader.id() + " (" + loader.ownerName() + ") está ativa."); + boolean isOwner = player.getUniqueId().toString().equalsIgnoreCase(loader.ownerUuid()); + boolean isAdmin = player.hasPermission("canalhandia.admin") || player.hasPermission("canalhandia.chunkloader.admin"); + + if (player.isSneaking() && (isOwner || isAdmin)) { + boolean newState = !loader.enabled(); + plugin.chunkLoaders().setEnabled(loader.id(), newState); + Location l = block.getLocation().add(0.5, 0.5, 0.5); + if (newState) { + try { + l.getWorld().playSound(l, Sound.BLOCK_BEACON_ACTIVATE, 1.0f, 1.2f); + l.getWorld().spawnParticle(Particle.PORTAL, l, 25, 0.2, 0.2, 0.2, 0.05); + } catch (Exception ignored) { + } + Msg.ok(player, "Âncora " + loader.displayName() + " ATIVADA."); + } else { + try { + l.getWorld().playSound(l, Sound.BLOCK_BEACON_DEACTIVATE, 1.0f, 0.8f); + l.getWorld().spawnParticle(Particle.SMOKE, l, 20, 0.2, 0.2, 0.2, 0.02); + } catch (Exception ignored) { + } + Msg.ok(player, "Âncora " + loader.displayName() + " PAUSADA/DESATIVADA."); + } + plugin.blueMap().syncChunkLoaders(); + return; + } + + String stateStr = loader.enabled() ? "ATIVA" : "PAUSADA"; + Msg.ok(player, "Âncora " + loader.displayName() + " (" + loader.ownerName() + ") está " + stateStr + ". (Shift + Clique Direito para alternar)"); } } diff --git a/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaders.java b/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaders.java index 37bd90e..52f6cb0 100644 --- a/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaders.java +++ b/src/main/java/dev/marcospaulo/canalhandia/ChunkLoaders.java @@ -69,6 +69,8 @@ final class ChunkLoaders { for (String key : root.getKeys(false)) { try { long id = Long.parseLong(key); + String name = root.getString(key + ".name", ""); + boolean enabled = root.getBoolean(key + ".enabled", true); String ownerUuid = root.getString(key + ".owner_uuid", ""); String ownerName = root.getString(key + ".owner_name", "?"); String world = root.getString(key + ".world", "world"); @@ -79,7 +81,7 @@ final class ChunkLoaders { int chunkZ = root.getInt(key + ".chunk_z", z >> 4); long createdAt = root.getLong(key + ".created_at", System.currentTimeMillis()); - loaders.add(new ChunkLoader(id, ownerUuid, ownerName, world, x, y, z, chunkX, chunkZ, createdAt)); + loaders.add(new ChunkLoader(id, name, enabled, ownerUuid, ownerName, world, x, y, z, chunkX, chunkZ, createdAt)); if (id > maxId) { maxId = id; } @@ -94,10 +96,14 @@ final class ChunkLoaders { * Registers a new chunk loader and activates the ticket in the world. */ ChunkLoader add(String ownerUuid, String ownerName, String world, int x, int y, int z) { + return add(ownerUuid, ownerName, world, x, y, z, ""); + } + + ChunkLoader add(String ownerUuid, String ownerName, String world, int x, int y, int z, String name) { int chunkX = x >> 4; int chunkZ = z >> 4; long id = nextId.getAndIncrement(); - ChunkLoader loader = new ChunkLoader(id, ownerUuid, ownerName, world, x, y, z, chunkX, chunkZ, System.currentTimeMillis()); + ChunkLoader loader = new ChunkLoader(id, name == null ? "" : name.trim(), true, ownerUuid, ownerName, world, x, y, z, chunkX, chunkZ, System.currentTimeMillis()); synchronized (loaders) { loaders.add(loader); @@ -107,6 +113,79 @@ final class ChunkLoaders { return loader; } + /** + * Renames an existing chunk loader. + */ + boolean rename(long id, String newName) { + synchronized (loaders) { + for (int i = 0; i < loaders.size(); i++) { + ChunkLoader curr = loaders.get(i); + if (curr.id() == id) { + loaders.set(i, curr.withName(newName)); + save(); + return true; + } + } + } + return false; + } + + /** + * Enables or disables (pauses) a chunk loader without destroying the block. + */ + boolean setEnabled(long id, boolean enabled) { + ChunkLoader oldLoader = null; + ChunkLoader updated = null; + synchronized (loaders) { + for (int i = 0; i < loaders.size(); i++) { + ChunkLoader curr = loaders.get(i); + if (curr.id() == id) { + oldLoader = curr; + updated = curr.withEnabled(enabled); + loaders.set(i, updated); + break; + } + } + } + if (oldLoader != null && updated != null) { + if (enabled) { + addTicket(updated); + } else { + removeTicket(oldLoader); + } + save(); + return true; + } + return false; + } + + /** + * Finds a chunk loader by its numeric ID (with or without '#') or custom name. + */ + ChunkLoader find(String query) { + if (query == null || query.isBlank()) { + return null; + } + String trimmed = query.trim(); + try { + long id = Long.parseLong(trimmed.startsWith("#") ? trimmed.substring(1) : trimmed); + ChunkLoader loader = byId(id); + if (loader != null) { + return loader; + } + } catch (NumberFormatException ignored) { + } + + synchronized (loaders) { + for (ChunkLoader loader : loaders) { + if (loader.name() != null && loader.name().equalsIgnoreCase(trimmed)) { + return loader; + } + } + } + return null; + } + /** * Removes a chunk loader by its unique ID and releases the chunk ticket. */ @@ -219,7 +298,9 @@ final class ChunkLoaders { void loadAllTickets() { synchronized (loaders) { for (ChunkLoader loader : loaders) { - addTicket(loader); + if (loader.enabled()) { + addTicket(loader); + } } } } @@ -256,6 +337,9 @@ final class ChunkLoaders { } for (ChunkLoader loader : currentLoaders) { + if (!loader.enabled()) { + continue; + } try { World w = Bukkit.getWorld(loader.world()); if (w == null || !w.isChunkLoaded(loader.chunkX(), loader.chunkZ())) { @@ -394,6 +478,8 @@ final class ChunkLoaders { synchronized (loaders) { for (ChunkLoader l : loaders) { String key = "loaders." + l.id(); + yaml.set(key + ".name", l.name()); + yaml.set(key + ".enabled", l.enabled()); yaml.set(key + ".owner_uuid", l.ownerUuid()); yaml.set(key + ".owner_name", l.ownerName()); yaml.set(key + ".world", l.world()); diff --git a/src/test/java/dev/marcospaulo/canalhandia/ChunkLoaderTest.java b/src/test/java/dev/marcospaulo/canalhandia/ChunkLoaderTest.java index 4ea4c7e..e5d37ea 100644 --- a/src/test/java/dev/marcospaulo/canalhandia/ChunkLoaderTest.java +++ b/src/test/java/dev/marcospaulo/canalhandia/ChunkLoaderTest.java @@ -105,6 +105,36 @@ class ChunkLoaderTest { assertEquals("uuid-ana", l2.ownerUuid()); } + @Test + void renamesAndTogglesEnabledState() { + ChunkLoader loader = loaders.add("uuid-marcos", "Marcos", "world", 100, 64, 200); + assertEquals("#1", loader.simpleName()); + assertTrue(loader.enabled()); + + assertTrue(loaders.rename(loader.id(), "Farm de Ferro")); + ChunkLoader renamed = loaders.byId(loader.id()); + assertNotNull(renamed); + assertEquals("Farm de Ferro", renamed.name()); + assertEquals("Farm de Ferro (#1)", renamed.displayName()); + assertEquals("Farm de Ferro", renamed.simpleName()); + + assertEquals(renamed, loaders.find("Farm de Ferro")); + assertEquals(renamed, loaders.find("#1")); + assertEquals(renamed, loaders.find("1")); + + assertTrue(loaders.setEnabled(loader.id(), false)); + ChunkLoader disabled = loaders.byId(loader.id()); + assertNotNull(disabled); + assertFalse(disabled.enabled()); + + loaders.flush(); + ChunkLoaders reloaded = new ChunkLoaders(null, file); + ChunkLoader reloadedLoader = reloaded.byId(loader.id()); + assertNotNull(reloadedLoader); + assertEquals("Farm de Ferro", reloadedLoader.name()); + assertFalse(reloadedLoader.enabled()); + } + @Test void simulationSafelyNoopsWithNullPlugin() { loaders.startSimulation();