Change autogenerate-to-visibilitylimits to have options for map-only (temporary generated chunks) versus permanent (world growing)

Fix exception catching code in thread pool
This commit is contained in:
Mike Primm 2011-06-25 16:01:06 -05:00
parent 6dac7f0689
commit 39281188bc
7 changed files with 90 additions and 20 deletions

View File

@ -315,9 +315,9 @@ worlds:
# # Use hidestyle to control how hidden-but-existing chunks are to be rendered (air=empty air (same as ungenerated), stone=a flat stone plain, ocean=a flat ocean)
# hidestyle: stone
# # Use 'autogenerate-to-visibilitylimits: true' to choose to force the generation of ungenerated chunks while rendering maps on this world, for any chunks within the defined
# # visibilitylimits (limits must be set). This will result in initializing all game world areas within the visible ranges that have not yet been initialized.
# # Note: BE SURE YOU WANT TO DO THIS - there isn't a good way to "ungenerate" terrain chunks once generated (although tools like WorldEdit can regenerate them)
# autogenerate-to-visibilitylimits: false
# # visibilitylimits (limits must be set). The three options here are: none (default - no autogenerate), map-only (temporarily generate chunks for map, but don't save them (no world change),
# # permanent (generate and save chunks - this permanently adds the chunks to the world, as if a player had visited them - BE SURE THIS IS WHAT YOU WANT)
# autogenerate-to-visibilitylimits: map-only
# Use 'template: mycustomtemplate' to use the properties specified in the template 'mycustomtemplate' to this world. Default it is set to the environment-name (normal or nether).
# template: mycustomtemplate
# Rest of comes from template - uncomment to tailor for world specifically

View File

