diff --git a/src/main/java/org/dynmap/DynmapWorld.java b/src/main/java/org/dynmap/DynmapWorld.java index c21dca2c..da7c22ac 100644 --- a/src/main/java/org/dynmap/DynmapWorld.java +++ b/src/main/java/org/dynmap/DynmapWorld.java @@ -348,23 +348,19 @@ public class DynmapWorld { im.flush(); /* Do binlinear scale to 64x64 */ Color c1 = new Color(); + int off = 0; for(int y = 0; y < height; y += 2) { - for(int x = 0; x < width; x += 2) { - int red = 0; - int green = 0; - int blue = 0; - int alpha = 0; - for(int yy = y; yy < y+2; yy++) { - for(int xx = x; xx < x+2; xx++) { - c1.setARGB(argb[(yy*width)+xx]); - red += c1.getRed(); - green += c1.getGreen(); - blue += c1.getBlue(); - alpha += c1.getAlpha(); - } - } - c1.setRGBA(red>>2, green>>2, blue>>2, alpha>>2); - argb[(y*width/2) + (x/2)] = c1.getARGB(); + off = y*width; + for(int x = 0; x < width; x += 2, off += 2) { + int p0 = argb[off]; + int p1 = argb[off+1]; + int p2 = argb[off+width]; + int p3 = argb[off+width+1]; + int alpha = ((p0 >> 24) & 0xFF) + ((p1 >> 24) & 0xFF) + ((p2 >> 24) & 0xFF) + ((p3 >> 24) & 0xFF); + int red = ((p0 >> 16) & 0xFF) + ((p1 >> 16) & 0xFF) + ((p2 >> 16) & 0xFF) + ((p3 >> 16) & 0xFF); + int green = ((p0 >> 8) & 0xFF) + ((p1 >> 8) & 0xFF) + ((p2 >> 8) & 0xFF) + ((p3 >> 8) & 0xFF); + int blue = (p0 & 0xFF) + (p1 & 0xFF) + (p2 & 0xFF) + (p3 & 0xFF); + argb[off>>1] = (((alpha>>2)&0xFF)<<24) | (((red>>2)&0xFF)<<16) | (((green>>2)&0xFF)<<8) | ((blue>>2)&0xFF); } } /* blit scaled rendered tile onto zoom-out tile */ diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index 5de07c69..8f7c6f8d 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -300,7 +300,6 @@ public class MapManager { public void run() { int cnt = max_chunk_loads_per_tick; long tick = System.currentTimeMillis(); - while(cnt > 0) { MapChunkCache c = chunkloads.peek(); if(c == null) @@ -313,16 +312,14 @@ public class MapManager { } } } - if(mapman.scheduler != null) { - /* Detect if bukkit is being stupid - add delay of 1 tick if we're being overfed */ - if((tick - last_tick) >= 35) { /* If at least 35msec since last run, try immediate */ - mapman.scheduler.scheduleSyncDelayedTask(mapman.plug_in, this); - } - else { - mapman.scheduler.scheduleSyncDelayedTask(mapman.plug_in, this, 1); - } - last_tick = tick; + if((tick - last_tick) < 30) { + Log.info("Chunk fetch running too often - " + (tick-last_tick) + "msec - rescheduled"); + scheduler.scheduleSyncDelayedTask(plug_in, this, 2); } + 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 ProcessChunkLoads(), 1, 2); - /* Chunk loader task - work around bukkit issue */ - scheduler.scheduleSyncDelayedTask(plugin, new ProcessChunkLoads()); + /* Workaround for Bukkit scheduler */ + ProcessChunkLoads pc = new ProcessChunkLoads(); + scheduler.scheduleSyncDelayedTask(plugin, pc, 1); } void renderFullWorld(Location l, CommandSender sender) { diff --git a/src/main/java/org/dynmap/TileHashManager.java b/src/main/java/org/dynmap/TileHashManager.java index 1191bfdb..e58e1042 100644 --- a/src/main/java/org/dynmap/TileHashManager.java +++ b/src/main/java/org/dynmap/TileHashManager.java @@ -101,6 +101,7 @@ public class TileHashManager { private Object lock = new Object(); private LRULinkedHashMap tilehash = new LRULinkedHashMap(MAX_CACHED_TILEHASHFILES); private CRC32 crc32 = new CRC32(); + private byte[] crcworkbuf = new byte[8192]; public TileHashManager(File tileroot, boolean enabled) { tiledir = tileroot; @@ -130,15 +131,19 @@ public class TileHashManager { return 0; /* Return value that doesn't match */ } 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 */ crc32.reset(); - for(int i = 0; i < newbuf.length; i++) { - int v = newbuf[i]; - crc32.update(0xFF & v); - crc32.update(0xFF & (v >> 8)); - crc32.update(0xFF & (v >> 16)); - crc32.update(0xFF & (v >> 24)); - } + crc32.update(crcworkbuf, 0, 4*newbuf.length); return crc32.getValue(); } } diff --git a/src/main/java/org/dynmap/flat/FlatMap.java b/src/main/java/org/dynmap/flat/FlatMap.java index 293a8109..1e619811 100644 --- a/src/main/java/org/dynmap/flat/FlatMap.java +++ b/src/main/java/org/dynmap/flat/FlatMap.java @@ -29,6 +29,7 @@ import org.dynmap.kzedmap.KzedMap.KzedBufferedImage; import org.dynmap.utils.FileLockManager; import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapIterator; +import org.dynmap.utils.MapIterator.BlockStep; import org.json.simple.JSONObject; 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); for (int x = 0; x < t.size; x++) { 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; mapiter.setY(127); if(isnether) { while((blockType = mapiter.getBlockTypeID()) != 0) { - mapiter.decrementY(); + mapiter.stepPosition(BlockStep.Y_MINUS); if(mapiter.getY() < 0) { /* Solid - use top */ mapiter.setY(127); blockType = mapiter.getBlockTypeID(); @@ -156,7 +157,7 @@ public class FlatMap extends MapType { } if(blockType == 0) { /* Hit air - now find non-air */ while((blockType = mapiter.getBlockTypeID()) == 0) { - mapiter.decrementY(); + mapiter.stepPosition(BlockStep.Y_MINUS); if(mapiter.getY() < 0) { mapiter.setY(0); break; @@ -209,7 +210,7 @@ public class FlatMap extends MapType { /* If ambient light less than 15, do scaling */ else if((shadowscale != null) && (ambientlight < 15)) { if(mapiter.getY() < 127) - mapiter.incrementY(); + mapiter.stepPosition(BlockStep.Y_PLUS); if(night_and_day) { /* Use unscaled color for day (no shadows from above) */ pixel_day[0] = pixel[0]; pixel_day[1] = pixel[1]; @@ -348,7 +349,7 @@ public class FlatMap extends MapType { if((shadowscale != null) && (ambientlight < 15)) { boolean did_inc = false; if(mapiter.getY() < 127) { - mapiter.incrementY(); + mapiter.stepPosition(BlockStep.Y_PLUS); did_inc = true; } 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; b = (b * shadowscale[light]) >> 8; if(did_inc) - mapiter.decrementY(); + mapiter.stepPosition(BlockStep.Y_MINUS); } if(a < 255) { /* If not opaque */ pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0; if(pixel_day != null) pixel_day[0] = pixel_day[1] = pixel_day[2] = pixel_day[3] = 0; - mapiter.decrementY(); + mapiter.stepPosition(BlockStep.Y_MINUS); if(mapiter.getY() >= 0) { int blockType = mapiter.getBlockTypeID(); int data = 0; diff --git a/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java b/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java index 12b52cfd..b54c26eb 100644 --- a/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java +++ b/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java @@ -1,17 +1,9 @@ package org.dynmap.hdmap; +import org.dynmap.utils.MapIterator.BlockStep; import org.dynmap.utils.Vector3D; 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 */ diff --git a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java index 03677759..1ffc726e 100644 --- a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java @@ -22,7 +22,7 @@ import org.dynmap.MapManager; import org.dynmap.MapTile; import org.dynmap.TileHashManager; 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; import org.dynmap.utils.FileLockManager; @@ -72,8 +72,6 @@ public class IsoHDPerspective implements HDPerspective { private boolean need_rawbiomedata = false; private class OurPerspectiveState implements HDPerspectiveState { - int skylightlevel = 15; - int emittedlightlevel = 0; int blocktypeid = 0; int blockdata = 0; Vector3D top, bottom; @@ -90,14 +88,55 @@ public class IsoHDPerspective implements HDPerspective { int subalpha; double mt; int[] subblock_xyz = new int[3]; + MapIterator mapiter; + + public OurPerspectiveState(MapIterator mi) { + mapiter = mi; + } /** * 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 */ - 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 */ @@ -210,40 +249,68 @@ public class IsoHDPerspective implements HDPerspective { } /* Walk through scene */ laststep = BlockStep.Y_MINUS; /* Last step is down into map */ - skylightlevel = 15; - emittedlightlevel = 0; 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 */ private boolean visit_block(MapIterator mapiter, HDShaderState[] shaderstate, boolean[] shaderdone) { blocktypeid = mapiter.getBlockTypeID(); - boolean skip_light_update = false; if(nonairhit || (blocktypeid != 0)) { blockdata = mapiter.getBlockData(); if(blocktypeid == 85) { /* Special case for fence - need to fake data so we can render properly */ - mapiter.decrementX(); /* Look north */ - blockdata = 0; - if(mapiter.getBlockTypeID() == 85) { /* Fence? */ - blockdata |= 1; - } - 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(); + blockdata = generateFenceBlockData(mapiter); + } + else if(blocktypeid == 54) { /* Special case for chest - need to fake data so we can render */ + blockdata = generateChestBlockData(mapiter); } boolean missed = false; @@ -251,14 +318,6 @@ public class IsoHDPerspective implements HDPerspective { short[] model = scalemodels.getScaledModel(blocktypeid, blockdata); if(model != null) { 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 { subalpha = -1; @@ -276,26 +335,6 @@ public class IsoHDPerspective implements HDPerspective { 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; } /** @@ -307,7 +346,6 @@ public class IsoHDPerspective implements HDPerspective { mapiter.initialize(x, y, z); - boolean nonairhit = false; for (; n > 0; --n) { /* Visit block */ if(visit_block(mapiter, shaderstate, shaderdone)) { @@ -320,12 +358,11 @@ public class IsoHDPerspective implements HDPerspective { t_next_x += dt_dx; if(x_inc > 0) { laststep = BlockStep.X_PLUS; - mapiter.incrementX(); } else { laststep = BlockStep.X_MINUS; - mapiter.decrementX(); } + mapiter.stepPosition(laststep); } /* If Y step is next best */ 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; if(y_inc > 0) { laststep = BlockStep.Y_PLUS; - mapiter.incrementY(); + mapiter.stepPosition(laststep); if(mapiter.getY() > 127) return; } else { laststep = BlockStep.Y_MINUS; - mapiter.decrementY(); + mapiter.stepPosition(laststep); if(mapiter.getY() < 0) return; } @@ -352,12 +389,11 @@ public class IsoHDPerspective implements HDPerspective { t_next_z += dt_dz; if(z_inc > 0) { laststep = BlockStep.Z_PLUS; - mapiter.incrementZ(); } else { laststep = BlockStep.Z_MINUS; - mapiter.decrementZ(); } + mapiter.stepPosition(laststep); } } } @@ -731,7 +767,7 @@ public class IsoHDPerspective implements HDPerspective { } /* Create perspective state object */ - OurPerspectiveState ps = new OurPerspectiveState(); + OurPerspectiveState ps = new OurPerspectiveState(mapiter); ps.top = new Vector3D(); ps.bottom = new Vector3D(); diff --git a/src/main/java/org/dynmap/hdmap/TexturePack.java b/src/main/java/org/dynmap/hdmap/TexturePack.java index 9671af09..1b82951c 100644 --- a/src/main/java/org/dynmap/hdmap/TexturePack.java +++ b/src/main/java/org/dynmap/hdmap/TexturePack.java @@ -21,7 +21,7 @@ import javax.imageio.ImageIO; import org.dynmap.Color; import org.dynmap.DynmapPlugin; import org.dynmap.Log; -import org.dynmap.hdmap.HDPerspectiveState.BlockStep; +import org.dynmap.utils.MapIterator.BlockStep; import org.dynmap.kzedmap.KzedMap; import org.dynmap.utils.MapIterator; @@ -736,7 +736,7 @@ public class TexturePack { break; case COLORMOD_GRASSSIDE: /* Check if snow above block */ - if(mapiter.getBlockTypeIDAbove() == 78) { + if(mapiter.getBlockTypeIDAt(BlockStep.Y_PLUS) == 78) { texture = terrain_argb[68]; /* Snow block */ textid = 68; } diff --git a/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java b/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java index faa0292e..9ef43125 100644 --- a/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java +++ b/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java @@ -2,15 +2,9 @@ package org.dynmap.hdmap; 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.ColorScheme; import org.dynmap.ConfigurationNode; import org.dynmap.Log; -import org.dynmap.hdmap.HDPerspectiveState.BlockStep; import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapIterator; import org.json.simple.JSONObject; diff --git a/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java b/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java index 7b540440..70f17240 100644 --- a/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java @@ -4,6 +4,7 @@ import org.bukkit.World; import org.dynmap.Color; import org.dynmap.ConfigurationNode; import org.dynmap.utils.MapIterator; +import org.dynmap.utils.MapIterator.BlockStep; public class CaveTileRenderer extends DefaultTileRenderer { @@ -32,14 +33,14 @@ public class CaveTileRenderer extends DefaultTileRenderer { switch (seq) { case 0: - mapiter.decrementX(); + mapiter.stepPosition(BlockStep.X_MINUS); break; case 1: case 3: - mapiter.decrementY(); + mapiter.stepPosition(BlockStep.Y_MINUS); break; case 2: - mapiter.incrementZ(); + mapiter.stepPosition(BlockStep.Z_PLUS); break; } diff --git a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java index 978abfbd..67c392e3 100644 --- a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java @@ -24,6 +24,7 @@ import org.dynmap.kzedmap.KzedMap.KzedBufferedImage; import org.dynmap.utils.FileLockManager; import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapIterator; +import org.dynmap.utils.MapIterator.BlockStep; import org.json.simple.JSONObject; public class DefaultTileRenderer implements MapTileRenderer { @@ -442,18 +443,7 @@ public class DefaultTileRenderer implements MapTileRenderer { } if((shadowscale != null) && (mapiter.getY() < 127)) { /* Find light level of previous chunk */ - switch(seq) { - case 0: - case 2: - mapiter.incrementY(); - break; - case 1: - mapiter.incrementX(); - break; - case 3: - mapiter.decrementZ(); - break; - } + BlockStep last = mapiter.unstepPosition(); lightlevel = lightlevel_day = mapiter.getBlockSkyLight(); if(lightscale != null) lightlevel = lightscale[lightlevel]; @@ -462,34 +452,23 @@ public class DefaultTileRenderer implements MapTileRenderer { lightlevel = Math.max(emitted, lightlevel); lightlevel_day = Math.max(emitted, lightlevel_day); } - switch(seq) { - case 0: - case 2: - mapiter.decrementY(); - break; - case 1: - mapiter.decrementX(); - break; - case 3: - mapiter.incrementZ(); - break; - } + mapiter.stepPosition(last); } } switch (seq) { - case 0: - mapiter.decrementX(); - break; - case 1: - case 3: - mapiter.decrementY(); - break; - case 2: - mapiter.incrementZ(); - break; + case 0: + mapiter.stepPosition(BlockStep.X_MINUS); + break; + case 1: + case 3: + mapiter.stepPosition(BlockStep.Y_MINUS); + break; + case 2: + mapiter.stepPosition(BlockStep.Z_PLUS); + break; } - + seq = (seq + 1) & 3; if (id != 0) { diff --git a/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java b/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java index f2f48850..35368f1f 100644 --- a/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java @@ -7,6 +7,7 @@ import org.bukkit.World; import org.dynmap.Color; import org.dynmap.ConfigurationNode; import org.dynmap.utils.MapIterator; +import org.dynmap.utils.MapIterator.BlockStep; public class HighlightTileRenderer extends DefaultTileRenderer { protected HashSet highlightBlocks = new HashSet(); @@ -46,16 +47,16 @@ public class HighlightTileRenderer extends DefaultTileRenderer { } switch (seq) { - case 0: - mapiter.decrementX(); - break; - case 1: - case 3: - mapiter.decrementY(); - break; - case 2: - mapiter.incrementZ(); - break; + case 0: + mapiter.stepPosition(BlockStep.X_MINUS); + break; + case 1: + case 3: + mapiter.stepPosition(BlockStep.Y_MINUS); + break; + case 2: + mapiter.stepPosition(BlockStep.Z_PLUS); + break; } seq = (seq + 1) & 3; diff --git a/src/main/java/org/dynmap/utils/LegacyMapChunkCache.java b/src/main/java/org/dynmap/utils/LegacyMapChunkCache.java index d977f01c..56709974 100644 --- a/src/main/java/org/dynmap/utils/LegacyMapChunkCache.java +++ b/src/main/java/org/dynmap/utils/LegacyMapChunkCache.java @@ -14,6 +14,7 @@ import org.dynmap.DynmapChunk; import org.dynmap.DynmapPlugin; import org.dynmap.DynmapWorld; import org.dynmap.Log; +import org.dynmap.utils.MapIterator.BlockStep; 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 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) */ public class OurMapIterator implements MapIterator { private int x, y, z; private LegacyChunkSnapshot snap; - + private BlockStep laststep; + private int typeid; + OurMapIterator(int x0, int y0, int z0) { initialize(x0, y0, z0); } @@ -61,9 +67,13 @@ public class LegacyMapChunkCache implements MapChunkCache { } catch (ArrayIndexOutOfBoundsException aioobx) { snap = EMPTY; } + laststep = BlockStep.Y_MINUS; + typeid = -1; } 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() { return snap.getBlockData(x & 0xF, y, z & 0xF); @@ -86,55 +96,76 @@ public class LegacyMapChunkCache implements MapChunkCache { public double getRawBiomeRainfall() { return 0.0; } - - public final void incrementX() { - x++; - if((x & 0xF) == 0) { /* Next chunk? */ - try { - snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; - } catch (ArrayIndexOutOfBoundsException aioobx) { - snap = EMPTY; - } + /** + * Step current position in given direction + */ + public final void stepPosition(BlockStep step) { + switch(step) { + case X_PLUS: + x++; + 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--; - if((x & 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 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; - } - } + /** + * Unstep current position to previous position + */ + public BlockStep unstepPosition() { + BlockStep ls = laststep; + stepPosition(unstep[ls.ordinal()]); + return ls; } public final void setY(int y) { + if(y > this.y) + laststep = BlockStep.Y_PLUS; + else + laststep = BlockStep.Y_PLUS; this.y = y; + typeid = -1; } public final int getX() { return x; @@ -145,12 +176,28 @@ public class LegacyMapChunkCache implements MapChunkCache { public final int getZ() { return z; } - public final int getBlockTypeIDAbove() { - if(y < 127) - return snap.getBlockTypeId(x & 0xF, y+1, z & 0xF); + public final int getBlockTypeIDAt(BlockStep s) { + if(s == BlockStep.Y_MINUS) { + 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; } - + public BlockStep getLastStep() { + return laststep; + } } /** diff --git a/src/main/java/org/dynmap/utils/MapIterator.java b/src/main/java/org/dynmap/utils/MapIterator.java index fa038504..fdad2c20 100644 --- a/src/main/java/org/dynmap/utils/MapIterator.java +++ b/src/main/java/org/dynmap/utils/MapIterator.java @@ -6,6 +6,15 @@ import org.bukkit.block.Biome; * Iterator for traversing map chunk cache (base is for non-snapshot) */ 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 * @@ -53,29 +62,13 @@ public interface MapIterator { */ 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(); - /** - * 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(); + BlockStep unstepPosition(); /** * Set Y coordinate of current position * @param y @@ -94,10 +87,13 @@ public interface MapIterator { */ int getZ(); /** - * Get block ID at one above current coordinates + * Get block ID at 1 step in given direction * * @return block id */ - int getBlockTypeIDAbove(); - + int getBlockTypeIDAt(BlockStep s); + /** + * Get last step taken + */ + BlockStep getLastStep(); } diff --git a/src/main/java/org/dynmap/utils/NewMapChunkCache.java b/src/main/java/org/dynmap/utils/NewMapChunkCache.java index 463af3fd..0bb01e08 100644 --- a/src/main/java/org/dynmap/utils/NewMapChunkCache.java +++ b/src/main/java/org/dynmap/utils/NewMapChunkCache.java @@ -16,6 +16,7 @@ import org.dynmap.DynmapPlugin; import org.dynmap.DynmapWorld; import org.dynmap.Log; 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 @@ -42,13 +43,18 @@ public class NewMapChunkCache implements MapChunkCache { private boolean isempty = true; 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) */ public class OurMapIterator implements MapIterator { - private int x, y, z; + private int x, y, z, chunkindex, bx, bz; private ChunkSnapshot snap; + private BlockStep laststep; + private int typeid = -1; OurMapIterator(int x0, int y0, int z0) { initialize(x0, y0, z0); @@ -57,84 +63,125 @@ public class NewMapChunkCache implements MapChunkCache { this.x = x0; this.y = y0; this.z = z0; + this.chunkindex = ((x >> 4) - x_min) + (((z >> 4) - z_min) * x_dim); + this.bx = x & 0xF; + this.bz = z & 0xF; try { - snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; + snap = snaparray[chunkindex]; } catch (ArrayIndexOutOfBoundsException aioobx) { snap = EMPTY; } + laststep = BlockStep.Y_MINUS; + typeid = -1; } 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() { - return snap.getBlockData(x & 0xF, y, z & 0xF); + return snap.getBlockData(bx, y, bz); } public final int getHighestBlockYAt() { - return snap.getHighestBlockYAt(x & 0xF, z & 0xF); + return snap.getHighestBlockYAt(bx, bz); } public final int getBlockSkyLight() { - return snap.getBlockSkyLight(x & 0xF, y, z & 0xF); + return snap.getBlockSkyLight(bx, y, bz); } public final int getBlockEmittedLight() { - return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF); + return snap.getBlockEmittedLight(bx, y, bz); } public Biome getBiome() { - return snap.getBiome(x & 0xF, z & 0xF); + return snap.getBiome(bx, bz); } public double getRawBiomeTemperature() { - return snap.getRawBiomeTemperature(x & 0xf, z & 0xf); + return snap.getRawBiomeTemperature(bx, bz); } public double getRawBiomeRainfall() { - return snap.getRawBiomeRainfall(x & 0xf, z & 0xf); + return snap.getRawBiomeRainfall(bx, bz); } - public final void incrementX() { - x++; - if((x & 0xF) == 0) { /* Next chunk? */ - try { - snap = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; - } catch (ArrayIndexOutOfBoundsException aioobx) { - snap = EMPTY; - } + /** + * Step current position in given direction + */ + public final void stepPosition(BlockStep step) { + switch(step.ordinal()) { + case 0: + 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--; - if((x & 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 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; - } - } + /** + * Unstep current position to previous position + */ + public BlockStep unstepPosition() { + BlockStep ls = laststep; + stepPosition(unstep[ls.ordinal()]); + return ls; } public final void setY(int y) { + if(y > this.y) + laststep = BlockStep.Y_PLUS; + else + laststep = BlockStep.Y_PLUS; this.y = y; + typeid = -1; } public final int getX() { return x; @@ -145,11 +192,28 @@ public class NewMapChunkCache implements MapChunkCache { public final int getZ() { return z; } - public final int getBlockTypeIDAbove() { - if(y < 127) - return snap.getBlockTypeId(x & 0xF, y+1, z & 0xF); + public final int getBlockTypeIDAt(BlockStep s) { + if(s == BlockStep.Y_MINUS) { + 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; } + public BlockStep getLastStep() { + return laststep; + } } /**