Merge pull request #288 from mikeprimm/hdrender

Performance tuning
This commit is contained in:
mikeprimm 2011-07-18 23:03:34 -07:00
commit 71a8195fc2
14 changed files with 412 additions and 303 deletions

View File

@ -348,23 +348,19 @@ public class DynmapWorld {
im.flush(); im.flush();
/* Do binlinear scale to 64x64 */ /* Do binlinear scale to 64x64 */
Color c1 = new Color(); Color c1 = new Color();
int off = 0;
for(int y = 0; y < height; y += 2) { for(int y = 0; y < height; y += 2) {
for(int x = 0; x < width; x += 2) { off = y*width;
int red = 0; for(int x = 0; x < width; x += 2, off += 2) {
int green = 0; int p0 = argb[off];
int blue = 0; int p1 = argb[off+1];
int alpha = 0; int p2 = argb[off+width];
for(int yy = y; yy < y+2; yy++) { int p3 = argb[off+width+1];
for(int xx = x; xx < x+2; xx++) { int alpha = ((p0 >> 24) & 0xFF) + ((p1 >> 24) & 0xFF) + ((p2 >> 24) & 0xFF) + ((p3 >> 24) & 0xFF);
c1.setARGB(argb[(yy*width)+xx]); int red = ((p0 >> 16) & 0xFF) + ((p1 >> 16) & 0xFF) + ((p2 >> 16) & 0xFF) + ((p3 >> 16) & 0xFF);
red += c1.getRed(); int green = ((p0 >> 8) & 0xFF) + ((p1 >> 8) & 0xFF) + ((p2 >> 8) & 0xFF) + ((p3 >> 8) & 0xFF);
green += c1.getGreen(); int blue = (p0 & 0xFF) + (p1 & 0xFF) + (p2 & 0xFF) + (p3 & 0xFF);
blue += c1.getBlue(); argb[off>>1] = (((alpha>>2)&0xFF)<<24) | (((red>>2)&0xFF)<<16) | (((green>>2)&0xFF)<<8) | ((blue>>2)&0xFF);
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 */ /* blit scaled rendered tile onto zoom-out tile */

View File

@ -300,7 +300,6 @@ public class MapManager {
public void run() { public void run() {
int cnt = max_chunk_loads_per_tick; int cnt = max_chunk_loads_per_tick;
long tick = System.currentTimeMillis(); long tick = System.currentTimeMillis();
while(cnt > 0) { while(cnt > 0) {
MapChunkCache c = chunkloads.peek(); MapChunkCache c = chunkloads.peek();
if(c == null) if(c == null)
@ -313,16 +312,14 @@ public class MapManager {
} }
} }
} }
if(mapman.scheduler != null) { if((tick - last_tick) < 30) {
/* Detect if bukkit is being stupid - add delay of 1 tick if we're being overfed */ Log.info("Chunk fetch running too often - " + (tick-last_tick) + "msec - rescheduled");
if((tick - last_tick) >= 35) { /* If at least 35msec since last run, try immediate */ scheduler.scheduleSyncDelayedTask(plug_in, this, 2);
mapman.scheduler.scheduleSyncDelayedTask(mapman.plug_in, this);
}
else {
mapman.scheduler.scheduleSyncDelayedTask(mapman.plug_in, this, 1);
}
last_tick = tick;
} }
else {
scheduler.scheduleSyncDelayedTask(plug_in, this, 1);
}
last_tick = tick;
} }
} }
@ -375,9 +372,9 @@ public class MapManager {
} }
scheduler.scheduleSyncRepeatingTask(plugin, new CheckWorldTimes(), 5*20, 5*20); /* Check very 5 seconds */ scheduler.scheduleSyncRepeatingTask(plugin, new CheckWorldTimes(), 5*20, 5*20); /* Check very 5 seconds */
// scheduler.scheduleSyncRepeatingTask(plugin, new ProcessChunkLoads(), 1, 2); /* Workaround for Bukkit scheduler */
/* Chunk loader task - work around bukkit issue */ ProcessChunkLoads pc = new ProcessChunkLoads();
scheduler.scheduleSyncDelayedTask(plugin, new ProcessChunkLoads()); scheduler.scheduleSyncDelayedTask(plugin, pc, 1);
} }
void renderFullWorld(Location l, CommandSender sender) { void renderFullWorld(Location l, CommandSender sender) {

View File

@ -101,6 +101,7 @@ public class TileHashManager {
private Object lock = new Object(); private Object lock = new Object();
private LRULinkedHashMap<TileHashFile, byte[]> tilehash = new LRULinkedHashMap<TileHashFile, byte[]>(MAX_CACHED_TILEHASHFILES); private LRULinkedHashMap<TileHashFile, byte[]> tilehash = new LRULinkedHashMap<TileHashFile, byte[]>(MAX_CACHED_TILEHASHFILES);
private CRC32 crc32 = new CRC32(); private CRC32 crc32 = new CRC32();
private byte[] crcworkbuf = new byte[8192];
public TileHashManager(File tileroot, boolean enabled) { public TileHashManager(File tileroot, boolean enabled) {
tiledir = tileroot; tiledir = tileroot;
@ -130,15 +131,19 @@ public class TileHashManager {
return 0; /* Return value that doesn't match */ return 0; /* Return value that doesn't match */
} }
synchronized(lock) { synchronized(lock) {
if(crcworkbuf.length < (4*newbuf.length)){
crcworkbuf = new byte[4*newbuf.length];
}
for(int i = 0, off = 0; i < newbuf.length; i++) {
int v = newbuf[i];
crcworkbuf[off++] = (byte)v;
crcworkbuf[off++] = (byte)(v>>8);
crcworkbuf[off++] = (byte)(v>>16);
crcworkbuf[off++] = (byte)(v>>24);
}
/* Calculate CRC-32 for buffer */ /* Calculate CRC-32 for buffer */
crc32.reset(); crc32.reset();
for(int i = 0; i < newbuf.length; i++) { crc32.update(crcworkbuf, 0, 4*newbuf.length);
int v = newbuf[i];
crc32.update(0xFF & v);
crc32.update(0xFF & (v >> 8));
crc32.update(0xFF & (v >> 16));
crc32.update(0xFF & (v >> 24));
}
return crc32.getValue(); return crc32.getValue();
} }
} }

View File

@ -29,6 +29,7 @@ import org.dynmap.kzedmap.KzedMap.KzedBufferedImage;
import org.dynmap.utils.FileLockManager; import org.dynmap.utils.FileLockManager;
import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.MapIterator; import org.dynmap.utils.MapIterator;
import org.dynmap.utils.MapIterator.BlockStep;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
public class FlatMap extends MapType { public class FlatMap extends MapType {
@ -142,12 +143,12 @@ public class FlatMap extends MapType {
MapIterator mapiter = cache.getIterator(t.x * t.size, 127, t.y * t.size); 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++) {
mapiter.initialize(t.x * t.size + x, 127, t.y * t.size); mapiter.initialize(t.x * t.size + x, 127, t.y * t.size);
for (int y = 0; y < t.size; y++, mapiter.incrementZ()) { for (int y = 0; y < t.size; y++, mapiter.stepPosition(BlockStep.Z_PLUS)) {
int blockType; int blockType;
mapiter.setY(127); mapiter.setY(127);
if(isnether) { if(isnether) {
while((blockType = mapiter.getBlockTypeID()) != 0) { while((blockType = mapiter.getBlockTypeID()) != 0) {
mapiter.decrementY(); mapiter.stepPosition(BlockStep.Y_MINUS);
if(mapiter.getY() < 0) { /* Solid - use top */ if(mapiter.getY() < 0) { /* Solid - use top */
mapiter.setY(127); mapiter.setY(127);
blockType = mapiter.getBlockTypeID(); blockType = mapiter.getBlockTypeID();
@ -156,7 +157,7 @@ public class FlatMap extends MapType {
} }
if(blockType == 0) { /* Hit air - now find non-air */ if(blockType == 0) { /* Hit air - now find non-air */
while((blockType = mapiter.getBlockTypeID()) == 0) { while((blockType = mapiter.getBlockTypeID()) == 0) {
mapiter.decrementY(); mapiter.stepPosition(BlockStep.Y_MINUS);
if(mapiter.getY() < 0) { if(mapiter.getY() < 0) {
mapiter.setY(0); mapiter.setY(0);
break; break;
@ -209,7 +210,7 @@ public class FlatMap extends MapType {
/* If ambient light less than 15, do scaling */ /* If ambient light less than 15, do scaling */
else if((shadowscale != null) && (ambientlight < 15)) { else if((shadowscale != null) && (ambientlight < 15)) {
if(mapiter.getY() < 127) if(mapiter.getY() < 127)
mapiter.incrementY(); mapiter.stepPosition(BlockStep.Y_PLUS);
if(night_and_day) { /* Use unscaled color for day (no shadows from above) */ if(night_and_day) { /* Use unscaled color for day (no shadows from above) */
pixel_day[0] = pixel[0]; pixel_day[0] = pixel[0];
pixel_day[1] = pixel[1]; pixel_day[1] = pixel[1];
@ -348,7 +349,7 @@ public class FlatMap extends MapType {
if((shadowscale != null) && (ambientlight < 15)) { if((shadowscale != null) && (ambientlight < 15)) {
boolean did_inc = false; boolean did_inc = false;
if(mapiter.getY() < 127) { if(mapiter.getY() < 127) {
mapiter.incrementY(); mapiter.stepPosition(BlockStep.Y_PLUS);
did_inc = true; did_inc = true;
} }
if(night_and_day) { /* Use unscaled color for day (no shadows from above) */ if(night_and_day) { /* Use unscaled color for day (no shadows from above) */
@ -359,13 +360,13 @@ public class FlatMap extends MapType {
g = (g * shadowscale[light]) >> 8; g = (g * shadowscale[light]) >> 8;
b = (b * shadowscale[light]) >> 8; b = (b * shadowscale[light]) >> 8;
if(did_inc) if(did_inc)
mapiter.decrementY(); mapiter.stepPosition(BlockStep.Y_MINUS);
} }
if(a < 255) { /* If not opaque */ if(a < 255) { /* If not opaque */
pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0; pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
if(pixel_day != null) if(pixel_day != null)
pixel_day[0] = pixel_day[1] = pixel_day[2] = pixel_day[3] = 0; pixel_day[0] = pixel_day[1] = pixel_day[2] = pixel_day[3] = 0;
mapiter.decrementY(); mapiter.stepPosition(BlockStep.Y_MINUS);
if(mapiter.getY() >= 0) { if(mapiter.getY() >= 0) {
int blockType = mapiter.getBlockTypeID(); int blockType = mapiter.getBlockTypeID();
int data = 0; int data = 0;

View File

@ -1,17 +1,9 @@
package org.dynmap.hdmap; package org.dynmap.hdmap;
import org.dynmap.utils.MapIterator.BlockStep;
import org.dynmap.utils.Vector3D; import org.dynmap.utils.Vector3D;
public interface HDPerspectiveState { public interface HDPerspectiveState {
/* Represents last step of movement of the ray */
public enum BlockStep {
X_PLUS,
Y_PLUS,
Z_PLUS,
X_MINUS,
Y_MINUS,
Z_MINUS
};
/** /**
* Get sky light level - only available if shader requested it * Get sky light level - only available if shader requested it
*/ */

View File

@ -22,7 +22,7 @@ import org.dynmap.MapManager;
import org.dynmap.MapTile; import org.dynmap.MapTile;
import org.dynmap.TileHashManager; import org.dynmap.TileHashManager;
import org.dynmap.debug.Debug; import org.dynmap.debug.Debug;
import org.dynmap.hdmap.HDPerspectiveState.BlockStep; import org.dynmap.utils.MapIterator.BlockStep;
import org.dynmap.kzedmap.KzedMap.KzedBufferedImage; import org.dynmap.kzedmap.KzedMap.KzedBufferedImage;
import org.dynmap.kzedmap.KzedMap; import org.dynmap.kzedmap.KzedMap;
import org.dynmap.utils.FileLockManager; import org.dynmap.utils.FileLockManager;
@ -72,8 +72,6 @@ public class IsoHDPerspective implements HDPerspective {
private boolean need_rawbiomedata = false; private boolean need_rawbiomedata = false;
private class OurPerspectiveState implements HDPerspectiveState { private class OurPerspectiveState implements HDPerspectiveState {
int skylightlevel = 15;
int emittedlightlevel = 0;
int blocktypeid = 0; int blocktypeid = 0;
int blockdata = 0; int blockdata = 0;
Vector3D top, bottom; Vector3D top, bottom;
@ -90,14 +88,55 @@ public class IsoHDPerspective implements HDPerspective {
int subalpha; int subalpha;
double mt; double mt;
int[] subblock_xyz = new int[3]; int[] subblock_xyz = new int[3];
MapIterator mapiter;
public OurPerspectiveState(MapIterator mi) {
mapiter = mi;
}
/** /**
* Get sky light level - only available if shader requested it * Get sky light level - only available if shader requested it
*/ */
public final int getSkyLightLevel() { return skylightlevel; } public final int getSkyLightLevel() {
int ll;
BlockStep ls = mapiter.unstepPosition();
/* Some blocks are light blocking, but not fully blocking - this sucks */
switch(mapiter.getBlockTypeID()) {
case 53: /* Wood stairs */
case 44: /* Slabs */
case 67: /* Cobblestone stairs */
mapiter.stepPosition(BlockStep.Y_PLUS); /* Look above */
ll = mapiter.getBlockSkyLight();
mapiter.stepPosition(BlockStep.Y_MINUS);
break;
default:
ll = mapiter.getBlockSkyLight();
break;
}
mapiter.stepPosition(ls);
return ll;
}
/** /**
* Get emitted light level - only available if shader requested it * Get emitted light level - only available if shader requested it
*/ */
public final int getEmittedLightLevel() { return emittedlightlevel; } public final int getEmittedLightLevel() {
int ll;
BlockStep ls = mapiter.unstepPosition();
/* Some blocks are light blocking, but not fully blocking - this sucks */
switch(mapiter.getBlockTypeID()) {
case 53: /* Wood stairs */
case 44: /* Slabs */
case 67: /* Cobblestone stairs */
mapiter.stepPosition(BlockStep.Y_PLUS); /* Look above */
ll = mapiter.getBlockEmittedLight();
mapiter.stepPosition(BlockStep.Y_MINUS);
break;
default:
ll = mapiter.getBlockEmittedLight();
break;
}
mapiter.stepPosition(ls);
return ll;
}
/** /**
* Get current block type ID * Get current block type ID
*/ */
@ -210,40 +249,68 @@ public class IsoHDPerspective implements HDPerspective {
} }
/* Walk through scene */ /* Walk through scene */
laststep = BlockStep.Y_MINUS; /* Last step is down into map */ laststep = BlockStep.Y_MINUS; /* Last step is down into map */
skylightlevel = 15;
emittedlightlevel = 0;
nonairhit = false; nonairhit = false;
} }
private int generateFenceBlockData(MapIterator mapiter) {
int blockdata = 0;
/* Check north */
if(mapiter.getBlockTypeIDAt(BlockStep.X_MINUS) == 85) { /* Fence? */
blockdata |= 1;
}
/* Look east */
if(mapiter.getBlockTypeIDAt(BlockStep.Z_MINUS) == 85) { /* Fence? */
blockdata |= 2;
}
/* Look south */
if(mapiter.getBlockTypeIDAt(BlockStep.X_PLUS) == 85) { /* Fence? */
blockdata |= 4;
}
/* Look west */
if(mapiter.getBlockTypeIDAt(BlockStep.Z_PLUS) == 85) { /* Fence? */
blockdata |= 8;
}
return blockdata;
}
/* Figure out which orientation possibility applies to chest:
* bit 1-0: 00=facing west, 01=facing-south, 10=facing-east, 11=facing-north
* bit 3-2: 00=single, 01=left half, 10=right half
* truth table:
* N S E W : facing
* - - - - : W
* X - - - : S
* - X - - : N
* - - X - : W
* - - - X : E
* X - X - : S
* X - - X : S
* X - X X : S
* - X - X : N
* - X X - : N
* - X X X : N
* X X X - : W
* X X - - : W
* - - X X : W
* X - - X : S
* X X - X : E
* X X X X : ?
*/
private int generateChestBlockData(MapIterator mapiter) {
int blockdata = 0;
return blockdata;
}
/** /**
* Process visit of ray to block * Process visit of ray to block
*/ */
private boolean visit_block(MapIterator mapiter, HDShaderState[] shaderstate, boolean[] shaderdone) { private boolean visit_block(MapIterator mapiter, HDShaderState[] shaderstate, boolean[] shaderdone) {
blocktypeid = mapiter.getBlockTypeID(); blocktypeid = mapiter.getBlockTypeID();
boolean skip_light_update = false;
if(nonairhit || (blocktypeid != 0)) { if(nonairhit || (blocktypeid != 0)) {
blockdata = mapiter.getBlockData(); blockdata = mapiter.getBlockData();
if(blocktypeid == 85) { /* Special case for fence - need to fake data so we can render properly */ if(blocktypeid == 85) { /* Special case for fence - need to fake data so we can render properly */
mapiter.decrementX(); /* Look north */ blockdata = generateFenceBlockData(mapiter);
blockdata = 0; }
if(mapiter.getBlockTypeID() == 85) { /* Fence? */ else if(blocktypeid == 54) { /* Special case for chest - need to fake data so we can render */
blockdata |= 1; blockdata = generateChestBlockData(mapiter);
}
mapiter.incrementX();
mapiter.decrementZ(); /* Look east */
if(mapiter.getBlockTypeID() == 85) { /* Fence? */
blockdata |= 2;
}
mapiter.incrementZ();
mapiter.incrementX(); /* Look south */
if(mapiter.getBlockTypeID() == 85) { /* Fence? */
blockdata |= 4;
}
mapiter.decrementX(); /* Look west */
mapiter.incrementZ();
if(mapiter.getBlockTypeID() == 85) { /* Fence? */
blockdata |= 8;
}
mapiter.decrementZ();
} }
boolean missed = false; boolean missed = false;
@ -251,14 +318,6 @@ public class IsoHDPerspective implements HDPerspective {
short[] model = scalemodels.getScaledModel(blocktypeid, blockdata); short[] model = scalemodels.getScaledModel(blocktypeid, blockdata);
if(model != null) { if(model != null) {
missed = raytraceSubblock(model); missed = raytraceSubblock(model);
/* Some blocks are light blocking, but not fully blocking - this sucks */
switch(blocktypeid) {
case 53: /* Wood stairs */
case 44: /* Slabs */
case 67: /* Cobblestone stairs */
skip_light_update = true;
break;
}
} }
else { else {
subalpha = -1; subalpha = -1;
@ -276,26 +335,6 @@ public class IsoHDPerspective implements HDPerspective {
nonairhit = true; nonairhit = true;
} }
} }
if(skip_light_update) { /* If considering skipping, do so if block is unlit */
int ll;
if(need_skylightlevel) {
ll = mapiter.getBlockSkyLight();
if(ll > 0)
skylightlevel = ll;
}
if(need_emittedlightlevel) {
ll = mapiter.getBlockEmittedLight();
if(ll > 0) {
emittedlightlevel = ll;
}
}
}
else {
if(need_skylightlevel)
skylightlevel = mapiter.getBlockSkyLight();
if(need_emittedlightlevel)
emittedlightlevel = mapiter.getBlockEmittedLight();
}
return false; return false;
} }
/** /**
@ -307,7 +346,6 @@ public class IsoHDPerspective implements HDPerspective {
mapiter.initialize(x, y, z); mapiter.initialize(x, y, z);
boolean nonairhit = false;
for (; n > 0; --n) { for (; n > 0; --n) {
/* Visit block */ /* Visit block */
if(visit_block(mapiter, shaderstate, shaderdone)) { if(visit_block(mapiter, shaderstate, shaderdone)) {
@ -320,12 +358,11 @@ public class IsoHDPerspective implements HDPerspective {
t_next_x += dt_dx; t_next_x += dt_dx;
if(x_inc > 0) { if(x_inc > 0) {
laststep = BlockStep.X_PLUS; laststep = BlockStep.X_PLUS;
mapiter.incrementX();
} }
else { else {
laststep = BlockStep.X_MINUS; laststep = BlockStep.X_MINUS;
mapiter.decrementX();
} }
mapiter.stepPosition(laststep);
} }
/* If Y step is next best */ /* If Y step is next best */
else if((t_next_y <= t_next_x) && (t_next_y <= t_next_z)) { else if((t_next_y <= t_next_x) && (t_next_y <= t_next_z)) {
@ -334,13 +371,13 @@ public class IsoHDPerspective implements HDPerspective {
t_next_y += dt_dy; t_next_y += dt_dy;
if(y_inc > 0) { if(y_inc > 0) {
laststep = BlockStep.Y_PLUS; laststep = BlockStep.Y_PLUS;
mapiter.incrementY(); mapiter.stepPosition(laststep);
if(mapiter.getY() > 127) if(mapiter.getY() > 127)
return; return;
} }
else { else {
laststep = BlockStep.Y_MINUS; laststep = BlockStep.Y_MINUS;
mapiter.decrementY(); mapiter.stepPosition(laststep);
if(mapiter.getY() < 0) if(mapiter.getY() < 0)
return; return;
} }
@ -352,12 +389,11 @@ public class IsoHDPerspective implements HDPerspective {
t_next_z += dt_dz; t_next_z += dt_dz;
if(z_inc > 0) { if(z_inc > 0) {
laststep = BlockStep.Z_PLUS; laststep = BlockStep.Z_PLUS;
mapiter.incrementZ();
} }
else { else {
laststep = BlockStep.Z_MINUS; laststep = BlockStep.Z_MINUS;
mapiter.decrementZ();
} }
mapiter.stepPosition(laststep);
} }
} }
} }
@ -731,7 +767,7 @@ public class IsoHDPerspective implements HDPerspective {
} }
/* Create perspective state object */ /* Create perspective state object */
OurPerspectiveState ps = new OurPerspectiveState(); OurPerspectiveState ps = new OurPerspectiveState(mapiter);
ps.top = new Vector3D(); ps.top = new Vector3D();
ps.bottom = new Vector3D(); ps.bottom = new Vector3D();

View File

@ -21,7 +21,7 @@ import javax.imageio.ImageIO;
import org.dynmap.Color; import org.dynmap.Color;
import org.dynmap.DynmapPlugin; import org.dynmap.DynmapPlugin;
import org.dynmap.Log; import org.dynmap.Log;
import org.dynmap.hdmap.HDPerspectiveState.BlockStep; import org.dynmap.utils.MapIterator.BlockStep;
import org.dynmap.kzedmap.KzedMap; import org.dynmap.kzedmap.KzedMap;
import org.dynmap.utils.MapIterator; import org.dynmap.utils.MapIterator;
@ -736,7 +736,7 @@ public class TexturePack {
break; break;
case COLORMOD_GRASSSIDE: case COLORMOD_GRASSSIDE:
/* Check if snow above block */ /* Check if snow above block */
if(mapiter.getBlockTypeIDAbove() == 78) { if(mapiter.getBlockTypeIDAt(BlockStep.Y_PLUS) == 78) {
texture = terrain_argb[68]; /* Snow block */ texture = terrain_argb[68]; /* Snow block */
textid = 68; textid = 68;
} }

View File

@ -2,15 +2,9 @@ package org.dynmap.hdmap;
import static org.dynmap.JSONUtils.s; import static org.dynmap.JSONUtils.s;
import java.io.File;
import java.io.IOException;
import org.bukkit.block.Biome;
import org.dynmap.Color; import org.dynmap.Color;
import org.dynmap.ColorScheme;
import org.dynmap.ConfigurationNode; import org.dynmap.ConfigurationNode;
import org.dynmap.Log; import org.dynmap.Log;
import org.dynmap.hdmap.HDPerspectiveState.BlockStep;
import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.MapIterator; import org.dynmap.utils.MapIterator;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;

View File

@ -4,6 +4,7 @@ import org.bukkit.World;
import org.dynmap.Color; import org.dynmap.Color;
import org.dynmap.ConfigurationNode; import org.dynmap.ConfigurationNode;
import org.dynmap.utils.MapIterator; import org.dynmap.utils.MapIterator;
import org.dynmap.utils.MapIterator.BlockStep;
public class CaveTileRenderer extends DefaultTileRenderer { public class CaveTileRenderer extends DefaultTileRenderer {
@ -32,14 +33,14 @@ public class CaveTileRenderer extends DefaultTileRenderer {
switch (seq) { switch (seq) {
case 0: case 0:
mapiter.decrementX(); mapiter.stepPosition(BlockStep.X_MINUS);
break; break;
case 1: case 1:
case 3: case 3:
mapiter.decrementY(); mapiter.stepPosition(BlockStep.Y_MINUS);
break; break;
case 2: case 2:
mapiter.incrementZ(); mapiter.stepPosition(BlockStep.Z_PLUS);
break; break;
} }

View File

@ -24,6 +24,7 @@ import org.dynmap.kzedmap.KzedMap.KzedBufferedImage;
import org.dynmap.utils.FileLockManager; import org.dynmap.utils.FileLockManager;
import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.MapIterator; import org.dynmap.utils.MapIterator;
import org.dynmap.utils.MapIterator.BlockStep;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
public class DefaultTileRenderer implements MapTileRenderer { public class DefaultTileRenderer implements MapTileRenderer {
@ -442,18 +443,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
} }
if((shadowscale != null) && (mapiter.getY() < 127)) { if((shadowscale != null) && (mapiter.getY() < 127)) {
/* Find light level of previous chunk */ /* Find light level of previous chunk */
switch(seq) { BlockStep last = mapiter.unstepPosition();
case 0:
case 2:
mapiter.incrementY();
break;
case 1:
mapiter.incrementX();
break;
case 3:
mapiter.decrementZ();
break;
}
lightlevel = lightlevel_day = mapiter.getBlockSkyLight(); lightlevel = lightlevel_day = mapiter.getBlockSkyLight();
if(lightscale != null) if(lightscale != null)
lightlevel = lightscale[lightlevel]; lightlevel = lightscale[lightlevel];
@ -462,34 +452,23 @@ public class DefaultTileRenderer implements MapTileRenderer {
lightlevel = Math.max(emitted, lightlevel); lightlevel = Math.max(emitted, lightlevel);
lightlevel_day = Math.max(emitted, lightlevel_day); lightlevel_day = Math.max(emitted, lightlevel_day);
} }
switch(seq) { mapiter.stepPosition(last);
case 0:
case 2:
mapiter.decrementY();
break;
case 1:
mapiter.decrementX();
break;
case 3:
mapiter.incrementZ();
break;
}
} }
} }
switch (seq) { switch (seq) {
case 0: case 0:
mapiter.decrementX(); mapiter.stepPosition(BlockStep.X_MINUS);
break; break;
case 1: case 1:
case 3: case 3:
mapiter.decrementY(); mapiter.stepPosition(BlockStep.Y_MINUS);
break; break;
case 2: case 2:
mapiter.incrementZ(); mapiter.stepPosition(BlockStep.Z_PLUS);
break; break;
} }
seq = (seq + 1) & 3; seq = (seq + 1) & 3;
if (id != 0) { if (id != 0) {

View File

@ -7,6 +7,7 @@ import org.bukkit.World;
import org.dynmap.Color; import org.dynmap.Color;
import org.dynmap.ConfigurationNode; import org.dynmap.ConfigurationNode;
import org.dynmap.utils.MapIterator; import org.dynmap.utils.MapIterator;
import org.dynmap.utils.MapIterator.BlockStep;
public class HighlightTileRenderer extends DefaultTileRenderer { public class HighlightTileRenderer extends DefaultTileRenderer {
protected HashSet<Integer> highlightBlocks = new HashSet<Integer>(); protected HashSet<Integer> highlightBlocks = new HashSet<Integer>();
@ -46,16 +47,16 @@ public class HighlightTileRenderer extends DefaultTileRenderer {
} }
switch (seq) { switch (seq) {
case 0: case 0:
mapiter.decrementX(); mapiter.stepPosition(BlockStep.X_MINUS);
break; break;
case 1: case 1:
case 3: case 3:
mapiter.decrementY(); mapiter.stepPosition(BlockStep.Y_MINUS);
break; break;
case 2: case 2:
mapiter.incrementZ(); mapiter.stepPosition(BlockStep.Z_PLUS);
break; break;
} }
seq = (seq + 1) & 3; seq = (seq + 1) & 3;

View File

@ -14,6 +14,7 @@ import org.dynmap.DynmapChunk;
import org.dynmap.DynmapPlugin; import org.dynmap.DynmapPlugin;
import org.dynmap.DynmapWorld; import org.dynmap.DynmapWorld;
import org.dynmap.Log; import org.dynmap.Log;
import org.dynmap.utils.MapIterator.BlockStep;
import java.util.List; import java.util.List;
@ -42,13 +43,18 @@ public class LegacyMapChunkCache implements MapChunkCache {
private LegacyChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */ private LegacyChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
private static final BlockStep unstep[] = { BlockStep.X_MINUS, BlockStep.Y_MINUS, BlockStep.Z_MINUS,
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
/** /**
* Iterator for traversing map chunk cache (base is for non-snapshot) * Iterator for traversing map chunk cache (base is for non-snapshot)
*/ */
public class OurMapIterator implements MapIterator { public class OurMapIterator implements MapIterator {
private int x, y, z; private int x, y, z;
private LegacyChunkSnapshot snap; private LegacyChunkSnapshot snap;
private BlockStep laststep;
private int typeid;
OurMapIterator(int x0, int y0, int z0) { OurMapIterator(int x0, int y0, int z0) {
initialize(x0, y0, z0); initialize(x0, y0, z0);
} }
@ -61,9 +67,13 @@ public class LegacyMapChunkCache implements MapChunkCache {
} catch (ArrayIndexOutOfBoundsException aioobx) { } catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY; snap = EMPTY;
} }
laststep = BlockStep.Y_MINUS;
typeid = -1;
} }
public final int getBlockTypeID() { public final int getBlockTypeID() {
return snap.getBlockTypeId(x & 0xF, y, z & 0xF); if(typeid < 0)
typeid = snap.getBlockTypeId(x & 0xF, y, z & 0xF);
return typeid;
} }
public final int getBlockData() { public final int getBlockData() {
return snap.getBlockData(x & 0xF, y, z & 0xF); return snap.getBlockData(x & 0xF, y, z & 0xF);
@ -86,55 +96,76 @@ public class LegacyMapChunkCache implements MapChunkCache {
public double getRawBiomeRainfall() { public double getRawBiomeRainfall() {
return 0.0; return 0.0;
} }
/**
public final void incrementX() { * Step current position in given direction
x++; */
if((x & 0xF) == 0) { /* Next chunk? */ public final void stepPosition(BlockStep step) {
try { switch(step) {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; case X_PLUS:
} catch (ArrayIndexOutOfBoundsException aioobx) { x++;
snap = EMPTY; if((x & 0xF) == 0) { /* Next chunk? */
} try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
case X_MINUS:
x--;
if((x & 0xF) == 15) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
case Y_PLUS:
y++;
break;
case Y_MINUS:
y--;
break;
case Z_PLUS:
z++;
if((z & 0xF) == 0) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
case Z_MINUS:
z--;
if((z & 0xF) == 15) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
} }
laststep = step;
typeid = -1;
} }
public final void decrementX() { /**
x--; * Unstep current position to previous position
if((x & 0xF) == 15) { /* Next chunk? */ */
try { public BlockStep unstepPosition() {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; BlockStep ls = laststep;
} catch (ArrayIndexOutOfBoundsException aioobx) { stepPosition(unstep[ls.ordinal()]);
snap = EMPTY; return ls;
}
}
}
public final void incrementY() {
y++;
}
public final void decrementY() {
y--;
}
public final void incrementZ() {
z++;
if((z & 0xF) == 0) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
}
public final void decrementZ() {
z--;
if((z & 0xF) == 15) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
} }
public final void setY(int y) { public final void setY(int y) {
if(y > this.y)
laststep = BlockStep.Y_PLUS;
else
laststep = BlockStep.Y_PLUS;
this.y = y; this.y = y;
typeid = -1;
} }
public final int getX() { public final int getX() {
return x; return x;
@ -145,12 +176,28 @@ public class LegacyMapChunkCache implements MapChunkCache {
public final int getZ() { public final int getZ() {
return z; return z;
} }
public final int getBlockTypeIDAbove() { public final int getBlockTypeIDAt(BlockStep s) {
if(y < 127) if(s == BlockStep.Y_MINUS) {
return snap.getBlockTypeId(x & 0xF, y+1, z & 0xF); if(y > 0)
return snap.getBlockTypeId(x & 0xF, y-1, z & 0xF);
}
else if(s == BlockStep.Y_PLUS) {
if(y < 127)
return snap.getBlockTypeId(x & 0xF, y+1, z & 0xF);
}
else {
BlockStep ls = laststep;
stepPosition(s);
int tid = snap.getBlockTypeId(x & 0xF, y, z & 0xF);
unstepPosition();
laststep = ls;
return tid;
}
return 0; return 0;
} }
public BlockStep getLastStep() {
return laststep;
}
} }
/** /**

View File

@ -6,6 +6,15 @@ import org.bukkit.block.Biome;
* Iterator for traversing map chunk cache (base is for non-snapshot) * Iterator for traversing map chunk cache (base is for non-snapshot)
*/ */
public interface MapIterator { public interface MapIterator {
/* Represents last step of movement of the ray (don't alter order here - ordinal sensitive) */
public enum BlockStep {
X_PLUS,
Y_PLUS,
Z_PLUS,
X_MINUS,
Y_MINUS,
Z_MINUS;
};
/** /**
* Initialize iterator at given coordinates * Initialize iterator at given coordinates
* *
@ -53,29 +62,13 @@ public interface MapIterator {
*/ */
public double getRawBiomeRainfall(); public double getRawBiomeRainfall();
/** /**
* Increment X of current position * Step current position in given direction
*/ */
void incrementX(); void stepPosition(BlockStep step);
/** /**
* Decrement X of current position * Unstep current position to previous position : return step to take to return
*/ */
void decrementX(); BlockStep unstepPosition();
/**
* Increment Y of current position
*/
void incrementY();
/**
* Decrement Y of current position
*/
void decrementY();
/**
* Increment Z of current position
*/
void incrementZ();
/**
* Decrement Y of current position
*/
void decrementZ();
/** /**
* Set Y coordinate of current position * Set Y coordinate of current position
* @param y * @param y
@ -94,10 +87,13 @@ public interface MapIterator {
*/ */
int getZ(); int getZ();
/** /**
* Get block ID at one above current coordinates * Get block ID at 1 step in given direction
* *
* @return block id * @return block id
*/ */
int getBlockTypeIDAbove(); int getBlockTypeIDAt(BlockStep s);
/**
* Get last step taken
*/
BlockStep getLastStep();
} }

View File

@ -16,6 +16,7 @@ import org.dynmap.DynmapPlugin;
import org.dynmap.DynmapWorld; import org.dynmap.DynmapWorld;
import org.dynmap.Log; import org.dynmap.Log;
import org.dynmap.MapManager; import org.dynmap.MapManager;
import org.dynmap.utils.MapIterator.BlockStep;
/** /**
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
@ -42,13 +43,18 @@ public class NewMapChunkCache implements MapChunkCache {
private boolean isempty = true; private boolean isempty = true;
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */ private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
private static final BlockStep unstep[] = { BlockStep.X_MINUS, BlockStep.Y_MINUS, BlockStep.Z_MINUS,
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
/** /**
* Iterator for traversing map chunk cache (base is for non-snapshot) * Iterator for traversing map chunk cache (base is for non-snapshot)
*/ */
public class OurMapIterator implements MapIterator { public class OurMapIterator implements MapIterator {
private int x, y, z; private int x, y, z, chunkindex, bx, bz;
private ChunkSnapshot snap; private ChunkSnapshot snap;
private BlockStep laststep;
private int typeid = -1;
OurMapIterator(int x0, int y0, int z0) { OurMapIterator(int x0, int y0, int z0) {
initialize(x0, y0, z0); initialize(x0, y0, z0);
@ -57,84 +63,125 @@ public class NewMapChunkCache implements MapChunkCache {
this.x = x0; this.x = x0;
this.y = y0; this.y = y0;
this.z = z0; this.z = z0;
this.chunkindex = ((x >> 4) - x_min) + (((z >> 4) - z_min) * x_dim);
this.bx = x & 0xF;
this.bz = z & 0xF;
try { try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; snap = snaparray[chunkindex];
} catch (ArrayIndexOutOfBoundsException aioobx) { } catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY; snap = EMPTY;
} }
laststep = BlockStep.Y_MINUS;
typeid = -1;
} }
public final int getBlockTypeID() { public final int getBlockTypeID() {
return snap.getBlockTypeId(x & 0xF, y, z & 0xF); if(typeid < 0)
typeid = snap.getBlockTypeId(bx, y, bz);
return typeid;
} }
public final int getBlockData() { public final int getBlockData() {
return snap.getBlockData(x & 0xF, y, z & 0xF); return snap.getBlockData(bx, y, bz);
} }
public final int getHighestBlockYAt() { public final int getHighestBlockYAt() {
return snap.getHighestBlockYAt(x & 0xF, z & 0xF); return snap.getHighestBlockYAt(bx, bz);
} }
public final int getBlockSkyLight() { public final int getBlockSkyLight() {
return snap.getBlockSkyLight(x & 0xF, y, z & 0xF); return snap.getBlockSkyLight(bx, y, bz);
} }
public final int getBlockEmittedLight() { public final int getBlockEmittedLight() {
return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF); return snap.getBlockEmittedLight(bx, y, bz);
} }
public Biome getBiome() { public Biome getBiome() {
return snap.getBiome(x & 0xF, z & 0xF); return snap.getBiome(bx, bz);
} }
public double getRawBiomeTemperature() { public double getRawBiomeTemperature() {
return snap.getRawBiomeTemperature(x & 0xf, z & 0xf); return snap.getRawBiomeTemperature(bx, bz);
} }
public double getRawBiomeRainfall() { public double getRawBiomeRainfall() {
return snap.getRawBiomeRainfall(x & 0xf, z & 0xf); return snap.getRawBiomeRainfall(bx, bz);
} }
public final void incrementX() { /**
x++; * Step current position in given direction
if((x & 0xF) == 0) { /* Next chunk? */ */
try { public final void stepPosition(BlockStep step) {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; switch(step.ordinal()) {
} catch (ArrayIndexOutOfBoundsException aioobx) { case 0:
snap = EMPTY; x++;
} bx++;
if(bx == 16) { /* Next chunk? */
try {
bx = 0;
chunkindex++;
snap = snaparray[chunkindex];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
case 1:
y++;
break;
case 2:
z++;
bz++;
if(bz == 16) { /* Next chunk? */
try {
bz = 0;
chunkindex += x_dim;
snap = snaparray[chunkindex];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
case 3:
x--;
bx--;
if(bx == -1) { /* Next chunk? */
try {
bx = 15;
chunkindex--;
snap = snaparray[chunkindex];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
case 4:
y--;
break;
case 5:
z--;
bz--;
if(bz == -1) { /* Next chunk? */
try {
bz = 15;
chunkindex -= x_dim;
snap = snaparray[chunkindex];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
break;
} }
laststep = step;
typeid = -1;
} }
public final void decrementX() { /**
x--; * Unstep current position to previous position
if((x & 0xF) == 15) { /* Next chunk? */ */
try { public BlockStep unstepPosition() {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; BlockStep ls = laststep;
} catch (ArrayIndexOutOfBoundsException aioobx) { stepPosition(unstep[ls.ordinal()]);
snap = EMPTY; return ls;
}
}
}
public final void incrementY() {
y++;
}
public final void decrementY() {
y--;
}
public final void incrementZ() {
z++;
if((z & 0xF) == 0) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
}
public final void decrementZ() {
z--;
if((z & 0xF) == 15) { /* Next chunk? */
try {
snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
} catch (ArrayIndexOutOfBoundsException aioobx) {
snap = EMPTY;
}
}
} }
public final void setY(int y) { public final void setY(int y) {
if(y > this.y)
laststep = BlockStep.Y_PLUS;
else
laststep = BlockStep.Y_PLUS;
this.y = y; this.y = y;
typeid = -1;
} }
public final int getX() { public final int getX() {
return x; return x;
@ -145,11 +192,28 @@ public class NewMapChunkCache implements MapChunkCache {
public final int getZ() { public final int getZ() {
return z; return z;
} }
public final int getBlockTypeIDAbove() { public final int getBlockTypeIDAt(BlockStep s) {
if(y < 127) if(s == BlockStep.Y_MINUS) {
return snap.getBlockTypeId(x & 0xF, y+1, z & 0xF); if(y > 0)
return snap.getBlockTypeId(bx, y-1, bz);
}
else if(s == BlockStep.Y_PLUS) {
if(y < 127)
return snap.getBlockTypeId(bx, y+1, bz);
}
else {
BlockStep ls = laststep;
stepPosition(s);
int tid = snap.getBlockTypeId(bx, y, bz);
unstepPosition();
laststep = ls;
return tid;
}
return 0; return 0;
} }
public BlockStep getLastStep() {
return laststep;
}
} }
/** /**