mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-24 19:25:15 +01:00
Add option to run incremental renders on sync thread, using same chunk
logic as timesliced full render, in order to handle cases where assumption that all chunks needed for incremental render are already resident (which can be false if player telepots, move quickly, multiple players are active, etc).
This commit is contained in:
parent
88db6445f9
commit
0a1de1b18e
@ -6,6 +6,9 @@ display-whitelist: false
|
|||||||
# How often a tile gets rendered (in seconds).
|
# How often a tile gets rendered (in seconds).
|
||||||
renderinterval: 1
|
renderinterval: 1
|
||||||
|
|
||||||
|
# Do render on main thread - may generate more server load, but safer and fixes broken tiles
|
||||||
|
renderonsync: true
|
||||||
|
|
||||||
render-triggers:
|
render-triggers:
|
||||||
# - playermove
|
# - playermove
|
||||||
# - playerjoin
|
# - playerjoin
|
||||||
|
@ -33,60 +33,42 @@ public class MapManager {
|
|||||||
private DynmapPlugin plug_in;
|
private DynmapPlugin plug_in;
|
||||||
private boolean do_timesliced_render = false;
|
private boolean do_timesliced_render = false;
|
||||||
private double timeslice_interval = 0.0;
|
private double timeslice_interval = 0.0;
|
||||||
|
private boolean do_sync_render = false; /* Do incremental renders on sync thread too */
|
||||||
/* Which timesliced renders are active */
|
/* Which timesliced renders are active */
|
||||||
private HashMap<String, FullWorldRenderState> active_renders = new HashMap<String, FullWorldRenderState>();
|
private HashMap<String, FullWorldRenderState> active_renders = new HashMap<String, FullWorldRenderState>();
|
||||||
|
|
||||||
/* lock for our data structures */
|
/* lock for our data structures */
|
||||||
public static final Object lock = new Object();
|
public static final Object lock = new Object();
|
||||||
|
|
||||||
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration) {
|
|
||||||
this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() {
|
|
||||||
@Override
|
|
||||||
public void handle(MapTile t) {
|
|
||||||
render(t);
|
|
||||||
}
|
|
||||||
}, (int) (configuration.getDouble("renderinterval", 0.5) * 1000));
|
|
||||||
|
|
||||||
for(Object worldConfigurationObj : (List<?>)configuration.getProperty("worlds")) {
|
|
||||||
Map<?, ?> worldConfiguration = (Map<?, ?>)worldConfigurationObj;
|
|
||||||
String worldName = (String)worldConfiguration.get("name");
|
|
||||||
DynmapWorld world = new DynmapWorld();
|
|
||||||
if (worldConfiguration.get("maps") != null) {
|
|
||||||
for(MapType map : loadMapTypes((List<?>)worldConfiguration.get("maps"))) {
|
|
||||||
world.maps.add(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inactiveworlds.put(worldName, world);
|
|
||||||
|
|
||||||
World bukkitWorld = plugin.getServer().getWorld(worldName);
|
|
||||||
if (bukkitWorld != null)
|
|
||||||
activateWorld(bukkitWorld);
|
|
||||||
}
|
|
||||||
do_timesliced_render = configuration.getBoolean("timeslicerender", true);
|
|
||||||
timeslice_interval = configuration.getDouble("timesliceinterval", 0.5);
|
|
||||||
|
|
||||||
scheduler = plugin.getServer().getScheduler();
|
|
||||||
plug_in = plugin;
|
|
||||||
|
|
||||||
tileQueue.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FullWorldRenderState implements Runnable {
|
private class FullWorldRenderState implements Runnable {
|
||||||
DynmapWorld world; /* Which world are we rendering */
|
DynmapWorld world; /* Which world are we rendering */
|
||||||
Location loc; /* Start location */
|
Location loc; /* Start location */
|
||||||
int map_index = -1; /* Which map are we on */
|
int map_index = -1; /* Which map are we on */
|
||||||
MapType map;
|
MapType map;
|
||||||
HashSet<MapTile> found = new HashSet<MapTile>();
|
HashSet<MapTile> found = null;
|
||||||
HashSet<MapTile> rendered = new HashSet<MapTile>();
|
HashSet<MapTile> rendered = null;
|
||||||
LinkedList<MapTile> renderQueue = new LinkedList<MapTile>();
|
LinkedList<MapTile> renderQueue = null;
|
||||||
|
MapTile tile0 = null;
|
||||||
|
|
||||||
|
/* Full world, all maps render */
|
||||||
FullWorldRenderState(DynmapWorld dworld, Location l) {
|
FullWorldRenderState(DynmapWorld dworld, Location l) {
|
||||||
world = dworld;
|
world = dworld;
|
||||||
loc = l;
|
loc = l;
|
||||||
|
found = new HashSet<MapTile>();
|
||||||
|
rendered = new HashSet<MapTile>();
|
||||||
|
renderQueue = new LinkedList<MapTile>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Single tile render - used for incremental renders */
|
||||||
|
FullWorldRenderState(MapTile t) {
|
||||||
|
world = worlds.get(t.getWorld().getName());
|
||||||
|
tile0 = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
MapTile tile;
|
MapTile tile;
|
||||||
|
|
||||||
|
if(tile0 == null) { /* Not single tile render */
|
||||||
/* If render queue is empty, start next map */
|
/* If render queue is empty, start next map */
|
||||||
if(renderQueue.isEmpty()) {
|
if(renderQueue.isEmpty()) {
|
||||||
found.clear();
|
found.clear();
|
||||||
@ -108,6 +90,10 @@ public class MapManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tile = renderQueue.pollFirst();
|
tile = renderQueue.pollFirst();
|
||||||
|
}
|
||||||
|
else { /* Else, single tile render */
|
||||||
|
tile = tile0;
|
||||||
|
}
|
||||||
|
|
||||||
DynmapChunk[] requiredChunks = tile.getMap().getRequiredChunks(tile);
|
DynmapChunk[] requiredChunks = tile.getMap().getRequiredChunks(tile);
|
||||||
LinkedList<DynmapChunk> loadedChunks = new LinkedList<DynmapChunk>();
|
LinkedList<DynmapChunk> loadedChunks = new LinkedList<DynmapChunk>();
|
||||||
@ -119,7 +105,10 @@ public class MapManager {
|
|||||||
if ((!wasLoaded) && didload)
|
if ((!wasLoaded) && didload)
|
||||||
loadedChunks.add(chunk);
|
loadedChunks.add(chunk);
|
||||||
}
|
}
|
||||||
|
if(tile0 != null) { /* Single tile? */
|
||||||
|
render(tile); /* Just render */
|
||||||
|
}
|
||||||
|
else {
|
||||||
if (render(tile)) {
|
if (render(tile)) {
|
||||||
found.remove(tile);
|
found.remove(tile);
|
||||||
rendered.add(tile);
|
rendered.add(tile);
|
||||||
@ -131,6 +120,7 @@ public class MapManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
found.remove(tile);
|
found.remove(tile);
|
||||||
|
}
|
||||||
/* And unload what we loaded */
|
/* And unload what we loaded */
|
||||||
while (!loadedChunks.isEmpty()) {
|
while (!loadedChunks.isEmpty()) {
|
||||||
DynmapChunk c = loadedChunks.pollFirst();
|
DynmapChunk c = loadedChunks.pollFirst();
|
||||||
@ -148,10 +138,50 @@ public class MapManager {
|
|||||||
* 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) */
|
||||||
w.unloadChunk(c.x, c.z, false, false);
|
w.unloadChunk(c.x, c.z, false, false);
|
||||||
}
|
}
|
||||||
|
if(tile0 == null) { /* fullrender */
|
||||||
/* Schedule the next tile to be worked */
|
/* Schedule the next tile to be worked */
|
||||||
scheduler.scheduleSyncDelayedTask(plug_in, this, (int)(timeslice_interval*20));
|
scheduler.scheduleSyncDelayedTask(plug_in, this, (int)(timeslice_interval*20));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration) {
|
||||||
|
this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() {
|
||||||
|
@Override
|
||||||
|
public void handle(MapTile t) {
|
||||||
|
if(do_sync_render)
|
||||||
|
scheduler.scheduleSyncDelayedTask(plug_in,
|
||||||
|
new FullWorldRenderState(t), (int)(timeslice_interval*20));
|
||||||
|
else
|
||||||
|
render(t);
|
||||||
|
}
|
||||||
|
}, (int) (configuration.getDouble("renderinterval", 0.5) * 1000));
|
||||||
|
|
||||||
|
for(Object worldConfigurationObj : (List<?>)configuration.getProperty("worlds")) {
|
||||||
|
Map<?, ?> worldConfiguration = (Map<?, ?>)worldConfigurationObj;
|
||||||
|
String worldName = (String)worldConfiguration.get("name");
|
||||||
|
DynmapWorld world = new DynmapWorld();
|
||||||
|
if (worldConfiguration.get("maps") != null) {
|
||||||
|
for(MapType map : loadMapTypes((List<?>)worldConfiguration.get("maps"))) {
|
||||||
|
world.maps.add(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inactiveworlds.put(worldName, world);
|
||||||
|
|
||||||
|
World bukkitWorld = plugin.getServer().getWorld(worldName);
|
||||||
|
if (bukkitWorld != null)
|
||||||
|
activateWorld(bukkitWorld);
|
||||||
|
}
|
||||||
|
do_timesliced_render = configuration.getBoolean("timeslicerender", true);
|
||||||
|
timeslice_interval = configuration.getDouble("timesliceinterval", 0.5);
|
||||||
|
do_sync_render = configuration.getBoolean("renderonsync", true);
|
||||||
|
|
||||||
|
scheduler = plugin.getServer().getScheduler();
|
||||||
|
plug_in = plugin;
|
||||||
|
|
||||||
|
tileQueue.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void renderFullWorld(Location l) {
|
void renderFullWorld(Location l) {
|
||||||
|
Loading…
Reference in New Issue
Block a user