From 62b42aa3028e31f7f72e276c8b830215853ba4ff Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sun, 24 Jul 2011 00:00:32 -0500 Subject: [PATCH] Add 'radiusrender' command to allow limited render by player in radius --- src/main/java/org/dynmap/DynmapPlugin.java | 24 ++++++- src/main/java/org/dynmap/MapManager.java | 75 ++++++++++++++++++++-- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index 1efae889..2bb2e39f 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -495,6 +495,7 @@ public class DynmapPlugin extends JavaPlugin { "hide", "show", "fullrender", + "radiusrender", "reload", "stats", "resetstats" })); @@ -516,8 +517,27 @@ public class DynmapPlugin extends JavaPlugin { if (player != null) { int invalidates = mapManager.touch(player.getLocation()); sender.sendMessage("Queued " + invalidates + " tiles" + (invalidates == 0 - ? " (world is not loaded?)" - : "...")); + ? " (world is not loaded?)" + : "...")); + } + else { + sender.sendMessage("Command can only be issued by player."); + } + } + else if(c.equals("radiusrender") && checkPlayerPermission(sender,"radiusrender")) { + if (player != null) { + int radius = 0; + if(args.length > 1) { + radius = Integer.parseInt(args[1]); /* Parse radius */ + if(radius < 0) + radius = 0; + } + Location loc = player.getLocation(); + if(loc != null) + mapManager.renderWorldRadius(loc, sender, radius); + } + else { + sender.sendMessage("Command can only be issued by player."); } } else if (c.equals("hide")) { if (args.length == 1) { diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index 2cf5530a..65e4b1b6 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -4,6 +4,7 @@ import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -163,21 +164,44 @@ public class MapManager { HashSet renderedmaps = new HashSet(); String activemaps; List activemaplist; + /* Min and max limits for chunk coords (for radius limit) */ + int cxmin, cxmax, czmin, czmax; + String rendertype; /* Full world, all maps render */ FullWorldRenderState(DynmapWorld dworld, Location l, CommandSender sender) { + this(dworld, l, sender, -1); + rendertype = "Full render"; + } + + /* Full world, all maps render, with optional render radius */ + FullWorldRenderState(DynmapWorld dworld, Location l, CommandSender sender, int radius) { world = dworld; loc = l; found = new HashSet(); rendered = new HashSet(); renderQueue = new LinkedList(); this.sender = sender; + if(radius < 0) { + cxmin = czmin = Integer.MIN_VALUE; + cxmax = czmax = Integer.MAX_VALUE; + rendertype = "Full render"; + } + else { + cxmin = (l.getBlockX() - radius)>>4; + czmin = (l.getBlockZ() - radius)>>4; + cxmax = (l.getBlockX() + radius+15)>>4; + czmax = (l.getBlockZ() + radius+15)>>4; + rendertype = "Radius render"; + } } /* Single tile render - used for incremental renders */ FullWorldRenderState(MapTile t) { world = getWorld(t.getWorld().getName()); tile0 = t; + cxmin = czmin = Integer.MIN_VALUE; + cxmax = czmax = Integer.MAX_VALUE; } public String toString() { @@ -200,10 +224,10 @@ public class MapManager { if(map_index >= 0) { /* Finished a map? */ double msecpertile = (double)timeaccum / (double)((rendercnt>0)?rendercnt:1)/(double)activemaplist.size(); if(activemaplist.size() > 1) - sender.sendMessage("Full render of maps [" + activemaps + "] of '" + + sender.sendMessage(rendertype + " of maps [" + activemaps + "] of '" + world.world.getName() + "' completed - " + rendercnt + " tiles rendered each (" + String.format("%.2f", msecpertile) + " msec/map-tile)."); else - sender.sendMessage("Full render of map '" + activemaps + "' of '" + + sender.sendMessage(rendertype + " of map '" + activemaps + "' of '" + world.world.getName() + "' completed - " + rendercnt + " tiles rendered (" + String.format("%.2f", msecpertile) + " msec/tile)."); } found.clear(); @@ -217,7 +241,7 @@ public class MapManager { break; } if(map_index >= world.maps.size()) { /* Last one done? */ - sender.sendMessage("Full render of '" + world.world.getName() + "' finished."); + sender.sendMessage(rendertype + " of '" + world.world.getName() + "' finished."); cleanup(); return; } @@ -257,8 +281,20 @@ public class MapManager { tile = tile0; } World w = world.world; - /* Fetch chunk cache from server thread */ + /* Get list of chunks required for tile */ List requiredChunks = tile.getRequiredChunks(); + /* If we are doing radius limit render, see if any are inside limits */ + if(cxmin != Integer.MIN_VALUE) { + boolean good = false; + for(DynmapChunk c : requiredChunks) { + if((c.x >= cxmin) && (c.x <= cxmax) && (c.z >= czmin) && (c.z <= czmax)) { + good = true; + break; + } + } + if(!good) requiredChunks = Collections.emptyList(); + } + /* Fetch chunk cache from server thread */ MapChunkCache cache = createMapChunkCache(world, requiredChunks, tile.isBlockTypeDataNeeded(), tile.isHightestBlockYDataNeeded(), tile.isBiomeDataNeeded(), tile.isRawBiomeDataNeeded()); @@ -288,10 +324,10 @@ public class MapManager { if((rendercnt % 100) == 0) { double msecpertile = (double)timeaccum / (double)rendercnt / (double)activemaplist.size(); if(activemaplist.size() > 1) - sender.sendMessage("Full render of maps [" + activemaps + "] of '" + + sender.sendMessage(rendertype + " of maps [" + activemaps + "] of '" + w.getName() + "' in progress - " + rendercnt + " tiles rendered each (" + String.format("%.2f", msecpertile) + " msec/map-tile)."); else - sender.sendMessage("Full render of map '" + activemaps + "' of '" + + sender.sendMessage(rendertype + " of map '" + activemaps + "' of '" + w.getName() + "' in progress - " + rendercnt + " tiles rendered (" + String.format("%.2f", msecpertile) + " msec/tile)."); } } @@ -389,7 +425,7 @@ public class MapManager { synchronized(lock) { rndr = active_renders.get(wname); if(rndr != null) { - sender.sendMessage("Full world render of world '" + wname + "' already active."); + sender.sendMessage(rndr.rendertype + " of world '" + wname + "' already active."); return; } rndr = new FullWorldRenderState(world,l,sender); /* Make new activation record */ @@ -400,6 +436,28 @@ public class MapManager { sender.sendMessage("Full render starting on world '" + wname + "'..."); } + void renderWorldRadius(Location l, CommandSender sender, int radius) { + DynmapWorld world = getWorld(l.getWorld().getName()); + if (world == null) { + sender.sendMessage("Could not render: world '" + l.getWorld().getName() + "' not defined in configuration."); + return; + } + String wname = l.getWorld().getName(); + FullWorldRenderState rndr; + synchronized(lock) { + rndr = active_renders.get(wname); + if(rndr != null) { + sender.sendMessage(rndr.rendertype + " of world '" + wname + "' already active."); + return; + } + rndr = new FullWorldRenderState(world,l,sender, radius); /* Make new activation record */ + active_renders.put(wname, rndr); /* Add to active table */ + } + /* Schedule first tile to be worked */ + renderpool.execute(rndr); + sender.sendMessage("Render of " + radius + " block radius starting on world '" + wname + "'..."); + } + public void activateWorld(World w) { ConfigurationNode worldConfiguration = plug_in.getWorldConfiguration(w); if (!worldConfiguration.getBoolean("enabled", false)) { @@ -588,6 +646,9 @@ public class MapManager { c.setChunks(w.world, chunks); if(c.setChunkDataTypes(blockdata, biome, highesty, rawbiome) == false) Log.severe("CraftBukkit build does not support biome APIs"); + if(chunks.size() == 0) { /* No chunks to get? */ + return c; + } synchronized(loadlock) { final MapChunkCache cc = c;