diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/CommandHelper.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/CommandHelper.java index 18dd3c0a..d0097112 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/CommandHelper.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/CommandHelper.java @@ -34,10 +34,18 @@ import de.bluecolored.bluemap.core.world.World; import org.apache.commons.lang3.time.DurationFormatUtils; import java.lang.ref.WeakReference; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; public class CommandHelper { + private static final DateTimeFormatter TIME_FORMAT = + DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss") + .withLocale(Locale.ROOT) + .withZone(ZoneId.systemDefault()); + private final Plugin plugin; private final Map> taskRefMap; @@ -67,7 +75,9 @@ public class CommandHelper { lines.add(Text.of(TextColor.WHITE, " Render-Threads are ", status, TextColor.WHITE, "!")); - if (!tasks.isEmpty()) { + if (tasks.isEmpty()) { + lines.add(Text.of(TextColor.GRAY, " Last time running: ", TextColor.DARK_GRAY, formatTime(renderer.getLastTimeBusy()))); + } else { lines.add(Text.of(TextColor.WHITE, " Queued Tasks (" + tasks.size() + "):")); for (int i = 0; i < tasks.size(); i++) { if (i >= 10){ @@ -76,20 +86,18 @@ public class CommandHelper { } RenderTask task = tasks.get(i); - lines.add(Text.of(TextColor.GRAY, " [" + getRefForTask(task) + "] ", TextColor.GOLD, task.getDescription())); + lines.add(Text.of(TextColor.GRAY, "\u00A0\u00A0[" + getRefForTask(task) + "] ", TextColor.GOLD, task.getDescription())); if (i == 0) { - String detail = task.getDetail().orElse(null); - if (detail != null) { - lines.add(Text.of(TextColor.GRAY, " Detail: ", TextColor.WHITE, detail)); - } + task.getDetail().ifPresent(detail -> + lines.add(Text.of(TextColor.GRAY, "\u00A0\u00A0\u00A0Detail: ", TextColor.WHITE, detail))); - lines.add(Text.of(TextColor.GRAY, " Progress: ", TextColor.WHITE, + lines.add(Text.of(TextColor.GRAY, "\u00A0\u00A0\u00A0Progress: ", TextColor.WHITE, (Math.round(task.estimateProgress() * 10000) / 100.0) + "%")); long etaMs = renderer.estimateCurrentRenderTaskTimeRemaining(); if (etaMs > 0) { - lines.add(Text.of(TextColor.GRAY, " ETA: ", TextColor.WHITE, DurationFormatUtils.formatDuration(etaMs, "HH:mm:ss"))); + lines.add(Text.of(TextColor.GRAY, "\u00A0\u00A0\u00A0ETA: ", TextColor.WHITE, DurationFormatUtils.formatDuration(etaMs, "HH:mm:ss"))); } } } @@ -98,7 +106,7 @@ public class CommandHelper { if (plugin.checkPausedByPlayerCount()) { lines.add(Text.of(TextColor.WHITE, " Render-Threads are ", Text.of(TextColor.GOLD, "paused"))); - lines.add(Text.of(TextColor.GRAY, TextFormat.ITALIC, " (there are " + plugin.getConfigs().getPluginConfig().getPlayerRenderLimit() + " or more players online)")); + lines.add(Text.of(TextColor.GRAY, TextFormat.ITALIC, "\u00A0\u00A0\u00A0(there are " + plugin.getConfigs().getPluginConfig().getPlayerRenderLimit() + " or more players online)")); } else { lines.add(Text.of(TextColor.WHITE, " Render-Threads are ", Text.of(TextColor.RED, "stopped") @@ -176,4 +184,9 @@ public class CommandHelper { return ref.subSequence(0, 4).toString(); } + public String formatTime(long timestamp) { + if (timestamp < 0) return "-"; + return TIME_FORMAT.format(Instant.ofEpochMilli(timestamp)); + } + } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java index ec66d641..fddba475 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java @@ -838,27 +838,28 @@ public class Commands { } public int mapsCommand(CommandContext context) { - CommandSource source = commandSourceInterface.apply(context.getSource()); + List lines = new ArrayList<>(); + lines.add(Text.of(TextColor.BLUE, "Maps loaded by BlueMap:")); - source.sendMessage(Text.of(TextColor.BLUE, "Maps loaded by BlueMap:")); for (BmMap map : plugin.getMaps().values()) { - boolean unfrozen = plugin.getPluginState().getMapState(map).isUpdateEnabled(); - if (unfrozen) { - source.sendMessage(Text.of( - TextColor.GRAY, " - ", - TextColor.WHITE, map.getId(), - TextColor.GRAY, " (" + map.getName() + ")" - ).setHoverText(Text.of(TextColor.WHITE, "World: ", TextColor.GRAY, map.getWorld().getName()))); - } else { - source.sendMessage(Text.of( - TextColor.GRAY, " - ", - TextColor.WHITE, map.getId(), - TextColor.GRAY, " (" + map.getName() + ") - ", - TextColor.AQUA, TextFormat.ITALIC, "frozen!" - ).setHoverText(Text.of(TextColor.WHITE, "World: ", TextColor.GRAY, map.getWorld().getName()))); - } + boolean frozen = !plugin.getPluginState().getMapState(map).isUpdateEnabled(); + + lines.add(Text.of(TextColor.GRAY, " - ", + TextColor.WHITE, map.getId(), + TextColor.GRAY, " (" + map.getName() + ")")); + + lines.add(Text.of(TextColor.GRAY, "\u00A0\u00A0\u00A0World: ", + TextColor.DARK_GRAY, map.getWorld().getName())); + lines.add(Text.of(TextColor.GRAY, "\u00A0\u00A0\u00A0Last Update: ", + TextColor.DARK_GRAY, helper.formatTime(map.getRenderState().getLatestRenderTime()))); + + if (frozen) + lines.add(Text.of(TextColor.AQUA, TextFormat.ITALIC, "This map is frozen!")); } + CommandSource source = commandSourceInterface.apply(context.getSource()); + source.sendMessages(lines); + return 1; } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/RenderManager.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/RenderManager.java index 34b4495d..222a54fa 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/RenderManager.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/RenderManager.java @@ -38,6 +38,8 @@ public class RenderManager { @DebugDump private final int id; @DebugDump private volatile boolean running; + @DebugDump private long lastTimeBusy; + private final AtomicInteger nextWorkerThreadIndex; @DebugDump private final Collection workerThreads; private final AtomicInteger busyCount; @@ -55,6 +57,8 @@ public class RenderManager { this.workerThreads = new ConcurrentLinkedDeque<>(); this.busyCount = new AtomicInteger(0); + this.lastTimeBusy = -1; + this.progressTracker = null; this.newTask = true; @@ -249,6 +253,10 @@ public class RenderManager { return workerThreads.size(); } + public long getLastTimeBusy() { + return lastTimeBusy; + } + private void removeTasksThatAreContainedIn(RenderTask containingTask) { synchronized (this.renderTasks) { if (renderTasks.size() < 2) return; @@ -290,13 +298,15 @@ public class RenderManager { } this.busyCount.incrementAndGet(); + this.lastTimeBusy = System.currentTimeMillis(); } try { task.doWork(); } finally { synchronized (renderTasks) { - this.busyCount.decrementAndGet(); + int busyCount = this.busyCount.decrementAndGet(); + if (busyCount > 0) this.lastTimeBusy = System.currentTimeMillis(); this.renderTasks.notifyAll(); } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java index b4c62766..57258e7c 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/BmMap.java @@ -219,7 +219,7 @@ public class BmMap { public synchronized void savePlayerState() { try ( - OutputStream out = storage.writeMeta(id, META_FILE_PLAYERS); + OutputStream out = storage.writeMeta(id, META_FILE_PLAYERS) ) { out.write("{}".getBytes(StandardCharsets.UTF_8)); } catch (Exception ex) { diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/MapRenderState.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/MapRenderState.java index 668fc26d..5adeabdf 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/MapRenderState.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/MapRenderState.java @@ -37,6 +37,7 @@ import java.util.zip.GZIPOutputStream; public class MapRenderState { private final Map regionRenderTimes; + private transient long latestRenderTime = -1; public MapRenderState() { regionRenderTimes = new HashMap<>(); @@ -44,6 +45,13 @@ public class MapRenderState { public synchronized void setRenderTime(Vector2i regionPos, long renderTime) { regionRenderTimes.put(regionPos, renderTime); + + if (latestRenderTime != -1) { + if (renderTime > latestRenderTime) + latestRenderTime = renderTime; + else + latestRenderTime = -1; + } } public synchronized long getRenderTime(Vector2i regionPos) { @@ -52,6 +60,19 @@ public class MapRenderState { else return renderTime; } + public long getLatestRenderTime() { + if (latestRenderTime == -1) { + synchronized (this) { + latestRenderTime = regionRenderTimes.values().stream() + .mapToLong(Long::longValue) + .max() + .orElse(-1); + } + } + + return latestRenderTime; + } + public synchronized void reset() { regionRenderTimes.clear(); }