Put 3D biome code in spigot 1.18 - still working on grass shading...

This commit is contained in:
Mike Primm 2021-12-05 01:57:59 -06:00
parent 983a2a4390
commit 37fd064434
8 changed files with 430 additions and 762 deletions

View File

@ -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<String, BiomeMap> biome_by_rl = new HashMap<String, BiomeMap>();
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,9 +174,20 @@ 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) {
resizeIfNeeded(idx);
biome_by_index[idx] = this;
}
this.resourcelocation = rl;

View File

@ -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 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 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 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 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 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;

View File

@ -62,7 +62,9 @@ import java.util.Map;
* Helper for isolation of bukkit version specific issues
*/
public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper {
public BukkitVersionHelperSpigot118() {
}
/**
@ -191,7 +193,7 @@ public class BukkitVersionHelperSpigot118 extends BukkitVersionHelper {
*/
@Override
public MapChunkCache getChunkCache(BukkitWorld dw, List<DynmapChunk> 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;
}
}

View File

@ -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,186 +33,67 @@ 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 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 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];
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];
}
}
public class MapChunkCache118 extends GenericMapChunkCache {
private World w;
/**
* Construct empty chunk snapshot
*
* @param x
* @param z
* Construct empty cache
*/
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;
public MapChunkCache118(GenericChunkCache cc) {
super(cc);
init();
}
/* Create empty height map */
this.hmap = new int[16 * 16];
this.inhabitedTicks = inhabitedTime;
private GenericChunk parseChunkFromNBT(NBTTagCompound nbt) {
if ((nbt != null) && nbt.e("Level")) {
nbt = nbt.p("Level");
}
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 == 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")) {
this.inhabitedTicks = nbt.i("InhabitedTime");
bld.inhabitedTicks(nbt.i("InhabitedTime"));
}
else {
this.inhabitedTicks = 0;
// Check for 2D or old 3D biome data from chunk level: need these when we build old sections
List<BiomeMap[]> 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<BiomeMap[]>();
// 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]);
}
/* Allocate arrays indexed by section */
LinkedList<Section> sections = new LinkedList<Section>();
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++;
old3d.add(smap);
}
//System.out.println("nbt.keys()=" + nbt.d().toString());
StdSection lastsectwithbiome = null;
}
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");
// 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)) {
@ -246,16 +132,18 @@ public class MapChunkCache118 extends AbstractMapChunkCache {
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);
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);
states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
DynmapBlockState bs = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, bs);
}
}
}
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
@ -297,23 +185,23 @@ public class MapChunkCache118 extends AbstractMapChunkCache {
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);
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);
states[j] = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
DynmapBlockState bs = (v < palette.length) ? palette[v] : DynmapBlockState.AIR;
sbld.xyzBlockState(j & 0xF, (j & 0xF00) >> 8, (j & 0xF0) >> 4, bs);
}
}
}
}
if (sec.e("BlockLight")) {
cursect.emitlight = dataCopy(sec.m("BlockLight"));
sbld.emittedLight(sec.m("BlockLight"));
}
if (sec.e("SkyLight")) {
cursect.skylight = dataCopy(sec.m("SkyLight"));
sbld.skyLight(sec.m("SkyLight"));
}
// If section biome palette
if (sec.e("biomes")) {
@ -325,120 +213,80 @@ public class MapChunkCache118 extends AbstractMapChunkCache {
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;
sbld.xyzBiome(j & 0x3, (j & 0x30) >> 4, (j & 0xC) >> 2, BiomeMap.byBiomeResourceLocation(bpalette.j(b)));
}
// Favor the Y=64 version
if ((secnum == 4) || (lastsectwithbiome == null)) {
lastsectwithbiome = cursect;
}
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]);
}
}
}
/* 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 if (old2d != null) {
for (int j = 0; j < 256; j++) {
sbld.xzBiome(j & 0xF, (j & 0xF0) >> 4, old2d[j]);
}
}
}
// Finish and add section
bld.addSection(secnum, sbld.build());
sbld.reset();
}
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;
return bld.build();
}
public int getX()
{
return x;
// 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<DynmapChunk> chunks) {
this.w = dw.getWorld();
super.setChunks(dw, chunks);
}
private NBTTagCompound fetchLoadedChunkNBT(World w, int x, int z) {
@ -464,155 +312,4 @@ 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;
}
}

View File

@ -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;
}
}

View File

@ -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()) {

View File

@ -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

View File

@ -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,12 +436,17 @@ 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() {
if (helper.useGenericCache()) {
BukkitVersionHelper.gencache.resetStats();
}
else {
SnapshotCache.sscache.resetStats();
}
}
@Override
public DynmapWorld getWorldByName(String wname) {
return DynmapPlugin.this.getWorldByName(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;
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");
}