diff --git a/src/main/java/org/dynmap/CraftChunkSnapshot.java b/src/main/java/org/dynmap/CraftChunkSnapshot.java index ccc3bdde..a11e8378 100644 --- a/src/main/java/org/dynmap/CraftChunkSnapshot.java +++ b/src/main/java/org/dynmap/CraftChunkSnapshot.java @@ -7,7 +7,7 @@ package org.dynmap; public class CraftChunkSnapshot implements ChunkSnapshot { private final int x, z; private final byte[] buf; /* Flat buffer in uncompressed chunk file format */ - + private final byte[] hmap; /* Highest Y map */ private static final int BLOCKDATA_OFF = 32768; private static final int BLOCKLIGHT_OFF = BLOCKDATA_OFF + 16384; private static final int SKYLIGHT_OFF = BLOCKLIGHT_OFF + 16384; @@ -15,10 +15,11 @@ public class CraftChunkSnapshot implements ChunkSnapshot { /** * Constructor */ - CraftChunkSnapshot(int x, int z, byte[] buf) { + CraftChunkSnapshot(int x, int z, byte[] buf, byte[] hmap) { this.x = x; this.z = z; this.buf = buf; + this.hmap = hmap; } /** @@ -94,13 +95,6 @@ public class CraftChunkSnapshot implements ChunkSnapshot { } public int getHighestBlockYAt(int x, int z) { - int off = x << 11 | z << 7 | 126; - int i; - for(i = 127; (i >= 2); i--, off--) { - if(buf[off] != 0) { - break; - } - } - return i; + return hmap[z << 4 | x] & 255; } } diff --git a/src/main/java/org/dynmap/MapChunkCache.java b/src/main/java/org/dynmap/MapChunkCache.java index b59d954f..636d2f48 100644 --- a/src/main/java/org/dynmap/MapChunkCache.java +++ b/src/main/java/org/dynmap/MapChunkCache.java @@ -1,6 +1,7 @@ package org.dynmap; import java.lang.reflect.Method; +import java.lang.reflect.Field; import java.util.LinkedList; import org.bukkit.World; import org.bukkit.Chunk; @@ -13,6 +14,7 @@ public class MapChunkCache { private World w; private static Method getchunkdata = null; private static Method gethandle = null; + private static Field heightmap = null; private static boolean initialized = false; private int x_min, x_max, z_min, z_max; @@ -26,7 +28,6 @@ public class MapChunkCache { public class MapIterator { public int x, y, z; private ChunkSnapshot snap; - private int x4, z4; MapIterator(int x0, int y0, int z0) { initialize(x0, y0, z0); @@ -40,27 +41,25 @@ public class MapChunkCache { } catch (ArrayIndexOutOfBoundsException aioobx) { snap = EMPTY; } - x4 = x0 & 0xF; - z4 = z0 & 0xF; } public final int getBlockTypeID() { - return snap.getBlockTypeId(x4, y, z4); + return snap.getBlockTypeId(x & 0xF, y, z & 0xF); } public final int getBlockData() { - return snap.getBlockData(x4, y, z4); + return snap.getBlockData(x & 0xF, y, z & 0xF); } public final int getHighestBlockYAt() { - return snap.getHighestBlockYAt(x4, z4); + return snap.getHighestBlockYAt(x & 0xF, z & 0xF); } public final int getBlockSkyLight() { - return snap.getBlockSkyLight(x4, y, z4); + return snap.getBlockSkyLight(x & 0xF, y, z & 0xF); } public final int getBlockEmittedLight() { - return snap.getBlockEmittedLight(x4, y, z4); + return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF); } public final void incrementX() { - x++; x4 = x & 0xF; - if(x4 == 0) { /* Next chunk? */ + x++; + if((x & 0xF) == 0) { /* Next chunk? */ try { snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; } catch (ArrayIndexOutOfBoundsException aioobx) { @@ -69,8 +68,8 @@ public class MapChunkCache { } } public final void decrementX() { - x--; x4 = x & 0xF; - if(x4 == 15) { /* Next chunk? */ + x--; + if((x & 0xF) == 15) { /* Next chunk? */ try { snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; } catch (ArrayIndexOutOfBoundsException aioobx) { @@ -85,8 +84,8 @@ public class MapChunkCache { y--; } public final void incrementZ() { - z++; z4 = z & 0xF; - if(z4 == 0) { /* Next chunk? */ + z++; + if((z & 0xF) == 0) { /* Next chunk? */ try { snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; } catch (ArrayIndexOutOfBoundsException aioobx) { @@ -95,8 +94,8 @@ public class MapChunkCache { } } public final void decrementZ() { - z--; z4 = z & 0xF; - if(z4 == 15) { /* Next chunk? */ + z--; + if((z & 0xF) == 15) { /* Next chunk? */ try { snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; } catch (ArrayIndexOutOfBoundsException aioobx) { @@ -171,10 +170,12 @@ public class MapChunkCache { Class c = Class.forName("net.minecraft.server.Chunk"); getchunkdata = c.getDeclaredMethod("a", new Class[] { byte[].class, int.class, int.class, int.class, int.class, int.class, int.class, int.class }); + heightmap = c.getDeclaredField("h"); c = Class.forName("org.bukkit.craftbukkit.CraftChunk"); gethandle = c.getDeclaredMethod("getHandle", new Class[0]); } catch (ClassNotFoundException cnfx) { } catch (NoSuchMethodException nsmx) { + } catch (NoSuchFieldException nsfx) { } initialized = true; if(gethandle != null) @@ -197,7 +198,10 @@ public class MapChunkCache { Object cc = gethandle.invoke(c); byte[] buf = new byte[32768 + 16384 + 16384 + 16384]; /* Get big enough buffer for whole chunk */ getchunkdata.invoke(cc, buf, 0, 0, 0, 16, 128, 16, 0); - CraftChunkSnapshot ss = new CraftChunkSnapshot(chunk.x, chunk.z, buf); + byte[] h = (byte[])heightmap.get(cc); + byte[] hmap = new byte[256]; + System.arraycopy(h, 0, hmap, 0, 256); + CraftChunkSnapshot ss = new CraftChunkSnapshot(chunk.x, chunk.z, buf, hmap); snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss; } catch (Exception x) { } diff --git a/src/main/java/org/dynmap/flat/FlatMap.java b/src/main/java/org/dynmap/flat/FlatMap.java index f64cd00a..25e52a56 100644 --- a/src/main/java/org/dynmap/flat/FlatMap.java +++ b/src/main/java/org/dynmap/flat/FlatMap.java @@ -32,6 +32,8 @@ public class FlatMap extends MapType { private int maximumHeight = 127; private int ambientlight = 15;; private int shadowscale[] = null; + private boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */ + public FlatMap(ConfigurationNode configuration) { this.configuration = configuration; prefix = (String) configuration.get("prefix"); @@ -61,6 +63,7 @@ public class FlatMap extends MapType { if(o != null) { ambientlight = Integer.parseInt(String.valueOf(o)); } + night_and_day = configuration.getBoolean("night-and-day", false); } @Override @@ -107,8 +110,12 @@ public class FlatMap extends MapType { boolean rendered = false; BufferedImage im = KzedMap.allocateBufferedImage(t.size, t.size); + BufferedImage im_day = null; + if(night_and_day) + im_day = KzedMap.allocateBufferedImage(t.size, t.size); Color rslt = new Color(); - int[] pixel = new int[4]; + int[] pixel = new int[3]; + int[] pixel_day = new int[3]; MapChunkCache.MapIterator mapiter = cache.getIterator(t.x * t.size, 127, t.y * t.size); for (int x = 0; x < t.size; x++) { @@ -160,6 +167,11 @@ public class FlatMap extends MapType { if((shadowscale != null) && (ambientlight < 15)) { if(mapiter.y < 127) mapiter.incrementY(); + if(night_and_day) { /* Use unscaled color for day (no shadows from above) */ + pixel_day[0] = pixel[0]; + pixel_day[1] = pixel[1]; + pixel_day[2] = pixel[2]; + } int light = Math.max(ambientlight, mapiter.getBlockEmittedLight()); pixel[0] = (pixel[0] * shadowscale[light]) >> 8; pixel[1] = (pixel[1] * shadowscale[light]) >> 8; @@ -192,9 +204,19 @@ public class FlatMap extends MapType { pixel[1] += (255-pixel[1]) * scale; pixel[2] += (255-pixel[2]) * scale; } + if(night_and_day) { + pixel_day[0] = pixel[0]; + pixel_day[1] = pixel[1]; + pixel_day[2] = pixel[2]; + } + } rslt.setRGBA(pixel[0], pixel[1], pixel[2], 255); im.setRGB(t.size-y-1, x, rslt.getARGB()); + if(night_and_day) { + rslt.setRGBA(pixel_day[0], pixel_day[1], pixel_day[2], 255); + im_day.setRGB(t.size-y-1, x, rslt.getARGB()); + } rendered = true; } } @@ -208,7 +230,21 @@ public class FlatMap extends MapType { } KzedMap.freeBufferedImage(im); MapManager.mapman.pushUpdate(tile.getWorld(), - new Client.Tile(tile.getFilename())); + new Client.Tile(tile.getFilename())); + if(night_and_day) { + File dayfile = new File(outputFile.getParent(), tile.getDayFilename()); + Debug.debug("saving image " + dayfile.getPath()); + try { + ImageIO.write(im_day, "png", dayfile); + } catch (IOException e) { + Debug.error("Failed to save image: " + dayfile.getPath(), e); + } catch (java.lang.NullPointerException e) { + Debug.error("Failed to save image (NullPointerException): " + dayfile.getPath(), e); + } + KzedMap.freeBufferedImage(im_day); + MapManager.mapman.pushUpdate(tile.getWorld(), + new Client.Tile(tile.getDayFilename())); + } return rendered; }