diff --git a/common/src/main/java/de/bluecolored/bluemap/common/config/CoreConfig.java b/common/src/main/java/de/bluecolored/bluemap/common/config/CoreConfig.java index c83d08631..8d30376fa 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/config/CoreConfig.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/config/CoreConfig.java @@ -36,6 +36,9 @@ public class CoreConfig { private int renderThreadCount = 1; + private int updateRegionAfterInactivity = 5; + private int updateRegionMaxInactivityWait = 60; + private boolean metrics = true; private Path data = Path.of("bluemap"); @@ -57,6 +60,14 @@ public int resolveRenderThreadCount() { return Math.max(Runtime.getRuntime().availableProcessors() + renderThreadCount, 1); } + public int getUpdateRegionAfterInactivity() { + return updateRegionAfterInactivity; + } + + public int getUpdateRegionMaxInactivityWait() { + return updateRegionMaxInactivityWait; + } + public boolean isMetrics() { return metrics; } diff --git a/common/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateService.java b/common/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateService.java index d398c17ba..635bc9d46 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateService.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateService.java @@ -25,6 +25,7 @@ package de.bluecolored.bluemap.common.plugin; import com.flowpowered.math.vector.Vector2i; +import de.bluecolored.bluemap.common.BlueMapConfiguration; import de.bluecolored.bluemap.common.rendermanager.RenderManager; import de.bluecolored.bluemap.common.rendermanager.WorldRegionRenderTask; import de.bluecolored.bluemap.core.logger.Logger; @@ -32,6 +33,7 @@ import de.bluecolored.bluemap.core.util.WatchService; import java.io.IOException; +import java.time.Instant; import java.util.HashMap; import java.util.Map; import java.util.Timer; @@ -42,19 +44,35 @@ public class MapUpdateService extends Thread { private final BmMap map; private final RenderManager renderManager; private final WatchService watchService; + private final int inactivityWait; + private final int inactivityMaxWait; private volatile boolean closed; private Timer delayTimer; - private final Map scheduledUpdates; + private final Map scheduledUpdates; - public MapUpdateService(RenderManager renderManager, BmMap map) throws IOException { + private static class RegionUpdateInfo { + TimerTask task; + Instant waitingSince; + + RegionUpdateInfo(TimerTask task, Instant waitingSince) { + this.task = task; + this.waitingSince = waitingSince; + } + } + + public MapUpdateService(BlueMapConfiguration configService, RenderManager renderManager, BmMap map) throws IOException { this.renderManager = renderManager; this.map = map; this.closed = false; this.scheduledUpdates = new HashMap<>(); this.watchService = map.getWorld().createRegionWatchService(); + + var coreConfig = configService.getCoreConfig(); + inactivityWait = coreConfig.getUpdateRegionAfterInactivity(); + inactivityMaxWait = coreConfig.getUpdateRegionMaxInactivityWait(); } @Override @@ -83,11 +101,17 @@ public void run() { private synchronized void updateRegion(Vector2i regionPos) { if (closed) return; - // we only want to start the render when there were no changes on a file for 5 seconds - TimerTask task = scheduledUpdates.remove(regionPos); - if (task != null) task.cancel(); + // we only want to start the render when there were no changes on a file for inactivityWait seconds + RegionUpdateInfo previous = scheduledUpdates.get(regionPos); + if (previous != null) { + if (previous.waitingSince.plusSeconds(inactivityMaxWait).isBefore(Instant.now())) { + // exceeded max inactivity timeout, don't reschedule + return; + } + previous.task.cancel(); + } - task = new TimerTask() { + TimerTask task = new TimerTask() { @Override public void run() { synchronized (MapUpdateService.this) { @@ -99,8 +123,13 @@ public void run() { } } }; - scheduledUpdates.put(regionPos, task); - delayTimer.schedule(task, 5000); + + if (previous == null) { + scheduledUpdates.put(regionPos, new RegionUpdateInfo(task, Instant.now())); + } else { + previous.task = task; + } + delayTimer.schedule(task, inactivityWait * 1000L); } public synchronized void close() { diff --git a/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java b/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java index 7ccd0fa30..cd4f85227 100644 --- a/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java +++ b/common/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java @@ -565,7 +565,7 @@ public synchronized void startWatchingMap(BmMap map) { stopWatchingMap(map); try { - MapUpdateService watcher = new MapUpdateService(renderManager, map); + MapUpdateService watcher = new MapUpdateService(blueMap.getConfig(), renderManager, map); watcher.start(); mapUpdateServices.put(map.getId(), watcher); } catch (IOException ex) { diff --git a/common/src/main/resources/de/bluecolored/bluemap/config/core.conf b/common/src/main/resources/de/bluecolored/bluemap/config/core.conf index 7e6f8bf3f..e5edeb259 100644 --- a/common/src/main/resources/de/bluecolored/bluemap/config/core.conf +++ b/common/src/main/resources/de/bluecolored/bluemap/config/core.conf @@ -23,6 +23,11 @@ data: "${data}" # Default is 1 render-thread-count: ${render-thread-count} +# Wait for a region to be inactive for this many seconds before rerendering. +update-region-after-inactivity: 5 +# Max time to wait for region inactivity (in seconds) before proceeding anyways. +update-region-max-inactivity-wait: 60 + # Controls whether BlueMap should try to find and load mod-resources and datapacks from the server/world-directories. # Default is true scan-for-mod-resources: true diff --git a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java index 451c63ce1..3413c3e35 100644 --- a/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java +++ b/implementations/cli/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java @@ -103,7 +103,7 @@ public void renderMaps(BlueMapService blueMap, boolean watch, TileUpdateStrategy if (watch) { for (BmMap map : maps.values()) { try { - MapUpdateService watcher = new MapUpdateService(renderManager, map); + MapUpdateService watcher = new MapUpdateService(blueMap.getConfig(), renderManager, map); watcher.start(); mapUpdateServices.add(watcher); } catch (IOException ex) {