diff --git a/src/main/java/org/dynmap/AsynchronousQueue.java b/src/main/java/org/dynmap/AsynchronousQueue.java index 30e6781d..d4c54757 100644 --- a/src/main/java/org/dynmap/AsynchronousQueue.java +++ b/src/main/java/org/dynmap/AsynchronousQueue.java @@ -12,10 +12,14 @@ public class AsynchronousQueue { private Set set = new HashSet(); private Handler handler; private int dequeueTime; - - public AsynchronousQueue(Handler handler, int dequeueTime) { + private int accelDequeueTime; + private int accelDequeueThresh; + + public AsynchronousQueue(Handler handler, int dequeueTime, int accelDequeueThresh, int accelDequeueTime) { this.handler = handler; this.dequeueTime = dequeueTime; + this.accelDequeueTime = accelDequeueTime; + this.accelDequeueThresh = accelDequeueThresh; } public boolean push(T t) { @@ -83,7 +87,10 @@ public class AsynchronousQueue { if (t != null) { handler.handle(t); } - sleep(dequeueTime); + if(set.size() >= accelDequeueThresh) + sleep(accelDequeueTime); + else + sleep(dequeueTime); } } catch (Exception ex) { diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index 414f59f4..e61211c5 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -27,6 +27,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.CustomEventListener; import org.bukkit.event.Event; +import org.bukkit.event.Event.Type; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBurnEvent; @@ -38,6 +39,8 @@ import org.bukkit.event.block.BlockPistonRetractEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockSpreadEvent; import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityListener; import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerListener; @@ -355,7 +358,7 @@ public class DynmapPlugin extends JavaPlugin { private boolean onplayermove; private boolean ongeneratechunk; private boolean onloadchunk; - + private boolean onexplosion; public void registerEvents() { @@ -517,26 +520,25 @@ public class DynmapPlugin extends JavaPlugin { if(onplayermove) registerEvent(Event.Type.PLAYER_MOVE, playerTrigger); - /* Register world event triggers */ - ongeneratechunk = isTrigger("chunkgenerated"); - if(ongeneratechunk) { - try { /* Test if new enough bukkit to allow this */ - ChunkLoadEvent.class.getDeclaredMethod("isNewChunk", new Class[0]); - } catch (NoSuchMethodException nsmx) { - Log.info("Warning: CraftBukkit build does not support function needed for 'chunkgenerated' trigger - disabling"); - ongeneratechunk = false; + /* Register entity event triggers */ + EntityListener entityTrigger = new EntityListener() { + @Override + public void onEntityExplode(EntityExplodeEvent event) { + List blocks = event.blockList(); + for(Block b: blocks) { + Location loc = b.getLocation(); + mapManager.sscache.invalidateSnapshot(loc); + if(onexplosion) { + mapManager.touch(loc); + } + } } - } - onloadchunk = isTrigger("chunkloaded"); - if(onloadchunk) { - generate_only = false; - } - else if (ongeneratechunk) { - generate_only = true; - } - registerEvent(Event.Type.CHUNK_LOAD, ourWorldEventHandler); - - // To link configuration to real loaded worlds. + }; + onexplosion = isTrigger("explosion"); + registerEvent(Event.Type.ENTITY_EXPLODE, entityTrigger); + + + /* Register world event triggers */ WorldListener worldTrigger = new WorldListener() { @Override public void onChunkLoad(ChunkLoadEvent event) { @@ -558,6 +560,26 @@ public class DynmapPlugin extends JavaPlugin { mapManager.activateWorld(event.getWorld()); } }; + + ongeneratechunk = isTrigger("chunkgenerated"); + if(ongeneratechunk) { + try { /* Test if new enough bukkit to allow this */ + ChunkLoadEvent.class.getDeclaredMethod("isNewChunk", new Class[0]); + } catch (NoSuchMethodException nsmx) { + Log.info("Warning: CraftBukkit build does not support function needed for 'chunkgenerated' trigger - disabling"); + ongeneratechunk = false; + } + } + onloadchunk = isTrigger("chunkloaded"); + if(onloadchunk) { + generate_only = false; + } + else if (ongeneratechunk) { + generate_only = true; + } + registerEvent(Event.Type.CHUNK_LOAD, worldTrigger); + + // To link configuration to real loaded worlds. registerEvent(Event.Type.WORLD_LOAD, worldTrigger); } @@ -1046,6 +1068,21 @@ public class DynmapPlugin extends JavaPlugin { } }; + private EntityListener ourEntityEventHandler = new EntityListener() { + @Override + public void onEntityExplode(EntityExplodeEvent event) { + if(event.isCancelled()) + return; + /* Call listeners */ + List ll = event_handlers.get(event.getType()); + if(ll != null) { + for(Listener l : ll) { + ((EntityListener)l).onEntityExplode(event); + } + } + } + }; + /** * Register event listener - this will be cleaned up properly on a /dynmap reload, unlike * registering with Bukkit directly @@ -1080,6 +1117,9 @@ public class DynmapPlugin extends JavaPlugin { case CUSTOM_EVENT: pm.registerEvent(type, ourCustomEventHandler, Event.Priority.Monitor, this); break; + case ENTITY_EXPLODE: + pm.registerEvent(type, ourEntityEventHandler, Event.Priority.Monitor, this); + break; default: Log.severe("registerEvent() in DynmapPlugin does not handle " + type); return; diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index 0d55ee34..195e8ed3 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -488,12 +488,16 @@ public class MapManager { sscache = new SnapshotCache(configuration.getInteger("snapshotcachesize", 500)); parallelrendercnt = configuration.getInteger("parallelrendercnt", 0); - this.tileQueue = new AsynchronousQueue(new Handler() { - @Override - public void handle(MapTile t) { - scheduleDelayedJob(new FullWorldRenderState(t), 0); - } - }, (int) (configuration.getDouble("renderinterval", 0.5) * 1000)); + this.tileQueue = new AsynchronousQueue( + new Handler() { + @Override + public void handle(MapTile t) { + scheduleDelayedJob(new FullWorldRenderState(t), 0); + } + }, + (int) (configuration.getDouble("renderinterval", 0.5) * 1000), + configuration.getInteger("renderacceleratethreshold", 30), + (int)(configuration.getDouble("renderaccelerateinterval", 0.2) * 1000)); /* On dedicated thread, so default to no delays */ timeslice_int = (long)(configuration.getDouble("timesliceinterval", 0.0) * 1000); diff --git a/src/main/resources/configuration.txt b/src/main/resources/configuration.txt index 6e85ad7d..5822b528 100644 --- a/src/main/resources/configuration.txt +++ b/src/main/resources/configuration.txt @@ -111,8 +111,14 @@ display-whitelist: false # How often a tile gets rendered (in seconds). renderinterval: 1 +# How many tiles on update queue before accelerate render interval +renderacceleratethreshold: 60 + +# How often to render tiles when backlog is above renderacceleratethreshold +renderaccelerateinterval: 0.2 + # Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds) -zoomoutperiod: 60 +zoomoutperiod: 30 # Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable enabletilehash: true @@ -130,6 +136,7 @@ render-triggers: - blockfaded - blockspread - pistonmoved + - explosion # The path where the tile-files are placed. tilespath: web/tiles