mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-24 11:15:21 +01:00
Add tile entity data collection
This commit is contained in:
parent
3a57261120
commit
c6d345d8f1
@ -4,12 +4,23 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import net.minecraft.server.BiomeBase;
|
import net.minecraft.server.BiomeBase;
|
||||||
import net.minecraft.server.ChunkProviderServer;
|
import net.minecraft.server.ChunkProviderServer;
|
||||||
|
import net.minecraft.server.NBTBase;
|
||||||
|
import net.minecraft.server.NBTTagByte;
|
||||||
|
import net.minecraft.server.NBTTagByteArray;
|
||||||
|
import net.minecraft.server.NBTTagCompound;
|
||||||
|
import net.minecraft.server.NBTTagDouble;
|
||||||
|
import net.minecraft.server.NBTTagFloat;
|
||||||
|
import net.minecraft.server.NBTTagInt;
|
||||||
|
import net.minecraft.server.NBTTagIntArray;
|
||||||
|
import net.minecraft.server.NBTTagLong;
|
||||||
|
import net.minecraft.server.NBTTagShort;
|
||||||
|
import net.minecraft.server.NBTTagString;
|
||||||
|
import net.minecraft.server.TileEntity;
|
||||||
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
@ -17,16 +28,16 @@ import org.bukkit.block.Biome;
|
|||||||
import org.bukkit.craftbukkit.CraftChunk;
|
import org.bukkit.craftbukkit.CraftChunk;
|
||||||
import org.bukkit.craftbukkit.CraftChunkSnapshot;
|
import org.bukkit.craftbukkit.CraftChunkSnapshot;
|
||||||
import org.bukkit.craftbukkit.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.util.LongHashset;
|
|
||||||
import org.bukkit.ChunkSnapshot;
|
import org.bukkit.ChunkSnapshot;
|
||||||
import org.dynmap.DynmapChunk;
|
import org.dynmap.DynmapChunk;
|
||||||
import org.dynmap.DynmapCore;
|
import org.dynmap.DynmapCore;
|
||||||
import org.dynmap.DynmapWorld;
|
import org.dynmap.DynmapWorld;
|
||||||
import org.dynmap.Log;
|
import org.dynmap.Log;
|
||||||
|
import org.dynmap.bukkit.SnapshotCache.SnapshotRec;
|
||||||
import org.dynmap.common.BiomeMap;
|
import org.dynmap.common.BiomeMap;
|
||||||
import org.dynmap.hdmap.HDBlockModels;
|
import org.dynmap.hdmap.HDBlockModels;
|
||||||
import org.dynmap.hdmap.HDBlockModels.HDBlockModel;
|
|
||||||
import org.dynmap.renderer.RenderPatchFactory;
|
import org.dynmap.renderer.RenderPatchFactory;
|
||||||
|
import org.dynmap.utils.DynIntHashMap;
|
||||||
import org.dynmap.utils.MapChunkCache;
|
import org.dynmap.utils.MapChunkCache;
|
||||||
import org.dynmap.utils.MapIterator;
|
import org.dynmap.utils.MapIterator;
|
||||||
import org.dynmap.utils.BlockStep;
|
import org.dynmap.utils.BlockStep;
|
||||||
@ -58,6 +69,7 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
private boolean do_save = false;
|
private boolean do_save = false;
|
||||||
private boolean isempty = true;
|
private boolean isempty = true;
|
||||||
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
|
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
|
||||||
|
private DynIntHashMap[] snaptile;
|
||||||
private byte[][] sameneighborbiomecnt;
|
private byte[][] sameneighborbiomecnt;
|
||||||
private BiomeMap[][] biomemap;
|
private BiomeMap[][] biomemap;
|
||||||
private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */
|
private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */
|
||||||
@ -72,7 +84,11 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
|
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
|
||||||
|
|
||||||
private static BiomeMap[] biome_to_bmap;
|
private static BiomeMap[] biome_to_bmap;
|
||||||
|
|
||||||
|
private static final int getIndexInChunk(int cx, int cy, int cz) {
|
||||||
|
return (cy << 8) | (cz << 4) | cx;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator for traversing map chunk cache (base is for non-snapshot)
|
* Iterator for traversing map chunk cache (base is for non-snapshot)
|
||||||
*/
|
*/
|
||||||
@ -552,6 +568,16 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Object getBlockTileEntityField(String fieldId) {
|
public Object getBlockTileEntityField(String fieldId) {
|
||||||
|
try {
|
||||||
|
int idx = getIndexInChunk(bx,y,bz);
|
||||||
|
Object[] vals = (Object[])snaptile[chunkindex].get(idx);
|
||||||
|
for (int i = 0; i < vals.length; i += 2) {
|
||||||
|
if (vals[i].equals(fieldId)) {
|
||||||
|
return vals[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@ -789,8 +815,10 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
x_dim = x_max - x_min + 1;
|
x_dim = x_max - x_min + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snaparray = new ChunkSnapshot[x_dim * (z_max-z_min+1)];
|
int snapcnt = x_dim * (z_max-z_min+1);
|
||||||
isSectionNotEmpty = new boolean[x_dim * (z_max-z_min+1)][];
|
snaparray = new ChunkSnapshot[snapcnt];
|
||||||
|
snaptile = new DynIntHashMap[snapcnt];
|
||||||
|
isSectionNotEmpty = new boolean[snapcnt][];
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChunkSnapshot checkSpoutData(Chunk c, ChunkSnapshot ss) {
|
private ChunkSnapshot checkSpoutData(Chunk c, ChunkSnapshot ss) {
|
||||||
@ -845,8 +873,11 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check if cached chunk snapshot found */
|
/* Check if cached chunk snapshot found */
|
||||||
ChunkSnapshot ss = DynmapPlugin.plugin.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
|
ChunkSnapshot ss = null;
|
||||||
if(ss != null) {
|
DynIntHashMap tileData = null;
|
||||||
|
SnapshotRec ssr = DynmapPlugin.plugin.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
|
||||||
|
if(ssr != null) {
|
||||||
|
ss = ssr.ss;
|
||||||
if(!vis) {
|
if(!vis) {
|
||||||
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
||||||
ss = STONE;
|
ss = STONE;
|
||||||
@ -855,7 +886,10 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
else
|
else
|
||||||
ss = EMPTY;
|
ss = EMPTY;
|
||||||
}
|
}
|
||||||
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
int idx = (chunk.x-x_min) + (chunk.z - z_min)*x_dim;
|
||||||
|
snaparray[idx] = ss;
|
||||||
|
snaptile[idx] = ssr.tileData;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
chunks_attempted++;
|
chunks_attempted++;
|
||||||
@ -892,6 +926,8 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
didgenerate = didload = w.loadChunk(chunk.x, chunk.z, true);
|
didgenerate = didload = w.loadChunk(chunk.x, chunk.z, true);
|
||||||
/* If it did load, make cache of it */
|
/* If it did load, make cache of it */
|
||||||
if(didload) {
|
if(didload) {
|
||||||
|
tileData = new DynIntHashMap();
|
||||||
|
|
||||||
Chunk c = w.getChunkAt(chunk.x, chunk.z); /* Get the chunk */
|
Chunk c = w.getChunkAt(chunk.x, chunk.z); /* Get the chunk */
|
||||||
/* Test if chunk isn't populated */
|
/* Test if chunk isn't populated */
|
||||||
boolean populated = true;
|
boolean populated = true;
|
||||||
@ -920,14 +956,80 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
if(use_spout) {
|
if(use_spout) {
|
||||||
ss = checkSpoutData(c, ss);
|
ss = checkSpoutData(c, ss);
|
||||||
}
|
}
|
||||||
|
/* Get tile entity data */
|
||||||
|
List<Object> vals = new ArrayList<Object>();
|
||||||
|
for(Object t : ((CraftChunk)c).getHandle().tileEntities.values()) {
|
||||||
|
TileEntity te = (TileEntity)t;
|
||||||
|
int cx = te.x & 0xF;
|
||||||
|
int cz = te.z & 0xF;
|
||||||
|
int blkid = ss.getBlockTypeId(cx, te.y, cz);
|
||||||
|
int blkdat = ss.getBlockData(cx, te.y, cz);
|
||||||
|
String[] te_fields = HDBlockModels.getTileEntityFieldsNeeded(blkid, blkdat);
|
||||||
|
if(te_fields != null) {
|
||||||
|
NBTTagCompound tc = new NBTTagCompound();
|
||||||
|
try {
|
||||||
|
te.b(tc);
|
||||||
|
} catch (Exception x) {
|
||||||
|
}
|
||||||
|
vals.clear();
|
||||||
|
for(String id: te_fields) {
|
||||||
|
NBTBase v = tc.get(id); /* Get field */
|
||||||
|
if(v != null) {
|
||||||
|
Object val = null;
|
||||||
|
switch(v.getTypeId()) {
|
||||||
|
case 1: // Byte
|
||||||
|
val = Byte.valueOf(((NBTTagByte)v).data);
|
||||||
|
break;
|
||||||
|
case 2: // Short
|
||||||
|
val = Short.valueOf(((NBTTagShort)v).data);
|
||||||
|
break;
|
||||||
|
case 3: // Int
|
||||||
|
val = Integer.valueOf(((NBTTagInt)v).data);
|
||||||
|
break;
|
||||||
|
case 4: // Long
|
||||||
|
val = Long.valueOf(((NBTTagLong)v).data);
|
||||||
|
break;
|
||||||
|
case 5: // Float
|
||||||
|
val = Float.valueOf(((NBTTagFloat)v).data);
|
||||||
|
break;
|
||||||
|
case 6: // Double
|
||||||
|
val = Double.valueOf(((NBTTagDouble)v).data);
|
||||||
|
break;
|
||||||
|
case 7: // Byte[]
|
||||||
|
val = ((NBTTagByteArray)v).data;
|
||||||
|
break;
|
||||||
|
case 8: // String
|
||||||
|
val = ((NBTTagString)v).data;
|
||||||
|
break;
|
||||||
|
case 11: // Int[]
|
||||||
|
val = ((NBTTagIntArray)v).data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(val != null) {
|
||||||
|
vals.add(id);
|
||||||
|
vals.add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(vals.size() > 0) {
|
||||||
|
Object[] vlist = vals.toArray(new Object[vals.size()]);
|
||||||
|
tileData.put(getIndexInChunk(cx,te.y,cz), vlist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ss = w.getEmptyChunkSnapshot(chunk.x, chunk.z, biome, biomeraw);
|
ss = w.getEmptyChunkSnapshot(chunk.x, chunk.z, biome, biomeraw);
|
||||||
if(ss != null) {
|
if(ss != null) {
|
||||||
DynmapPlugin.plugin.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ss, blockdata, biome, biomeraw, highesty);
|
ssr = new SnapshotRec();
|
||||||
|
ssr.ss = ss;
|
||||||
|
ssr.tileData = tileData;
|
||||||
|
DynmapPlugin.plugin.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
|
||||||
|
snaptile[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = tileData;
|
||||||
|
|
||||||
/* If wasn't loaded before, we need to do unload */
|
/* If wasn't loaded before, we need to do unload */
|
||||||
if (!wasLoaded) {
|
if (!wasLoaded) {
|
||||||
chunks_read++;
|
chunks_read++;
|
||||||
|
@ -8,15 +8,21 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.bukkit.ChunkSnapshot;
|
import org.bukkit.ChunkSnapshot;
|
||||||
|
import org.dynmap.utils.DynIntHashMap;
|
||||||
|
|
||||||
public class SnapshotCache {
|
public class SnapshotCache {
|
||||||
|
public static class SnapshotRec {
|
||||||
|
public ChunkSnapshot ss;
|
||||||
|
public DynIntHashMap tileData;
|
||||||
|
};
|
||||||
|
|
||||||
private CacheHashMap snapcache;
|
private CacheHashMap snapcache;
|
||||||
private ReferenceQueue<ChunkSnapshot> refqueue;
|
private ReferenceQueue<SnapshotRec> refqueue;
|
||||||
private long cache_attempts;
|
private long cache_attempts;
|
||||||
private long cache_success;
|
private long cache_success;
|
||||||
|
|
||||||
private static class CacheRec {
|
private static class CacheRec {
|
||||||
WeakReference<ChunkSnapshot> ref;
|
WeakReference<SnapshotRec> ref;
|
||||||
boolean hasbiome;
|
boolean hasbiome;
|
||||||
boolean hasrawbiome;
|
boolean hasrawbiome;
|
||||||
boolean hasblockdata;
|
boolean hasblockdata;
|
||||||
@ -26,12 +32,12 @@ public class SnapshotCache {
|
|||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class CacheHashMap extends LinkedHashMap<String, CacheRec> {
|
public class CacheHashMap extends LinkedHashMap<String, CacheRec> {
|
||||||
private int limit;
|
private int limit;
|
||||||
private IdentityHashMap<WeakReference<ChunkSnapshot>, String> reverselookup;
|
private IdentityHashMap<WeakReference<SnapshotRec>, String> reverselookup;
|
||||||
|
|
||||||
public CacheHashMap(int lim) {
|
public CacheHashMap(int lim) {
|
||||||
super(16, (float)0.75, true);
|
super(16, (float)0.75, true);
|
||||||
limit = lim;
|
limit = lim;
|
||||||
reverselookup = new IdentityHashMap<WeakReference<ChunkSnapshot>, String>();
|
reverselookup = new IdentityHashMap<WeakReference<SnapshotRec>, String>();
|
||||||
}
|
}
|
||||||
protected boolean removeEldestEntry(Map.Entry<String, CacheRec> last) {
|
protected boolean removeEldestEntry(Map.Entry<String, CacheRec> last) {
|
||||||
boolean remove = (size() >= limit);
|
boolean remove = (size() >= limit);
|
||||||
@ -47,7 +53,7 @@ public class SnapshotCache {
|
|||||||
*/
|
*/
|
||||||
public SnapshotCache(int max_size) {
|
public SnapshotCache(int max_size) {
|
||||||
snapcache = new CacheHashMap(max_size);
|
snapcache = new CacheHashMap(max_size);
|
||||||
refqueue = new ReferenceQueue<ChunkSnapshot>();
|
refqueue = new ReferenceQueue<SnapshotRec>();
|
||||||
}
|
}
|
||||||
private String getKey(String w, int cx, int cz) {
|
private String getKey(String w, int cx, int cz) {
|
||||||
return w + ":" + cx + ":" + cz;
|
return w + ":" + cx + ":" + cz;
|
||||||
@ -83,11 +89,11 @@ public class SnapshotCache {
|
|||||||
/**
|
/**
|
||||||
* Look for chunk snapshot in cache
|
* Look for chunk snapshot in cache
|
||||||
*/
|
*/
|
||||||
public ChunkSnapshot getSnapshot(String w, int chunkx, int chunkz,
|
public SnapshotRec getSnapshot(String w, int chunkx, int chunkz,
|
||||||
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
|
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
|
||||||
String key = getKey(w, chunkx, chunkz);
|
String key = getKey(w, chunkx, chunkz);
|
||||||
processRefQueue();
|
processRefQueue();
|
||||||
ChunkSnapshot ss = null;
|
SnapshotRec ss = null;
|
||||||
CacheRec rec = snapcache.get(key);
|
CacheRec rec = snapcache.get(key);
|
||||||
if(rec != null) {
|
if(rec != null) {
|
||||||
ss = rec.ref.get();
|
ss = rec.ref.get();
|
||||||
@ -112,7 +118,7 @@ public class SnapshotCache {
|
|||||||
/**
|
/**
|
||||||
* Add chunk snapshot to cache
|
* Add chunk snapshot to cache
|
||||||
*/
|
*/
|
||||||
public void putSnapshot(String w, int chunkx, int chunkz, ChunkSnapshot ss,
|
public void putSnapshot(String w, int chunkx, int chunkz, SnapshotRec ss,
|
||||||
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
|
boolean blockdata, boolean biome, boolean biomeraw, boolean highesty) {
|
||||||
String key = getKey(w, chunkx, chunkz);
|
String key = getKey(w, chunkx, chunkz);
|
||||||
processRefQueue();
|
processRefQueue();
|
||||||
@ -121,7 +127,7 @@ public class SnapshotCache {
|
|||||||
rec.hasbiome = biome;
|
rec.hasbiome = biome;
|
||||||
rec.hasrawbiome = biomeraw;
|
rec.hasrawbiome = biomeraw;
|
||||||
rec.hashighesty = highesty;
|
rec.hashighesty = highesty;
|
||||||
rec.ref = new WeakReference<ChunkSnapshot>(ss, refqueue);
|
rec.ref = new WeakReference<SnapshotRec>(ss, refqueue);
|
||||||
CacheRec prevrec = snapcache.put(key, rec);
|
CacheRec prevrec = snapcache.put(key, rec);
|
||||||
if(prevrec != null) {
|
if(prevrec != null) {
|
||||||
snapcache.reverselookup.remove(prevrec.ref);
|
snapcache.reverselookup.remove(prevrec.ref);
|
||||||
@ -132,7 +138,7 @@ public class SnapshotCache {
|
|||||||
* Process reference queue
|
* Process reference queue
|
||||||
*/
|
*/
|
||||||
private void processRefQueue() {
|
private void processRefQueue() {
|
||||||
Reference<? extends ChunkSnapshot> ref;
|
Reference<? extends SnapshotRec> ref;
|
||||||
while((ref = refqueue.poll()) != null) {
|
while((ref = refqueue.poll()) != null) {
|
||||||
String k = snapcache.reverselookup.remove(ref);
|
String k = snapcache.reverselookup.remove(ref);
|
||||||
if(k != null) {
|
if(k != null) {
|
||||||
|
Loading…
Reference in New Issue
Block a user