mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-12-26 18:47:40 +01:00
Merge pull request #170 from mikeprimm/master
Use height map from Chunk - better performance on flat map
This commit is contained in:
commit
340da29e18
@ -7,7 +7,7 @@ package org.dynmap;
|
|||||||
public class CraftChunkSnapshot implements ChunkSnapshot {
|
public class CraftChunkSnapshot implements ChunkSnapshot {
|
||||||
private final int x, z;
|
private final int x, z;
|
||||||
private final byte[] buf; /* Flat buffer in uncompressed chunk file format */
|
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 BLOCKDATA_OFF = 32768;
|
||||||
private static final int BLOCKLIGHT_OFF = BLOCKDATA_OFF + 16384;
|
private static final int BLOCKLIGHT_OFF = BLOCKDATA_OFF + 16384;
|
||||||
private static final int SKYLIGHT_OFF = BLOCKLIGHT_OFF + 16384;
|
private static final int SKYLIGHT_OFF = BLOCKLIGHT_OFF + 16384;
|
||||||
@ -15,10 +15,11 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
CraftChunkSnapshot(int x, int z, byte[] buf) {
|
CraftChunkSnapshot(int x, int z, byte[] buf, byte[] hmap) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
this.buf = buf;
|
this.buf = buf;
|
||||||
|
this.hmap = hmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,13 +95,6 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getHighestBlockYAt(int x, int z) {
|
public int getHighestBlockYAt(int x, int z) {
|
||||||
int off = x << 11 | z << 7 | 126;
|
return hmap[z << 4 | x] & 255;
|
||||||
int i;
|
|
||||||
for(i = 127; (i >= 2); i--, off--) {
|
|
||||||
if(buf[off] != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.dynmap;
|
package org.dynmap;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
@ -13,6 +14,7 @@ public class MapChunkCache {
|
|||||||
private World w;
|
private World w;
|
||||||
private static Method getchunkdata = null;
|
private static Method getchunkdata = null;
|
||||||
private static Method gethandle = null;
|
private static Method gethandle = null;
|
||||||
|
private static Field heightmap = null;
|
||||||
private static boolean initialized = false;
|
private static boolean initialized = false;
|
||||||
|
|
||||||
private int x_min, x_max, z_min, z_max;
|
private int x_min, x_max, z_min, z_max;
|
||||||
@ -26,7 +28,6 @@ public class MapChunkCache {
|
|||||||
public class MapIterator {
|
public class MapIterator {
|
||||||
public int x, y, z;
|
public int x, y, z;
|
||||||
private ChunkSnapshot snap;
|
private ChunkSnapshot snap;
|
||||||
private int x4, z4;
|
|
||||||
|
|
||||||
MapIterator(int x0, int y0, int z0) {
|
MapIterator(int x0, int y0, int z0) {
|
||||||
initialize(x0, y0, z0);
|
initialize(x0, y0, z0);
|
||||||
@ -40,27 +41,25 @@ public class MapChunkCache {
|
|||||||
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
||||||
snap = EMPTY;
|
snap = EMPTY;
|
||||||
}
|
}
|
||||||
x4 = x0 & 0xF;
|
|
||||||
z4 = z0 & 0xF;
|
|
||||||
}
|
}
|
||||||
public final int getBlockTypeID() {
|
public final int getBlockTypeID() {
|
||||||
return snap.getBlockTypeId(x4, y, z4);
|
return snap.getBlockTypeId(x & 0xF, y, z & 0xF);
|
||||||
}
|
}
|
||||||
public final int getBlockData() {
|
public final int getBlockData() {
|
||||||
return snap.getBlockData(x4, y, z4);
|
return snap.getBlockData(x & 0xF, y, z & 0xF);
|
||||||
}
|
}
|
||||||
public final int getHighestBlockYAt() {
|
public final int getHighestBlockYAt() {
|
||||||
return snap.getHighestBlockYAt(x4, z4);
|
return snap.getHighestBlockYAt(x & 0xF, z & 0xF);
|
||||||
}
|
}
|
||||||
public final int getBlockSkyLight() {
|
public final int getBlockSkyLight() {
|
||||||
return snap.getBlockSkyLight(x4, y, z4);
|
return snap.getBlockSkyLight(x & 0xF, y, z & 0xF);
|
||||||
}
|
}
|
||||||
public final int getBlockEmittedLight() {
|
public final int getBlockEmittedLight() {
|
||||||
return snap.getBlockEmittedLight(x4, y, z4);
|
return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF);
|
||||||
}
|
}
|
||||||
public final void incrementX() {
|
public final void incrementX() {
|
||||||
x++; x4 = x & 0xF;
|
x++;
|
||||||
if(x4 == 0) { /* Next chunk? */
|
if((x & 0xF) == 0) { /* Next chunk? */
|
||||||
try {
|
try {
|
||||||
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
||||||
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
||||||
@ -69,8 +68,8 @@ public class MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public final void decrementX() {
|
public final void decrementX() {
|
||||||
x--; x4 = x & 0xF;
|
x--;
|
||||||
if(x4 == 15) { /* Next chunk? */
|
if((x & 0xF) == 15) { /* Next chunk? */
|
||||||
try {
|
try {
|
||||||
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
||||||
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
||||||
@ -85,8 +84,8 @@ public class MapChunkCache {
|
|||||||
y--;
|
y--;
|
||||||
}
|
}
|
||||||
public final void incrementZ() {
|
public final void incrementZ() {
|
||||||
z++; z4 = z & 0xF;
|
z++;
|
||||||
if(z4 == 0) { /* Next chunk? */
|
if((z & 0xF) == 0) { /* Next chunk? */
|
||||||
try {
|
try {
|
||||||
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
||||||
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
||||||
@ -95,8 +94,8 @@ public class MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public final void decrementZ() {
|
public final void decrementZ() {
|
||||||
z--; z4 = z & 0xF;
|
z--;
|
||||||
if(z4 == 15) { /* Next chunk? */
|
if((z & 0xF) == 15) { /* Next chunk? */
|
||||||
try {
|
try {
|
||||||
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
|
||||||
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
} catch (ArrayIndexOutOfBoundsException aioobx) {
|
||||||
@ -171,10 +170,12 @@ public class MapChunkCache {
|
|||||||
Class c = Class.forName("net.minecraft.server.Chunk");
|
Class c = Class.forName("net.minecraft.server.Chunk");
|
||||||
getchunkdata = c.getDeclaredMethod("a", new Class[] { byte[].class, int.class,
|
getchunkdata = c.getDeclaredMethod("a", new Class[] { byte[].class, int.class,
|
||||||
int.class, int.class, int.class, int.class, int.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");
|
c = Class.forName("org.bukkit.craftbukkit.CraftChunk");
|
||||||
gethandle = c.getDeclaredMethod("getHandle", new Class[0]);
|
gethandle = c.getDeclaredMethod("getHandle", new Class[0]);
|
||||||
} catch (ClassNotFoundException cnfx) {
|
} catch (ClassNotFoundException cnfx) {
|
||||||
} catch (NoSuchMethodException nsmx) {
|
} catch (NoSuchMethodException nsmx) {
|
||||||
|
} catch (NoSuchFieldException nsfx) {
|
||||||
}
|
}
|
||||||
initialized = true;
|
initialized = true;
|
||||||
if(gethandle != null)
|
if(gethandle != null)
|
||||||
@ -197,7 +198,10 @@ public class MapChunkCache {
|
|||||||
Object cc = gethandle.invoke(c);
|
Object cc = gethandle.invoke(c);
|
||||||
byte[] buf = new byte[32768 + 16384 + 16384 + 16384]; /* Get big enough buffer for whole chunk */
|
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);
|
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;
|
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ public class FlatMap extends MapType {
|
|||||||
private int maximumHeight = 127;
|
private int maximumHeight = 127;
|
||||||
private int ambientlight = 15;;
|
private int ambientlight = 15;;
|
||||||
private int shadowscale[] = null;
|
private int shadowscale[] = null;
|
||||||
|
private boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */
|
||||||
|
|
||||||
public FlatMap(ConfigurationNode configuration) {
|
public FlatMap(ConfigurationNode configuration) {
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
prefix = (String) configuration.get("prefix");
|
prefix = (String) configuration.get("prefix");
|
||||||
@ -61,6 +63,7 @@ public class FlatMap extends MapType {
|
|||||||
if(o != null) {
|
if(o != null) {
|
||||||
ambientlight = Integer.parseInt(String.valueOf(o));
|
ambientlight = Integer.parseInt(String.valueOf(o));
|
||||||
}
|
}
|
||||||
|
night_and_day = configuration.getBoolean("night-and-day", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -107,8 +110,12 @@ public class FlatMap extends MapType {
|
|||||||
|
|
||||||
boolean rendered = false;
|
boolean rendered = false;
|
||||||
BufferedImage im = KzedMap.allocateBufferedImage(t.size, t.size);
|
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();
|
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);
|
MapChunkCache.MapIterator mapiter = cache.getIterator(t.x * t.size, 127, t.y * t.size);
|
||||||
for (int x = 0; x < t.size; x++) {
|
for (int x = 0; x < t.size; x++) {
|
||||||
@ -160,6 +167,11 @@ public class FlatMap extends MapType {
|
|||||||
if((shadowscale != null) && (ambientlight < 15)) {
|
if((shadowscale != null) && (ambientlight < 15)) {
|
||||||
if(mapiter.y < 127)
|
if(mapiter.y < 127)
|
||||||
mapiter.incrementY();
|
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());
|
int light = Math.max(ambientlight, mapiter.getBlockEmittedLight());
|
||||||
pixel[0] = (pixel[0] * shadowscale[light]) >> 8;
|
pixel[0] = (pixel[0] * shadowscale[light]) >> 8;
|
||||||
pixel[1] = (pixel[1] * 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[1] += (255-pixel[1]) * scale;
|
||||||
pixel[2] += (255-pixel[2]) * 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);
|
rslt.setRGBA(pixel[0], pixel[1], pixel[2], 255);
|
||||||
im.setRGB(t.size-y-1, x, rslt.getARGB());
|
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;
|
rendered = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,6 +231,20 @@ public class FlatMap extends MapType {
|
|||||||
KzedMap.freeBufferedImage(im);
|
KzedMap.freeBufferedImage(im);
|
||||||
MapManager.mapman.pushUpdate(tile.getWorld(),
|
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;
|
return rendered;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user