mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-12-26 18:47:40 +01:00
Add support for saving/restoring of pending tile updates on server stops/start
This commit is contained in:
parent
0627e2675f
commit
0704413829
@ -1,7 +1,9 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
@ -45,6 +47,16 @@ public class AsynchronousQueue<T> {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
public List<T> popAll() {
|
||||
List<T> s;
|
||||
synchronized(lock) {
|
||||
s = new ArrayList<T>(queue);
|
||||
queue.clear();
|
||||
set.clear();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
synchronized (lock) {
|
||||
thread = new Thread(new Runnable() {
|
||||
|
@ -45,6 +45,7 @@ public class MapManager {
|
||||
private int max_chunk_loads_per_tick = DEFAULT_CHUNKS_PER_TICK;
|
||||
private int parallelrendercnt = 0;
|
||||
private int progressinterval = 100;
|
||||
private boolean saverestorepending = true;
|
||||
|
||||
private int zoomout_period = DEFAULT_ZOOMOUT_PERIOD; /* Zoom-out tile processing period, in seconds */
|
||||
/* Which fullrenders are active */
|
||||
@ -501,6 +502,7 @@ public class MapManager {
|
||||
parallelrendercnt = configuration.getInteger("parallelrendercnt", 0);
|
||||
progressinterval = configuration.getInteger("progressloginterval", 100);
|
||||
if(progressinterval < 100) progressinterval = 100;
|
||||
saverestorepending = configuration.getBoolean("saverestorepending", true);
|
||||
|
||||
this.tileQueue = new AsynchronousQueue<MapTile>(
|
||||
new Handler<MapTile>() {
|
||||
@ -708,6 +710,54 @@ public class MapManager {
|
||||
}
|
||||
worldsLookup.put(w.getName(), dynmapWorld);
|
||||
plug_in.events.trigger("worldactivated", dynmapWorld);
|
||||
/* Now, restore any pending renders for this world */
|
||||
if(saverestorepending)
|
||||
loadPending(dynmapWorld);
|
||||
}
|
||||
|
||||
private void loadPending(DynmapWorld w) {
|
||||
File f = new File(plug_in.getDataFolder(), w.world.getName() + ".pending");
|
||||
if(f.exists()) {
|
||||
org.bukkit.util.config.Configuration saved = new org.bukkit.util.config.Configuration(f);
|
||||
saved.load();
|
||||
ConfigurationNode cn = new ConfigurationNode(saved);
|
||||
/* Get the saved tile definitions */
|
||||
List<ConfigurationNode> tiles = cn.getNodes("tiles");
|
||||
if(tiles != null) {
|
||||
int cnt = 0;
|
||||
for(ConfigurationNode tile : tiles) {
|
||||
MapTile mt = MapTile.restoreTile(w, tile); /* Restore tile, if possible */
|
||||
if(mt != null) {
|
||||
invalidateTile(mt);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
if(cnt > 0)
|
||||
Log.info("Loaded " + cnt + " pending tile renders for world '" + w.world.getName());
|
||||
}
|
||||
f.delete(); /* And clean it up */
|
||||
}
|
||||
}
|
||||
|
||||
private void savePending() {
|
||||
List<MapTile> mt = tileQueue.popAll();
|
||||
for(DynmapWorld w : worlds) {
|
||||
File f = new File(plug_in.getDataFolder(), w.world.getName() + ".pending");
|
||||
org.bukkit.util.config.Configuration saved = new org.bukkit.util.config.Configuration(f);
|
||||
ArrayList<ConfigurationNode> savedtiles = new ArrayList<ConfigurationNode>();
|
||||
for(MapTile tile : mt) {
|
||||
if(tile.getDynmapWorld() != w) continue;
|
||||
ConfigurationNode tilenode = tile.saveTile();
|
||||
if(tilenode != null) {
|
||||
savedtiles.add(tilenode);
|
||||
}
|
||||
}
|
||||
if(savedtiles.size() > 0) { /* Something to save? */
|
||||
saved.setProperty("tiles", savedtiles);
|
||||
saved.save();
|
||||
Log.info("Saved " + savedtiles.size() + " pending tile renders in world '" + w.world.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int touch(Location l) {
|
||||
@ -773,6 +823,9 @@ public class MapManager {
|
||||
tileQueue.stop();
|
||||
mapman = null;
|
||||
hdmapman = null;
|
||||
|
||||
if(saverestorepending)
|
||||
savePending();
|
||||
}
|
||||
|
||||
private HashMap<World, File> worldTileDirectories = new HashMap<World, File>();
|
||||
|
@ -1,6 +1,8 @@
|
||||
package org.dynmap;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.World;
|
||||
@ -54,4 +56,29 @@ public abstract class MapTile {
|
||||
public abstract int tileOrdinalX();
|
||||
public abstract int tileOrdinalY();
|
||||
|
||||
public ConfigurationNode saveTile() {
|
||||
ConfigurationNode cn = new ConfigurationNode();
|
||||
cn.put("class", this.getClass().getName());
|
||||
cn.put("data", saveTileData());
|
||||
return cn;
|
||||
}
|
||||
|
||||
protected abstract String saveTileData();
|
||||
|
||||
public static MapTile restoreTile(DynmapWorld w, ConfigurationNode node) {
|
||||
String cn = node.getString("class");
|
||||
String dat = node.getString("data");
|
||||
if((cn == null) || (dat == null)) return null;
|
||||
try {
|
||||
Class cls = Class.forName(cn);
|
||||
Constructor con = cls.getConstructor(DynmapWorld.class, String.class);
|
||||
return (MapTile)con.newInstance(w, dat);
|
||||
} catch (ClassNotFoundException cnfx) {
|
||||
} catch (NoSuchMethodException nsmx) {
|
||||
} catch (InvocationTargetException itx) {
|
||||
} catch (IllegalAccessException iax) {
|
||||
} catch (InstantiationException ix) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -80,4 +80,5 @@ public abstract class MapType {
|
||||
* Values correspond to tile X,Y (0), X+step,Y (1), X,Y+step (2), X+step,Y+step (3)
|
||||
*/
|
||||
public abstract int[] zoomFileStepSequence();
|
||||
|
||||
}
|
||||
|
@ -495,6 +495,28 @@ public class FlatMap extends MapType {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public FlatMapTile(DynmapWorld world, String parm) throws Exception {
|
||||
super(world);
|
||||
|
||||
String[] parms = parm.split(",");
|
||||
if(parms.length < 4) throw new Exception("wrong parameter count");
|
||||
this.x = Integer.parseInt(parms[0]);
|
||||
this.y = Integer.parseInt(parms[1]);
|
||||
this.size = Integer.parseInt(parms[2]);
|
||||
for(MapType t : world.maps) {
|
||||
if(t.getName().equals(parms[3]) && (t instanceof FlatMap)) {
|
||||
this.map = (FlatMap)t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(this.map == null) throw new Exception("invalid map");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return String.format("%d,%d,%d,%s", x, y, size, map.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
if(fname == null) {
|
||||
|
@ -7,6 +7,8 @@ import org.dynmap.MapType;
|
||||
|
||||
import java.util.List;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.kzedmap.KzedMap;
|
||||
import org.dynmap.kzedmap.MapTileRenderer;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public class HDMapTile extends MapTile {
|
||||
@ -20,6 +22,22 @@ public class HDMapTile extends MapTile {
|
||||
this.ty = ty;
|
||||
}
|
||||
|
||||
public HDMapTile(DynmapWorld world, String parm) throws Exception {
|
||||
super(world);
|
||||
|
||||
String[] parms = parm.split(",");
|
||||
if(parms.length < 3) throw new Exception("wrong parameter count");
|
||||
this.tx = Integer.parseInt(parms[0]);
|
||||
this.ty = Integer.parseInt(parms[1]);
|
||||
this.perspective = MapManager.mapman.hdmapman.perspectives.get(parms[2]);
|
||||
if(this.perspective == null) throw new Exception("invalid perspective");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return String.format("%d,%d,%s", tx, ty, perspective.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return getFilename("hdmap", MapType.ImageFormat.FORMAT_PNG);
|
||||
|
@ -3,11 +3,13 @@ package org.dynmap.kzedmap;
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.MapType;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.flat.FlatMap;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public class KzedMapTile extends MapTile {
|
||||
@ -28,6 +30,35 @@ public class KzedMapTile extends MapTile {
|
||||
this.py = py;
|
||||
}
|
||||
|
||||
public KzedMapTile(DynmapWorld world, String parm) throws Exception {
|
||||
super(world);
|
||||
|
||||
String[] parms = parm.split(",");
|
||||
if(parms.length < 4) throw new Exception("wrong parameter count");
|
||||
this.px = Integer.parseInt(parms[0]);
|
||||
this.py = Integer.parseInt(parms[1]);
|
||||
|
||||
for(MapType t : world.maps) {
|
||||
if(t.getName().equals(parms[2]) && (t instanceof KzedMap)) {
|
||||
this.map = (KzedMap)t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(this.map == null) throw new Exception("invalid map");
|
||||
for(MapTileRenderer r : map.renderers) {
|
||||
if(r.getName().equals(parms[3])) {
|
||||
this.renderer = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(this.renderer == null) throw new Exception("invalid renderer");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return String.format("%d,%d,%s,%s", px, py, map.getName(), renderer.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
if(fname == null) {
|
||||
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.MapType;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
public class KzedZoomedMapTile extends MapTile {
|
||||
@ -41,6 +42,11 @@ public class KzedZoomedMapTile extends MapTile {
|
||||
super(world);
|
||||
this.originalTile = original;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String saveTileData() {
|
||||
return originalTile.saveTileData();
|
||||
}
|
||||
|
||||
public int getTileX() {
|
||||
return ztilex(originalTile.px + KzedMap.tileWidth);
|
||||
|
@ -228,6 +228,9 @@ renderacceleratethreshold: 60
|
||||
# How often to render tiles when backlog is above renderacceleratethreshold
|
||||
renderaccelerateinterval: 0.2
|
||||
|
||||
# Save and restore pending tile renders - prevents their loss on server shutdown or /reload
|
||||
saverestorepending: true
|
||||
|
||||
# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds)
|
||||
zoomoutperiod: 30
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user