mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-28 13:15:30 +01:00
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:
parent
6dac7f0689
commit
39281188bc
@ -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)
|
# # 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
|
# 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
|
# # 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.
|
# # 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),
|
||||||
# # 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)
|
# # 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: false
|
# 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).
|
# 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
|
# template: mycustomtemplate
|
||||||
# Rest of comes from template - uncomment to tailor for world specifically
|
# Rest of comes from template - uncomment to tailor for world specifically
|
||||||
|
@ -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 */
|
/* Flag to let code know that we're doing reload - make sure we don't double-register event handlers */
|
||||||
public boolean is_reload = false;
|
public boolean is_reload = false;
|
||||||
private boolean generate_only = 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 dataDirectory;
|
||||||
public static File tilesDirectory;
|
public static File tilesDirectory;
|
||||||
@ -248,6 +249,8 @@ public class DynmapPlugin extends JavaPlugin {
|
|||||||
WorldListener renderTrigger = new WorldListener() {
|
WorldListener renderTrigger = new WorldListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onChunkLoad(ChunkLoadEvent event) {
|
public void onChunkLoad(ChunkLoadEvent event) {
|
||||||
|
if(ignore_chunk_loads)
|
||||||
|
return;
|
||||||
if(generate_only) {
|
if(generate_only) {
|
||||||
if(!isNewChunk(event))
|
if(!isNewChunk(event))
|
||||||
return;
|
return;
|
||||||
@ -494,4 +497,8 @@ public class DynmapPlugin extends JavaPlugin {
|
|||||||
public String getWebPath() {
|
public String getWebPath() {
|
||||||
return configuration.getString("webpath", "web");
|
return configuration.getString("webpath", "web");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setIgnoreChunkLoads(boolean ignore) {
|
||||||
|
ignore_chunk_loads = ignore;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,18 @@ import java.util.HashSet;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
public class DynmapWorld {
|
public class DynmapWorld {
|
||||||
|
public enum AutoGenerateOption {
|
||||||
|
NONE,
|
||||||
|
FORMAPONLY,
|
||||||
|
PERMANENT
|
||||||
|
}
|
||||||
public World world;
|
public World world;
|
||||||
public List<MapType> maps = new ArrayList<MapType>();
|
public List<MapType> maps = new ArrayList<MapType>();
|
||||||
public UpdateQueue updates = new UpdateQueue();
|
public UpdateQueue updates = new UpdateQueue();
|
||||||
public ConfigurationNode configuration;
|
public ConfigurationNode configuration;
|
||||||
public List<Location> seedloc;
|
public List<Location> seedloc;
|
||||||
public List<MapChunkCache.VisibilityLimit> visibility_limits;
|
public List<MapChunkCache.VisibilityLimit> visibility_limits;
|
||||||
public boolean do_autogenerate;
|
public AutoGenerateOption do_autogenerate;
|
||||||
public MapChunkCache.HiddenChunkStyle hiddenchunkstyle;
|
public MapChunkCache.HiddenChunkStyle hiddenchunkstyle;
|
||||||
public int servertime;
|
public int servertime;
|
||||||
public boolean sendposition;
|
public boolean sendposition;
|
||||||
|
@ -10,6 +10,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -17,6 +18,7 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.dynmap.DynmapWorld.AutoGenerateOption;
|
||||||
import org.dynmap.debug.Debug;
|
import org.dynmap.debug.Debug;
|
||||||
import org.dynmap.utils.LegacyMapChunkCache;
|
import org.dynmap.utils.LegacyMapChunkCache;
|
||||||
import org.dynmap.utils.MapChunkCache;
|
import org.dynmap.utils.MapChunkCache;
|
||||||
@ -94,6 +96,33 @@ public class MapManager {
|
|||||||
x.printStackTrace();
|
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 */
|
/* This always runs on render pool threads - no bukkit calls from here */
|
||||||
private class FullWorldRenderState implements Runnable {
|
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.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);
|
String autogen = worldConfiguration.getString("autogenerate-to-visibilitylimits", "none");
|
||||||
if(dynmapWorld.do_autogenerate && (dynmapWorld.visibility_limits == null)) {
|
if(autogen.equals("permanent")) {
|
||||||
Log.info("Warning: Automatic world generation to visible limits option requires that visiblelimits be set - option disabled");
|
dynmapWorld.do_autogenerate = AutoGenerateOption.PERMANENT;
|
||||||
dynmapWorld.do_autogenerate = false;
|
}
|
||||||
|
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");
|
String hiddenchunkstyle = worldConfiguration.getString("hidestyle", "stone");
|
||||||
if(hiddenchunkstyle.equals("air"))
|
if(hiddenchunkstyle.equals("air"))
|
||||||
|
@ -11,6 +11,8 @@ import org.bukkit.Chunk;
|
|||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.dynmap.DynmapChunk;
|
import org.dynmap.DynmapChunk;
|
||||||
|
import org.dynmap.DynmapPlugin;
|
||||||
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.Log;
|
import org.dynmap.Log;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -28,7 +30,9 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
private World w;
|
private World w;
|
||||||
private List<DynmapChunk> chunks;
|
private List<DynmapChunk> chunks;
|
||||||
private ListIterator<DynmapChunk> iterator;
|
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 boolean isempty = true;
|
||||||
|
|
||||||
private int x_min, x_max, z_min, z_max;
|
private int x_min, x_max, z_min, z_max;
|
||||||
@ -263,6 +267,7 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
if(iterator == null)
|
if(iterator == null)
|
||||||
iterator = chunks.listIterator();
|
iterator = chunks.listIterator();
|
||||||
|
|
||||||
|
DynmapPlugin.setIgnoreChunkLoads(true);
|
||||||
// Load the required chunks.
|
// Load the required chunks.
|
||||||
while((cnt < max_to_load) && iterator.hasNext()) {
|
while((cnt < max_to_load) && iterator.hasNext()) {
|
||||||
DynmapChunk chunk = iterator.next();
|
DynmapChunk chunk = iterator.next();
|
||||||
@ -278,7 +283,7 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
|
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;
|
boolean didgenerate = false;
|
||||||
/* If we didn't load, and we're supposed to generate, do it */
|
/* If we didn't load, and we're supposed to generate, do it */
|
||||||
if((!didload) && do_generate && vis)
|
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
|
* 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).
|
* by the MC base server is 21x21 (or about a 160 block radius).
|
||||||
* Also, if we did generate it, need to save it */
|
* 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 */
|
/* And pop preserved chunk - this is a bad leak in Bukkit for map traversals like us */
|
||||||
try {
|
try {
|
||||||
if(poppreservedchunk != null)
|
if(poppreservedchunk != null)
|
||||||
@ -337,6 +342,8 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
DynmapPlugin.setIgnoreChunkLoads(false);
|
||||||
|
|
||||||
/* If done, finish table */
|
/* If done, finish table */
|
||||||
if(iterator.hasNext() == false) {
|
if(iterator.hasNext() == false) {
|
||||||
isempty = true;
|
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
|
* 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 generateopt) {
|
||||||
if(do_generate && ((visible_limits == null) || (visible_limits.size() == 0))) {
|
if((generateopt != DynmapWorld.AutoGenerateOption.NONE) && ((visible_limits == null) || (visible_limits.size() == 0))) {
|
||||||
Log.severe("Cannot setAutoGenerateVisibleRanges() without visible ranges defined");
|
Log.severe("Cannot setAutoGenerateVisibleRanges() without visible ranges defined");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.do_generate = do_generate;
|
this.generateopt = generateopt;
|
||||||
|
this.do_generate = (generateopt != DynmapWorld.AutoGenerateOption.NONE);
|
||||||
|
this.do_save = (generateopt == DynmapWorld.AutoGenerateOption.PERMANENT);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean setChunkDataTypes(boolean blockdata, boolean biome, boolean highestblocky, boolean rawbiome) {
|
public boolean setChunkDataTypes(boolean blockdata, boolean biome, boolean highestblocky, boolean rawbiome) {
|
||||||
|
@ -4,6 +4,7 @@ import org.bukkit.block.Biome;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.dynmap.DynmapChunk;
|
import org.dynmap.DynmapChunk;
|
||||||
|
import org.dynmap.DynmapWorld;
|
||||||
|
|
||||||
public interface MapChunkCache {
|
public interface MapChunkCache {
|
||||||
public enum HiddenChunkStyle {
|
public enum HiddenChunkStyle {
|
||||||
@ -94,5 +95,5 @@ public interface MapChunkCache {
|
|||||||
/**
|
/**
|
||||||
* Set autogenerate - must be done after at least one visible range has been set
|
* 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);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@ import org.bukkit.block.Biome;
|
|||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.ChunkSnapshot;
|
import org.bukkit.ChunkSnapshot;
|
||||||
import org.dynmap.DynmapChunk;
|
import org.dynmap.DynmapChunk;
|
||||||
|
import org.dynmap.DynmapPlugin;
|
||||||
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.Log;
|
import org.dynmap.Log;
|
||||||
|
import org.dynmap.MapManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
|
* 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 boolean biome, biomeraw, highesty, blockdata;
|
||||||
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
|
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
|
||||||
private List<VisibilityLimit> visible_limits = null;
|
private List<VisibilityLimit> visible_limits = null;
|
||||||
|
private DynmapWorld.AutoGenerateOption generateopt;
|
||||||
private boolean do_generate = false;
|
private boolean do_generate = false;
|
||||||
|
private boolean do_save = false;
|
||||||
private boolean isempty = true;
|
private boolean isempty = true;
|
||||||
|
|
||||||
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
|
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
|
||||||
@ -284,6 +289,7 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
if(iterator == null)
|
if(iterator == null)
|
||||||
iterator = chunks.listIterator();
|
iterator = chunks.listIterator();
|
||||||
|
|
||||||
|
DynmapPlugin.setIgnoreChunkLoads(true);
|
||||||
// Load the required chunks.
|
// Load the required chunks.
|
||||||
while((cnt < max_to_load) && iterator.hasNext()) {
|
while((cnt < max_to_load) && iterator.hasNext()) {
|
||||||
DynmapChunk chunk = iterator.next();
|
DynmapChunk chunk = iterator.next();
|
||||||
@ -298,7 +304,7 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
|
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;
|
boolean didgenerate = false;
|
||||||
/* If we didn't load, and we're supposed to generate, do it */
|
/* If we didn't load, and we're supposed to generate, do it */
|
||||||
if((!didload) && do_generate && vis)
|
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
|
* 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).
|
* by the MC base server is 21x21 (or about a 160 block radius).
|
||||||
* Also, if we did generate it, need to save it */
|
* 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 */
|
/* And pop preserved chunk - this is a bad leak in Bukkit for map traversals like us */
|
||||||
try {
|
try {
|
||||||
if(poppreservedchunk != null)
|
if(poppreservedchunk != null)
|
||||||
@ -359,6 +365,8 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
DynmapPlugin.setIgnoreChunkLoads(false);
|
||||||
|
|
||||||
if(iterator.hasNext() == false) { /* If we're done */
|
if(iterator.hasNext() == false) { /* If we're done */
|
||||||
isempty = true;
|
isempty = true;
|
||||||
/* Fill missing chunks with empty dummy chunk */
|
/* 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
|
* 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 generateopt) {
|
||||||
if(do_generate && ((visible_limits == null) || (visible_limits.size() == 0))) {
|
if((generateopt != DynmapWorld.AutoGenerateOption.NONE) && ((visible_limits == null) || (visible_limits.size() == 0))) {
|
||||||
Log.severe("Cannot setAutoGenerateVisibleRanges() without visible ranges defined");
|
Log.severe("Cannot setAutoGenerateVisibleRanges() without visible ranges defined");
|
||||||
return;
|
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
|
* Add visible area limit - can be called more than once
|
||||||
|
Loading…
Reference in New Issue
Block a user