@ -53,6 +53,7 @@ public class DynmapPlugin extends JavaPlugin {
/* Flag to let code know that we're doing reload - make sure we don't double-register event handlers */
public boolean is_reload = false;
private boolean generate_only = false;
private static boolean ignore_chunk_loads = false; /* Flat to keep us from processing our own chunk loads */
public static File dataDirectory;
public static File tilesDirectory;
@ -248,6 +249,8 @@ public class DynmapPlugin extends JavaPlugin {
WorldListener renderTrigger = new WorldListener() {
@Override
public void onChunkLoad(ChunkLoadEvent event) {
if(ignore_chunk_loads)
return;
if(generate_only) {
if(!isNewChunk(event))
return;
@ -494,4 +497,8 @@ public class DynmapPlugin extends JavaPlugin {
public String getWebPath() {
return configuration.getString("webpath", "web");
}
public static void setIgnoreChunkLoads(boolean ignore) {
ignore_chunk_loads = ignore;
}
}

View File

@ -21,13 +21,18 @@ import java.util.HashSet;
import javax.imageio.ImageIO;
public class DynmapWorld {
public enum AutoGenerateOption {
NONE,
FORMAPONLY,
PERMANENT
}
public World world;
public List<MapType> maps = new ArrayList<MapType>();
public UpdateQueue updates = new UpdateQueue();
public ConfigurationNode configuration;
public List<Location> seedloc;
public List<MapChunkCache.VisibilityLimit> visibility_limits;
public boolean do_autogenerate;
public AutoGenerateOption do_autogenerate;
public MapChunkCache.HiddenChunkStyle hiddenchunkstyle;
public int servertime;
public boolean sendposition;

View File

@ -10,6 +10,7 @@ import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@ -17,6 +18,7 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.command.CommandSender;
import org.dynmap.DynmapWorld.AutoGenerateOption;
import org.dynmap.debug.Debug;
import org.dynmap.utils.LegacyMapChunkCache;
import org.dynmap.utils.MapChunkCache;
@ -94,6 +96,33 @@ public class MapManager {
x.printStackTrace();
}
}
@Override
public void execute(final Runnable r) {
final Runnable rr = r;
super.execute(new Runnable() {
public void run() {
try {
r.run();
} catch (Exception x) {
Log.severe("Exception during render job: " + r);
x.printStackTrace();
}
}
});
}
@Override
public ScheduledFuture<?> schedule(final Runnable command, long delay, TimeUnit unit) {
return super.schedule(new Runnable() {
public void run() {
try {
command.run();
} catch (Exception x) {
Log.severe("Exception during render job: " + command);
x.printStackTrace();
}
}
}, delay, unit);
}
}
/* This always runs on render pool threads - no bukkit calls from here */
private class FullWorldRenderState implements Runnable {
@ -391,10 +420,19 @@ public class MapManager {
dynmapWorld.seedloc.add(new Location(w, (lim.x0+lim.x1)/2, 64, (lim.z0+lim.z1)/2));
}
}
dynmapWorld.do_autogenerate = worldConfiguration.getBoolean("autogenerate-to-visibilitylimits", false);
if(dynmapWorld.do_autogenerate && (dynmapWorld.visibility_limits == null)) {
Log.info("Warning: Automatic world generation to visible limits option requires that visiblelimits be set - option disabled");
dynmapWorld.do_autogenerate = false;
String autogen = worldConfiguration.getString("autogenerate-to-visibilitylimits", "none");
if(autogen.equals("permanent")) {
dynmapWorld.do_autogenerate = AutoGenerateOption.PERMANENT;
}
else if(autogen.equals("map-only")) {
dynmapWorld.do_autogenerate = AutoGenerateOption.FORMAPONLY;
}
else {
dynmapWorld.do_autogenerate = AutoGenerateOption.NONE;
}
if((dynmapWorld.do_autogenerate != AutoGenerateOption.NONE) && (dynmapWorld.visibility_limits == null)) {
Log.info("Warning: Automatic world generation to visible limits option requires that visibitylimits be set - option disabled");
dynmapWorld.do_autogenerate = AutoGenerateOption.NONE;
}
String hiddenchunkstyle = worldConfiguration.getString("hidestyle", "stone");
if(hiddenchunkstyle.equals("air"))

View File

@ -11,6 +11,8 @@ import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.entity.Entity;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapPlugin;
import org.dynmap.DynmapWorld;
import org.dynmap.Log;
import java.util.List;
@ -28,7 +30,9 @@ public class LegacyMapChunkCache implements MapChunkCache {
private World w;
private List<DynmapChunk> chunks;
private ListIterator<DynmapChunk> iterator;
private boolean do_generate;
private DynmapWorld.AutoGenerateOption generateopt;
private boolean do_generate = false;
private boolean do_save = false;
private boolean isempty = true;
private int x_min, x_max, z_min, z_max;
@ -263,6 +267,7 @@ public class LegacyMapChunkCache implements MapChunkCache {
if(iterator == null)
iterator = chunks.listIterator();
DynmapPlugin.setIgnoreChunkLoads(true);
// Load the required chunks.
while((cnt < max_to_load) && iterator.hasNext()) {
DynmapChunk chunk = iterator.next();
@ -278,7 +283,7 @@ public class LegacyMapChunkCache implements MapChunkCache {
}
}
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
boolean didload = w.loadChunk(chunk.x, chunk.z, do_generate && vis);
boolean didload = w.loadChunk(chunk.x, chunk.z, false);
boolean didgenerate = false;
/* If we didn't load, and we're supposed to generate, do it */
if((!didload) && do_generate && vis)
@ -325,7 +330,7 @@ public class LegacyMapChunkCache implements MapChunkCache {
* while the actual in-use chunk area for a player where the chunks are managed
* by the MC base server is 21x21 (or about a 160 block radius).
* Also, if we did generate it, need to save it */
w.unloadChunk(chunk.x, chunk.z, didgenerate, false);
w.unloadChunk(chunk.x, chunk.z, didgenerate && do_save, false);
/* And pop preserved chunk - this is a bad leak in Bukkit for map traversals like us */
try {
if(poppreservedchunk != null)
@ -337,6 +342,8 @@ public class LegacyMapChunkCache implements MapChunkCache {
}
cnt++;
}
DynmapPlugin.setIgnoreChunkLoads(false);
/* If done, finish table */
if(iterator.hasNext() == false) {
isempty = true;
@ -456,12 +463,14 @@ public class LegacyMapChunkCache implements MapChunkCache {
/**
* Set autogenerate - must be done after at least one visible range has been set
*/
public void setAutoGenerateVisbileRanges(boolean do_generate) {
if(do_generate && ((visible_limits == null) || (visible_limits.size() == 0))) {
public void setAutoGenerateVisbileRanges(DynmapWorld.AutoGenerateOption generateopt) {
if((generateopt != DynmapWorld.AutoGenerateOption.NONE) && ((visible_limits == null) || (visible_limits.size() == 0))) {
Log.severe("Cannot setAutoGenerateVisibleRanges() without visible ranges defined");
return;
}
this.do_generate = do_generate;
this.generateopt = generateopt;
this.do_generate = (generateopt != DynmapWorld.AutoGenerateOption.NONE);
this.do_save = (generateopt == DynmapWorld.AutoGenerateOption.PERMANENT);
}
@Override
public boolean setChunkDataTypes(boolean blockdata, boolean biome, boolean highestblocky, boolean rawbiome) {

View File

@ -4,6 +4,7 @@ import org.bukkit.block.Biome;
import java.util.List;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapWorld;
public interface MapChunkCache {
public enum HiddenChunkStyle {
@ -94,5 +95,5 @@ public interface MapChunkCache {
/**
* Set autogenerate - must be done after at least one visible range has been set
*/
public void setAutoGenerateVisbileRanges(boolean do_generate);
public void setAutoGenerateVisbileRanges(DynmapWorld.AutoGenerateOption do_generate);
}

View File

@ -12,7 +12,10 @@ import org.bukkit.block.Biome;
import org.bukkit.entity.Entity;
import org.bukkit.ChunkSnapshot;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapPlugin;
import org.dynmap.DynmapWorld;
import org.dynmap.Log;
import org.dynmap.MapManager;
/**
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
@ -31,7 +34,9 @@ public class NewMapChunkCache implements MapChunkCache {
private boolean biome, biomeraw, highesty, blockdata;
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
private List<VisibilityLimit> visible_limits = null;
private DynmapWorld.AutoGenerateOption generateopt;
private boolean do_generate = false;
private boolean do_save = false;
private boolean isempty = true;
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
@ -284,6 +289,7 @@ public class NewMapChunkCache implements MapChunkCache {
if(iterator == null)
iterator = chunks.listIterator();
DynmapPlugin.setIgnoreChunkLoads(true);
// Load the required chunks.
while((cnt < max_to_load) && iterator.hasNext()) {
DynmapChunk chunk = iterator.next();
@ -298,7 +304,7 @@ public class NewMapChunkCache implements MapChunkCache {
}
}
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
boolean didload = w.loadChunk(chunk.x, chunk.z, do_generate && vis);
boolean didload = w.loadChunk(chunk.x, chunk.z, false);
boolean didgenerate = false;
/* If we didn't load, and we're supposed to generate, do it */
if((!didload) && do_generate && vis)
@ -348,7 +354,7 @@ public class NewMapChunkCache implements MapChunkCache {
* while the actual in-use chunk area for a player where the chunks are managed
* by the MC base server is 21x21 (or about a 160 block radius).
* Also, if we did generate it, need to save it */
w.unloadChunk(chunk.x, chunk.z, didgenerate, false);
w.unloadChunk(chunk.x, chunk.z, didgenerate && do_save, false);
/* And pop preserved chunk - this is a bad leak in Bukkit for map traversals like us */
try {
if(poppreservedchunk != null)
@ -359,6 +365,8 @@ public class NewMapChunkCache implements MapChunkCache {
}
cnt++;
}
DynmapPlugin.setIgnoreChunkLoads(false);
if(iterator.hasNext() == false) { /* If we're done */
isempty = true;
/* Fill missing chunks with empty dummy chunk */
@ -457,12 +465,14 @@ public class NewMapChunkCache implements MapChunkCache {
/**
* Set autogenerate - must be done after at least one visible range has been set
*/
public void setAutoGenerateVisbileRanges(boolean do_generate) {
if(do_generate && ((visible_limits == null) || (visible_limits.size() == 0))) {
public void setAutoGenerateVisbileRanges(DynmapWorld.AutoGenerateOption generateopt) {
if((generateopt != DynmapWorld.AutoGenerateOption.NONE) && ((visible_limits == null) || (visible_limits.size() == 0))) {
Log.severe("Cannot setAutoGenerateVisibleRanges() without visible ranges defined");
return;
}
this.do_generate = do_generate;
this.generateopt = generateopt;
this.do_generate = (generateopt != DynmapWorld.AutoGenerateOption.NONE);
this.do_save = (generateopt == DynmapWorld.AutoGenerateOption.PERMANENT);
}
/**
* Add visible area limit - can be called more than once