From f722c6fdc82d23bad9aff68e32b8462ef1a546be Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Thu, 23 Jun 2011 00:53:56 -0500 Subject: [PATCH] Finish zoom out on normal and 'bigworld' mode, fix marker coordinates --- src/main/java/org/dynmap/DynmapWorld.java | 122 +++++++++++------- src/main/java/org/dynmap/MapManager.java | 4 +- src/main/java/org/dynmap/flat/FlatMap.java | 2 +- .../dynmap/kzedmap/DefaultTileRenderer.java | 12 +- .../org/dynmap/utils/FileLockManager.java | 1 + web/js/flatmap.js | 4 +- web/js/kzedmaps.js | 7 +- 7 files changed, 97 insertions(+), 55 deletions(-) diff --git a/src/main/java/org/dynmap/DynmapWorld.java b/src/main/java/org/dynmap/DynmapWorld.java index ed841caf..ffa3bea6 100644 --- a/src/main/java/org/dynmap/DynmapWorld.java +++ b/src/main/java/org/dynmap/DynmapWorld.java @@ -32,6 +32,7 @@ public class DynmapWorld { public boolean sendhealth; public boolean bigworld; /* If true, deeper directory hierarchy */ public int extrazoomoutlevels; /* Number of additional zoom out levels to generate */ + public File worldtilepath; private static class DirFilter implements FilenameFilter { public boolean accept(File f, String n) { @@ -55,9 +56,9 @@ public class DynmapWorld { } } - public void freshenZoomOutFiles(File tilepath) { + public void freshenZoomOutFiles() { for(int i = 0; i < extrazoomoutlevels; i++) { - freshenZoomOutFilesByLevel(tilepath, i); + freshenZoomOutFilesByLevel(i); } } @@ -65,70 +66,96 @@ public class DynmapWorld { int stepsize; int[] stepseq; boolean neg_step_x; + String baseprefix; + int zoomlevel; + String zoomprefix; + String fnprefix; + String zfnprefix; } - public void freshenZoomOutFilesByLevel(File tilepath, int zoomlevel) { - Debug.debug("freshenZoomOutFiles(" + tilepath.getPath() + "," + zoomlevel + ")"); - File worldpath = new File(tilepath, world.getName()); /* Make path to our world */ - if(worldpath.exists() == false) /* Quit if not found */ + public void freshenZoomOutFilesByLevel(int zoomlevel) { + int cnt = 0; + Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ")"); + if(worldtilepath.exists() == false) /* Quit if not found */ return; HashMap maptab = new HashMap(); /* Build table of file prefixes and step sizes */ for(MapType mt : maps) { - PrefixData pd = new PrefixData(); List pfx = mt.baseZoomFilePrefixes(); - pd.stepsize = mt.baseZoomFileStepSize(); - if(pd.stepsize < 0) { - pd.stepsize = -pd.stepsize; - pd.neg_step_x = true; + int stepsize = mt.baseZoomFileStepSize(); + boolean neg_step_x = false; + if(stepsize < 0) { + stepsize = -stepsize; + neg_step_x = true; } - pd.stepseq = mt.zoomFileStepSequence(); + int[] stepseq = mt.zoomFileStepSequence(); for(String p : pfx) { + PrefixData pd = new PrefixData(); + pd.stepsize = stepsize; + pd.neg_step_x = neg_step_x; + pd.stepseq = stepseq; + pd.baseprefix = p; + pd.zoomlevel = zoomlevel; + pd.zoomprefix = "zzzzzzzzzzzz".substring(0, zoomlevel); + if(bigworld) { + if(zoomlevel > 0) { + pd.zoomprefix += "_"; + pd.zfnprefix = "z" + pd.zoomprefix; + } + else { + pd.zfnprefix = "z_"; + } + pd.fnprefix = pd.zoomprefix; + } + else { + pd.fnprefix = pd.zoomprefix + pd.baseprefix; + pd.zfnprefix = "z" + pd.fnprefix; + } + maptab.put(p, pd); } } if(bigworld) { /* If big world, next directories are map name specific */ DirFilter df = new DirFilter(); - for(String pfx : maptab.keySet()) { /* Walk thrugh prefixes, as directories */ - File dname = new File(worldpath, pfx); + for(String pfx : maptab.keySet()) { /* Walk through prefixes, as directories */ + PrefixData pd = maptab.get(pfx); + File dname = new File(worldtilepath, pfx); /* Now, go through subdirectories under this one, and process them */ String[] subdir = dname.list(df); + if(subdir == null) continue; for(String s : subdir) { File sdname = new File(dname, s); - /* Each middle tier directory is redundant - just go through them */ - String[] ssubdir = sdname.list(df); - for(String ss : ssubdir) { - File ssdname = new File(sdname, ss); - processZoomDirectory(ssdname, maptab.get(pfx), "", zoomlevel); - } + cnt += processZoomDirectory(sdname, pd); } } } else { /* Else, classic file layout */ - for(String pfx : maptab.keySet()) { /* Walk thrugh prefixes, as directories */ - processZoomDirectory(worldpath, maptab.get(pfx), pfx + "_", zoomlevel); + for(String pfx : maptab.keySet()) { /* Walk through prefixes, as directories */ + cnt += processZoomDirectory(worldtilepath, maptab.get(pfx)); } } + Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ") - done (" + cnt + " updated files)"); } private static class ProcessTileRec { File zf; + String zfname; int x, y; } - private void processZoomDirectory(File dir, PrefixData pd, String prefix, int zoomlevel) { - Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.stepsize + "," + prefix + "," + zoomlevel + ")"); - String zoomprefix = "zzzzzzzzzzzzzzzzzzzz".substring(0, zoomlevel); - HashMap toprocess = new HashMap(); - if(prefix.equals("")) { - if(zoomlevel > 0) - prefix = zoomprefix + "_"; - } + private String makeFilePath(PrefixData pd, int x, int y, boolean zoomed) { + if(bigworld) + return pd.baseprefix + "/" + ((x/pd.stepsize) >> 5) + "_" + ((y/pd.stepsize) >> 5) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + ".png"; else - prefix = zoomprefix + prefix; - int step = pd.stepsize << zoomlevel; - zoomlevel++; - String[] files = dir.list(new PNGFileFilter(prefix)); + return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + ".png"; + } + private int processZoomDirectory(File dir, PrefixData pd) { + Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.baseprefix + ")"); + HashMap toprocess = new HashMap(); + int step = pd.stepsize << pd.zoomlevel; + String[] files = dir.list(new PNGFileFilter(pd.fnprefix)); + if(files == null) + return 0; for(String fn : files) { /* Build file object */ File f = new File(dir, fn); @@ -158,11 +185,9 @@ public class DynmapWorld { y = y - (y % (2*step)); else y = y + (y % (2*step)); - File zf; - if(prefix.equals("")) - zf = new File(dir, "z_" + x + "_" + y + ".png"); - else - zf = new File(dir, "z" + prefix + x + "_" + y + ".png"); + /* Make name of corresponding zoomed tile */ + String zfname = makeFilePath(pd, x, y, true); + File zf = new File(worldtilepath, zfname); /* If zoom file exists and is older than our file, nothing to do */ if(zf.exists() && (zf.lastModified() >= f.lastModified())) { continue; @@ -173,27 +198,33 @@ public class DynmapWorld { rec.zf = zf; rec.x = x; rec.y = y; + rec.zfname = zfname; toprocess.put(zfpath, rec); } } + int cnt = 0; /* Do processing */ for(ProcessTileRec s : toprocess.values()) { - processZoomTile(dir, s.zf, s.x - (pd.neg_step_x?step:0), s.y, step, prefix, pd.stepseq); + processZoomTile(pd, dir, s.zf, s.zfname, s.x - (pd.neg_step_x?step:0), s.y); + cnt++; } + Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.baseprefix + ") - done (" + cnt + " files)"); + return cnt; } - private void processZoomTile(File dir, File zf, int tx, int ty, int stepsize, String prefix, int[] stepseq) { - Debug.debug("processZoomFile(" + dir.getPath() + "," + zf.getPath() + "," + tx + "," + ty + "," + stepsize + "," + prefix); + private void processZoomTile(PrefixData pd, File dir, File zf, String zfname, int tx, int ty) { + Debug.debug("processZoomFile(" + pd.baseprefix + "," + dir.getPath() + "," + zf.getPath() + "," + tx + "," + ty + ")"); int width = 128, height = 128; BufferedImage zIm = null; KzedBufferedImage kzIm = null; int[] argb = new int[width*height]; + int step = pd.stepsize << pd.zoomlevel; /* create image buffer */ kzIm = KzedMap.allocateBufferedImage(width, height); zIm = kzIm.buf_img; for(int i = 0; i < 4; i++) { - File f = new File(dir, prefix + (tx + stepsize*(1&stepseq[i])) + "_" + (ty + stepsize*(stepseq[i]>>1)) + ".png"); + File f = new File(worldtilepath, makeFilePath(pd, (tx + step*(1&pd.stepseq[i])), (ty + step*(pd.stepseq[i]>>1)), false)); if(f.exists()) { BufferedImage im = null; FileLockManager.getReadLock(f); @@ -234,8 +265,10 @@ public class DynmapWorld { } FileLockManager.getWriteLock(zf); try { + if(!zf.getParentFile().exists()) + zf.getParentFile().mkdirs(); FileLockManager.imageIOWrite(zIm, "png", zf); - Debug.debug("Saved zoom-out tile at " + zf.getName()); + Debug.debug("Saved zoom-out tile at " + zf.getPath()); } catch (IOException e) { Debug.error("Failed to save zoom-out tile: " + zf.getName(), e); } catch (java.lang.NullPointerException e) { @@ -243,5 +276,6 @@ public class DynmapWorld { } FileLockManager.releaseWriteLock(zf); KzedMap.freeBufferedImage(kzIm); + MapManager.mapman.pushUpdate(this.world, new Client.Tile(zfname)); } } diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index ce149601..88c68893 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -267,7 +267,7 @@ public class MapManager { public void run() { Debug.debug("DoZoomOutProcessing started"); for(DynmapWorld w : worlds) { - w.freshenZoomOutFiles(DynmapPlugin.tilesDirectory); + w.freshenZoomOutFiles(); } renderpool.schedule(this, zoomout_period, TimeUnit.SECONDS); Debug.debug("DoZoomOutProcessing finished"); @@ -362,7 +362,7 @@ public class MapManager { dynmapWorld.sendhealth = worldConfiguration.getBoolean("sendhealth", true); dynmapWorld.bigworld = worldConfiguration.getBoolean("bigworld", false); dynmapWorld.extrazoomoutlevels = worldConfiguration.getInteger("extrazoomout", 0); - + dynmapWorld.worldtilepath = new File(plug_in.tilesDirectory, w.getName()); if(loclist != null) { for(ConfigurationNode loc : loclist) { Location lx = new Location(w, loc.getDouble("x", 0), loc.getDouble("y", 64), loc.getDouble("z", 0)); diff --git a/src/main/java/org/dynmap/flat/FlatMap.java b/src/main/java/org/dynmap/flat/FlatMap.java index 78e828e6..2274feea 100644 --- a/src/main/java/org/dynmap/flat/FlatMap.java +++ b/src/main/java/org/dynmap/flat/FlatMap.java @@ -300,7 +300,7 @@ public class FlatMap extends MapType { /* If day too, handle it */ if(night_and_day) { - File dayfile = new File(outputFile.getParent(), tile.getDayFilename()); + File dayfile = new File(tile.getDynmapWorld().worldtilepath, tile.getDayFilename()); FileLockManager.getWriteLock(dayfile); crc = hashman.calculateTileHash(argb_buf_day); if((!dayfile.exists()) || (crc != hashman.getImageHashCode(tile.getKey(), "day", t.x, t.y))) { diff --git a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java index 07c01d12..b32101d4 100644 --- a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java @@ -284,7 +284,8 @@ public class DefaultTileRenderer implements MapTileRenderer { mtile.file = fname; boolean updated_dfname = false; - File dfname = new File(fname.getParent(), mtile.getDayFilename()); + + File dfname = new File(mtile.getDynmapWorld().worldtilepath, mtile.getDayFilename()); if(img_day != null) { FileLockManager.getWriteLock(dfname); crc = hashman.calculateTileHash(img.argb_buf); @@ -313,7 +314,7 @@ public class DefaultTileRenderer implements MapTileRenderer { boolean ztile_updated = false; FileLockManager.getWriteLock(zoomFile); if(updated_fname || (!zoomFile.exists())) { - saveZoomedTile(zmtile, zoomFile, zimg, ox, oy); + saveZoomedTile(zmtile, zoomFile, zimg, ox, oy, null); MapManager.mapman.pushUpdate(zmtile.getWorld(), new Client.Tile(zmtile.getFilename())); ztile_updated = true; @@ -323,11 +324,11 @@ public class DefaultTileRenderer implements MapTileRenderer { MapManager.mapman.updateStatistics(zmtile, null, true, ztile_updated, !rendered); if(zimg_day != null) { - File zoomFile_day = new File(zoomFile.getParent(), zmtile.getDayFilename()); + File zoomFile_day = new File(zmtile.getDynmapWorld().worldtilepath, zmtile.getDayFilename()); ztile_updated = false; FileLockManager.getWriteLock(zoomFile_day); if(updated_dfname || (!zoomFile_day.exists())) { - saveZoomedTile(zmtile, zoomFile_day, zimg_day, ox, oy); + saveZoomedTile(zmtile, zoomFile_day, zimg_day, ox, oy, "day"); MapManager.mapman.pushUpdate(zmtile.getWorld(), new Client.Tile(zmtile.getDayFilename())); ztile_updated = true; @@ -339,7 +340,7 @@ public class DefaultTileRenderer implements MapTileRenderer { } private void saveZoomedTile(final KzedZoomedMapTile zmtile, final File zoomFile, - final KzedBufferedImage zimg, int ox, int oy) { + final KzedBufferedImage zimg, int ox, int oy, String subkey) { BufferedImage zIm = null; KzedBufferedImage kzIm = null; try { @@ -374,6 +375,7 @@ public class DefaultTileRenderer implements MapTileRenderer { } catch (java.lang.NullPointerException e) { Debug.error("Failed to save zoom-out tile (NullPointerException): " + zoomFile.getName(), e); } + if(zIm_allocated) KzedMap.freeBufferedImage(kzIm); else diff --git a/src/main/java/org/dynmap/utils/FileLockManager.java b/src/main/java/org/dynmap/utils/FileLockManager.java index c3f4d679..a95b4f80 100644 --- a/src/main/java/org/dynmap/utils/FileLockManager.java +++ b/src/main/java/org/dynmap/utils/FileLockManager.java @@ -117,6 +117,7 @@ public class FileLockManager { while(!done) { try { ImageIO.write(img, type, fname); + fname.setLastModified(System.currentTimeMillis()); done = true; } catch (FileNotFoundException fnfx) { /* This seems to be what we get when file is locked by reader */ if(retrycnt < MAX_WRITE_RETRIES) { diff --git a/web/js/flatmap.js b/web/js/flatmap.js index 33b7ae79..67633b50 100644 --- a/web/js/flatmap.js +++ b/web/js/flatmap.js @@ -1,5 +1,6 @@ function FlatProjection() {} FlatProjection.prototype = { + extrazoom: 0, fromLatLngToPoint: function(latLng) { return new google.maps.Point(latLng.lat()*config.tileWidth, latLng.lng()*config.tileHeight); }, @@ -7,7 +8,7 @@ FlatProjection.prototype = { return new google.maps.LatLng(point.x/config.tileWidth, point.y/config.tileHeight); }, fromWorldToLatLng: function(x, y, z) { - return new google.maps.LatLng(-z / config.tileWidth, x / config.tileHeight); + return new google.maps.LatLng(-z / config.tileWidth / (1 << this.extrazoom), x / config.tileHeight / (1 << this.extrazoom)); } }; @@ -71,6 +72,7 @@ FlatMapType.prototype = $.extend(new DynMapType(), { updateTileSize: function(zoom) { var size; var extrazoom = this.dynmap.world.extrazoomout; + this.projection.extrazoom = extrazoom; this.maxZoom = 3 + extrazoom; if (zoom <= extrazoom) { size = 128; diff --git a/web/js/kzedmaps.js b/web/js/kzedmaps.js index aa8c468d..971af58e 100644 --- a/web/js/kzedmaps.js +++ b/web/js/kzedmaps.js @@ -1,5 +1,6 @@ function KzedProjection() {} KzedProjection.prototype = { + extrazoom: 0, fromLatLngToPoint: function(latLng) { var x = latLng.lng() * config.tileWidth; var y = latLng.lat() * config.tileHeight; @@ -18,9 +19,10 @@ KzedProjection.prototype = { var dz = +z; var px = dx + dz; var py = dx - dz - dy; + var scale = 2 << this.extrazoom; - var lng = -px / config.tileWidth / 2 + 0.5; - var lat = py / config.tileHeight / 2; + var lng = -px / config.tileWidth / scale + (1.0 / scale); + var lat = py / config.tileHeight / scale; return new google.maps.LatLng(lat, lng); } @@ -112,6 +114,7 @@ KzedMapType.prototype = $.extend(new DynMapType(), { updateTileSize: function(zoom) { var size; var extrazoom = this.dynmap.world.extrazoomout; + this.projection.extrazoom = extrazoom; this.maxZoom = 3 + extrazoom; if (zoom <= extrazoom) { size = 128;