Merge pull request #2633 from Marvosg/v3.0

Resume full renders (skip already rendered tiles)
This commit is contained in:
mikeprimm 2019-12-15 01:10:28 -06:00 committed by GitHub
commit 49ea99b703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 278 additions and 44 deletions

View File

@ -1046,7 +1046,9 @@ public class DynmapCore implements DynmapCommonAPI {
new CommandInfo("dynmap", "render", "Renders the tile at your location."),
new CommandInfo("dynmap", "fullrender", "Render all maps for entire world from your location."),
new CommandInfo("dynmap", "fullrender", "<world>", "Render all maps for world <world>."),
new CommandInfo("dynmap", "fullrender", "<world>:<map>", "Render map <map> of world'<world>."),
new CommandInfo("dynmap", "fullrender", "<world>:<map>", "Render map <map> of world <world>."),
new CommandInfo("dynmap", "fullrender", "resume <world>", "Resume render of all maps for world <world>. Skip already rendered tiles."),
new CommandInfo("dynmap", "fullrender", "resume <world>:<map>", "Resume render of map <map> of world <world>. Skip already rendered tiles."),
new CommandInfo("dynmap", "radiusrender", "<radius>", "Render at least <radius> block radius from your location on all maps."),
new CommandInfo("dynmap", "radiusrender", "<radius> <mapname>", "Render at least <radius> block radius from your location on map <mapname>."),
new CommandInfo("dynmap", "radiusrender", "<world> <x> <z> <radius>", "Render at least <radius> block radius from location <x>,<z> on world <world>."),
@ -1319,7 +1321,7 @@ public class DynmapCore implements DynmapCommonAPI {
loc = new DynmapLocation(w.getName(), x, 64, z);
}
if(loc != null)
mapManager.renderFullWorld(loc, sender, mapname, true);
mapManager.renderFullWorld(loc, sender, mapname, true, false);
} else if (c.equals("hide")) {
if (args.length == 1) {
if(player != null && checkPlayerPermission(sender,"hide.self")) {
@ -1347,7 +1349,12 @@ public class DynmapCore implements DynmapCommonAPI {
} else if (c.equals("fullrender") && checkPlayerPermission(sender,"fullrender")) {
String map = null;
if (args.length > 1) {
boolean resume = false;
for (int i = 1; i < args.length; i++) {
if (args[i].equalsIgnoreCase("resume")) {
resume = true;
continue;
}
int dot = args[i].indexOf(":");
DynmapWorld w;
String wname = args[i];
@ -1362,7 +1369,7 @@ public class DynmapCore implements DynmapCommonAPI {
loc = w.center;
else
loc = w.getSpawnLocation();
mapManager.renderFullWorld(loc,sender, map, false);
mapManager.renderFullWorld(loc,sender, map, false, resume);
}
else
sender.sendMessage("World '" + wname + "' not defined/loaded");
@ -1372,7 +1379,7 @@ public class DynmapCore implements DynmapCommonAPI {
if(args.length > 1)
map = args[1];
if(loc != null)
mapManager.renderFullWorld(loc, sender, map, false);
mapManager.renderFullWorld(loc, sender, map, false, false);
} else {
sender.sendMessage("World name is required");
}

View File

@ -22,6 +22,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@ -32,6 +33,10 @@ import org.dynmap.debug.Debug;
import org.dynmap.exporter.OBJExport;
import org.dynmap.hdmap.HDMapManager;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.storage.MapStorage;
import org.dynmap.storage.MapStorageBaseTileEnumCB;
import org.dynmap.storage.MapStorageTileSearchEndCB;
import org.dynmap.storage.MapStorageTile;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.Polygon;
import org.dynmap.utils.TileFlags;
@ -67,7 +72,7 @@ public class MapManager {
private boolean tpspauseupdaterenders = false;
private boolean tpspausefullrenders = false;
private boolean tpspausezoomout = false;
private boolean did_start = false;
private int zoomout_period = DEFAULT_ZOOMOUT_PERIOD; /* Zoom-out tile processing period, in seconds */
@ -233,6 +238,7 @@ public class MapManager {
LinkedList<MapTile> renderQueue = null;
MapTile tile0 = null;
int rendercnt = 0;
int skipcnt = 0;
DynmapCommandSender sender;
String player;
long timeaccum;
@ -246,21 +252,51 @@ public class MapManager {
boolean shutdown = false;
boolean pausedforworld = false;
boolean updaterender = false;
boolean resume = false;
boolean quiet = false;
String mapname;
AtomicLong total_render_ns = new AtomicLong(0L);
AtomicInteger rendercalls = new AtomicInteger(0);
long lastPendingSaveTS = 0; // Timestamp of last pending state save (msec)
HashSet<String> storedTileIds = new HashSet<>();
/* Full world, all maps render */
FullWorldRenderState(DynmapWorld dworld, DynmapLocation l, DynmapCommandSender sender, String mapname, boolean updaterender) {
FullWorldRenderState(DynmapWorld dworld, DynmapLocation l, DynmapCommandSender sender, String mapname, boolean updaterender, boolean resume) {
this(dworld, l, sender, mapname, -1);
if(updaterender) {
rendertype = RENDERTYPE_UPDATERENDER;
this.updaterender = true;
}
else
else {
rendertype = RENDERTYPE_FULLRENDER;
}
this.resume = resume;
final CountDownLatch latch = new CountDownLatch(1);
if (resume) { // if resume render
final MapStorage ms = world.getMapStorage();
ms.enumMapBaseTiles(world, map, new MapStorageBaseTileEnumCB() {
@Override
public void tileFound(MapStorageTile tile, MapType.ImageEncoding enc) {
String tileId = String.format("%s_%s_%d_%d", tile.world.getName(), tile.map.getName(), tile.x, tile.y);
//sender.sendMessage("Tile found: " + tileId);
storedTileIds.add(tileId);
}
}, new MapStorageTileSearchEndCB() {
@Override
public void searchEnded() {
latch.countDown();
}
});
try {
latch.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
sender.sendMessage(e.toString());
}
}
}
/* Full world, all maps render, with optional render radius */
@ -481,13 +517,22 @@ public class MapManager {
if(rndcalls == 0) rndcalls = 1;
double rendtime = total_render_ns.doubleValue() * 0.000001 / rndcalls;
if(activemapcnt > 1) {
sendMessage(String.format("%s of maps [%s] of '%s' completed - %d tiles rendered each (%.2f msec/map-tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
if (skipcnt > 1)
sendMessage(String.format("%s of maps [%s] of '%s' completed - %d tiles rendered each (%.2f msec/map-tile, %.2f msec per render) (%d tiles skipped)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime, skipcnt));
else
sendMessage(String.format("%s of maps [%s] of '%s' completed - %d tiles rendered each (%.2f msec/map-tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
}
else {
sendMessage(String.format("%s of map '%s' of '%s' completed - %d tiles rendered (%.2f msec/map-tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
if (skipcnt > 1)
sendMessage(String.format("%s of map '%s' of '%s' completed - %d tiles rendered (%.2f msec/map-tile, %.2f msec per render) (%d tiles skipped)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime, skipcnt));
else
sendMessage(String.format("%s of map '%s' of '%s' completed - %d tiles rendered (%.2f msec/map-tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
}
skipcnt = 0;
/* Now, if fullrender, use the render bitmap to purge obsolete tiles */
if(rendertype.equals(RENDERTYPE_FULLRENDER)) {
if(activemapcnt == 1) {
@ -698,19 +743,37 @@ public class MapManager {
chunks_read[cs.ordinal()].addAndGet(cache.getChunksLoaded(cs));
chunks_read_times[cs.ordinal()].addAndGet(cache.getTotalRuntimeNanos(cs));
}
boolean skipTile = false;
if (resume) {
String tileId = String.format("%s_%s_%d_%d", tile.world.getName(), map.getName(), tile.tileOrdinalX(), tile.tileOrdinalY());
skipTile = storedTileIds.contains(tileId);
}
if(tile0 != null) { /* Single tile? */
if(cache.isEmpty() == false)
tile.render(cache, null);
if(cache.isEmpty() == false) {
if (skipTile) {
skipcnt++;
} else {
tile.render(cache, null);
}
}
}
else {
/* Remove tile from tile queue, since we're processing it already */
tileQueue.remove(tile);
/* Switch to not checking if rendered tile is blank - breaks us on skylands, where tiles can be nominally blank - just work off chunk cache empty */
if (cache.isEmpty() == false) {
long rt0 = System.nanoTime();
boolean upd = tile.render(cache, mapname);
total_render_ns.addAndGet(System.nanoTime()-rt0);
rendercalls.incrementAndGet();
boolean upd;
if (skipTile) {
upd = false;
skipcnt++;
} else {
long rt0 = System.nanoTime();
upd = tile.render(cache, mapname);
total_render_ns.addAndGet(System.nanoTime()-rt0);
rendercalls.incrementAndGet();
}
synchronized(lock) {
rendered.setFlag(tile.tileOrdinalX(), tile.tileOrdinalY(), true);
if(upd || (!updaterender)) { /* If updated or not an update render */
@ -733,12 +796,22 @@ public class MapManager {
if (rndcalls == 0) rndcalls = 1;
double rendtime = total_render_ns.doubleValue() * 0.000001 / rndcalls;
double msecpertile = (double)timeaccum / (double)rendercnt / (double)activemapcnt;
if(activemapcnt > 1)
sendMessage(String.format("%s of maps [%s] of '%s' in progress - %d tiles rendered each (%.2f msec/map-tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
else
sendMessage(String.format("%s of map '%s' of '%s' in progress - %d tiles rendered (%.2f msec/tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
if(activemapcnt > 1) {
if (skipcnt > 1)
sendMessage(String.format("%s of maps [%s] of '%s' in progress - %d tiles rendered each (%.2f msec/map-tile, %.2f msec per render) (%d tiles skipped)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime, skipcnt));
else
sendMessage(String.format("%s of maps [%s] of '%s' in progress - %d tiles rendered each (%.2f msec/map-tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
} else {
if (skipcnt > 1)
sendMessage(String.format("%s of map '%s' of '%s' in progress - %d tiles rendered (%.2f msec/tile, %.2f msec per render) (%d tiles skipped)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime, skipcnt));
else
sendMessage(String.format("%s of map '%s' of '%s' in progress - %d tiles rendered (%.2f msec/tile, %.2f msec per render)",
rendertype, activemaps, world.getName(), rendercnt, msecpertile, rendtime));
}
skipcnt = 0;
}
}
}
@ -751,6 +824,7 @@ public class MapManager {
public void cancelRender() {
cancelled = true;
storedTileIds.clear();
}
public void shutdownRender() {
@ -968,7 +1042,7 @@ public class MapManager {
tileQueue.start();
}
void renderFullWorld(DynmapLocation l, DynmapCommandSender sender, String mapname, boolean update) {
void renderFullWorld(DynmapLocation l, DynmapCommandSender sender, String mapname, boolean update, boolean resume) {
DynmapWorld world = getWorld(l.world);
if (world == null) {
sender.sendMessage("Could not render: world '" + l.world + "' not defined in configuration.");
@ -982,7 +1056,7 @@ public class MapManager {
sender.sendMessage(rndr.rendertype + " of world '" + wname + "' already active.");
return;
}
rndr = new FullWorldRenderState(world,l,sender, mapname, update); /* Make new activation record */
rndr = new FullWorldRenderState(world,l,sender, mapname, update, resume); /* Make new activation record */
active_renders.put(wname, rndr); /* Add to active table */
}
/* Schedule first tile to be worked */
@ -990,6 +1064,8 @@ public class MapManager {
if(update)
sender.sendMessage("Update render starting on world '" + wname + "'...");
else if (resume)
sender.sendMessage("Full render resuming on world '" + wname + "'...");
else
sender.sendMessage("Full render starting on world '" + wname + "'...");
}

View File

@ -86,6 +86,15 @@ public abstract class MapStorage {
*/
public abstract void enumMapTiles(DynmapWorld world, MapType map, MapStorageTileEnumCB cb);
/**
* Enumerate existing map tiles, matching given constraints, with zoom at 0
* @param world - specific world
* @param map - specific map (if non-null)
* @param cbBase - callback to receive matching tiles
* @param cbEnd - callback to receive end-of-search event
*/
public abstract void enumMapBaseTiles(DynmapWorld world, MapType map, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd);
/**
* Purge existing map tiles, matching given constraints
* @param world - specific world

View File

@ -0,0 +1,12 @@
package org.dynmap.storage;
import org.dynmap.MapType.ImageEncoding;
public interface MapStorageBaseTileEnumCB {
/**
* Callback for base (non-zoomed) tile enumeration calls
* @param tile - tile found
* @param enc - image encoding
*/
public void tileFound(MapStorageTile tile, ImageEncoding enc);
}

View File

@ -0,0 +1,10 @@
package org.dynmap.storage;
import org.dynmap.MapType.ImageEncoding;
public interface MapStorageTileSearchEndCB {
/**
* Callback for end of tile enumeration calls
*/
public void searchEnded();
}

View File

@ -22,6 +22,8 @@ import org.dynmap.debug.Debug;
import org.dynmap.storage.MapStorage;
import org.dynmap.storage.MapStorageTile;
import org.dynmap.storage.MapStorageTileEnumCB;
import org.dynmap.storage.MapStorageBaseTileEnumCB;
import org.dynmap.storage.MapStorageTileSearchEndCB;
import org.dynmap.utils.BufferInputStream;
import org.dynmap.utils.BufferOutputStream;
@ -295,9 +297,13 @@ public class FileTreeMapStorage extends MapStorage {
}
private void processEnumMapTiles(DynmapWorld world, MapType map, File base, ImageVariant var, MapStorageTileEnumCB cb) {
private void processEnumMapTiles(DynmapWorld world, MapType map, File base, ImageVariant var, MapStorageTileEnumCB cb, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
File bdir = new File(base, map.getPrefix() + var.variantSuffix);
if (bdir.isDirectory() == false) return;
if (bdir.isDirectory() == false) {
if(cbEnd != null)
cbEnd.searchEnded();
return;
}
LinkedList<File> dirs = new LinkedList<File>(); // List to traverse
dirs.add(bdir); // Directory for map
@ -343,7 +349,10 @@ public class FileTreeMapStorage extends MapStorage {
int y = Integer.parseInt(coord[1]);
// Invoke callback
MapStorageTile t = new StorageTile(world, map, x, y, zoom, var);
cb.tileFound(t, fmt);
if(cb != null)
cb.tileFound(t, fmt);
if(cbBase != null && t.zoom == 0)
cbBase.tileFound(t, fmt);
t.cleanup();
} catch (NumberFormatException nfx) {
}
@ -351,6 +360,9 @@ public class FileTreeMapStorage extends MapStorage {
}
}
}
if(cbEnd != null) {
cbEnd.searchEnded();
}
}
@Override
@ -367,7 +379,26 @@ public class FileTreeMapStorage extends MapStorage {
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, base, var, cb);
processEnumMapTiles(world, mt, base, var, cb, null, null);
}
}
}
@Override
public void enumMapBaseTiles(DynmapWorld world, MapType map, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
File base = new File(baseTileDir, world.getName()); // Get base directory for world
List<MapType> mtlist;
if (map != null) {
mtlist = Collections.singletonList(map);
}
else { // Else, add all directories under world directory (for maps)
mtlist = new ArrayList<MapType>(world.maps);
}
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, base, var, null, cbBase, cbEnd);
}
}
}

View File

@ -25,6 +25,8 @@ import org.dynmap.PlayerFaces.FaceType;
import org.dynmap.storage.MapStorage;
import org.dynmap.storage.MapStorageTile;
import org.dynmap.storage.MapStorageTileEnumCB;
import org.dynmap.storage.MapStorageBaseTileEnumCB;
import org.dynmap.storage.MapStorageTileSearchEndCB;
import org.dynmap.utils.BufferInputStream;
import org.dynmap.utils.BufferOutputStream;
@ -608,7 +610,7 @@ public class MariaDBMapStorage extends MapStorage {
@Override
public void enumMapTiles(DynmapWorld world, MapType map,
MapStorageTileEnumCB cb) {
MapStorageTileEnumCB cb) {
List<MapType> mtlist;
if (map != null) {
@ -620,15 +622,36 @@ public class MariaDBMapStorage extends MapStorage {
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, var, cb);
processEnumMapTiles(world, mt, var, cb, null, null);
}
}
}
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb) {
@Override
public void enumMapBaseTiles(DynmapWorld world, MapType map, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
List<MapType> mtlist;
if (map != null) {
mtlist = Collections.singletonList(map);
}
else { // Else, add all directories under world directory (for maps)
mtlist = new ArrayList<MapType>(world.maps);
}
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, var, null, cbBase, cbEnd);
}
}
}
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
Connection c = null;
boolean err = false;
Integer mapkey = getMapKey(world, map, var);
if (mapkey == null) return;
if (mapkey == null) {
if(cbEnd != null)
cbEnd.searchEnded();
return;
}
try {
c = getConnection();
// Query tiles for given mapkey
@ -636,9 +659,15 @@ public class MariaDBMapStorage extends MapStorage {
ResultSet rs = stmt.executeQuery("SELECT x,y,zoom,Format FROM " + tableTiles + " WHERE MapID=" + mapkey + ";");
while (rs.next()) {
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
cb.tileFound(st, MapType.ImageEncoding.fromOrd(rs.getInt("Format")));
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
if(cb != null)
cb.tileFound(st, encoding);
if(cbBase != null && st.zoom == 0)
cbBase.tileFound(st, encoding);
st.cleanup();
}
if(cbEnd != null)
cbEnd.searchEnded();
rs.close();
stmt.close();
} catch (SQLException x) {

View File

@ -25,6 +25,8 @@ import org.dynmap.PlayerFaces.FaceType;
import org.dynmap.storage.MapStorage;
import org.dynmap.storage.MapStorageTile;
import org.dynmap.storage.MapStorageTileEnumCB;
import org.dynmap.storage.MapStorageBaseTileEnumCB;
import org.dynmap.storage.MapStorageTileSearchEndCB;
import org.dynmap.utils.BufferInputStream;
import org.dynmap.utils.BufferOutputStream;
@ -610,7 +612,7 @@ public class MySQLMapStorage extends MapStorage {
@Override
public void enumMapTiles(DynmapWorld world, MapType map,
MapStorageTileEnumCB cb) {
MapStorageTileEnumCB cb) {
List<MapType> mtlist;
if (map != null) {
@ -622,15 +624,36 @@ public class MySQLMapStorage extends MapStorage {
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, var, cb);
processEnumMapTiles(world, mt, var, cb, null, null);
}
}
}
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb) {
@Override
public void enumMapBaseTiles(DynmapWorld world, MapType map, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
List<MapType> mtlist;
if (map != null) {
mtlist = Collections.singletonList(map);
}
else { // Else, add all directories under world directory (for maps)
mtlist = new ArrayList<MapType>(world.maps);
}
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, var, null, cbBase, cbEnd);
}
}
}
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
Connection c = null;
boolean err = false;
Integer mapkey = getMapKey(world, map, var);
if (mapkey == null) return;
if (mapkey == null) {
if(cbEnd != null)
cbEnd.searchEnded();
return;
}
try {
c = getConnection();
// Query tiles for given mapkey
@ -638,9 +661,15 @@ public class MySQLMapStorage extends MapStorage {
ResultSet rs = stmt.executeQuery("SELECT x,y,zoom,Format FROM " + tableTiles + " WHERE MapID=" + mapkey + ";");
while (rs.next()) {
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
cb.tileFound(st, MapType.ImageEncoding.fromOrd(rs.getInt("Format")));
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
if(cb != null)
cb.tileFound(st, encoding);
if(cbBase != null && st.zoom == 0)
cbBase.tileFound(st, encoding);
st.cleanup();
}
if(cbEnd != null)
cbEnd.searchEnded();
rs.close();
stmt.close();
} catch (SQLException x) {

View File

@ -23,6 +23,8 @@ import org.dynmap.PlayerFaces.FaceType;
import org.dynmap.storage.MapStorage;
import org.dynmap.storage.MapStorageTile;
import org.dynmap.storage.MapStorageTileEnumCB;
import org.dynmap.storage.MapStorageBaseTileEnumCB;
import org.dynmap.storage.MapStorageTileSearchEndCB;
import org.dynmap.utils.BufferInputStream;
import org.dynmap.utils.BufferOutputStream;
@ -541,7 +543,7 @@ public class SQLiteMapStorage extends MapStorage {
@Override
public void enumMapTiles(DynmapWorld world, MapType map,
MapStorageTileEnumCB cb) {
MapStorageTileEnumCB cb) {
List<MapType> mtlist;
if (map != null) {
@ -553,15 +555,38 @@ public class SQLiteMapStorage extends MapStorage {
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, var, cb);
processEnumMapTiles(world, mt, var, cb, null, null);
}
}
}
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb) {
@Override
public void enumMapBaseTiles(DynmapWorld world, MapType map, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
List<MapType> mtlist;
if (map != null) {
mtlist = Collections.singletonList(map);
}
else { // Else, add all directories under world directory (for maps)
mtlist = new ArrayList<MapType>(world.maps);
}
for (MapType mt : mtlist) {
ImageVariant[] vars = mt.getVariants();
for (ImageVariant var : vars) {
processEnumMapTiles(world, mt, var, null, cbBase, cbEnd);
}
}
}
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
Connection c = null;
boolean err = false;
Integer mapkey = getMapKey(world, map, var);
if (mapkey == null) return;
if (mapkey == null) {
if(cbEnd != null)
cbEnd.searchEnded();
return;
}
try {
c = getConnection();
// Query tiles for given mapkey
@ -570,9 +595,15 @@ public class SQLiteMapStorage extends MapStorage {
ResultSet rs = doExecuteQuery(stmt, "SELECT x,y,zoom,Format FROM Tiles WHERE MapID=" + mapkey + ";");
while (rs.next()) {
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
cb.tileFound(st, MapType.ImageEncoding.fromOrd(rs.getInt("Format")));
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
if(cb != null)
cb.tileFound(st, encoding);
if(cbBase != null && st.zoom == 0)
cbBase.tileFound(st, encoding);
st.cleanup();
}
if(cbEnd != null)
cbEnd.searchEnded();
rs.close();
stmt.close();
} catch (SQLException x) {