diff --git a/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/MapChunkCache114.java b/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/MapChunkCache114.java index b58b97b8..9bc72a5e 100644 --- a/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/MapChunkCache114.java +++ b/bukkit-helper-114/src/main/java/org/dynmap/bukkit/helper/v114/MapChunkCache114.java @@ -1,6 +1,12 @@ package org.dynmap.bukkit.helper.v114; import org.bukkit.block.Biome; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; + import org.bukkit.ChunkSnapshot; import org.bukkit.World; import org.dynmap.bukkit.helper.AbstractMapChunkCache; @@ -64,13 +70,14 @@ public class MapChunkCache114 extends AbstractMapChunkCache { public Snapshot wrapChunkSnapshot(ChunkSnapshot css) { return new WrappedSnapshot(css); } + @Override public boolean loadChunkNoGenerate(World w, int x, int z) { boolean generated = true; // Check one in each direction: see if all are generated - for (int xx = x-4; xx <= x+4; xx++) { - for (int zz = z-4; zz <= z+4; zz++) { - if (w.isChunkGenerated(xx, zz) == false) { + for (int xx = x-3; xx <= x+3; xx++) { + for (int zz = z-3; zz <= z+3; zz++) { + if (isChunkGenerated(w, xx, zz) == false) { generated = false; break; } @@ -82,4 +89,52 @@ public class MapChunkCache114 extends AbstractMapChunkCache { } return rslt; } + + private static class CacheRec { + long timestamp; + long[] blockmap; // ( bit = 1 at blockmap[z] & (1 << x)) + } + private static HashMap regioncache = new HashMap(); + private static long CACHE_TIMEOUT = 15000L; // 15 second cache + + private static boolean isChunkGenerated(World w, int x, int z) { + String fn = String.format("%s/region/r.%d.%d.mca", w.getWorldFolder().getPath(), (x >> 5), (z >> 5)); + CacheRec rec = regioncache.get(fn); + long ts = System.currentTimeMillis(); + if ((rec == null) || (rec.timestamp < ts)) { + if (rec == null) { + rec = new CacheRec(); + rec.blockmap = new long[32]; + } + rec.timestamp = ts + CACHE_TIMEOUT; + RandomAccessFile raf = null; + byte[] dat = new byte[4096]; + try { + raf = new RandomAccessFile(fn, "r"); + raf.seek(0); + raf.read(dat); + } catch (IOException iox) { + } finally { + if (raf != null) { + try { + raf.close(); + } catch (IOException iox) { + } + } + } + // Build cache map + for (int zz = 0; zz < 32; zz++) { + long val = 0; + for (int xx = 0; xx < 32; xx++) { + int off = 4*((zz << 5) + xx); + int v = dat[off] | dat[off+1] | dat[off+2] | dat[off+3]; + if (v != 0) + val |= (1L << xx); + } + rec.blockmap[zz] = val; + } + regioncache.put(fn, rec); + } + return (rec.blockmap[z & 31] & (1L << (x & 31))) != 0; + } }