From 2b2891bd0a5b85de03e7b92ff1d4fc2e94c251aa Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Sun, 9 Jan 2011 01:12:35 +0100 Subject: [PATCH] Readded zoom-tiles. Still needs some work. --- .../java/org/dynmap/debug/NullDebugger.java | 16 + .../dynmap/kzedmap/DefaultTileRenderer.java | 554 +++++++------- src/main/java/org/dynmap/kzedmap/KzedMap.java | 703 +++++++++--------- .../java/org/dynmap/kzedmap/KzedMapTile.java | 292 ++++---- .../org/dynmap/kzedmap/KzedZoomedMapTile.java | 57 ++ .../dynmap/kzedmap/ZoomedTileRenderer.java | 77 ++ web/map.js | 6 +- 7 files changed, 933 insertions(+), 772 deletions(-) create mode 100644 src/main/java/org/dynmap/debug/NullDebugger.java create mode 100644 src/main/java/org/dynmap/kzedmap/KzedZoomedMapTile.java create mode 100644 src/main/java/org/dynmap/kzedmap/ZoomedTileRenderer.java diff --git a/src/main/java/org/dynmap/debug/NullDebugger.java b/src/main/java/org/dynmap/debug/NullDebugger.java new file mode 100644 index 00000000..7d23b8d1 --- /dev/null +++ b/src/main/java/org/dynmap/debug/NullDebugger.java @@ -0,0 +1,16 @@ +package org.dynmap.debug; + +public class NullDebugger implements Debugger { + @Override + public void debug(String message) { + } + + @Override + public void error(String message) { + } + + @Override + public void error(String message, Throwable thrown) { + } + +} diff --git a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java index f7b2b744..ba44f350 100644 --- a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java @@ -1,275 +1,279 @@ -package org.dynmap.kzedmap; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.awt.image.WritableRaster; -import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.imageio.ImageIO; - -import org.bukkit.World; -import org.dynmap.MapManager; -import org.dynmap.MapTile; -import org.dynmap.debug.Debugger; - -public class DefaultTileRenderer implements MapTileRenderer { - private String name; - protected Debugger debugger; - - public String getName() { - return name; - } - - public DefaultTileRenderer(String name, Debugger debugger) { - this.name = name; - this.debugger = debugger; - } - - public void render(KzedMapTile tile, String path) { - World world = tile.getMap().getWorld(); - BufferedImage im = new BufferedImage(KzedMap.tileWidth, KzedMap.tileHeight, BufferedImage.TYPE_INT_RGB); - - WritableRaster r = im.getRaster(); - - int ix = tile.mx; - int iy = tile.my; - int iz = tile.mz; - int jx, jz; - - int x, y; - - /* draw the map */ - for(y=0; y=0; x-=2) { - Color c1 = scan(world, jx, iy, jz, 0); - Color c2 = scan(world, jx, iy, jz, 2); - - r.setPixel(x, y, new int[] { c1.getRed(), c1.getGreen(), c1.getBlue() }); - r.setPixel(x-1, y, new int[] { c2.getRed(), c2.getGreen(), c2.getBlue() }); - - jx++; - jz++; - - } - - y ++; - - jx = ix; - jz = iz - 1; - - for(x=KzedMap.tileWidth-1; x>=0; x-=2) { - Color c1 = scan(world, jx, iy, jz, 2); - jx++; - jz++; - Color c2 = scan(world, jx, iy, jz, 0); - - r.setPixel(x, y, new int[] { c1.getRed(), c1.getGreen(), c1.getBlue() }); - r.setPixel(x-1, y, new int[] { c2.getRed(), c2.getGreen(), c2.getBlue() }); - } - - y ++; - - ix ++; - iz --; - } - - /* save the generated tile */ - saveTile(tile, im, path); - } - - protected Color scan(World world, int x, int y, int z, int seq) - { - for(;;) { - if(y < 0) - return Color.BLUE; - - int id = world.getBlockAt(x, y, z).getTypeID(); - - switch(seq) { - case 0: - x--; - break; - case 1: - y--; - break; - case 2: - z++; - break; - case 3: - y--; - break; - } - - seq = (seq + 1) & 3; - - if(id != 0) { - Color[] colors = KzedMap.colors.get(id); - if(colors != null) { - Color c = colors[seq]; - if(c.getAlpha() > 0) { - /* we found something that isn't transparent! */ - if(c.getAlpha() == 255) { - /* it's opaque - the ray ends here */ - return c; - } - - /* this block is transparent, so recurse */ - Color bg = scan(world, x, y, z, seq); - - int cr = c.getRed(); - int cg = c.getGreen(); - int cb = c.getBlue(); - int ca = c.getAlpha(); - cr *= ca; - cg *= ca; - cb *= ca; - int na = 255 - ca; - - return new Color((bg.getRed() * na + cr) >> 8, (bg.getGreen() * na + cg) >> 8, (bg.getBlue() * na + cb) >> 8); - } - } - } - } - } - - /* save rendered tile, update zoom-out tile */ - public void saveTile(KzedMapTile tile, BufferedImage im, String path) - { - String tilePath = getPath(tile, path); - - debugger.debug("saving tile " + tilePath); - - /* save image */ - try { - File file = new File(tilePath); - ImageIO.write(im, "png", file); - } catch(IOException e) { - debugger.error("Failed to save tile: " + tilePath, e); - } catch(java.lang.NullPointerException e) { - debugger.error("Failed to save tile (NullPointerException): " + tilePath, e); - } - - /* now update zoom-out tile */ - /*BufferedImage zIm = mgr.zoomCache.get(zoomPath); - - - if(zIm == null) { - // zoom-out tile doesn't exist - try to load it from disk - - mgr.debug("Trying to load zoom-out tile: " + zoomPath); - - try { - File file = new File(zoomPath); - zIm = ImageIO.read(file); - } catch(IOException e) { - } - - if(zIm == null) { - mgr.debug("Failed to load zoom-out tile: " + zoomPath); - // create new one - // TODO: we might use existing tiles that we could load - // to fill the zoomed out tile in... - zIm = new BufferedImage(MapManager.tileWidth, MapManager.tileHeight, BufferedImage.TYPE_INT_RGB); - } else { - mgr.debug("Loaded zoom-out tile from " + zoomPath); - } - } else { - mgr.debug("Using zoom-out tile from cache: " + zoomPath); - } - - // update zoom-out tile - - // scaled size - int scw = mgr.tileWidth / 2; - int sch = mgr.tileHeight / 2; - - // origin in zoomed-out tile - int ox = scw; - int oy = 0; - - if(zpx != px) ox = 0; - if(zpy != py) oy = sch; - - // blit scaled rendered tile onto zoom-out tile - WritableRaster zr = zIm.getRaster(); - Graphics2D g2 = zIm.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g2.drawImage(im, ox, oy, scw, sch, null); - - // update zoom-out tile cache - BufferedImage oldIm = mgr.zoomCache.put(zoomPath, zIm); - if(oldIm != null && oldIm != zIm) { - oldIm.flush(); - } - - // save zoom-out tile - try { - File file = new File(zoomPath); - ImageIO.write(zIm, "png", file); - mgr.debug("saved zoom-out tile at " + zoomPath); - - //log.info("Saved tile: " + path); - } catch(IOException e) { - log.log(Level.SEVERE, "Failed to save zoom-out tile: " + zoomPath, e); - } catch(java.lang.NullPointerException e) { - log.log(Level.SEVERE, "Failed to save zoom-out tile (NullPointerException): " + zoomPath, e); - }*/ - } - - public String getPath(KzedMapTile tile, String outputPath) - { - return new File(new File(outputPath), tile.getName() + ".png").getPath(); - } - - /* try to load already generated image */ - /*public BufferedImage loadTile(KzedMapTile tile) - { - try { - String path = getPath(tile); - //log.info("Loading tile from " + path); - File file = new File(path); - BufferedImage im = ImageIO.read(file); - //log.info("OK"); - return im; - } catch(IOException e) { - //log.info("failed: " + e.toString()); - } - - return null; - }*/ - - /* - // generate a path name for this map tile - public String getPath(MapManager mgr) - { - return mgr.tilepath + "t_" + px + "_" + py + ".png"; - } - - // generate a path name for the zoomed-out tile - public String getZoomPath(MapManager mgr) - { - return mgr.tilepath + "zt_" + zpx + "_" + zpy + ".png"; - } - - // generate a path name for this cave map tile - public String getCavePath(MapManager mgr) - { - return mgr.tilepath + "ct_" + px + "_" + py + ".png"; - } - - // generate a path name for the zoomed-out cave tile - public String getZoomCavePath(MapManager mgr) - { - return mgr.tilepath + "czt_" + zpx + "_" + zpy + ".png"; - } - */ -} +package org.dynmap.kzedmap; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.IOException; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.imageio.ImageIO; + +import org.bukkit.World; +import org.dynmap.MapManager; +import org.dynmap.MapTile; +import org.dynmap.debug.Debugger; + +public class DefaultTileRenderer implements MapTileRenderer { + private String name; + protected Debugger debugger; + + public String getName() { + return name; + } + + public DefaultTileRenderer(String name, Debugger debugger) { + this.name = name; + this.debugger = debugger; + } + + public void render(KzedMapTile tile, String path) { + World world = tile.getMap().getWorld(); + BufferedImage im = new BufferedImage(KzedMap.tileWidth, KzedMap.tileHeight, BufferedImage.TYPE_INT_RGB); + + WritableRaster r = im.getRaster(); + + int ix = tile.mx; + int iy = tile.my; + int iz = tile.mz; + int jx, jz; + + int x, y; + + /* draw the map */ + for(y=0; y=0; x-=2) { + Color c1 = scan(world, jx, iy, jz, 0); + Color c2 = scan(world, jx, iy, jz, 2); + + r.setPixel(x, y, new int[] { c1.getRed(), c1.getGreen(), c1.getBlue() }); + r.setPixel(x-1, y, new int[] { c2.getRed(), c2.getGreen(), c2.getBlue() }); + + jx++; + jz++; + + } + + y ++; + + jx = ix; + jz = iz - 1; + + for(x=KzedMap.tileWidth-1; x>=0; x-=2) { + Color c1 = scan(world, jx, iy, jz, 2); + jx++; + jz++; + Color c2 = scan(world, jx, iy, jz, 0); + + r.setPixel(x, y, new int[] { c1.getRed(), c1.getGreen(), c1.getBlue() }); + r.setPixel(x-1, y, new int[] { c2.getRed(), c2.getGreen(), c2.getBlue() }); + } + + y ++; + + ix ++; + iz --; + } + + /* save the generated tile */ + saveTile(tile, im, path); + + ((KzedMap)tile.getMap()).invalidateTile(new KzedZoomedMapTile((KzedMap)tile.getMap(), im, tile)); + } + + protected Color scan(World world, int x, int y, int z, int seq) + { + for(;;) { + if(y < 0) + return Color.BLUE; + + int id = world.getBlockAt(x, y, z).getTypeID(); + + switch(seq) { + case 0: + x--; + break; + case 1: + y--; + break; + case 2: + z++; + break; + case 3: + y--; + break; + } + + seq = (seq + 1) & 3; + + if(id != 0) { + Color[] colors = KzedMap.colors.get(id); + if(colors != null) { + Color c = colors[seq]; + if(c.getAlpha() > 0) { + /* we found something that isn't transparent! */ + if(c.getAlpha() == 255) { + /* it's opaque - the ray ends here */ + return c; + } + + /* this block is transparent, so recurse */ + Color bg = scan(world, x, y, z, seq); + + int cr = c.getRed(); + int cg = c.getGreen(); + int cb = c.getBlue(); + int ca = c.getAlpha(); + cr *= ca; + cg *= ca; + cb *= ca; + int na = 255 - ca; + + return new Color((bg.getRed() * na + cr) >> 8, (bg.getGreen() * na + cg) >> 8, (bg.getBlue() * na + cb) >> 8); + } + } + } + } + } + + /* save rendered tile, update zoom-out tile */ + public void saveTile(KzedMapTile tile, BufferedImage im, String path) + { + String tilePath = getPath(tile, path); + + debugger.debug("saving tile " + tilePath); + + /* save image */ + try { + File file = new File(tilePath); + ImageIO.write(im, "png", file); + } catch(IOException e) { + debugger.error("Failed to save tile: " + tilePath, e); + } catch(java.lang.NullPointerException e) { + debugger.error("Failed to save tile (NullPointerException): " + tilePath, e); + } + + + + /* now update zoom-out tile */ + /*BufferedImage zIm = mgr.zoomCache.get(zoomPath); + + + if(zIm == null) { + // zoom-out tile doesn't exist - try to load it from disk + + mgr.debug("Trying to load zoom-out tile: " + zoomPath); + + try { + File file = new File(zoomPath); + zIm = ImageIO.read(file); + } catch(IOException e) { + } + + if(zIm == null) { + mgr.debug("Failed to load zoom-out tile: " + zoomPath); + // create new one + // TODO: we might use existing tiles that we could load + // to fill the zoomed out tile in... + zIm = new BufferedImage(MapManager.tileWidth, MapManager.tileHeight, BufferedImage.TYPE_INT_RGB); + } else { + mgr.debug("Loaded zoom-out tile from " + zoomPath); + } + } else { + mgr.debug("Using zoom-out tile from cache: " + zoomPath); + } + + // update zoom-out tile + + // scaled size + int scw = mgr.tileWidth / 2; + int sch = mgr.tileHeight / 2; + + // origin in zoomed-out tile + int ox = scw; + int oy = 0; + + if(zpx != px) ox = 0; + if(zpy != py) oy = sch; + + // blit scaled rendered tile onto zoom-out tile + WritableRaster zr = zIm.getRaster(); + Graphics2D g2 = zIm.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2.drawImage(im, ox, oy, scw, sch, null); + + // update zoom-out tile cache + BufferedImage oldIm = mgr.zoomCache.put(zoomPath, zIm); + if(oldIm != null && oldIm != zIm) { + oldIm.flush(); + } + + // save zoom-out tile + try { + File file = new File(zoomPath); + ImageIO.write(zIm, "png", file); + mgr.debug("saved zoom-out tile at " + zoomPath); + + //log.info("Saved tile: " + path); + } catch(IOException e) { + log.log(Level.SEVERE, "Failed to save zoom-out tile: " + zoomPath, e); + } catch(java.lang.NullPointerException e) { + log.log(Level.SEVERE, "Failed to save zoom-out tile (NullPointerException): " + zoomPath, e); + }*/ + } + + public String getPath(KzedMapTile tile, String outputPath) + { + return new File(new File(outputPath), tile.getName() + ".png").getPath(); + } + + /* try to load already generated image */ + /*public BufferedImage loadTile(KzedMapTile tile) + { + try { + String path = getPath(tile); + //log.info("Loading tile from " + path); + File file = new File(path); + BufferedImage im = ImageIO.read(file); + //log.info("OK"); + return im; + } catch(IOException e) { + //log.info("failed: " + e.toString()); + } + + return null; + }*/ + + /* + // generate a path name for this map tile + public String getPath(MapManager mgr) + { + return mgr.tilepath + "t_" + px + "_" + py + ".png"; + } + + // generate a path name for the zoomed-out tile + public String getZoomPath(MapManager mgr) + { + return mgr.tilepath + "zt_" + zpx + "_" + zpy + ".png"; + } + + // generate a path name for this cave map tile + public String getCavePath(MapManager mgr) + { + return mgr.tilepath + "ct_" + px + "_" + py + ".png"; + } + + // generate a path name for the zoomed-out cave tile + public String getZoomCavePath(MapManager mgr) + { + return mgr.tilepath + "czt_" + zpx + "_" + zpy + ".png"; + } + */ +} diff --git a/src/main/java/org/dynmap/kzedmap/KzedMap.java b/src/main/java/org/dynmap/kzedmap/KzedMap.java index 494aa1ce..3124f54b 100644 --- a/src/main/java/org/dynmap/kzedmap/KzedMap.java +++ b/src/main/java/org/dynmap/kzedmap/KzedMap.java @@ -1,349 +1,354 @@ -package org.dynmap.kzedmap; - -import java.awt.Color; -import java.io.File; -import java.util.HashMap; -import java.util.Scanner; -import java.util.logging.Level; - -import org.bukkit.Location; -import org.bukkit.World; -import org.dynmap.Map; -import org.dynmap.MapManager; -import org.dynmap.MapTile; -import org.dynmap.StaleQueue; -import org.dynmap.debug.Debugger; - -public class KzedMap extends Map { - /* dimensions of a map tile */ - public static final int tileWidth = 128; - public static final int tileHeight = 128; - - /* (logical!) dimensions of a zoomed out map tile - * must be twice the size of the normal tile */ - public static final int zTileWidth = 256; - public static final int zTileHeight = 256; - - /* map x, y, z for projection origin */ - public static final int anchorx = 0; - public static final int anchory = 127; - public static final int anchorz = 0; - - public static java.util.Map colors; - MapTileRenderer[] renderers; - - public KzedMap(MapManager manager, World world, Debugger debugger) { - super(manager, world, debugger); - if (colors == null) - colors = loadColorSet("colors.txt"); - renderers = new MapTileRenderer[] { - new DefaultTileRenderer("t", debugger), - new CaveTileRenderer("ct", debugger) - }; - } - - @Override - public void touch(Location l) { - int x = l.getBlockX(); - int y = l.getBlockY(); - int z = l.getBlockZ(); - - int dx = x - anchorx; - int dy = y - anchory; - int dz = z - anchorz; - int px = dx + dz; - int py = dx - dz - dy; - - int tx = tilex(px); - int ty = tiley(py); - - invalidateTile(tx, ty); - - boolean ledge = tilex(px - 4) != tx; - boolean tedge = tiley(py - 4) != ty; - boolean redge = tilex(px + 4) != tx; - boolean bedge = tiley(py + 4) != ty; - - if(ledge) invalidateTile(tx - tileWidth, ty); - if(redge) invalidateTile(tx + tileWidth, ty); - if(tedge) invalidateTile(tx, ty - tileHeight); - if(bedge) invalidateTile(tx, ty + tileHeight); - - if(ledge && tedge) invalidateTile(tx - tileWidth, ty - tileHeight); - if(ledge && bedge) invalidateTile(tx - tileWidth, ty + tileHeight); - if(redge && tedge) invalidateTile(tx + tileWidth, ty - tileHeight); - if(redge && bedge) invalidateTile(tx + tileWidth, ty + tileHeight); - } - - public void invalidateTile(int px, int py) { - for(MapTileRenderer renderer : renderers) { - invalidateTile(new KzedMapTile(this, renderer, px, py)); - } - } - - @Override - public void render(MapTile tile) { - KzedMapTile t = (KzedMapTile)tile; - t.renderer.render(t, getMapManager().tilepath); - } - - /* tile X for position x */ - static int tilex(int x) - { - if(x < 0) - return x - (tileWidth + (x % tileWidth)); - else - return x - (x % tileWidth); - } - - /* tile Y for position y */ - static int tiley(int y) - { - if(y < 0) - return y - (tileHeight + (y % tileHeight)); - else - return y - (y % tileHeight); - } - - /* zoomed-out tile X for tile position x */ - static int ztilex(int x) - { - if(x < 0) - return x + x % zTileWidth; - else - return x - (x % zTileWidth); - } - - /* zoomed-out tile Y for tile position y */ - static int ztiley(int y) - { - if(y < 0) - return y + y % zTileHeight; - //return y - (zTileHeight + (y % zTileHeight)); - else - return y - (y % zTileHeight); - } - - /* - // regenerate the entire map, starting at position - public void regenerate(int x, int y, int z) - { - int dx = x - anchorx; - int dy = y - anchory; - int dz = z - anchorz; - int px = dx + dz; - int py = dx - dz - dy; - - int tx = tilex(px); - int ty = tiley(py); - - MapTile first = getTileByPosition(tx, ty); - - Vector open = new Vector(); - open.add(first); - - while(open.size() > 0) { - MapTile t = open.remove(open.size() - 1); - if(t.stale) continue; - int h = world.getHighestBlockYAt(t.mx, t.mz); - - log.info("walking: " + t.mx + ", " + t.mz + ", h = " + h); - if(h < 1) - continue; - - pushStaleTile(t); - - open.add(getTileByPosition(t.px + tileWidth, t.py)); - open.add(getTileByPosition(t.px - tileWidth, t.py)); - open.add(getTileByPosition(t.px, t.py + tileHeight)); - open.add(getTileByPosition(t.px, t.py - tileHeight)); - } - } - - // regenerate all zoom tiles, starting at position - public void regenerateZoom(int x, int y, int z) - { - int dx = x - anchorx; - int dy = y - anchory; - int dz = z - anchorz; - int px = dx + dz; - int py = dx - dz - dy; - - int fzpx = ztilex(tilex(px)); - int fzpy = ztiley(tiley(py)); - - class Pair implements Comparator { - public int x; - public int y; - public Pair(int x, int y) - { - this.x = x; - this.y = y; - } - - public int hashCode() - { - return (x << 16) ^ y; - } - - public boolean equals(Object o) - { - Pair p = (Pair) o; - return x == p.x && y == p.y; - } - - public int compare(Object o1, Object o2) - { - Pair p1 = (Pair) o1; - Pair p2 = (Pair) o2; - if(p1.x < p1.x) return -1; - if(p1.x > p1.x) return 1; - if(p1.y < p1.y) return -1; - if(p1.y > p1.y) return 1; - return 0; - } - } - - HashSet visited = new HashSet(); - Vector open = new Vector(); - - Pair fp = new Pair(fzpx, fzpy); - open.add(fp); - visited.add(fp); - - while(open.size() > 0) { - Pair p = open.remove(open.size() - 1); - - int zpx = p.x; - int zpy = p.y; - - log.info("Regenerating zoom tile " + zpx + "," + zpy); - - int g = regenZoomTile(zpx, zpy); - - if(g > 0) { - Pair[] np = new Pair[4]; - np[0] = new Pair(zpx-zTileWidth, zpy); - np[1] = new Pair(zpx+zTileWidth, zpy); - np[2] = new Pair(zpx, zpy-zTileHeight); - np[3] = new Pair(zpx, zpy+zTileHeight); - - for(int i=0; i<4; i++) { - if(!visited.contains(np[i])) { - visited.add(np[i]); - open.add(np[i]); - } - } - } - } - } - - // regenerate zoom-out tile - // returns number of valid subtiles - public int regenZoomTile(int zpx, int zpy) - { - int px1 = zpx + tileWidth; - int py1 = zpy; - int px2 = zpx; - int py2 = py1 + tileHeight; - - MapTile t1 = getTileByPosition(px1, py1); - MapTile t2 = getTileByPosition(px2, py1); - MapTile t3 = getTileByPosition(px1, py2); - MapTile t4 = getTileByPosition(px2, py2); - - BufferedImage im1 = t1.loadTile(this); - BufferedImage im2 = t2.loadTile(this); - BufferedImage im3 = t3.loadTile(this); - BufferedImage im4 = t4.loadTile(this); - - BufferedImage zIm = new BufferedImage(MapManager.tileWidth, MapManager.tileHeight, BufferedImage.TYPE_INT_RGB); - WritableRaster zr = zIm.getRaster(); - Graphics2D g2 = zIm.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - int scw = tileWidth / 2; - int sch = tileHeight / 2; - - int good = 0; - - if(im1 != null) { - g2.drawImage(im1, 0, 0, scw, sch, null); - good ++; - } - - if(im2 != null) { - g2.drawImage(im2, scw, 0, scw, sch, null); - good ++; - } - - if(im3 != null) { - g2.drawImage(im3, 0, sch, scw, sch, null); - good ++; - } - - if(im4 != null) { - g2.drawImage(im4, scw, sch, scw, sch, null); - good ++; - } - - if(good == 0) { - return 0; - } - - String zPath = t1.getZoomPath(this); - // save zoom-out tile - try { - File file = new File(zPath); - ImageIO.write(zIm, "png", file); - log.info("regenZoomTile saved zoom-out tile at " + zPath); - } catch(IOException e) { - log.log(Level.SEVERE, "Failed to save zoom-out tile: " + zPath, e); - } catch(java.lang.NullPointerException e) { - log.log(Level.SEVERE, "Failed to save zoom-out tile (NullPointerException): " + zPath, e); - } - - return good; - } - */ - - public static java.util.Map loadColorSet(String colorsetpath) { - java.util.Map colors = new HashMap(); - - /* load colorset */ - File cfile = new File(colorsetpath); - - try { - Scanner scanner = new Scanner(cfile); - int nc = 0; - while(scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (line.startsWith("#") || line.equals("")) { - continue; - } - - String[] split = line.split("\t"); - if (split.length < 17) { - continue; - } - - Integer id = new Integer(split[0]); - - Color[] c = new Color[4]; - - /* store colors by raycast sequence number */ - c[0] = new Color(Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); - c[3] = new Color(Integer.parseInt(split[5]), Integer.parseInt(split[6]), Integer.parseInt(split[7]), Integer.parseInt(split[8])); - c[1] = new Color(Integer.parseInt(split[9]), Integer.parseInt(split[10]), Integer.parseInt(split[11]), Integer.parseInt(split[12])); - c[2] = new Color(Integer.parseInt(split[13]), Integer.parseInt(split[14]), Integer.parseInt(split[15]), Integer.parseInt(split[16])); - - colors.put(id, c); - nc += 1; - } - scanner.close(); - } catch(Exception e) { - return null; - } - return colors; - } -} +package org.dynmap.kzedmap; + +import java.awt.Color; +import java.io.File; +import java.util.HashMap; +import java.util.Scanner; +import java.util.logging.Level; + +import org.bukkit.Location; +import org.bukkit.World; +import org.dynmap.Map; +import org.dynmap.MapManager; +import org.dynmap.MapTile; +import org.dynmap.StaleQueue; +import org.dynmap.debug.Debugger; + +public class KzedMap extends Map { + /* dimensions of a map tile */ + public static final int tileWidth = 128; + public static final int tileHeight = 128; + + /* (logical!) dimensions of a zoomed out map tile + * must be twice the size of the normal tile */ + public static final int zTileWidth = 256; + public static final int zTileHeight = 256; + + /* map x, y, z for projection origin */ + public static final int anchorx = 0; + public static final int anchory = 127; + public static final int anchorz = 0; + + public static java.util.Map colors; + MapTileRenderer[] renderers; + ZoomedTileRenderer zoomrenderer; + + public KzedMap(MapManager manager, World world, Debugger debugger) { + super(manager, world, debugger); + if (colors == null) + colors = loadColorSet("colors.txt"); + renderers = new MapTileRenderer[] { + new DefaultTileRenderer("t", debugger), + new CaveTileRenderer("ct", debugger), + }; + zoomrenderer = new ZoomedTileRenderer(debugger); + } + + @Override + public void touch(Location l) { + int x = l.getBlockX(); + int y = l.getBlockY(); + int z = l.getBlockZ(); + + int dx = x - anchorx; + int dy = y - anchory; + int dz = z - anchorz; + int px = dx + dz; + int py = dx - dz - dy; + + int tx = tilex(px); + int ty = tiley(py); + + invalidateTile(tx, ty); + + boolean ledge = tilex(px - 4) != tx; + boolean tedge = tiley(py - 4) != ty; + boolean redge = tilex(px + 4) != tx; + boolean bedge = tiley(py + 4) != ty; + + if(ledge) invalidateTile(tx - tileWidth, ty); + if(redge) invalidateTile(tx + tileWidth, ty); + if(tedge) invalidateTile(tx, ty - tileHeight); + if(bedge) invalidateTile(tx, ty + tileHeight); + + if(ledge && tedge) invalidateTile(tx - tileWidth, ty - tileHeight); + if(ledge && bedge) invalidateTile(tx - tileWidth, ty + tileHeight); + if(redge && tedge) invalidateTile(tx + tileWidth, ty - tileHeight); + if(redge && bedge) invalidateTile(tx + tileWidth, ty + tileHeight); + } + + public void invalidateTile(int px, int py) { + for(MapTileRenderer renderer : renderers) { + invalidateTile(new KzedMapTile(this, renderer, px, py)); + } + } + + @Override + public void render(MapTile tile) { + if (tile instanceof KzedZoomedMapTile) { + zoomrenderer.render((KzedZoomedMapTile)tile, getMapManager().tilepath); + } else if (tile instanceof KzedMapTile) { + ((KzedMapTile)tile).renderer.render((KzedMapTile)tile, getMapManager().tilepath); + } + } + + /* tile X for position x */ + static int tilex(int x) + { + if(x < 0) + return x - (tileWidth + (x % tileWidth)); + else + return x - (x % tileWidth); + } + + /* tile Y for position y */ + static int tiley(int y) + { + if(y < 0) + return y - (tileHeight + (y % tileHeight)); + else + return y - (y % tileHeight); + } + + /* zoomed-out tile X for tile position x */ + static int ztilex(int x) + { + if(x < 0) + return x + x % zTileWidth; + else + return x - (x % zTileWidth); + } + + /* zoomed-out tile Y for tile position y */ + static int ztiley(int y) + { + if(y < 0) + return y + y % zTileHeight; + //return y - (zTileHeight + (y % zTileHeight)); + else + return y - (y % zTileHeight); + } + + /* + // regenerate the entire map, starting at position + public void regenerate(int x, int y, int z) + { + int dx = x - anchorx; + int dy = y - anchory; + int dz = z - anchorz; + int px = dx + dz; + int py = dx - dz - dy; + + int tx = tilex(px); + int ty = tiley(py); + + MapTile first = getTileByPosition(tx, ty); + + Vector open = new Vector(); + open.add(first); + + while(open.size() > 0) { + MapTile t = open.remove(open.size() - 1); + if(t.stale) continue; + int h = world.getHighestBlockYAt(t.mx, t.mz); + + log.info("walking: " + t.mx + ", " + t.mz + ", h = " + h); + if(h < 1) + continue; + + pushStaleTile(t); + + open.add(getTileByPosition(t.px + tileWidth, t.py)); + open.add(getTileByPosition(t.px - tileWidth, t.py)); + open.add(getTileByPosition(t.px, t.py + tileHeight)); + open.add(getTileByPosition(t.px, t.py - tileHeight)); + } + } + + // regenerate all zoom tiles, starting at position + public void regenerateZoom(int x, int y, int z) + { + int dx = x - anchorx; + int dy = y - anchory; + int dz = z - anchorz; + int px = dx + dz; + int py = dx - dz - dy; + + int fzpx = ztilex(tilex(px)); + int fzpy = ztiley(tiley(py)); + + class Pair implements Comparator { + public int x; + public int y; + public Pair(int x, int y) + { + this.x = x; + this.y = y; + } + + public int hashCode() + { + return (x << 16) ^ y; + } + + public boolean equals(Object o) + { + Pair p = (Pair) o; + return x == p.x && y == p.y; + } + + public int compare(Object o1, Object o2) + { + Pair p1 = (Pair) o1; + Pair p2 = (Pair) o2; + if(p1.x < p1.x) return -1; + if(p1.x > p1.x) return 1; + if(p1.y < p1.y) return -1; + if(p1.y > p1.y) return 1; + return 0; + } + } + + HashSet visited = new HashSet(); + Vector open = new Vector(); + + Pair fp = new Pair(fzpx, fzpy); + open.add(fp); + visited.add(fp); + + while(open.size() > 0) { + Pair p = open.remove(open.size() - 1); + + int zpx = p.x; + int zpy = p.y; + + log.info("Regenerating zoom tile " + zpx + "," + zpy); + + int g = regenZoomTile(zpx, zpy); + + if(g > 0) { + Pair[] np = new Pair[4]; + np[0] = new Pair(zpx-zTileWidth, zpy); + np[1] = new Pair(zpx+zTileWidth, zpy); + np[2] = new Pair(zpx, zpy-zTileHeight); + np[3] = new Pair(zpx, zpy+zTileHeight); + + for(int i=0; i<4; i++) { + if(!visited.contains(np[i])) { + visited.add(np[i]); + open.add(np[i]); + } + } + } + } + } + + // regenerate zoom-out tile + // returns number of valid subtiles + public int regenZoomTile(int zpx, int zpy) + { + int px1 = zpx + tileWidth; + int py1 = zpy; + int px2 = zpx; + int py2 = py1 + tileHeight; + + MapTile t1 = getTileByPosition(px1, py1); + MapTile t2 = getTileByPosition(px2, py1); + MapTile t3 = getTileByPosition(px1, py2); + MapTile t4 = getTileByPosition(px2, py2); + + BufferedImage im1 = t1.loadTile(this); + BufferedImage im2 = t2.loadTile(this); + BufferedImage im3 = t3.loadTile(this); + BufferedImage im4 = t4.loadTile(this); + + BufferedImage zIm = new BufferedImage(MapManager.tileWidth, MapManager.tileHeight, BufferedImage.TYPE_INT_RGB); + WritableRaster zr = zIm.getRaster(); + Graphics2D g2 = zIm.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + int scw = tileWidth / 2; + int sch = tileHeight / 2; + + int good = 0; + + if(im1 != null) { + g2.drawImage(im1, 0, 0, scw, sch, null); + good ++; + } + + if(im2 != null) { + g2.drawImage(im2, scw, 0, scw, sch, null); + good ++; + } + + if(im3 != null) { + g2.drawImage(im3, 0, sch, scw, sch, null); + good ++; + } + + if(im4 != null) { + g2.drawImage(im4, scw, sch, scw, sch, null); + good ++; + } + + if(good == 0) { + return 0; + } + + String zPath = t1.getZoomPath(this); + // save zoom-out tile + try { + File file = new File(zPath); + ImageIO.write(zIm, "png", file); + log.info("regenZoomTile saved zoom-out tile at " + zPath); + } catch(IOException e) { + log.log(Level.SEVERE, "Failed to save zoom-out tile: " + zPath, e); + } catch(java.lang.NullPointerException e) { + log.log(Level.SEVERE, "Failed to save zoom-out tile (NullPointerException): " + zPath, e); + } + + return good; + } + */ + + public static java.util.Map loadColorSet(String colorsetpath) { + java.util.Map colors = new HashMap(); + + /* load colorset */ + File cfile = new File(colorsetpath); + + try { + Scanner scanner = new Scanner(cfile); + int nc = 0; + while(scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith("#") || line.equals("")) { + continue; + } + + String[] split = line.split("\t"); + if (split.length < 17) { + continue; + } + + Integer id = new Integer(split[0]); + + Color[] c = new Color[4]; + + /* store colors by raycast sequence number */ + c[0] = new Color(Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4])); + c[3] = new Color(Integer.parseInt(split[5]), Integer.parseInt(split[6]), Integer.parseInt(split[7]), Integer.parseInt(split[8])); + c[1] = new Color(Integer.parseInt(split[9]), Integer.parseInt(split[10]), Integer.parseInt(split[11]), Integer.parseInt(split[12])); + c[2] = new Color(Integer.parseInt(split[13]), Integer.parseInt(split[14]), Integer.parseInt(split[15]), Integer.parseInt(split[16])); + + colors.put(id, c); + nc += 1; + } + scanner.close(); + } catch(Exception e) { + return null; + } + return colors; + } +} diff --git a/src/main/java/org/dynmap/kzedmap/KzedMapTile.java b/src/main/java/org/dynmap/kzedmap/KzedMapTile.java index ce0c09b8..9620a071 100644 --- a/src/main/java/org/dynmap/kzedmap/KzedMapTile.java +++ b/src/main/java/org/dynmap/kzedmap/KzedMapTile.java @@ -1,146 +1,146 @@ -package org.dynmap.kzedmap; - -import java.util.logging.Logger; -import java.util.logging.Level; - -import java.awt.*; -import java.awt.image.*; - -import java.io.File; -import java.io.IOException; - -import javax.imageio.ImageIO; - -import org.bukkit.Player; -import org.bukkit.World; -import org.bukkit.Server; -import org.dynmap.MapTile; - -public class KzedMapTile extends MapTile { - protected static final Logger log = Logger.getLogger("Minecraft"); - - public KzedMap map; - - public MapTileRenderer renderer; - - /* projection position */ - public int px, py; - - /* minecraft space origin */ - public int mx, my, mz; - - /* create new MapTile */ - public KzedMapTile(KzedMap map, MapTileRenderer renderer, int px, int py) { - super(map); - this.renderer = renderer; - this.px = px; - this.py = py; - - mx = KzedMap.anchorx + px / 2 + py / 2; - my = KzedMap.anchory; - mz = KzedMap.anchorz + px / 2 - py / 2; - } - - @Override - public String getName() { - return renderer.getName() + "_" + px + "_" + py; - } - - /* try to get the server to load the relevant chunks */ - public void loadChunks() - { - int x1 = mx - 64; - int x2 = mx + KzedMap.tileWidth / 2 + KzedMap.tileHeight / 2; - - int z1 = mz - KzedMap.tileHeight / 2; - int z2 = mz + KzedMap.tileWidth / 2 + 64; - - int x, z; - - for(x=x1; x 0) { var tilename = pfx + "t_" + (- coord.x * config.tileWidth) + '_' + coord.y * config.tileHeight; } else { - var tilename = pfx + "zt_" + (- coord.x * config.tileWidth * 2) + '_' + coord.y * config.tileHeight * 2; + var tilename = pfx + "zt_" + (- coord.x * config.tileWidth * 2) + '_' + (coord.y * config.tileHeight * 2); } tileDict[tilename] = img;