From 37fd0644347ace4d794b462544dfbec50d06059d Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sun, 5 Dec 2021 01:57:59 -0600 Subject: [PATCH] Put 3D biome code in spigot 1.18 - still working on grass shading... --- .../main/java/org/dynmap/common/BiomeMap.java | 34 +- .../common/chunk/GenericMapChunkCache.java | 262 ++---- .../v118/BukkitVersionHelperSpigot118.java | 11 +- .../bukkit/helper/v118/MapChunkCache118.java | 799 ++++++------------ .../bukkit/helper/BukkitVersionHelper.java | 6 + .../org/dynmap/fabric_1_18/DynmapPlugin.java | 2 +- .../org/dynmap/forge_1_18/DynmapPlugin.java | 2 +- .../java/org/dynmap/bukkit/DynmapPlugin.java | 76 +- 8 files changed, 430 insertions(+), 762 deletions(-) diff --git a/DynmapCore/src/main/java/org/dynmap/common/BiomeMap.java b/DynmapCore/src/main/java/org/dynmap/common/BiomeMap.java index 993382f7..e782e688 100644 --- a/DynmapCore/src/main/java/org/dynmap/common/BiomeMap.java +++ b/DynmapCore/src/main/java/org/dynmap/common/BiomeMap.java @@ -1,5 +1,6 @@ package org.dynmap.common; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -9,7 +10,7 @@ import org.dynmap.hdmap.HDBlockModels; /* Generic biome mapping */ public class BiomeMap { public static final int NO_INDEX = -2; - private static BiomeMap[] biome_by_index = new BiomeMap[1025]; + private static BiomeMap[] biome_by_index = new BiomeMap[256]; private static Map biome_by_rl = new HashMap(); public static final BiomeMap NULL = new BiomeMap(-1, "NULL", 0.5, 0.5, 0xFFFFFF, 0, 0, null); @@ -37,7 +38,7 @@ public class BiomeMap { public static final BiomeMap JUNGLE = new BiomeMap(21, "JUNGLE", 1.2, 0.9, "minecraft:jungle"); public static final BiomeMap JUNGLE_HILLS = new BiomeMap(22, "JUNGLE_HILLS", 1.2, 0.9, "minecraft:jungle_hills"); - public static final int LAST_WELL_KNOWN = 22; + public static final int LAST_WELL_KNOWN = 175; private double tmp; private double rain; @@ -128,7 +129,7 @@ public class BiomeMap { } static { - for (int i = 0; i < 1024; i++) { + for (int i = 0; i < 256; i++) { BiomeMap bm = BiomeMap.byBiomeID(i); if (bm == null) { bm = new BiomeMap(i, "BIOME_" + i); @@ -145,6 +146,20 @@ public class BiomeMap { } return true; } + + private static void resizeIfNeeded(int idx) { + if ((idx >= biome_by_index.length) ) { + int oldlen = biome_by_index.length; + biome_by_index = Arrays.copyOf(biome_by_index, biome_by_index.length * 3 / 2); + for (int i = oldlen; i < biome_by_index.length; i++) { + if (biome_by_index[i] == null) { + BiomeMap bm = new BiomeMap(i, "BIOME_" + i); + bm.isDef = true; + } + } + } + } + private BiomeMap(int idx, String id, double tmp, double rain, int waterColorMultiplier, int grassmult, int foliagemult, String rl) { /* Clamp values : we use raw values from MC code, which are clamped during color mapping only */ setTemperature(tmp); @@ -159,10 +174,21 @@ public class BiomeMap { id = id + "_" + idx; } this.id = id; + // If index is NO_INDEX, find one after the well known ones + if (idx == NO_INDEX) { + idx = LAST_WELL_KNOWN + 1; + while (true) { + resizeIfNeeded(idx); + if (biome_by_index[idx].isDef) { + break; + } + } + } idx++; /* Insert one after ID value - null is zero index */ this.index = idx; if (idx >= 0) { - biome_by_index[idx] = this; + resizeIfNeeded(idx); + biome_by_index[idx] = this; } this.resourcelocation = rl; if (rl != null) { 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 6cfe0b2c..c9828e14 100644 --- a/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericMapChunkCache.java +++ b/DynmapCore/src/main/java/org/dynmap/common/chunk/GenericMapChunkCache.java @@ -36,8 +36,6 @@ public abstract class GenericMapChunkCache extends MapChunkCache { private boolean isempty = true; private int snapcnt; private GenericChunk[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */ - private byte[][] sameneighborbiomecnt; - private BiomeMap[][] biomemap; private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */ private static final BlockStep unstep[] = { BlockStep.X_MINUS, BlockStep.Y_MINUS, BlockStep.Z_MINUS, @@ -64,8 +62,6 @@ public abstract class GenericMapChunkCache extends MapChunkCache { x_base = x_min << 4; z_base = z_min << 4; - biomePrep(); - initialize(x0, y0, z0); worldheight = dw.worldheight; ymin = dw.minY; @@ -113,100 +109,46 @@ public abstract class GenericMapChunkCache extends MapChunkCache { } } - private void biomePrep() { - if (sameneighborbiomecnt != null) { - return; - } - - int x_size = x_dim << 4; - int z_size = (z_max - z_min + 1) << 4; - sameneighborbiomecnt = new byte[x_size][]; - biomemap = new BiomeMap[x_size][]; - - for (int i = 0; i < x_size; i++) { - sameneighborbiomecnt[i] = new byte[z_size]; - biomemap[i] = new BiomeMap[z_size]; - } - - for (int i = 0; i < x_size; i++) { - for (int j = 0; j < z_size; j++) { - if (j == 0) - initialize(i + x_base, 64, z_base); - else - stepPosition(BlockStep.Z_PLUS); - - BiomeMap bm = snap.getBiome(bx, y, bz); - - biomemap[i][j] = bm; - int cnt = 0; - - if (i > 0) { - if (bm == biomemap[i - 1][j]) /* Same as one to left */ - { - cnt++; - sameneighborbiomecnt[i - 1][j]++; - } - - if ((j > 0) && (bm == biomemap[i - 1][j - 1])) { - cnt++; - sameneighborbiomecnt[i - 1][j - 1]++; - } - - if ((j < (z_size - 1)) && (bm == biomemap[i - 1][j + 1])) { - cnt++; - sameneighborbiomecnt[i - 1][j + 1]++; - } - } - - if ((j > 0) && (biomemap[i][j] == biomemap[i][j - 1])) /* Same as one to above */ - { - cnt++; - sameneighborbiomecnt[i][j - 1]++; - } - - sameneighborbiomecnt[i][j] = (byte) cnt; - } - } - } - @Override public final BiomeMap getBiome() { try { - return biomemap[x - x_base][z - z_base]; + return snap.getBiome(bx, y, bz); } catch (Exception ex) { return BiomeMap.NULL; } } + private final BiomeMap getBiomeRel(int dx, int dz) { + int nx = x + dx; + int nz = z + dz; + int nchunkindex = ((nx >> 4) - x_min) + (((nz >> 4) - z_min) * x_dim); + if ((nchunkindex >= snapcnt) || (nchunkindex < 0)) { + return BiomeMap.NULL; + } else { + return snaparray[chunkindex].getBiome(nx, y, nz); + } + } + @Override public final int getSmoothGrassColorMultiplier(int[] colormap) { int mult = 0xFFFFFF; try { - int rx = x - x_base; - int rz = z - z_base; - BiomeMap bm = biomemap[rx][rz]; - - if (sameneighborbiomecnt[rx][rz] >= (byte) 8) /* All neighbors same? */ - { - mult = bm.getModifiedGrassMultiplier(colormap[bm.biomeLookup()]); - } else { - int raccum = 0; - int gaccum = 0; - int baccum = 0; - - for (int xoff = -1; xoff < 2; xoff++) { - for (int zoff = -1; zoff < 2; zoff++) { - bm = biomemap[rx + xoff][rz + zoff]; - int rmult = bm.getModifiedGrassMultiplier(colormap[bm.biomeLookup()]); - raccum += (rmult >> 16) & 0xFF; - gaccum += (rmult >> 8) & 0xFF; - baccum += rmult & 0xFF; - } + int raccum = 0; + int gaccum = 0; + int baccum = 0; + int cnt = 0; + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + BiomeMap bm = getBiomeRel(dx, dz); + int rmult = bm.getModifiedGrassMultiplier(colormap[bm.biomeLookup()]); + raccum += (rmult >> 16) & 0xFF; + gaccum += (rmult >> 8) & 0xFF; + baccum += rmult & 0xFF; + cnt++; } - - mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9); } + mult = ((raccum / cnt) << 16) | ((gaccum / cnt) << 8) | (baccum / cnt); } catch (Exception x) { //Log.info("getSmoothGrassColorMultiplier() error: " + x); mult = 0xFFFFFF; @@ -221,30 +163,21 @@ public abstract class GenericMapChunkCache extends MapChunkCache { int mult = 0xFFFFFF; try { - int rx = x - x_base; - int rz = z - z_base; - BiomeMap bm = biomemap[rx][rz]; - - if (sameneighborbiomecnt[rx][rz] >= (byte) 8) /* All neighbors same? */ - { - mult = bm.getModifiedFoliageMultiplier(colormap[bm.biomeLookup()]); - } else { - int raccum = 0; - int gaccum = 0; - int baccum = 0; - - for (int xoff = -1; xoff < 2; xoff++) { - for (int zoff = -1; zoff < 2; zoff++) { - bm = biomemap[rx + xoff][rz + zoff]; - int rmult = bm.getModifiedFoliageMultiplier(colormap[bm.biomeLookup()]); - raccum += (rmult >> 16) & 0xFF; - gaccum += (rmult >> 8) & 0xFF; - baccum += rmult & 0xFF; - } + int raccum = 0; + int gaccum = 0; + int baccum = 0; + int cnt = 0; + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + BiomeMap bm = getBiomeRel(dx, dz); + int rmult = bm.getModifiedFoliageMultiplier(colormap[bm.biomeLookup()]); + raccum += (rmult >> 16) & 0xFF; + gaccum += (rmult >> 8) & 0xFF; + baccum += rmult & 0xFF; + cnt++; } - - mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9); } + mult = ((raccum / cnt) << 16) | ((gaccum / cnt) << 8) | (baccum / cnt); } catch (Exception x) { //Log.info("getSmoothFoliageColorMultiplier() error: " + x); mult = 0xFFFFFF; @@ -259,41 +192,26 @@ public abstract class GenericMapChunkCache extends MapChunkCache { int mult = 0xFFFFFF; try { - int rx = x - x_base; - int rz = z - z_base; - BiomeMap bm = biomemap[rx][rz]; - - if (sameneighborbiomecnt[rx][rz] >= (byte) 8) /* All neighbors same? */ - { - if (bm == BiomeMap.SWAMPLAND) { - mult = swampmap[bm.biomeLookup()]; - } else { - mult = colormap[bm.biomeLookup()]; - } - } else { - int raccum = 0; - int gaccum = 0; - int baccum = 0; - - for (int xoff = -1; xoff < 2; xoff++) { - for (int zoff = -1; zoff < 2; zoff++) { - bm = biomemap[rx + xoff][rz + zoff]; - int rmult; - - if (bm == BiomeMap.SWAMPLAND) { - rmult = swampmap[bm.biomeLookup()]; - } else { - rmult = colormap[bm.biomeLookup()]; - } - - raccum += (rmult >> 16) & 0xFF; - gaccum += (rmult >> 8) & 0xFF; - baccum += rmult & 0xFF; + int raccum = 0; + int gaccum = 0; + int baccum = 0; + int cnt = 0; + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + BiomeMap bm = getBiomeRel(dx, dz); + int rmult; + if (bm == BiomeMap.SWAMPLAND) { + rmult = swampmap[bm.biomeLookup()]; + } else { + rmult = colormap[bm.biomeLookup()]; } + raccum += (rmult >> 16) & 0xFF; + gaccum += (rmult >> 8) & 0xFF; + baccum += rmult & 0xFF; + cnt++; } - - mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9); } + mult = ((raccum / cnt) << 16) | ((gaccum / cnt) << 8) | (baccum / cnt); } catch (Exception x) { //Log.info("getSmoothColorMultiplier() error: " + x); mult = 0xFFFFFF; @@ -307,30 +225,21 @@ public abstract class GenericMapChunkCache extends MapChunkCache { public final int getSmoothWaterColorMultiplier() { int multv; try { - int rx = x - x_base; - int rz = z - z_base; - BiomeMap bm = biomemap[rx][rz]; - - if (sameneighborbiomecnt[rx][rz] >= (byte) 8) /* All neighbors same? */ - { - multv = bm.getWaterColorMult(); - } else { - int raccum = 0; - int gaccum = 0; - int baccum = 0; - - for (int xoff = -1; xoff < 2; xoff++) { - for (int zoff = -1; zoff < 2; zoff++) { - bm = biomemap[rx + xoff][rz + zoff]; - int mult = bm.getWaterColorMult(); - raccum += (mult >> 16) & 0xFF; - gaccum += (mult >> 8) & 0xFF; - baccum += mult & 0xFF; - } + int raccum = 0; + int gaccum = 0; + int baccum = 0; + int cnt = 0; + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + BiomeMap bm = getBiomeRel(dx, dz); + int rmult = bm.getWaterColorMult(); + raccum += (rmult >> 16) & 0xFF; + gaccum += (rmult >> 8) & 0xFF; + baccum += rmult & 0xFF; + cnt++; } - - multv = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9); } + multv = ((raccum / cnt) << 16) | ((gaccum / cnt) << 8) | (baccum / cnt); } catch (Exception x) { //Log.info("getSmoothWaterColorMultiplier(nomap) error: " + x); @@ -346,30 +255,21 @@ public abstract class GenericMapChunkCache extends MapChunkCache { int mult = 0xFFFFFF; try { - int rx = x - x_base; - int rz = z - z_base; - BiomeMap bm = biomemap[rx][rz]; - - if (sameneighborbiomecnt[rx][rz] >= (byte) 8) /* All neighbors same? */ - { - mult = colormap[bm.biomeLookup()]; - } else { - int raccum = 0; - int gaccum = 0; - int baccum = 0; - - for (int xoff = -1; xoff < 2; xoff++) { - for (int zoff = -1; zoff < 2; zoff++) { - bm = biomemap[rx + xoff][rz + zoff]; - int rmult = colormap[bm.biomeLookup()]; - raccum += (rmult >> 16) & 0xFF; - gaccum += (rmult >> 8) & 0xFF; - baccum += rmult & 0xFF; - } + int raccum = 0; + int gaccum = 0; + int baccum = 0; + int cnt = 0; + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + BiomeMap bm = getBiomeRel(dx, dz); + int rmult = colormap[bm.biomeLookup()]; + raccum += (rmult >> 16) & 0xFF; + gaccum += (rmult >> 8) & 0xFF; + baccum += rmult & 0xFF; + cnt++; } - - mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9); } + mult = ((raccum / cnt) << 16) | ((gaccum / cnt) << 8) | (baccum / cnt); } catch (Exception x) { //Log.info("getSmoothWaterColorMultiplier() error: " + x); mult = 0xFFFFFF; diff --git a/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/BukkitVersionHelperSpigot118.java b/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/BukkitVersionHelperSpigot118.java index f5d3f93f..c5702aba 100644 --- a/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/BukkitVersionHelperSpigot118.java +++ b/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/BukkitVersionHelperSpigot118.java @@ -61,8 +61,10 @@ import java.util.Map; /** * Helper for isolation of bukkit version specific issues */ -public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper { +public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper { + public BukkitVersionHelperSpigot118() { + } /** @@ -191,7 +193,7 @@ public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper { */ @Override public MapChunkCache getChunkCache(BukkitWorld dw, List chunks) { - MapChunkCache118 c = new MapChunkCache118(); + MapChunkCache118 c = new MapChunkCache118(gencache); c.setChunks(dw, chunks); return c; } @@ -437,4 +439,9 @@ public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper { CraftWorld cw = (CraftWorld) w; return cw.getMinHeight(); } + @Override + public boolean useGenericCache() { + return true; + } + } diff --git a/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/MapChunkCache118.java b/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/MapChunkCache118.java index ee759f15..9c9e0007 100644 --- a/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/MapChunkCache118.java +++ b/bukkit-helper-118/src/main/java/org/dynmap/bukkit/helper/v118/MapChunkCache118.java @@ -6,11 +6,16 @@ import org.bukkit.block.Biome; import org.bukkit.craftbukkit.v1_18_R1.CraftWorld; import org.dynmap.DynmapChunk; import org.dynmap.DynmapCore; +import org.dynmap.bukkit.helper.BukkitWorld; import org.dynmap.bukkit.helper.AbstractMapChunkCache; import org.dynmap.bukkit.helper.BukkitVersionHelper; import org.dynmap.bukkit.helper.SnapshotCache; import org.dynmap.bukkit.helper.SnapshotCache.SnapshotRec; import org.dynmap.common.BiomeMap; +import org.dynmap.common.chunk.GenericChunk; +import org.dynmap.common.chunk.GenericChunkCache; +import org.dynmap.common.chunk.GenericChunkSection; +import org.dynmap.common.chunk.GenericMapChunkCache; import org.dynmap.renderer.DynmapBlockState; import org.dynmap.utils.DataBitsPacked; import org.dynmap.utils.DynIntHashMap; @@ -28,417 +33,260 @@ import net.minecraft.world.level.chunk.Chunk; import java.io.IOException; import java.util.Arrays; import java.util.LinkedList; +import java.util.List; +import java.util.ArrayList; /** * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread */ -public class MapChunkCache118 extends AbstractMapChunkCache { +public class MapChunkCache118 extends GenericMapChunkCache { + private World w; + /** + * Construct empty cache + */ + public MapChunkCache118(GenericChunkCache cc) { + super(cc); + init(); + } - public static class NBTSnapshot implements Snapshot { - private static interface Section { - public DynmapBlockState getBlockType(int x, int y, int z); - public int getBlockSkyLight(int x, int y, int z); - public int getBlockEmittedLight(int x, int y, int z); - public boolean isEmpty(); - public int getBiome(int x, int y, int z); - } - private final int x, z; - private final Section[] section; - private final int sectionOffset; - private final int[] hmap; // Height map - private final int[] biome; - private final Object[] biomebase; - private final long captureFulltime; - private final int sectionCnt; - private final long inhabitedTicks; + private GenericChunk parseChunkFromNBT(NBTTagCompound nbt) { + if ((nbt != null) && nbt.e("Level")) { + nbt = nbt.p("Level"); + } + if (nbt == null) return null; + // Start generic chunk builder + GenericChunk.Builder bld = new GenericChunk.Builder(dw.minY, dw.worldheight); + bld.coords(nbt.h("xPos"), nbt.h("zPos")); + if (nbt.e("InhabitedTime")) { + bld.inhabitedTicks(nbt.i("InhabitedTime")); + } + // Check for 2D or old 3D biome data from chunk level: need these when we build old sections + List old3d = null; // By section, then YZX list + BiomeMap[] old2d = null; + if (nbt.e("Biomes")) { + int[] bb = nbt.n("Biomes"); + if (bb != null) { + // If v1.15+ format + if (bb.length > 256) { + old3d = new ArrayList(); + // Get 4 x 4 x 4 list for each section + for (int sect = 0; sect < (bb.length / 64); sect++) { + BiomeMap smap[] = new BiomeMap[64]; + for (int i = 0; i < 64; i++) { + smap[i] = BiomeMap.byBiomeID(bb[sect*64 + i]); + } + old3d.add(smap); + } + } + else { // Else, older chunks + old2d = new BiomeMap[256]; + for (int i = 0; i < bb.length; i++) { + old2d[i] = BiomeMap.byBiomeID(bb[i]); + } + } + } + } + // Start section builder + GenericChunkSection.Builder sbld = new GenericChunkSection.Builder(); + /* Get sections */ + NBTTagList sect = nbt.e("sections") ? nbt.c("sections", 10) : nbt.c("Sections", 10); + for (int i = 0; i < sect.size(); i++) { + NBTTagCompound sec = sect.a(i); + int secnum = sec.h("Y"); + + DynmapBlockState[] palette = null; + // If we've got palette and block states list, process non-empty section + if (sec.b("Palette", 9) && sec.b("BlockStates", 12)) { + NBTTagList plist = sec.c("Palette", 10); + long[] statelist = sec.o("BlockStates"); + palette = new DynmapBlockState[plist.size()]; + for (int pi = 0; pi < plist.size(); pi++) { + NBTTagCompound tc = plist.a(pi); + String pname = tc.l("Name"); + if (tc.e("Properties")) { + StringBuilder statestr = new StringBuilder(); + NBTTagCompound prop = tc.p("Properties"); + for (String pid : prop.d()) { + if (statestr.length() > 0) statestr.append(','); + statestr.append(pid).append('=').append(prop.c(pid).e_()); + } + palette[pi] = DynmapBlockState.getStateByNameAndState(pname, statestr.toString()); + } + if (palette[pi] == null) { + palette[pi] = DynmapBlockState.getBaseStateByName(pname); + } + if (palette[pi] == null) { + palette[pi] = DynmapBlockState.AIR; + } + } + int recsperblock = (4096 + statelist.length - 1) / statelist.length; + int bitsperblock = 64 / recsperblock; + DataBits db = null; + DataBitsPacked dbp = null; + try { + db = new SimpleBitStorage(bitsperblock, 4096, statelist); + } catch (Exception x) { // Handle legacy encoded + bitsperblock = (statelist.length * 64) / 4096; + dbp = new DataBitsPacked(bitsperblock, 4096, statelist); + } + if (bitsperblock > 8) { // Not palette + for (int j = 0; j < 4096; j++) { + int v = (dbp != null) ? dbp.getAt(j) : db.a(j); + sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, DynmapBlockState.getStateByGlobalIndex(v)); + } + } + else { + for (int j = 0; j < 4096; j++) { + int v = (dbp != null) ? dbp.getAt(j) : db.a(j); + DynmapBlockState bs = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; + sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, bs); + } + } + } - private static final int BLOCKS_PER_SECTION = 16 * 16 * 16; - private static final int BIOMES_PER_SECTION = 4 * 4 * 4; - private static final int COLUMNS_PER_CHUNK = 16 * 16; - private static final byte[] emptyData = new byte[BLOCKS_PER_SECTION / 2]; - private static final byte[] fullData = new byte[BLOCKS_PER_SECTION / 2]; + else if (sec.e("block_states")) { // 1.18 + NBTTagCompound block_states = sec.p("block_states"); + // If we've block state data, process non-empty section + if (block_states.b("data", 12)) { + long[] statelist = block_states.o("data"); + NBTTagList plist = block_states.c("palette", 10); + palette = new DynmapBlockState[plist.size()]; + for (int pi = 0; pi < plist.size(); pi++) { + NBTTagCompound tc = plist.a(pi); + String pname = tc.l("Name"); + if (tc.e("Properties")) { + StringBuilder statestr = new StringBuilder(); + NBTTagCompound prop = tc.p("Properties"); + for (String pid : prop.d()) { + if (statestr.length() > 0) statestr.append(','); + statestr.append(pid).append('=').append(prop.c(pid).e_()); + } + palette[pi] = DynmapBlockState.getStateByNameAndState(pname, statestr.toString()); + } + if (palette[pi] == null) { + palette[pi] = DynmapBlockState.getBaseStateByName(pname); + } + if (palette[pi] == null) { + palette[pi] = DynmapBlockState.AIR; + } + } + SimpleBitStorage db = null; + DataBitsPacked dbp = null; - static - { - Arrays.fill(fullData, (byte)0xFF); - } - - private static byte[] dataCopy(byte[] v) { - if (Arrays.equals(v, emptyData)) - return emptyData; - else if (Arrays.equals(v, fullData)) - return fullData; - else - return v.clone(); - } - - private static class EmptySection implements Section { - @Override - public DynmapBlockState getBlockType(int x, int y, int z) { - return DynmapBlockState.AIR; - } - @Override - public int getBlockSkyLight(int x, int y, int z) { - return 15; - } - @Override - public int getBlockEmittedLight(int x, int y, int z) { - return 0; - } - @Override - public boolean isEmpty() { - return true; - } - @Override - public int getBiome(int x, int y, int z) { - return BiomeMap.PLAINS.getBiomeID(); - } - } - - private static final EmptySection empty_section = new EmptySection(); - - private static class StdSection implements Section { - DynmapBlockState[] states; - byte[] skylight; - byte[] emitlight; - int[] biomes; - - public StdSection() { - states = new DynmapBlockState[BLOCKS_PER_SECTION]; - Arrays.fill(states, DynmapBlockState.AIR); - biomes = new int[BIOMES_PER_SECTION]; - skylight = emptyData; - emitlight = emptyData; - } - @Override - public DynmapBlockState getBlockType(int x, int y, int z) { - return states[((y & 0xF) << 8) | (z << 4) | x]; - } - @Override - public int getBlockSkyLight(int x, int y, int z) { - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - return (skylight[off] >> (4 * (x & 1))) & 0xF; - } - @Override - public int getBlockEmittedLight(int x, int y, int z) - { - int off = ((y & 0xF) << 7) | (z << 3) | (x >> 1); - return (emitlight[off] >> (4 * (x & 1))) & 0xF; - } - @Override - public boolean isEmpty() { - return false; - } - @Override - public int getBiome(int x, int y, int z) { - int off = (((y & 0xF) >> 2) << 4) | ((z >> 2) << 2) | (x >> 2); - return biomes[off]; - } - } - /** - * Construct empty chunk snapshot - * - * @param x - * @param z - */ - public NBTSnapshot(int worldheight, int x, int z, long captime, long inhabitedTime) - { - this.x = x; - this.z = z; - this.captureFulltime = captime; - this.biome = new int[COLUMNS_PER_CHUNK]; - this.biomebase = new Object[COLUMNS_PER_CHUNK]; - this.sectionCnt = worldheight / 16; - /* Allocate arrays indexed by section */ - this.section = new Section[this.sectionCnt+1]; - this.sectionOffset = 0; - /* Fill with empty data */ - for (int i = 0; i <= this.sectionCnt; i++) { - this.section[i] = empty_section; - } - - /* Create empty height map */ - this.hmap = new int[16 * 16]; - - this.inhabitedTicks = inhabitedTime; - } - - public NBTSnapshot(NBTTagCompound nbt, int worldheight) { - this.x = nbt.h("xPos"); - this.z = nbt.h("zPos"); - this.captureFulltime = 0; - this.hmap = nbt.n("HeightMap"); - this.sectionCnt = worldheight / 16; - if (nbt.e("InhabitedTime")) { - this.inhabitedTicks = nbt.i("InhabitedTime"); - } - else { - this.inhabitedTicks = 0; - } - /* Allocate arrays indexed by section */ - LinkedList
sections = new LinkedList
(); - int sectoff = 0; // Default to zero - int sectcnt = 0; - /* Fill with empty data */ - for (int i = 0; i <= this.sectionCnt; i++) { - sections.add(empty_section); - sectcnt++; - } - //System.out.println("nbt.keys()=" + nbt.d().toString()); - StdSection lastsectwithbiome = null; - /* Get sections */ - - NBTTagList sect = nbt.e("sections") ? nbt.c("sections", 10) : nbt.c("Sections", 10); - for (int i = 0; i < sect.size(); i++) { - NBTTagCompound sec = sect.a(i); - int secnum = sec.h("Y"); - // Beyond end - extend up - while (secnum >= (sectcnt - sectoff)) { - sections.addLast(empty_section); // Pad with empty - sectcnt++; - } - // Negative - see if we need to extend sectionOffset - while ((secnum + sectoff) < 0) { - sections.addFirst(empty_section); // Pad with empty - sectoff++; - sectcnt++; - } - //System.out.println("section(" + secnum + ")=" + sec.toString()); - // Create normal section to initialize - StdSection cursect = new StdSection(); - sections.set(secnum + sectoff, cursect); - DynmapBlockState[] states = cursect.states; - DynmapBlockState[] palette = null; - // If we've got palette and block states list, process non-empty section - if (sec.b("Palette", 9) && sec.b("BlockStates", 12)) { - NBTTagList plist = sec.c("Palette", 10); - long[] statelist = sec.o("BlockStates"); - palette = new DynmapBlockState[plist.size()]; - for (int pi = 0; pi < plist.size(); pi++) { - NBTTagCompound tc = plist.a(pi); - String pname = tc.l("Name"); - if (tc.e("Properties")) { - StringBuilder statestr = new StringBuilder(); - NBTTagCompound prop = tc.p("Properties"); - for (String pid : prop.d()) { - if (statestr.length() > 0) statestr.append(','); - statestr.append(pid).append('=').append(prop.c(pid).e_()); - } - palette[pi] = DynmapBlockState.getStateByNameAndState(pname, statestr.toString()); - } - if (palette[pi] == null) { - palette[pi] = DynmapBlockState.getBaseStateByName(pname); - } - if (palette[pi] == null) { - palette[pi] = DynmapBlockState.AIR; - } - } - int recsperblock = (4096 + statelist.length - 1) / statelist.length; - int bitsperblock = 64 / recsperblock; - DataBits db = null; - DataBitsPacked dbp = null; - try { - db = new SimpleBitStorage(bitsperblock, 4096, statelist); - } catch (Exception x) { // Handle legacy encoded + int bitsperblock = (statelist.length * 64) / 4096; + int expectedStatelistLength = (4096 + (64 / bitsperblock) - 1) / (64 / bitsperblock); + if (statelist.length == expectedStatelistLength) { + db = new SimpleBitStorage(bitsperblock, 4096, statelist); + } + else { bitsperblock = (statelist.length * 64) / 4096; dbp = new DataBitsPacked(bitsperblock, 4096, statelist); - } - if (bitsperblock > 8) { // Not palette - for (int j = 0; j < 4096; j++) { - int v = (dbp != null) ? dbp.getAt(j) : db.a(j); - states[j] = DynmapBlockState.getStateByGlobalIndex(v); - } - } - else { - for (int j = 0; j < 4096; j++) { - int v = (dbp != null) ? dbp.getAt(j) : db.a(j); - states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; - } - } + } + if (bitsperblock > 8) { // Not palette + for (int j = 0; j < 4096; j++) { + int v = db != null ? db.a(j) : dbp.getAt(j); + sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, DynmapBlockState.getStateByGlobalIndex(v)); + } + } + else { + for (int j = 0; j < 4096; j++) { + int v = db != null ? db.a(j) : dbp.getAt(j); + DynmapBlockState bs = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; + sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, bs); + } + } + } + } + if (sec.e("BlockLight")) { + sbld.emittedLight(sec.m("BlockLight")); + } + if (sec.e("SkyLight")) { + sbld.skyLight(sec.m("SkyLight")); + } + // If section biome palette + if (sec.e("biomes")) { + NBTTagCompound nbtbiomes = sec.p("biomes"); + long[] bdataPacked = nbtbiomes.o("data"); + NBTTagList bpalette = nbtbiomes.c("palette", 8); + SimpleBitStorage bdata = null; + if (bdataPacked.length > 0) + bdata = new SimpleBitStorage(bdataPacked.length, 64, bdataPacked); + for (int j = 0; j < 64; j++) { + int b = bdata != null ? bdata.a(j) : 0; + sbld.xyzBiome(j & 0x3, (j & 0x30) >> 4, (j & 0xC) >> 2, BiomeMap.byBiomeResourceLocation(bpalette.j(b))); + } + } + else { // Else, apply legacy biomes + if (old3d != null) { + BiomeMap m[] = old3d.get(secnum); + if (m != null) { + for (int j = 0; j < 64; j++) { + sbld.xyzBiome(j & 0x3, (j & 0x30) >> 4, (j & 0xC) >> 2, m[j]); + } + } } - else if (sec.e("block_states")) { // 1.18 - NBTTagCompound block_states = sec.p("block_states"); - // If we've block state data, process non-empty section - if (block_states.b("data", 12)) { - long[] statelist = block_states.o("data"); - NBTTagList plist = block_states.c("palette", 10); - palette = new DynmapBlockState[plist.size()]; - for (int pi = 0; pi < plist.size(); pi++) { - NBTTagCompound tc = plist.a(pi); - String pname = tc.l("Name"); - if (tc.e("Properties")) { - StringBuilder statestr = new StringBuilder(); - NBTTagCompound prop = tc.p("Properties"); - for (String pid : prop.d()) { - if (statestr.length() > 0) statestr.append(','); - statestr.append(pid).append('=').append(prop.c(pid).e_()); - } - palette[pi] = DynmapBlockState.getStateByNameAndState(pname, statestr.toString()); - } - if (palette[pi] == null) { - palette[pi] = DynmapBlockState.getBaseStateByName(pname); - } - if (palette[pi] == null) { - palette[pi] = DynmapBlockState.AIR; - } - } - SimpleBitStorage db = null; - DataBitsPacked dbp = null; - - int bitsperblock = (statelist.length * 64) / 4096; - int expectedStatelistLength = (4096 + (64 / bitsperblock) - 1) / (64 / bitsperblock); - if (statelist.length == expectedStatelistLength) { - db = new SimpleBitStorage(bitsperblock, 4096, statelist); - } - else { - bitsperblock = (statelist.length * 64) / 4096; - dbp = new DataBitsPacked(bitsperblock, 4096, statelist); - } - if (bitsperblock > 8) { // Not palette - for (int j = 0; j < 4096; j++) { - int v = db != null ? db.a(j) : dbp.getAt(j); - states[j] = DynmapBlockState.getStateByGlobalIndex(v); - } - } - else { - for (int j = 0; j < 4096; j++) { - int v = db != null ? db.a(j) : dbp.getAt(j); - states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR; - } - } - } - } - - if (sec.e("BlockLight")) { - cursect.emitlight = dataCopy(sec.m("BlockLight")); - } - if (sec.e("SkyLight")) { - cursect.skylight = dataCopy(sec.m("SkyLight")); + else if (old2d != null) { + for (int j = 0; j < 256; j++) { + sbld.xzBiome(j & 0xF, (j & 0xF0) >> 4, old2d[j]); + } } - // If section biome palette - if (sec.e("biomes")) { - NBTTagCompound nbtbiomes = sec.p("biomes"); - long[] bdataPacked = nbtbiomes.o("data"); - NBTTagList bpalette = nbtbiomes.c("palette", 8); - SimpleBitStorage bdata = null; - if (bdataPacked.length > 0) - bdata = new SimpleBitStorage(bdataPacked.length, 64, bdataPacked); - for (int j = 0; j < 64; j++) { - int b = bdata != null ? bdata.a(j) : 0; - cursect.biomes[j] = b < bpalette.size() ? BiomeMap.byBiomeResourceLocation(bpalette.j(b)).getBiomeID() : -1; - } - // Favor the Y=64 version - if ((secnum == 4) || (lastsectwithbiome == null)) { - lastsectwithbiome = cursect; - } - } - } - /* Get biome data */ - this.biome = new int[COLUMNS_PER_CHUNK]; - this.biomebase = new Object[COLUMNS_PER_CHUNK]; - Object[] bbl = BukkitVersionHelper.helper.getBiomeBaseList(); - if (nbt.e("Biomes")) { - int[] bb = nbt.n("Biomes"); - if (bb != null) { - // If v1.15+ format - if (bb.length > COLUMNS_PER_CHUNK) { - // For now, just pad the grid with the first 16 - for (int i = 0; i < COLUMNS_PER_CHUNK; i++) { - int off = ((i >> 4) & 0xC) + ((i >> 2) & 0x3); - int bv = bb[off + 64]; // Offset to y=64 - if (bv < 0) bv = 0; - this.biome[i] = bv; - this.biomebase[i] = bbl[bv]; - } - } - else { // Else, older chunks - for (int i = 0; i < bb.length; i++) { - int bv = bb[i]; - if (bv < 0) bv = 0; - this.biome[i] = bv; - this.biomebase[i] = bbl[bv]; - } - } - } - } - else { // Make up 2D version for now - if (lastsectwithbiome != null) { - // For now, just pad the grid with the first 16 - for (int i = 0; i < COLUMNS_PER_CHUNK; i++) { - int off = ((i >> 4) & 0xC) + ((i >> 2) & 0x3); - int bv = lastsectwithbiome.biomes[off]; // Offset to y=64 - if (bv < 0) bv = 0; - this.biome[i] = bv; - this.biomebase[i] = bbl[bv]; - } - } - } - // Finalize sections array - this.section = sections.toArray(new Section[sections.size()]); - this.sectionOffset = sectoff; - } - - public int getX() - { - return x; - } + } + // Finish and add section + bld.addSection(secnum, sbld.build()); + sbld.reset(); + } + return bld.build(); + } + + // Load generic chunk from existing and already loaded chunk + protected GenericChunk getLoadedChunk(DynmapChunk chunk) { + CraftWorld cw = (CraftWorld) w; + NBTTagCompound nbt = null; + if (cw.isChunkLoaded(chunk.x, chunk.z)) { + Chunk c = cw.getHandle().getChunkIfLoaded(chunk.x, chunk.z); + if ((c != null) && c.o) { // c.loaded + nbt = ChunkRegionLoader.a(cw.getHandle(), c); + } + if (nbt.e("Level")) { + nbt = nbt.p("Level"); + } + if (nbt != null) { + String stat = nbt.l("Status"); + ChunkStatus cs = ChunkStatus.a(stat); + if ((stat == null) || (!cs.b(ChunkStatus.l))) { // ChunkStatus.LIGHT + nbt = null; + } + } + } + return parseChunkFromNBT(nbt); + } + // Load generic chunk from unloaded chunk + protected GenericChunk loadChunk(DynmapChunk chunk) { + CraftWorld cw = (CraftWorld) w; + NBTTagCompound nbt = null; + ChunkCoordIntPair cc = new ChunkCoordIntPair(chunk.x, chunk.z); + try { + nbt = cw.getHandle().k().a.f(cc); // playerChunkMap + } catch (IOException iox) { + } + if (nbt != null) { + // See if we have Level - unwrap this if so + if (nbt.e("Level")) { + nbt = nbt.p("Level"); + } + if (nbt != null) { + String stat = nbt.l("Status"); + if ((stat == null) || (stat.equals("full") == false)) { + nbt = null; + } + } + } + return parseChunkFromNBT(nbt); + } - public int getZ() - { - return z; - } - - public DynmapBlockState getBlockType(int x, int y, int z) - { - int idx = (y >> 4) + sectionOffset; - if ((idx < 0) || (idx >= section.length)) return DynmapBlockState.AIR; - return section[idx].getBlockType(x, y, z); - } - - public int getBlockSkyLight(int x, int y, int z) - { - int idx = (y >> 4) + sectionOffset; - if ((idx < 0) || (idx >= section.length)) return 15; - return section[idx].getBlockSkyLight(x, y, z); - } - - public int getBlockEmittedLight(int x, int y, int z) - { - int idx = (y >> 4) + sectionOffset; - if ((idx < 0) || (idx >= section.length)) return 0; - return section[idx].getBlockEmittedLight(x, y, z); - } - - public int getHighestBlockYAt(int x, int z) - { - return hmap[z << 4 | x]; - } - - public final long getCaptureFullTime() - { - return captureFulltime; - } - - public boolean isSectionEmpty(int sy) - { - int idx = sy + sectionOffset; - if ((idx < 0) || (idx >= section.length)) return true; - return section[idx].isEmpty(); - } - - public long getInhabitedTicks() { - return inhabitedTicks; - } - - @Override - public Biome getBiome(int x, int z) { - return AbstractMapChunkCache.getBiomeByID(biome[z << 4 | x]); - } - - @Override - public Object[] getBiomeBaseFromSnapshot() { - return this.biomebase; - } + public void setChunks(BukkitWorld dw, List chunks) { + this.w = dw.getWorld(); + super.setChunks(dw, chunks); } private NBTTagCompound fetchLoadedChunkNBT(World w, int x, int z) { @@ -463,156 +311,5 @@ public class MapChunkCache118 extends AbstractMapChunkCache { } } return nbt; - } - - private NBTTagCompound loadChunkNBT(World w, int x, int z) { - //.info("loadChunkNBT(" + w.getName() + "," + x + "," + z); - CraftWorld cw = (CraftWorld) w; - NBTTagCompound nbt = null; - ChunkCoordIntPair cc = new ChunkCoordIntPair(x, z); - try { - nbt = cw.getHandle().k().a.f(cc); // playerChunkMap - } catch (IOException iox) { - } - if (nbt != null) { - // See if we have Level - unwrap this if so - if (nbt.e("Level")) { - nbt = nbt.p("Level"); - } - if (nbt != null) { - String stat = nbt.l("Status"); - if ((stat == null) || (stat.equals("full") == false)) { - nbt = null; - if ((stat == null) || stat.equals("") && DynmapCore.migrateChunks()) { - Chunk c = cw.getHandle().getChunkIfLoaded(x, z); - if (c != null) { - nbt = fetchLoadedChunkNBT(w, x, z); - cw.getHandle().a(c); - } - } - } - } - } - return nbt; - } - - @Override - public Snapshot wrapChunkSnapshot(ChunkSnapshot css) { - // TODO Auto-generated method stub - return null; - } - - // Load chunk snapshots - @Override - public int loadChunks(int max_to_load) { - if(dw.isLoaded() == false) - return 0; - int cnt = 0; - if(iterator == null) - iterator = chunks.listIterator(); - - DynmapCore.setIgnoreChunkLoads(true); - // Load the required chunks. - while((cnt < max_to_load) && iterator.hasNext()) { - long startTime = System.nanoTime(); - DynmapChunk chunk = iterator.next(); - boolean vis = true; - if(visible_limits != null) { - vis = false; - for(VisibilityLimit limit : visible_limits) { - if (limit.doIntersectChunk(chunk.x, chunk.z)) { - vis = true; - break; - } - } - } - if(vis && (hidden_limits != null)) { - for(VisibilityLimit limit : hidden_limits) { - if (limit.doIntersectChunk(chunk.x, chunk.z)) { - vis = false; - break; - } - } - } - /* Check if cached chunk snapshot found */ - Snapshot ss = null; - long inhabited_ticks = 0; - DynIntHashMap tileData = null; - int idx = (chunk.x-x_min) + (chunk.z - z_min)*x_dim; - SnapshotRec ssr = SnapshotCache.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty); - if(ssr != null) { - inhabited_ticks = ssr.inhabitedTicks; - if(!vis) { - if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN) - ss = STONE; - else if(hidestyle == HiddenChunkStyle.FILL_OCEAN) - ss = OCEAN; - else - ss = EMPTY; - } - else { - ss = ssr.ss; - } - snaparray[idx] = ss; - snaptile[idx] = ssr.tileData; - inhabitedTicks[idx] = inhabited_ticks; - - endChunkLoad(startTime, ChunkStats.CACHED_SNAPSHOT_HIT); - continue; - } - // Fetch NTB for chunk if loaded - NBTTagCompound nbt = fetchLoadedChunkNBT(w, chunk.x, chunk.z); - boolean did_load = false; - if (nbt == null) { - // Load NTB for chunk, if it exists - nbt = loadChunkNBT(w, chunk.x, chunk.z); - did_load = true; - } - if (nbt != null) { - NBTSnapshot nss = new NBTSnapshot(nbt, w.getMaxHeight()); - ss = nss; - inhabited_ticks = nss.getInhabitedTicks(); - if(!vis) { - if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN) - ss = STONE; - else if(hidestyle == HiddenChunkStyle.FILL_OCEAN) - ss = OCEAN; - else - ss = EMPTY; - } - } - else { - ss = EMPTY; - } - ssr = new SnapshotRec(); - ssr.ss = ss; - ssr.inhabitedTicks = inhabited_ticks; - ssr.tileData = tileData; - SnapshotCache.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty); - snaparray[idx] = ss; - snaptile[idx] = ssr.tileData; - inhabitedTicks[idx] = inhabited_ticks; - if (nbt == null) - endChunkLoad(startTime, ChunkStats.UNGENERATED_CHUNKS); - else if (did_load) - endChunkLoad(startTime, ChunkStats.UNLOADED_CHUNKS); - else - endChunkLoad(startTime, ChunkStats.LOADED_CHUNKS); - cnt++; - } - DynmapCore.setIgnoreChunkLoads(false); - - if(iterator.hasNext() == false) { /* If we're done */ - isempty = true; - /* Fill missing chunks with empty dummy chunk */ - for(int i = 0; i < snaparray.length; i++) { - if(snaparray[i] == null) - snaparray[i] = EMPTY; - else if(snaparray[i] != EMPTY) - isempty = false; - } - } - - return cnt; - } + } } diff --git a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelper.java b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelper.java index 58f6db8f..bd243709 100644 --- a/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelper.java +++ b/bukkit-helper/src/main/java/org/dynmap/bukkit/helper/BukkitVersionHelper.java @@ -10,6 +10,7 @@ import org.bukkit.World; import org.bukkit.entity.Player; import org.dynmap.DynmapChunk; import org.dynmap.Log; +import org.dynmap.common.chunk.GenericChunkCache; import org.dynmap.renderer.DynmapBlockState; import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.Polygon; @@ -20,6 +21,8 @@ import org.dynmap.utils.Polygon; public abstract class BukkitVersionHelper { public static BukkitVersionHelper helper = null; + public static GenericChunkCache gencache; + public static DynmapBlockState[] stateByID; protected boolean isBlockIdNeeded() { @@ -218,4 +221,7 @@ public abstract class BukkitVersionHelper { if (subtitle != null) p.sendMessage(subtitle); } } + public boolean useGenericCache() { + return false; + } } \ No newline at end of file diff --git a/fabric-1.18/src/main/java/org/dynmap/fabric_1_18/DynmapPlugin.java b/fabric-1.18/src/main/java/org/dynmap/fabric_1_18/DynmapPlugin.java index dbafbee9..dd7d49b6 100644 --- a/fabric-1.18/src/main/java/org/dynmap/fabric_1_18/DynmapPlugin.java +++ b/fabric-1.18/src/main/java/org/dynmap/fabric_1_18/DynmapPlugin.java @@ -385,7 +385,7 @@ public class DynmapPlugin { if (rl != null) { // If resource location, lookup by this bmap = BiomeMap.byBiomeResourceLocation(rl); } - if (bmap == BiomeMap.NULL) { + else { bmap = BiomeMap.byBiomeID(i); } if (bmap.isDefault()) { diff --git a/forge-1.18/src/main/java/org/dynmap/forge_1_18/DynmapPlugin.java b/forge-1.18/src/main/java/org/dynmap/forge_1_18/DynmapPlugin.java index 01fbeac2..2b04b8b1 100644 --- a/forge-1.18/src/main/java/org/dynmap/forge_1_18/DynmapPlugin.java +++ b/forge-1.18/src/main/java/org/dynmap/forge_1_18/DynmapPlugin.java @@ -1400,7 +1400,7 @@ public class DynmapPlugin if (rl != null) { // If resource location, lookup by this bmap = BiomeMap.byBiomeResourceLocation(rl); } - if (bmap == BiomeMap.NULL) { + else { bmap = BiomeMap.byBiomeID(i); } if (bmap.isDefault()) { // If matched default, replace with new one diff --git a/spigot/src/main/java/org/dynmap/bukkit/DynmapPlugin.java b/spigot/src/main/java/org/dynmap/bukkit/DynmapPlugin.java index 7eca0eb8..f3ccf8e8 100644 --- a/spigot/src/main/java/org/dynmap/bukkit/DynmapPlugin.java +++ b/spigot/src/main/java/org/dynmap/bukkit/DynmapPlugin.java @@ -101,6 +101,7 @@ import org.dynmap.common.BiomeMap; import org.dynmap.common.DynmapCommandSender; import org.dynmap.common.DynmapPlayer; import org.dynmap.common.DynmapServerInterface; +import org.dynmap.common.chunk.GenericChunkCache; import org.dynmap.common.DynmapListenerManager.EventType; import org.dynmap.hdmap.HDMap; import org.dynmap.markers.MarkerAPI; @@ -435,11 +436,16 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { } @Override public double getCacheHitRate() { - return SnapshotCache.sscache.getHitRate(); + return helper.useGenericCache() ? BukkitVersionHelper.gencache.getHitRate() : SnapshotCache.sscache.getHitRate(); } @Override public void resetCacheStats() { - SnapshotCache.sscache.resetStats(); + if (helper.useGenericCache()) { + BukkitVersionHelper.gencache.resetStats(); + } + else { + SnapshotCache.sscache.resetStats(); + } } @Override public DynmapWorld getWorldByName(String wname) { @@ -828,7 +834,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { if (rl != null) { // If resource location, lookup by this bmap = BiomeMap.byBiomeResourceLocation(rl); } - if (bmap == BiomeMap.NULL) { + else { bmap = BiomeMap.byBiomeID(i); } if (bmap.isDefault()) { @@ -1009,7 +1015,12 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { return; } playerList = core.playerList; - SnapshotCache.sscache = new SnapshotCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache()); + if (helper.useGenericCache()) { + BukkitVersionHelper.gencache = new GenericChunkCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache()); + } + else { + SnapshotCache.sscache = new SnapshotCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache()); + } /* Get map manager from core */ mapManager = core.getMapManager(); @@ -1047,6 +1058,10 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { SnapshotCache.sscache.cleanup(); SnapshotCache.sscache = null; } + if (BukkitVersionHelper.gencache != null) { + BukkitVersionHelper.gencache.cleanup(); + BukkitVersionHelper.gencache = null; + } Log.info("Disabled"); } @@ -1101,13 +1116,13 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { @Override public final int triggerRenderOfVolume(String wid, int minx, int miny, int minz, int maxx, int maxy, int maxz) { - SnapshotCache.sscache.invalidateSnapshot(wid, minx, miny, minz, maxx, maxy, maxz); + invalidateSnapshot(wid, minx, miny, minz, maxx, maxy, maxz); return core.triggerRenderOfVolume(wid, minx, miny, minz, maxx, maxy, maxz); } @Override public final int triggerRenderOfBlock(String wid, int x, int y, int z) { - SnapshotCache.sscache.invalidateSnapshot(wid, x, y, z); + invalidateSnapshot(wid, x, y, z); return core.triggerRenderOfBlock(wid, x, y, z); } @@ -1233,7 +1248,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { if(btt.typeid == 9) btt.typeid = 8; if((bt != btt.typeid) || (btt.data != w.getBlockAt(loc).getData())) { String wn = getWorld(w).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), btt.trigger); } } @@ -1279,6 +1294,23 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { private boolean onblockgrow; private boolean onblockredstone; + private void invalidateSnapshot(String wn, int x, int y, int z) { + if (helper.useGenericCache()) { + BukkitVersionHelper.gencache.invalidateSnapshot(wn, x, y, z); + } + else { + SnapshotCache.sscache.invalidateSnapshot(wn, x, y, z); + } + } + private void invalidateSnapshot(String wname, int minx, int miny, int minz, int maxx, int maxy, int maxz) { + if (helper.useGenericCache()) { + BukkitVersionHelper.gencache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz); + } + else { + SnapshotCache.sscache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz); + } + } + private void registerEvents() { // To trigger rendering. @@ -1300,7 +1332,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onBlockPlace(BlockPlaceEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockplace"); } }; @@ -1315,7 +1347,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { if(b == null) return; /* Stupid mod workaround */ Location loc = b.getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockbreak"); } }; @@ -1328,7 +1360,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onLeavesDecay(LeavesDecayEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); if(onleaves) { mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "leavesdecay"); } @@ -1343,7 +1375,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onBlockBurn(BlockBurnEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); if(onburn) { mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockburn"); } @@ -1409,14 +1441,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { } String wn = getWorld(loc.getWorld()).getName(); int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); - SnapshotCache.sscache.invalidateSnapshot(wn, x, y, z); + invalidateSnapshot(wn, x, y, z); if(onpiston) mapManager.touch(wn, x, y, z, "pistonretract"); for(int i = 0; i < 2; i++) { x += dir.getModX(); y += dir.getModY(); z += dir.getModZ(); - SnapshotCache.sscache.invalidateSnapshot(wn, x, y, z); + invalidateSnapshot(wn, x, y, z); mapManager.touch(wn, x, y, z, "pistonretract"); } } @@ -1433,14 +1465,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { } String wn = getWorld(loc.getWorld()).getName(); int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ(); - SnapshotCache.sscache.invalidateSnapshot(wn, x, y, z); + invalidateSnapshot(wn, x, y, z); if(onpiston) mapManager.touch(wn, x, y, z, "pistonretract"); for(int i = 0; i < 1+event.getLength(); i++) { x += dir.getModX(); y += dir.getModY(); z += dir.getModZ(); - SnapshotCache.sscache.invalidateSnapshot(wn, x, y, z); + invalidateSnapshot(wn, x, y, z); mapManager.touch(wn, x, y, z, "pistonretract"); } } @@ -1454,7 +1486,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onBlockSpread(BlockSpreadEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockspread"); } }; @@ -1467,7 +1499,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onBlockForm(BlockFormEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockform"); } }; @@ -1480,7 +1512,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onBlockFade(BlockFadeEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockfade"); } }; @@ -1495,7 +1527,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onBlockGrow(BlockGrowEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockgrow"); } }; @@ -1508,7 +1540,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public void onBlockRedstone(BlockRedstoneEvent event) { Location loc = event.getBlock().getLocation(); String wn = getWorld(loc.getWorld()).getName(); - SnapshotCache.sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockredstone"); } }; @@ -1565,7 +1597,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { if(z < minz) minz = z; if(z > maxz) maxz = z; } - SnapshotCache.sscache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz); + invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz); if(onexplosion) { mapManager.touchVolume(wname, minx, miny, minz, maxx, maxy, maxz, "entityexplode"); } @@ -1612,7 +1644,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { if(z < minz) minz = z; if(z > maxz) maxz = z; } - SnapshotCache.sscache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz); + invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz); if(onstructuregrow) { mapManager.touchVolume(wname, minx, miny, minz, maxx, maxy, maxz, "structuregrow"); }