From 18ac5a5d17a7f0be937ac75197a799e044fe2f72 Mon Sep 17 00:00:00 2001 From: marcos Date: Tue, 4 Aug 2026 20:52:38 +0000 Subject: [PATCH] fix: locate stats directory under Paper's dimensions layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rankings returned "sem dados" because World#getWorldFolder points at the dimension directory in Paper's newer layout, so /players/stats does not exist. The real path is //players/stats. Try that first, fall back to the older locations, then climb out of the dimension folder, and warn instead of silently returning nothing. Also fixes "1 dias e 0 horas" — durations now agree in number and drop a zero remainder. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01ActvLGJApdxEAd2yfKPwqv --- .../java/dev/marcospaulo/canalhandia/Msg.java | 15 +++++-- .../marcospaulo/canalhandia/OfflineStats.java | 43 +++++++++++++++---- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/main/java/dev/marcospaulo/canalhandia/Msg.java b/src/main/java/dev/marcospaulo/canalhandia/Msg.java index a1dd172..0608b8c 100644 --- a/src/main/java/dev/marcospaulo/canalhandia/Msg.java +++ b/src/main/java/dev/marcospaulo/canalhandia/Msg.java @@ -45,16 +45,23 @@ final class Msg { .append(Component.text(value, NamedTextColor.AQUA))); } - /** Renders a duration in ticks as "3 dias e 4 horas" / "5 horas" / "12 minutos". */ + /** Renders a duration in ticks as "3 dias e 4 horas" / "1 hora" / "12 minutos". */ static String duration(long ticks) { long minutes = ticks / 20L / 60L; if (minutes < 60) { - return minutes + " minutos"; + return plural(minutes, "minuto", "minutos"); } long hours = minutes / 60; if (hours < 24) { - return hours + " horas"; + return plural(hours, "hora", "horas"); } - return hours / 24 + " dias e " + hours % 24 + " horas"; + long days = hours / 24; + long rest = hours % 24; + String text = plural(days, "dia", "dias"); + return rest == 0 ? text : text + " e " + plural(rest, "hora", "horas"); + } + + private static String plural(long value, String singular, String plural) { + return value + " " + (value == 1 ? singular : plural); } } diff --git a/src/main/java/dev/marcospaulo/canalhandia/OfflineStats.java b/src/main/java/dev/marcospaulo/canalhandia/OfflineStats.java index 21b3969..d80427c 100644 --- a/src/main/java/dev/marcospaulo/canalhandia/OfflineStats.java +++ b/src/main/java/dev/marcospaulo/canalhandia/OfflineStats.java @@ -120,19 +120,46 @@ final class OfflineStats { } /** - * Paper writes to {@code /players/stats}; older layouts used - * {@code /stats}. Try both rather than assume. + * Locates the statistics directory. + * + *

Not as simple as it looks. Paper's newer layout puts dimensions under + * {@code /dimensions/…}, and {@code World#getWorldFolder} points at + * the dimension rather than the world root — so {@code getWorldFolder() + + * "/players/stats"} does not exist. The real path is + * {@code //players/stats}. Older servers used + * {@code /stats}. Try each in turn, then walk up from the dimension + * folder as a last resort. */ private File statsDirectory() { if (Bukkit.getWorlds().isEmpty()) { return null; } - File world = Bukkit.getWorlds().get(0).getWorldFolder(); - File modern = new File(world, "players/stats"); - if (modern.isDirectory()) { - return modern; + String levelName = Bukkit.getWorlds().get(0).getName(); + File worldFolder = Bukkit.getWorlds().get(0).getWorldFolder(); + + File[] candidates = { + new File(new File(Bukkit.getWorldContainer(), levelName), "players/stats"), + new File(worldFolder, "players/stats"), + new File(new File(Bukkit.getWorldContainer(), levelName), "stats"), + new File(worldFolder, "stats"), + }; + for (File candidate : candidates) { + if (candidate.isDirectory()) { + return candidate; + } } - File legacy = new File(world, "stats"); - return legacy.isDirectory() ? legacy : null; + + // Last resort: climb out of the dimension folder looking for players/stats. + File current = worldFolder; + for (int depth = 0; depth < 4 && current != null; depth++) { + File found = new File(current, "players/stats"); + if (found.isDirectory()) { + return found; + } + current = current.getParentFile(); + } + plugin.getLogger().warning("Não encontrei o diretório de estatísticas a partir de " + + worldFolder.getAbsolutePath()); + return null; } }