From 0166895a7fb892af089aa671bd282089fa1abe56 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Tue, 28 Dec 2021 22:14:19 -0600 Subject: [PATCH] Tune memory use on generic chunks, lighting lookup performance --- .../org/dynmap/common/chunk/GenericChunk.java | 8 +-- .../common/chunk/GenericChunkSection.java | 49 +++++++++++++++++++ .../common/chunk/GenericMapChunkCache.java | 41 +++++++++++++--- .../org/dynmap/hdmap/IsoHDPerspective.java | 28 ++++------- .../java/org/dynmap/utils/DynLongHashMap.java | 9 ++-- .../java/org/dynmap/utils/MapIterator.java | 5 ++ .../bukkit/helper/AbstractMapChunkCache.java | 24 +++++++++ .../fabric_1_14_4/FabricMapChunkCache.java | 23 +++++++++ .../fabric_1_15_2/FabricMapChunkCache.java | 23 +++++++++ .../forge_1_11_2/ForgeMapChunkCache.java | 23 +++++++++ .../forge_1_12_2/ForgeMapChunkCache.java | 26 +++++++++- .../forge_1_13_2/ForgeMapChunkCache.java | 26 +++++++++- .../forge_1_14_4/ForgeMapChunkCache.java | 26 +++++++++- .../forge_1_15_2/ForgeMapChunkCache.java | 26 +++++++++- 14 files changed, 300 insertions(+), 37 deletions(-) diff --git a/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunk.java b/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunk.java index 62c746c4..d6c97045 100644 --- a/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunk.java +++ b/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunk.java @@ -9,6 +9,7 @@ import org.dynmap.common.BiomeMap; public class GenericChunk { public final int cx, cz; // Chunk coord (world coord / 16) public final GenericChunkSection[] sections; + public final int sectionCnt; public final int cy_min; // CY value of first section in sections list (index = (Y >> 4) - cy_min public final long inhabitedTicks; public final int dataVersion; // Version of chunk data loaded @@ -31,15 +32,16 @@ public class GenericChunk { empty = empty && sections[off].isEmpty; } } + this.sectionCnt = sections.length; this.isEmpty = empty; } // Get section for given block Y coord public final GenericChunkSection getSection(int y) { - try { - return this.sections[(y >> 4) - cy_min]; - } catch (IndexOutOfBoundsException ioobx) { // Builder and padding should be avoiding this, but be safe + int idx = (y >> 4) - this.cy_min; + if ((idx < 0) || (idx >= sectionCnt)) { return GenericChunkSection.EMPTY; } + return this.sections[idx]; } public final DynmapBlockState getBlockType(int x, int y, int z) { diff --git a/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunkSection.java b/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunkSection.java index d674b3a8..0d7fd630 100644 --- a/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunkSection.java +++ b/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericChunkSection.java @@ -31,6 +31,21 @@ public class GenericChunkSection { return blocks[pos.soffset]; } } + private static class BlockStateAccess3DPalette implements BlockStateAccess { + private final DynmapBlockState palette[]; + private final short[] blocks; // YZX order + // Array given to us by builder + BlockStateAccess3DPalette(DynmapBlockState pal[], short[] blks) { + blocks = blks; + palette = pal; + } + public final DynmapBlockState getBlock(int x, int y, int z) { + return palette[blocks[(256 * (y & 0xF)) + (16 * (z & 0xF)) + (x & 0xF)]]; + } + public final DynmapBlockState getBlock(GenericChunkPos pos) { + return palette[blocks[pos.soffset]]; + } + } private static class BlockStateAccessSingle implements BlockStateAccess { private final DynmapBlockState block; BlockStateAccessSingle(DynmapBlockState bs) { @@ -157,6 +172,8 @@ public class GenericChunkSection { private LightingAccess em; private DynmapBlockState bsaccumsing; // Used for single private DynmapBlockState bsaccum[]; // Use for incremental setting of 3D - YZX order + private short[] bsblks; // Use for incremental setting of 3D palette - XZY order + private DynmapBlockState[] bspal; // Palette for bsblks private BiomeMap baaccumsingle; // Use for single private BiomeMap baaccum[]; // Use for incremental setting of 3D biome - YZX order or 2D biome (ZX order) length used to control which private boolean empty; @@ -170,6 +187,8 @@ public class GenericChunkSection { bsaccum = null; baaccumsingle = BiomeMap.NULL; baaccum = null; + bsblks = null; + bspal = null; sk = defaultLight; em = defaultLight; empty = true; @@ -224,6 +243,8 @@ public class GenericChunkSection { public Builder singleBlockState(DynmapBlockState block) { bsaccumsing = block; bsaccum = null; + bsblks = null; + bspal = null; empty = block.isAir(); return this; } @@ -238,6 +259,23 @@ public class GenericChunkSection { empty = false; return this; } + // Set block state palette (states will be indexes vs this + public Builder xyzBlockStatePalette(DynmapBlockState[] bspalette) { + if (bsblks == null) { + bsblks = new short[4096]; + } + bspal = Arrays.copyOf(bspalette, bspalette.length); + return this; + } + // Set block state using palette + public Builder xyzBlockStateInPalette(int x, int y, int z, short palidx) { + if (bsblks == null) { + bsblks = new short[4096]; + } + bsblks[((y & 0xF) << 8) + ((z & 0xF) << 4) + (x & 0xF)] = palidx; + empty = false; + return this; + } // Build copy from existing section with new skylight (YZX nibble array) public GenericChunkSection buildFrom(GenericChunkSection s, byte[] sky) { LightingAccess skyA = new LightingAccess3D(sky); @@ -272,6 +310,17 @@ public class GenericChunkSection { bsaccum = null; empty = false; } + else if (bspal != null) { // 3D palette + // Only one state in palette? + if (bspal.length == 1) { + bs = new BlockStateAccessSingle(bspal[0]); // Just single + } + else { + bs = new BlockStateAccess3DPalette(bspal, bsblks); + } + bspal = null; + bsblks = null; + } else if (bsaccumsing == DynmapBlockState.AIR) { // Just air? bs = defaultBlockState; empty = true; diff --git a/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericMapChunkCache.java b/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericMapChunkCache.java index c3b4f9c3..560843ae 100644 --- a/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericMapChunkCache.java +++ b/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericMapChunkCache.java @@ -101,7 +101,32 @@ public abstract class GenericMapChunkCache extends MapChunkCache { return 0; } } - + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + GenericChunkSection sect; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + sect = snap.getSection(ny); + emit = sect.emitted.getLight(x, ny, z); + sky = sect.sky.getLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + sect = snaparray[nchunkindex].getSection(y); + emit = sect.emitted.getLight(nx, y, nz); + sky = sect.sky.getLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } @Override public final BiomeMap getBiome() { try { @@ -1007,11 +1032,11 @@ public abstract class GenericMapChunkCache extends MapChunkCache { } } else { - for (int j = 0; j < 4096; j++) { - int v = (dbp != null) ? dbp.getAt(j) : db.get(j); - DynmapBlockState bs = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; - sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, bs); - } + sbld.xyzBlockStatePalette(palette); // Set palette + for (int j = 0; j < 4096; j++) { + int v = db != null ? db.get(j) : dbp.getAt(j); + sbld.xyzBlockStateInPalette(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, (short)v); + } } } else if (sec.contains("block_states", GenericNBTCompound.TAG_COMPOUND)) { // 1.18 @@ -1059,10 +1084,10 @@ public abstract class GenericMapChunkCache extends MapChunkCache { } } else { + sbld.xyzBlockStatePalette(palette); // Set palette for (int j = 0; j < 4096; j++) { int v = db != null ? db.get(j) : dbp.getAt(j); - DynmapBlockState bs = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; - sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, bs); + sbld.xyzBlockStateInPalette(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, (short)v); } } } diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java b/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java index 2b2abcdf..1ae259be 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java @@ -149,8 +149,8 @@ public class IsoHDPerspective implements HDPerspective { llcache = new LightLevels[4]; for(int i = 0; i < llcache.length; i++) llcache[i] = new LightLevels(); - custom_meshes = new DynLongHashMap(); - custom_fluid_meshes = new DynLongHashMap(); + custom_meshes = new DynLongHashMap(4096); + custom_fluid_meshes = new DynLongHashMap(4096); modscale = basemodscale << scaled; scalemodels = HDBlockModels.getModelsForScale(basemodscale << scaled); } @@ -158,13 +158,9 @@ public class IsoHDPerspective implements HDPerspective { private final void updateSemitransparentLight(LightLevels ll) { int emitted = 0, sky = 0; for(int i = 0; i < semi_steps.length; i++) { - BlockStep s = semi_steps[i]; - mapiter.stepPosition(s); - int v = mapiter.getBlockEmittedLight(); - if(v > emitted) emitted = v; - v = mapiter.getBlockSkyLight(); - if(v > sky) sky = v; - mapiter.unstepPosition(s); + int emit_sky_light = mapiter.getBlockLight(semi_steps[i]); + if ((emit_sky_light >> 8) > emitted) emitted = (emit_sky_light >> 8); + if ((emit_sky_light & 0xF) > sky) sky = (emit_sky_light & 0xF); } ll.sky = sky; ll.emitted = emitted; @@ -181,16 +177,10 @@ public class IsoHDPerspective implements HDPerspective { ll.emitted = mapiter.getBlockEmittedLight(); break; case OPAQUE: - if(HDBlockStateTextureMap.getTransparency(lastblocktype) != BlockTransparency.SEMITRANSPARENT) { - mapiter.unstepPosition(laststep); /* Back up to block we entered on */ - if(mapiter.getY() < worldheight) { - ll.sky = mapiter.getBlockSkyLight(); - ll.emitted = mapiter.getBlockEmittedLight(); - } else { - ll.sky = 15; - ll.emitted = 0; - } - mapiter.stepPosition(laststep); + if (HDBlockStateTextureMap.getTransparency(lastblocktype) != BlockTransparency.SEMITRANSPARENT) { + int emit_sky_light = mapiter.getBlockLight(laststep.opposite()); + ll.sky = emit_sky_light & 0xF; + ll.emitted = emit_sky_light >> 8; } else { mapiter.unstepPosition(laststep); /* Back up to block we entered on */ diff --git a/DynmapCore/src/main/java/org/dynmap/utils/DynLongHashMap.java b/DynmapCore/src/main/java/org/dynmap/utils/DynLongHashMap.java index d7e36a16..23126a0c 100644 --- a/DynmapCore/src/main/java/org/dynmap/utils/DynLongHashMap.java +++ b/DynmapCore/src/main/java/org/dynmap/utils/DynLongHashMap.java @@ -236,6 +236,9 @@ public class DynLongHashMap return getEntry(key) != null; } + private static final int toHash(long key) { + return (int)((key >>> 32) ^ key); + } /** * Returns the entry associated with the specified key in the * HashMap. Returns null if the HashMap contains no mapping @@ -243,7 +246,7 @@ public class DynLongHashMap */ Entry getEntry(long key) { Entry tab[] = table; - int hash = (int) key; + int hash = toHash(key); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry e = tab[index]; e != null; e = e.next) @@ -293,7 +296,7 @@ public class DynLongHashMap */ public Object put(long key, Object value) { Entry tab[] = table; - int hash = (int) key; + int hash = toHash(key); int index = (hash & 0x7FFFFFFF) % tab.length; // Look for entry in hash table @@ -340,7 +343,7 @@ public class DynLongHashMap */ Entry removeEntryForKey(long key) { Entry tab[] = table; - int hash = (int) key; + int hash = toHash(key); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry e = tab[index], prev = null; e != null; diff --git a/DynmapCore/src/main/java/org/dynmap/utils/MapIterator.java b/DynmapCore/src/main/java/org/dynmap/utils/MapIterator.java index f4865303..839cca3c 100644 --- a/DynmapCore/src/main/java/org/dynmap/utils/MapIterator.java +++ b/DynmapCore/src/main/java/org/dynmap/utils/MapIterator.java @@ -26,6 +26,11 @@ public interface MapIterator extends MapDataContext { * @return emitted light level */ int getBlockEmittedLight(); + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + int getBlockLight(BlockStep step); /** * Get biome at coordinates * @return biome diff --git a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/AbstractMapChunkCache.java b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/AbstractMapChunkCache.java index fa2e5dd0..460eb548 100644 --- a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/AbstractMapChunkCache.java +++ b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/AbstractMapChunkCache.java @@ -158,6 +158,30 @@ public abstract class AbstractMapChunkCache extends MapChunkCache { } return 0; } + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } + private void biomePrep() { if(sameneighborbiomecnt != null) return; diff --git a/fabric-1.14.4/src/main/java/org/dynmap/fabric_1_14_4/FabricMapChunkCache.java b/fabric-1.14.4/src/main/java/org/dynmap/fabric_1_14_4/FabricMapChunkCache.java index b3fce991..482d7950 100644 --- a/fabric-1.14.4/src/main/java/org/dynmap/fabric_1_14_4/FabricMapChunkCache.java +++ b/fabric-1.14.4/src/main/java/org/dynmap/fabric_1_14_4/FabricMapChunkCache.java @@ -132,6 +132,29 @@ public class FabricMapChunkCache extends MapChunkCache { return 0; } } + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } private void biomePrep() { if (sameneighborbiomecnt != null) { diff --git a/fabric-1.15.2/src/main/java/org/dynmap/fabric_1_15_2/FabricMapChunkCache.java b/fabric-1.15.2/src/main/java/org/dynmap/fabric_1_15_2/FabricMapChunkCache.java index c20d6a3e..3a71dc11 100644 --- a/fabric-1.15.2/src/main/java/org/dynmap/fabric_1_15_2/FabricMapChunkCache.java +++ b/fabric-1.15.2/src/main/java/org/dynmap/fabric_1_15_2/FabricMapChunkCache.java @@ -132,6 +132,29 @@ public class FabricMapChunkCache extends MapChunkCache { return 0; } } + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } private void biomePrep() { if (sameneighborbiomecnt != null) { diff --git a/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ForgeMapChunkCache.java b/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ForgeMapChunkCache.java index 481cfc56..6abe9d3c 100644 --- a/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ForgeMapChunkCache.java +++ b/forge-1.11.2/src/main/java/org/dynmap/forge_1_11_2/ForgeMapChunkCache.java @@ -177,6 +177,29 @@ public class ForgeMapChunkCache extends MapChunkCache return 0; } } + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } private void biomePrep() { if (sameneighborbiomecnt != null) diff --git a/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ForgeMapChunkCache.java b/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ForgeMapChunkCache.java index e329d7ba..a878820a 100644 --- a/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ForgeMapChunkCache.java +++ b/forge-1.12.2/src/main/java/org/dynmap/forge_1_12_2/ForgeMapChunkCache.java @@ -177,7 +177,31 @@ public class ForgeMapChunkCache extends MapChunkCache return 0; } } - private void biomePrep() + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } + + private void biomePrep() { if (sameneighborbiomecnt != null) { diff --git a/forge-1.13.2/src/main/java/org/dynmap/forge_1_13_2/ForgeMapChunkCache.java b/forge-1.13.2/src/main/java/org/dynmap/forge_1_13_2/ForgeMapChunkCache.java index 2fc6f4d9..cc25d6e7 100644 --- a/forge-1.13.2/src/main/java/org/dynmap/forge_1_13_2/ForgeMapChunkCache.java +++ b/forge-1.13.2/src/main/java/org/dynmap/forge_1_13_2/ForgeMapChunkCache.java @@ -178,7 +178,31 @@ public class ForgeMapChunkCache extends MapChunkCache return 0; } } - private void biomePrep() + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } + + private void biomePrep() { if (sameneighborbiomecnt != null) { diff --git a/forge-1.14.4/src/main/java/org/dynmap/forge_1_14_4/ForgeMapChunkCache.java b/forge-1.14.4/src/main/java/org/dynmap/forge_1_14_4/ForgeMapChunkCache.java index 3f7952c8..48d13de7 100644 --- a/forge-1.14.4/src/main/java/org/dynmap/forge_1_14_4/ForgeMapChunkCache.java +++ b/forge-1.14.4/src/main/java/org/dynmap/forge_1_14_4/ForgeMapChunkCache.java @@ -174,7 +174,31 @@ public class ForgeMapChunkCache extends MapChunkCache return 0; } } - private void biomePrep() + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } + + private void biomePrep() { if (sameneighborbiomecnt != null) { diff --git a/forge-1.15.2/src/main/java/org/dynmap/forge_1_15_2/ForgeMapChunkCache.java b/forge-1.15.2/src/main/java/org/dynmap/forge_1_15_2/ForgeMapChunkCache.java index 3d89500d..9dfc4904 100644 --- a/forge-1.15.2/src/main/java/org/dynmap/forge_1_15_2/ForgeMapChunkCache.java +++ b/forge-1.15.2/src/main/java/org/dynmap/forge_1_15_2/ForgeMapChunkCache.java @@ -174,7 +174,31 @@ public class ForgeMapChunkCache extends MapChunkCache return 0; } } - private void biomePrep() + @Override + /** + * Get block sky and emitted light, relative to current coordinate + * @return (emitted light * 256) + sky light + */ + public final int getBlockLight(BlockStep step) { + int emit = 0, sky = 15; + if (step.yoff != 0) { // Y coord - snap is valid already + int ny = y + step.yoff; + emit = snap.getBlockEmittedLight(x, ny, z); + sky = snap.getBlockSkyLight(x, ny, z); + } + else { + int nx = x + step.xoff; + int nz = z + step.zoff; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex < snapcnt) && (nchunkindex >= 0)) { + emit = snaparray[nchunkindex].getBlockEmittedLight(nx, y, nz); + sky = snaparray[nchunkindex].getBlockSkyLight(nx, y, nz); + } + } + return (emit << 8) + sky; + } + + private void biomePrep() { if (sameneighborbiomecnt != null) {