mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-24 19:25:15 +01:00
Merge pull request #232 from mikeprimm/master
Add support for configurable extra zoom out levels on each world - generates more tiers of zoomed images
This commit is contained in:
commit
6d6a5f4db0
@ -73,6 +73,9 @@ display-whitelist: false
|
||||
# How often a tile gets rendered (in seconds).
|
||||
renderinterval: 1
|
||||
|
||||
# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds)
|
||||
zoomoutperiod: 60
|
||||
|
||||
# Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable
|
||||
enabletilehash: true
|
||||
|
||||
@ -133,6 +136,8 @@ templates:
|
||||
enabled: true
|
||||
# # If bigworld set to true, use alternate directory layout better suited to large worlds
|
||||
# bigworld: true
|
||||
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
|
||||
# extrazoomout: 3
|
||||
center:
|
||||
x: 0
|
||||
y: 64
|
||||
@ -209,6 +214,8 @@ templates:
|
||||
enabled: true
|
||||
# # If bigworld set to true, use alternate directory layout better suited to large worlds
|
||||
# bigworld: true
|
||||
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
|
||||
# extrazoomout: 3
|
||||
center:
|
||||
x: 0
|
||||
y: 64
|
||||
@ -238,6 +245,8 @@ templates:
|
||||
enabled: true
|
||||
# # If bigworld set to true, use alternate directory layout better suited to large worlds
|
||||
# bigworld: true
|
||||
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
|
||||
# extrazoomout: 3
|
||||
center:
|
||||
x: 0
|
||||
y: 64
|
||||
@ -312,6 +321,8 @@ worlds:
|
||||
# z: 0
|
||||
# # If bigworld set to true, use alternate directory layout better suited to large worlds
|
||||
# bigworld: true
|
||||
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
|
||||
# extrazoomout: 3
|
||||
# maps:
|
||||
# - class: org.dynmap.flat.FlatMap
|
||||
# name: flat
|
||||
@ -381,6 +392,8 @@ worlds:
|
||||
# x: 0
|
||||
# y: 64
|
||||
# z: 0
|
||||
# # Number of extra zoom-out levels for world (each level is twice as big as the previous one)
|
||||
# extrazoomout: 3
|
||||
# maps:
|
||||
# - class: org.dynmap.flat.FlatMap
|
||||
# name: flat
|
||||
|
@ -33,6 +33,7 @@ public class ClientConfigurationComponent extends Component {
|
||||
s(wo, "center/y", wn.getFloat("center/y", 64.0f));
|
||||
s(wo, "center/z", wn.getFloat("center/z", 0.0f));
|
||||
s(wo, "bigworld", world.bigworld);
|
||||
s(wo, "extrazoomout", world.extrazoomoutlevels);
|
||||
a(t, "worlds", wo);
|
||||
|
||||
for(MapType mt : world.maps) {
|
||||
|
@ -5,8 +5,20 @@ import java.util.List;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.Location;
|
||||
import org.dynmap.debug.Debug;
|
||||
import org.dynmap.kzedmap.KzedMap;
|
||||
import org.dynmap.kzedmap.KzedMap.KzedBufferedImage;
|
||||
import org.dynmap.utils.FileLockManager;
|
||||
import org.dynmap.utils.MapChunkCache;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class DynmapWorld {
|
||||
public World world;
|
||||
public List<MapType> maps = new ArrayList<MapType>();
|
||||
@ -19,4 +31,251 @@ public class DynmapWorld {
|
||||
public boolean sendposition;
|
||||
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) {
|
||||
if(!n.equals("..") && !n.equals(".")) {
|
||||
File fn = new File(f, n);
|
||||
return fn.isDirectory();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PNGFileFilter implements FilenameFilter {
|
||||
String prefix;
|
||||
public PNGFileFilter(String pre) { prefix = pre; }
|
||||
public boolean accept(File f, String n) {
|
||||
if(n.endsWith(".png") && n.startsWith(prefix)) {
|
||||
File fn = new File(f, n);
|
||||
return fn.isFile();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void freshenZoomOutFiles() {
|
||||
for(int i = 0; i < extrazoomoutlevels; i++) {
|
||||
freshenZoomOutFilesByLevel(i);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PrefixData {
|
||||
int stepsize;
|
||||
int[] stepseq;
|
||||
boolean neg_step_x;
|
||||
String baseprefix;
|
||||
int zoomlevel;
|
||||
String zoomprefix;
|
||||
String fnprefix;
|
||||
String zfnprefix;
|
||||
}
|
||||
|
||||
public void freshenZoomOutFilesByLevel(int zoomlevel) {
|
||||
int cnt = 0;
|
||||
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ")");
|
||||
if(worldtilepath.exists() == false) /* Quit if not found */
|
||||
return;
|
||||
HashMap<String, PrefixData> maptab = new HashMap<String, PrefixData>();
|
||||
/* Build table of file prefixes and step sizes */
|
||||
for(MapType mt : maps) {
|
||||
List<String> pfx = mt.baseZoomFilePrefixes();
|
||||
int stepsize = mt.baseZoomFileStepSize();
|
||||
boolean neg_step_x = false;
|
||||
if(stepsize < 0) {
|
||||
stepsize = -stepsize;
|
||||
neg_step_x = true;
|
||||
}
|
||||
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 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);
|
||||
cnt += processZoomDirectory(sdname, pd);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* Else, classic file layout */
|
||||
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 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
|
||||
return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + ".png";
|
||||
}
|
||||
private int processZoomDirectory(File dir, PrefixData pd) {
|
||||
Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.baseprefix + ")");
|
||||
HashMap<String, ProcessTileRec> toprocess = new HashMap<String, ProcessTileRec>();
|
||||
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);
|
||||
/* Parse filename to predict zoomed out file */
|
||||
fn = fn.substring(0, fn.lastIndexOf('.')); /* Strip off extension */
|
||||
String[] tok = fn.split("_"); /* Split by underscores */
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
boolean parsed = false;
|
||||
if(tok.length >= 2) {
|
||||
try {
|
||||
x = Integer.parseInt(tok[tok.length-2]);
|
||||
y = Integer.parseInt(tok[tok.length-1]);
|
||||
parsed = true;
|
||||
} catch (NumberFormatException nfx) {
|
||||
}
|
||||
}
|
||||
if(!parsed)
|
||||
continue;
|
||||
if(pd.neg_step_x) x = -x;
|
||||
if(x >= 0)
|
||||
x = x - (x % (2*step));
|
||||
else
|
||||
x = x + (x % (2*step));
|
||||
if(pd.neg_step_x) x = -x;
|
||||
if(y >= 0)
|
||||
y = y - (y % (2*step));
|
||||
else
|
||||
y = y + (y % (2*step));
|
||||
/* 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;
|
||||
}
|
||||
String zfpath = zf.getPath();
|
||||
if(!toprocess.containsKey(zfpath)) {
|
||||
ProcessTileRec rec = new ProcessTileRec();
|
||||
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(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(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(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);
|
||||
try {
|
||||
im = ImageIO.read(f);
|
||||
} catch (IOException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
}
|
||||
FileLockManager.releaseReadLock(f);
|
||||
if(im != null) {
|
||||
im.getRGB(0, 0, width, height, argb, 0, width); /* Read data */
|
||||
im.flush();
|
||||
/* Do binlinear scale to 64x64 */
|
||||
Color c1 = new Color();
|
||||
for(int y = 0; y < height; y += 2) {
|
||||
for(int x = 0; x < width; x += 2) {
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int alpha = 0;
|
||||
for(int yy = y; yy < y+2; yy++) {
|
||||
for(int xx = x; xx < x+2; xx++) {
|
||||
c1.setARGB(argb[(yy*width)+xx]);
|
||||
red += c1.getRed();
|
||||
green += c1.getGreen();
|
||||
blue += c1.getBlue();
|
||||
alpha += c1.getAlpha();
|
||||
}
|
||||
}
|
||||
c1.setRGBA(red>>2, green>>2, blue>>2, alpha>>2);
|
||||
argb[(y*width/2) + (x/2)] = c1.getARGB();
|
||||
}
|
||||
}
|
||||
/* blit scaled rendered tile onto zoom-out tile */
|
||||
zIm.setRGB(((i>>1) != 0)?0:width/2, (i & 1) * height/2, width/2, height/2, argb, 0, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
FileLockManager.getWriteLock(zf);
|
||||
try {
|
||||
if(!zf.getParentFile().exists())
|
||||
zf.getParentFile().mkdirs();
|
||||
FileLockManager.imageIOWrite(zIm, "png", zf);
|
||||
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) {
|
||||
Debug.error("Failed to save zoom-out tile (NullPointerException): " + zf.getName(), e);
|
||||
}
|
||||
FileLockManager.releaseWriteLock(zf);
|
||||
KzedMap.freeBufferedImage(kzIm);
|
||||
MapManager.mapman.pushUpdate(this.world, new Client.Tile(zfname));
|
||||
}
|
||||
}
|
||||
|
@ -26,13 +26,15 @@ public class MapManager {
|
||||
public AsynchronousQueue<MapTile> tileQueue;
|
||||
|
||||
private static final int DEFAULT_CHUNKS_PER_TICK = 200;
|
||||
|
||||
private static final int DEFAULT_ZOOMOUT_PERIOD = 60;
|
||||
public List<DynmapWorld> worlds = new ArrayList<DynmapWorld>();
|
||||
public Map<String, DynmapWorld> worldsLookup = new HashMap<String, DynmapWorld>();
|
||||
private BukkitScheduler scheduler;
|
||||
private DynmapPlugin plug_in;
|
||||
private long timeslice_int = 0; /* In milliseconds */
|
||||
private int max_chunk_loads_per_tick = DEFAULT_CHUNKS_PER_TICK;
|
||||
|
||||
private int zoomout_period = DEFAULT_ZOOMOUT_PERIOD; /* Zoom-out tile processing period, in seconds */
|
||||
/* Which fullrenders are active */
|
||||
private HashMap<String, FullWorldRenderState> active_renders = new HashMap<String, FullWorldRenderState>();
|
||||
/* List of MapChunkCache requests to be processed */
|
||||
@ -261,6 +263,17 @@ public class MapManager {
|
||||
}
|
||||
}
|
||||
|
||||
private class DoZoomOutProcessing implements Runnable {
|
||||
public void run() {
|
||||
Debug.debug("DoZoomOutProcessing started");
|
||||
for(DynmapWorld w : worlds) {
|
||||
w.freshenZoomOutFiles();
|
||||
}
|
||||
renderpool.schedule(this, zoomout_period, TimeUnit.SECONDS);
|
||||
Debug.debug("DoZoomOutProcessing finished");
|
||||
}
|
||||
}
|
||||
|
||||
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration) {
|
||||
plug_in = plugin;
|
||||
mapman = this;
|
||||
@ -276,6 +289,10 @@ public class MapManager {
|
||||
timeslice_int = (long)(configuration.getDouble("timesliceinterval", 0.0) * 1000);
|
||||
max_chunk_loads_per_tick = configuration.getInteger("maxchunkspertick", DEFAULT_CHUNKS_PER_TICK);
|
||||
if(max_chunk_loads_per_tick < 5) max_chunk_loads_per_tick = 5;
|
||||
/* Get zoomout processing periond in seconds */
|
||||
zoomout_period = configuration.getInteger("zoomoutperiod", DEFAULT_ZOOMOUT_PERIOD);
|
||||
if(zoomout_period < 5) zoomout_period = 5;
|
||||
|
||||
scheduler = plugin.getServer().getScheduler();
|
||||
|
||||
hashman = new TileHashManager(DynmapPlugin.tilesDirectory, configuration.getBoolean("enabletilehash", true));
|
||||
@ -288,6 +305,7 @@ public class MapManager {
|
||||
|
||||
scheduler.scheduleSyncRepeatingTask(plugin, new CheckWorldTimes(), 5*20, 5*20); /* Check very 5 seconds */
|
||||
scheduler.scheduleSyncRepeatingTask(plugin, new ProcessChunkLoads(), 1, 1); /* Chunk loader task */
|
||||
|
||||
}
|
||||
|
||||
void renderFullWorld(Location l, CommandSender sender) {
|
||||
@ -343,6 +361,8 @@ public class MapManager {
|
||||
dynmapWorld.sendposition = worldConfiguration.getBoolean("sendposition", true);
|
||||
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));
|
||||
@ -422,6 +442,7 @@ public class MapManager {
|
||||
public void startRendering() {
|
||||
tileQueue.start();
|
||||
renderpool = new DynmapScheduledThreadPoolExecutor();
|
||||
renderpool.schedule(new DoZoomOutProcessing(), 60000, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void stopRendering() {
|
||||
|
@ -27,5 +27,12 @@ public abstract class MapType {
|
||||
public boolean isHightestBlockYDataNeeded() { return false; }
|
||||
public boolean isRawBiomeDataNeeded() { return false; }
|
||||
public boolean isBlockTypeDataNeeded() { return true; }
|
||||
|
||||
|
||||
public abstract List<String> baseZoomFilePrefixes();
|
||||
public abstract int baseZoomFileStepSize();
|
||||
/**
|
||||
* Step sequence for creating zoomed file: first index is top-left, second top-right, third bottom-left, forth bottom-right
|
||||
* Values correspond to tile X,Y (0), X+step,Y (1), X,Y+step (2), X+step,Y+step (3)
|
||||
*/
|
||||
public abstract int[] zoomFileStepSequence();
|
||||
}
|
||||
|
@ -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))) {
|
||||
@ -406,6 +406,19 @@ public class FlatMap extends MapType {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public List<String> baseZoomFilePrefixes() {
|
||||
ArrayList<String> s = new ArrayList<String>();
|
||||
s.add(getName() + "_128");
|
||||
if(night_and_day)
|
||||
s.add(getName()+"_day_128");
|
||||
return s;
|
||||
}
|
||||
|
||||
public int baseZoomFileStepSize() { return 1; }
|
||||
|
||||
private static final int[] stepseq = { 1, 3, 0, 2 };
|
||||
|
||||
public int[] zoomFileStepSequence() { return stepseq; }
|
||||
|
||||
public static class FlatMapTile extends MapTile {
|
||||
FlatMap map;
|
||||
@ -427,7 +440,7 @@ public class FlatMap extends MapType {
|
||||
public String getFilename() {
|
||||
if(fname == null) {
|
||||
if(world.bigworld)
|
||||
fname = map.prefix + "/" + ((-(y+1))>>5) + "_" + (x>>5) + "/" + size + "_" + -(y+1) + "_" + x + ".png";
|
||||
fname = map.prefix + "_" + size + "/" + ((-(y+1))>>5) + "_" + (x>>5) + "/" + -(y+1) + "_" + x + ".png";
|
||||
else
|
||||
fname = map.prefix + "_" + size + "_" + -(y+1) + "_" + x + ".png";
|
||||
}
|
||||
@ -437,7 +450,7 @@ public class FlatMap extends MapType {
|
||||
public String getDayFilename() {
|
||||
if(fname_day == null) {
|
||||
if(world.bigworld)
|
||||
fname_day = map.prefix + "_day/" + ((-(y+1))>>5) + "_" + (x>>5) + "/" + size + "_" + -(y+1) + "_" + x + ".png";
|
||||
fname_day = map.prefix + "_day_" + size + "/" + ((-(y+1))>>5) + "_" + (x>>5) + "/" + -(y+1) + "_" + x + ".png";
|
||||
else
|
||||
fname_day = map.prefix + "_day_" + size + "_" + -(y+1) + "_" + x + ".png";
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ public class CaveTileRenderer extends DefaultTileRenderer {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
public boolean isNightAndDayEnabled() { return false; }
|
||||
|
||||
@Override
|
||||
protected void scan(World world, int seq, boolean isnether, final Color result, final Color result_day,
|
||||
MapIterator mapiter) {
|
||||
|
@ -48,6 +48,8 @@ public class DefaultTileRenderer implements MapTileRenderer {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isNightAndDayEnabled() { return night_and_day; }
|
||||
|
||||
public DefaultTileRenderer(ConfigurationNode configuration) {
|
||||
this.configuration = configuration;
|
||||
name = (String) configuration.get("prefix");
|
||||
@ -282,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);
|
||||
@ -311,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;
|
||||
@ -321,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;
|
||||
@ -337,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 {
|
||||
@ -372,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
|
||||
|
@ -326,6 +326,22 @@ public class KzedMap extends MapType {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<String> baseZoomFilePrefixes() {
|
||||
ArrayList<String> s = new ArrayList<String>();
|
||||
for(MapTileRenderer r : renderers) {
|
||||
s.add("z" + r.getName());
|
||||
if(r.isNightAndDayEnabled())
|
||||
s.add("z" + r.getName() + "_day");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
/* Return negative to flag negative X walk */
|
||||
public int baseZoomFileStepSize() { return -zTileWidth; }
|
||||
|
||||
private static final int[] stepseq = { 0, 2, 1, 3 };
|
||||
|
||||
public int[] zoomFileStepSequence() { return stepseq; }
|
||||
|
||||
public String getName() {
|
||||
return "KzedMap";
|
||||
}
|
||||
|
@ -15,4 +15,5 @@ public interface MapTileRenderer {
|
||||
|
||||
boolean isBiomeDataNeeded();
|
||||
boolean isRawBiomeDataNeeded();
|
||||
boolean isNightAndDayEnabled();
|
||||
}
|
||||
|
@ -72,10 +72,7 @@ public class RegionHandler extends FileHandler {
|
||||
/* If not in list, remove it */
|
||||
if(!idlist.contains(id)) {
|
||||
regionData.remove(id);
|
||||
log.info("discard " + id);
|
||||
}
|
||||
else
|
||||
log.info("keep " + id);
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
@ -28,13 +29,25 @@ FlatMapType.prototype = $.extend(new DynMapType(), {
|
||||
var dnprefix = '';
|
||||
if(this.dynmap.map.mapTypes[this.dynmap.map.mapTypeId].nightandday && this.dynmap.serverday)
|
||||
dnprefix = '_day';
|
||||
|
||||
if(this.dynmap.world.bigworld)
|
||||
tileName = this.prefix + dnprefix + '/' + (coord.x >> 5) + '_' + (coord.y >> 5) +
|
||||
'/128_' + coord.x + '_' + coord.y + '.png';
|
||||
else
|
||||
tileName = this.prefix + dnprefix + '_128_' + coord.x + '_' + coord.y + '.png';
|
||||
imgSize = Math.pow(2, 7+zoom);
|
||||
var extrazoom = this.dynmap.world.extrazoomout;
|
||||
if(zoom < extrazoom) {
|
||||
var scale = 1 << (extrazoom-zoom);
|
||||
var zprefix = "zzzzzzzzzzzz".substring(0, extrazoom-zoom);
|
||||
if(this.dynmap.world.bigworld)
|
||||
tileName = this.prefix + dnprefix + '_128/' + ((scale*coord.x) >> 5) + '_' + ((scale*coord.y) >> 5) +
|
||||
'/' + zprefix + "_" + (scale*coord.x) + '_' + (scale*coord.y) + '.png';
|
||||
else
|
||||
tileName = zprefix + this.prefix + dnprefix + '_128_' + (scale*coord.x) + '_' + (scale*coord.y) + '.png';
|
||||
imgSize = 128;
|
||||
}
|
||||
else {
|
||||
if(this.dynmap.world.bigworld)
|
||||
tileName = this.prefix + dnprefix + '_128/' + (coord.x >> 5) + '_' + (coord.y >> 5) +
|
||||
'/' + coord.x + '_' + coord.y + '.png';
|
||||
else
|
||||
tileName = this.prefix + dnprefix + '_128_' + coord.x + '_' + coord.y + '.png';
|
||||
imgSize = Math.pow(2, 7+zoom-extrazoom);
|
||||
}
|
||||
var tile = $('<div/>')
|
||||
.addClass('tile')
|
||||
.css({
|
||||
@ -58,7 +71,15 @@ FlatMapType.prototype = $.extend(new DynMapType(), {
|
||||
},
|
||||
updateTileSize: function(zoom) {
|
||||
var size;
|
||||
size = Math.pow(2, 7+zoom);
|
||||
var extrazoom = this.dynmap.world.extrazoomout;
|
||||
this.projection.extrazoom = extrazoom;
|
||||
this.maxZoom = 3 + extrazoom;
|
||||
if (zoom <= extrazoom) {
|
||||
size = 128;
|
||||
}
|
||||
else {
|
||||
size = Math.pow(2, 7+zoom-extrazoom);
|
||||
}
|
||||
this.tileSize = new google.maps.Size(size, size);
|
||||
}
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
@ -45,25 +47,27 @@ KzedMapType.prototype = $.extend(new DynMapType(), {
|
||||
|
||||
var dnprefix = '';
|
||||
if(this.dynmap.map.mapTypes[this.dynmap.map.mapTypeId].nightandday && this.dynmap.serverday)
|
||||
dnprefix = '_day';
|
||||
|
||||
if (zoom == 0) {
|
||||
dnprefix = '_day';
|
||||
var extrazoom = this.dynmap.world.extrazoomout;
|
||||
if (zoom <= extrazoom) {
|
||||
var zpre = 'zzzzzzzzzzzzzzzz'.substring(0, extrazoom-zoom+1);
|
||||
// Most zoomed out tiles.
|
||||
tileSize = 128;
|
||||
imgSize = tileSize;
|
||||
imgSize = tileSize;
|
||||
var tilescale = 2 << (extrazoom-zoom);
|
||||
if (this.dynmap.world.bigworld) {
|
||||
tileName = 'z' + this.prefix + dnprefix + '/' + ((-coord.x * tileSize*2)>>12) +
|
||||
'_' + ((coord.y * tileSize*2) >> 12) + '/' +
|
||||
(-coord.x * tileSize*2) + '_' + (coord.y * tileSize*2) + '.png';
|
||||
tileName = zpre + this.prefix + dnprefix + '/' + ((-coord.x * tileSize*tilescale)>>12) +
|
||||
'_' + ((coord.y * tileSize*tilescale) >> 12) + '/' +
|
||||
(-coord.x * tileSize*tilescale) + '_' + (coord.y * tileSize*tilescale) + '.png';
|
||||
}
|
||||
else {
|
||||
tileName = 'z' + this.prefix + dnprefix + '_' + (-coord.x * tileSize*2) + '_' + (coord.y * tileSize*2) + '.png';
|
||||
tileName = zpre + this.prefix + dnprefix + '_' + (-coord.x * tileSize*tilescale) + '_' + (coord.y * tileSize*tilescale) + '.png';
|
||||
}
|
||||
} else {
|
||||
// Other zoom levels.
|
||||
tileSize = 128;
|
||||
|
||||
imgSize = Math.pow(2, 6+zoom);
|
||||
imgSize = Math.pow(2, 6+zoom-extrazoom);
|
||||
if(this.dynmap.world.bigworld) {
|
||||
tileName = this.prefix + dnprefix + '/' + ((-coord.x*tileSize) >> 12) + '_' +
|
||||
((coord.y*tileSize)>>12) + '/' +
|
||||
@ -109,10 +113,13 @@ KzedMapType.prototype = $.extend(new DynMapType(), {
|
||||
},
|
||||
updateTileSize: function(zoom) {
|
||||
var size;
|
||||
if (zoom == 0) {
|
||||
var extrazoom = this.dynmap.world.extrazoomout;
|
||||
this.projection.extrazoom = extrazoom;
|
||||
this.maxZoom = 3 + extrazoom;
|
||||
if (zoom <= extrazoom) {
|
||||
size = 128;
|
||||
} else {
|
||||
size = Math.pow(2, 6+zoom);
|
||||
size = Math.pow(2, 6+zoom-extrazoom);
|
||||
}
|
||||
this.tileSize = new google.maps.Size(size, size);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user