Combine support for pre 1.4.5 versions and new 1.4.x packaging crud

This commit is contained in:
Mike Primm 2012-12-09 22:28:21 -06:00
parent da5e2cf24a
commit 07cbd84d44
3 changed files with 481 additions and 173 deletions

View File

@ -0,0 +1,434 @@
package org.dynmap.bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Server;
import org.bukkit.World;
import org.dynmap.Log;
/**
* Helper for isolation of bukkit version specific issues
*/
public class BukkitVersionHelper {
private String obc_package; // Package used for org.bukkit.craftbukkit
private String nms_package; // Package used for net.minecraft.server
private static BukkitVersionHelper helper;
private boolean failed;
private static final Object[] nullargs = new Object[0];
private static final Map nullmap = Collections.emptyMap();
/** BiomeBase related helpers */
private Class<?> biomebase;
private Class<?> biomebasearray;
private Field biomebaselist;
private Field biomebasetemp;
private Field biomebasehumi;
private Field biomebaseidstring;
private Field biomebaseid;
/** CraftWorld */
private Class<?> craftworld;
private Method cw_gethandle;
/** n.m.s.World */
private Class<?> nmsworld;
private Class<?> chunkprovserver;
private Class<?> longhashset;
private Field nmsw_chunkproviderserver;
private Field cps_unloadqueue;
private Method lhs_containskey;
/** CraftChunkSnapshot */
private Class<?> craftchunksnapshot;
private Field ccss_biome;
/** CraftChunk */
private Class<?> craftchunk;
private Method cc_gethandle;
/** o.m.s.Chunk */
private Class<?> nmschunk;
private Method nmsc_removeentities;
private Field nmsc_tileentities;
/** nbt classes */
private Class<?> nbttagcompound;
private Class<?> nbttagbyte;
private Class<?> nbttagshort;
private Class<?> nbttagint;
private Class<?> nbttaglong;
private Class<?> nbttagfloat;
private Class<?> nbttagdouble;
private Class<?> nbttagbytearray;
private Class<?> nbttagstring;
private Class<?> nbttagintarray;
private Method compound_get;
private Field nbttagbyte_val;
private Field nbttagshort_val;
private Field nbttagint_val;
private Field nbttaglong_val;
private Field nbttagfloat_val;
private Field nbttagdouble_val;
private Field nbttagbytearray_val;
private Field nbttagstring_val;
private Field nbttagintarray_val;
/** Tile entity */
private Class<?> nms_tileentity;
private Method nmst_readnbt;
private Field nmst_x;
private Field nmst_y;
private Field nmst_z;
public static final BukkitVersionHelper getHelper() {
if(helper == null) {
helper = new BukkitVersionHelper();
}
return helper;
}
private BukkitVersionHelper() {
failed = false;
Server srv = Bukkit.getServer();
/* Look up base classname for bukkit server - tells us OBC package */
obc_package = Bukkit.getServer().getClass().getPackage().getName();
/* Get getHandle() method */
try {
Method m = srv.getClass().getMethod("getHandle");
Object scm = m.invoke(srv); /* And use it to get SCM (nms object) */
nms_package = scm.getClass().getPackage().getName();
} catch (Exception x) {
Log.severe("Error finding net.minecraft.server packages");
nms_package = "net.minecraft.server" + obc_package.substring("org.bukkit.craftbukkit".length());
failed = true;
}
/* Set up biomebase fields */
biomebase = getNMSClass("net.minecraft.server.BiomeBase");
biomebasearray = getNMSClass("[Lnet.minecraft.server.BiomeBase;");
biomebaselist = getField(biomebase, new String[] { "biomes" }, biomebasearray);
biomebasetemp = getField(biomebase, new String[] { "temperature", "F" }, float.class);
biomebasehumi = getField(biomebase, new String[] { "humidity", "G" }, float.class);
biomebaseidstring = getField(biomebase, new String[] { "y" }, String.class);
biomebaseid = getField(biomebase, new String[] { "id" }, int.class);
/* Craftworld fields */
craftworld = getOBCClass("org.bukkit.craftbukkit.CraftWorld");
cw_gethandle = getMethod(craftworld, new String[] { "getHandle" }, new Class[0]);
/* n.m.s.World */
nmsworld = getNMSClass("net.minecraft.server.WorldServer");
chunkprovserver = getNMSClass("net.minecraft.server.ChunkProviderServer");
longhashset = getOBCClassNoFail("org.bukkit.craftbukkit.util.LongHashSet");
if(longhashset != null) {
lhs_containskey = getMethod(longhashset, new String[] { "contains" }, new Class[] { int.class, int.class });
}
else {
longhashset = getOBCClass("org.bukkit.craftbukkit.util.LongHashset");
lhs_containskey = getMethod(longhashset, new String[] { "containsKey" }, new Class[] { int.class, int.class });
}
nmsw_chunkproviderserver = getField(nmsworld, new String[] { "chunkProviderServer" }, chunkprovserver);
cps_unloadqueue = getFieldNoFail(chunkprovserver, new String[] { "unloadQueue" }, longhashset);
if(cps_unloadqueue == null) {
Log.info("Unload queue not found - default to unload all chunks");
}
/* CraftChunkSnapshot */
craftchunksnapshot = getOBCClass("org.bukkit.craftbukkit.CraftChunkSnapshot");
ccss_biome = getPrivateField(craftchunksnapshot, new String[] { "biome" }, biomebasearray);
/** CraftChunk */
craftchunk = getOBCClass("org.bukkit.craftbukkit.CraftChunk");
cc_gethandle = getMethod(craftchunk, new String[] { "getHandle" }, new Class[0]);
/** n.m.s.Chunk */
nmschunk = getNMSClass("net.minecraft.server.Chunk");
nmsc_removeentities = getMethod(nmschunk, new String[] { "removeEntities" }, new Class[0]);
nmsc_tileentities = getField(nmschunk, new String[] { "tileEntities" }, Map.class);
/** nbt classes */
nbttagcompound = getNMSClass("net.minecraft.server.NBTTagCompound");
nbttagbyte = getNMSClass("net.minecraft.server.NBTTagByte");
nbttagshort = getNMSClass("net.minecraft.server.NBTTagShort");
nbttagint = getNMSClass("net.minecraft.server.NBTTagInt");
nbttaglong = getNMSClass("net.minecraft.server.NBTTagLong");
nbttagfloat = getNMSClass("net.minecraft.server.NBTTagFloat");
nbttagdouble = getNMSClass("net.minecraft.server.NBTTagDouble");
nbttagbytearray = getNMSClass("net.minecraft.server.NBTTagByteArray");
nbttagstring = getNMSClass("net.minecraft.server.NBTTagString");
nbttagintarray = getNMSClass("net.minecraft.server.NBTTagIntArray");
compound_get = getMethod(nbttagcompound, new String[] { "get" }, new Class[] { String.class });
nbttagbyte_val = getField(nbttagbyte, new String[] { "data" }, byte.class);
nbttagshort_val = getField(nbttagshort, new String[] { "data" }, short.class);
nbttagint_val = getField(nbttagint, new String[] { "data" }, int.class);
nbttaglong_val = getField(nbttaglong, new String[] { "data" }, long.class);
nbttagfloat_val = getField(nbttagfloat, new String[] { "data" }, float.class);
nbttagdouble_val = getField(nbttagdouble, new String[] { "data" }, double.class);
nbttagbytearray_val = getField(nbttagbytearray, new String[] { "data" }, byte[].class);
nbttagstring_val = getField(nbttagstring, new String[] { "data" }, String.class);
nbttagintarray_val = getField(nbttagintarray, new String[] { "data" }, int[].class);
/** Tile entity */
nms_tileentity = getNMSClass("net.minecraft.server.TileEntity");
nmst_readnbt = getMethod(nms_tileentity, new String[] { "b" }, new Class[] { nbttagcompound });
nmst_x = getField(nms_tileentity, new String[] { "x" }, int.class);
nmst_y = getField(nms_tileentity, new String[] { "y" }, int.class);
nmst_z = getField(nms_tileentity, new String[] { "z" }, int.class);
if(failed)
throw new IllegalArgumentException("Error initializing dynmap - bukkit version incompatible!");
}
public Class<?> getOBCClass(String classname) {
return getClassByName(classname, "org.bukkit.craftbukkit", obc_package, false);
}
public Class<?> getOBCClassNoFail(String classname) {
return getClassByName(classname, "org.bukkit.craftbukkit", obc_package, true);
}
public Class<?> getNMSClass(String classname) {
return getClassByName(classname, "net.minecraft.server", nms_package, false);
}
public Class<?> getClassByName(String classname, String base, String mapping, boolean nofail) {
String n = classname;
int idx = classname.indexOf(base);
if(idx >= 0) {
n = classname.substring(0, idx) + mapping + classname.substring(idx + base.length());
}
try {
return Class.forName(n);
} catch (ClassNotFoundException cnfx) {
try {
return Class.forName(classname);
} catch (ClassNotFoundException cnfx2) {
if(!nofail) {
Log.severe("Cannot find " + classname);
failed = true;
}
return null;
}
}
}
/**
* Get field
*/
private Field getField(Class<?> cls, String[] ids, Class<?> type) {
return getField(cls, ids, type, false);
}
private Field getFieldNoFail(Class<?> cls, String[] ids, Class<?> type) {
return getField(cls, ids, type, true);
}
/**
* Get field
*/
private Field getField(Class<?> cls, String[] ids, Class<?> type, boolean nofail) {
if((cls == null) || (type == null)) return null;
for(String id : ids) {
try {
Field f = cls.getField(id);
if(f.getType().isAssignableFrom(type)) {
return f;
}
} catch (NoSuchFieldException nsfx) {
}
}
if(!nofail) {
Log.severe("Unable to find field " + ids[0] + " for " + cls.getName());
failed = true;
}
return null;
}
/**
* Get private field
*/
private Field getPrivateField(Class<?> cls, String[] ids, Class<?> type) {
if((cls == null) || (type == null)) return null;
for(String id : ids) {
try {
Field f = cls.getDeclaredField(id);
if(f.getType().isAssignableFrom(type)) {
f.setAccessible(true);
return f;
}
} catch (NoSuchFieldException nsfx) {
}
}
Log.severe("Unable to find field " + ids[0] + " for " + cls.getName());
failed = true;
return null;
}
private Object getFieldValue(Object obj, Field field, Object def) {
if((obj != null) && (field != null)) {
try {
return field.get(obj);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
return def;
}
/**
* Get method
*/
private Method getMethod(Class<?> cls, String[] ids, Class[] args) {
if(cls == null) return null;
for(String id : ids) {
try {
return cls.getMethod(id, args);
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
}
}
Log.severe("Unable to find method " + ids[0] + " for " + cls.getName());
failed = true;
return null;
}
private Object callMethod(Object obj, Method meth, Object[] args, Object def) {
if((obj == null) || (meth == null)) {
return def;
}
try {
return meth.invoke(obj, args);
} catch (IllegalArgumentException iax) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return def;
}
/**
* Get list of defined biomebase objects
*/
public Object[] getBiomeBaseList() {
return (Object[]) getFieldValue(biomebase, biomebaselist, new Object[0]);
}
/** Get temperature from biomebase */
public float getBiomeBaseTemperature(Object bb) {
return (Float) getFieldValue(bb, biomebasetemp, 0.5F);
}
/** Get humidity from biomebase */
public float getBiomeBaseHumidity(Object bb) {
return (Float) getFieldValue(bb, biomebasehumi, 0.5F);
}
/** Get ID string from biomebase */
public String getBiomeBaseIDString(Object bb) {
return (String) getFieldValue(bb, biomebaseidstring, null);
}
/** Get ID from biomebase */
public int getBiomeBaseID(Object bb) {
return (Integer) getFieldValue(bb, biomebaseid, -1);
}
/* Get net.minecraft.server.world for given world */
public Object getNMSWorld(World w) {
return callMethod(w, cw_gethandle, nullargs, null);
}
/* Get unload queue for given NMS world */
public Object getUnloadQueue(Object nmsworld) {
Object cps = getFieldValue(nmsworld, nmsw_chunkproviderserver, null); // Get chunkproviderserver
if(cps != null) {
return getFieldValue(cps, cps_unloadqueue, null);
}
return null;
}
/* For testing unload queue for presence of givne chunk */
public boolean isInUnloadQueue(Object unloadqueue, int x, int z) {
if(unloadqueue != null) {
return (Boolean)callMethod(unloadqueue, lhs_containskey, new Object[] { x, z }, true);
}
return true;
}
public Object[] getBiomeBaseFromSnapshot(ChunkSnapshot css) {
return (Object[])getFieldValue(css, ccss_biome, null);
}
public boolean isCraftChunkSnapshot(ChunkSnapshot css) {
if(craftchunksnapshot != null) {
return craftchunksnapshot.isAssignableFrom(css.getClass());
}
return false;
}
/** Remove entities from given chunk */
public void removeEntitiesFromChunk(Chunk c) {
Object omsc = callMethod(c, cc_gethandle, nullargs, null);
if(omsc != null) {
callMethod(omsc, nmsc_removeentities, nullargs, null);
}
}
/** Get tile entities map from chunk */
public Map getTileEntitiesForChunk(Chunk c) {
Object omsc = callMethod(c, cc_gethandle, nullargs, null);
if(omsc != null) {
return (Map)getFieldValue(omsc, nmsc_tileentities, nullmap);
}
return nullmap;
}
/**
* Get X coordinate of tile entity
*/
public int getTileEntityX(Object te) {
return (Integer)getFieldValue(te, nmst_x, 0);
}
/**
* Get Y coordinate of tile entity
*/
public int getTileEntityY(Object te) {
return (Integer)getFieldValue(te, nmst_y, 0);
}
/**
* Get Z coordinate of tile entity
*/
public int getTileEntityZ(Object te) {
return (Integer)getFieldValue(te, nmst_z, 0);
}
/**
* Read tile entity NBT
*/
public Object readTileEntityNBT(Object te) {
if(nbttagcompound == null) return null;
Object nbt = null;
try {
nbt = nbttagcompound.newInstance();
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
if(nbt != null) {
callMethod(te, nmst_readnbt, new Object[] { nbt }, null);
}
return nbt;
}
/**
* Get field value from NBT compound
*/
public Object getFieldValue(Object nbt, String field) {
Object val = callMethod(nbt, compound_get, new Object[] { field }, null);
if(val == null) return null;
Class<?> valcls = val.getClass();
if(valcls.equals(nbttagbyte)) {
return getFieldValue(val, nbttagbyte_val, null);
}
else if(valcls.equals(nbttagshort)) {
return getFieldValue(val, nbttagshort_val, null);
}
else if(valcls.equals(nbttagint)) {
return getFieldValue(val, nbttagint_val, null);
}
else if(valcls.equals(nbttaglong)) {
return getFieldValue(val, nbttaglong_val, null);
}
else if(valcls.equals(nbttagfloat)) {
return getFieldValue(val, nbttagfloat_val, null);
}
else if(valcls.equals(nbttagdouble)) {
return getFieldValue(val, nbttagdouble_val, null);
}
else if(valcls.equals(nbttagbytearray)) {
return getFieldValue(val, nbttagbytearray_val, null);
}
else if(valcls.equals(nbttagstring)) {
return getFieldValue(val, nbttagstring_val, null);
}
else if(valcls.equals(nbttagintarray)) {
return getFieldValue(val, nbttagintarray_val, null);
}
return null;
}
}

View File

@ -2,7 +2,6 @@ package org.dynmap.bukkit;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
@ -16,8 +15,6 @@ import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Future;
import net.minecraft.server.BiomeBase;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
@ -60,8 +57,6 @@ import org.bukkit.event.world.SpawnChangeEvent;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.material.MaterialData;
import org.bukkit.material.Tree;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.Plugin;
@ -112,7 +107,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
/* Lookup cache */
private World last_world;
private BukkitWorld last_bworld;
private BukkitVersionHelper helper = BukkitVersionHelper.getHelper();
private final BukkitWorld getWorldByName(String name) {
if((last_world != null) && (last_world.getName().equals(name))) {
return last_bworld;
@ -636,57 +633,29 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
public void loadExtraBiomes() {
Field tmpfld;
Field humfld;
int cnt = 0;
try {
tmpfld = BiomeBase.class.getField("temperature");
} catch (NoSuchFieldException nsfx) {
try {
tmpfld = BiomeBase.class.getField("F");
} catch (NoSuchFieldException nsfx2) {
Log.warning("BiomeBase.temperature field not found");
tmpfld = null;
}
}
if((tmpfld != null) && (tmpfld.getType().getClass().isAssignableFrom(float.class) == false)) {
tmpfld = null;
}
try {
humfld = BiomeBase.class.getField("humidity");
} catch (NoSuchFieldException nsfx) {
try {
humfld = BiomeBase.class.getField("G");
} catch (NoSuchFieldException nsfx2) {
Log.warning("BiomeBase.humidity field not found");
humfld = null;
}
}
if((humfld != null) && (humfld.getType().getClass().isAssignableFrom(float.class) == false)) {
humfld = null;
}
for(int i = BiomeMap.LAST_WELL_KNOWN+1; i < BiomeBase.biomes.length; i++) {
BiomeBase bb = BiomeBase.biomes[i];
/* Find array of biomes in biomebase */
Object[] biomelist = helper.getBiomeBaseList();
/* Loop through list, starting afer well known biomes */
for(int i = BiomeMap.LAST_WELL_KNOWN+1; i < biomelist.length; i++) {
Object bb = biomelist[i];
if(bb != null) {
String id = "BIOME_" + i;
float tmp = 0.5F, hum = 0.5F;
try {
id = bb.y;
} catch (Exception x) {}
try {
if(tmpfld != null)
tmp = tmpfld.getFloat(bb);
if(humfld != null)
hum = humfld.getFloat(bb);
} catch (Exception x) {
String id = helper.getBiomeBaseIDString(bb);
if(id == null) {
id = "BIOME_" + i;
}
float tmp = helper.getBiomeBaseTemperature(bb);
float hum = helper.getBiomeBaseHumidity(bb);
BiomeMap m = new BiomeMap(i, id, tmp, hum);
Log.verboseinfo("Add custom biome [" + m.toString() + "] (" + i + ")");
cnt++;
}
}
Log.info("Added " + cnt + " custom biome mappings");
if(cnt > 0) {
Log.info("Added " + cnt + " custom biome mappings");
}
}
@Override

View File

@ -1,33 +1,13 @@
package org.dynmap.bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import net.minecraft.server.BiomeBase;
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 java.util.Map;
import org.bukkit.World;
import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftChunk;
import org.bukkit.craftbukkit.CraftChunkSnapshot;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.ChunkSnapshot;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapCore;
@ -48,11 +28,7 @@ import org.getspout.spoutapi.block.SpoutChunk;
*/
public class NewMapChunkCache implements MapChunkCache {
private static boolean init = false;
private static boolean use_spout = false;
private static Field unloadqueue = null;
private static Method queuecontainskey = null;
private static Field biomesnapshot = null;
private static boolean use_spout = false;
private World w;
private DynmapWorld dw;
@ -80,6 +56,8 @@ public class NewMapChunkCache implements MapChunkCache {
private long exceptions;
private static BukkitVersionHelper helper = BukkitVersionHelper.getHelper();
private static final BlockStep unstep[] = { BlockStep.X_MINUS, BlockStep.Y_MINUS, BlockStep.Z_MINUS,
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
@ -168,29 +146,23 @@ public class NewMapChunkCache implements MapChunkCache {
sameneighborbiomecnt[i] = new byte[z_size];
biomemap[i] = new BiomeMap[z_size];
}
BiomeBase[] biomebase = null;
Object[] biomebase = null;
ChunkSnapshot biome_css = null;
for(int i = 0; i < x_size; i++) {
initialize(i + x_base, 64, z_base);
for(int j = 0; j < z_size; j++) {
BiomeMap bm;
if((biomesnapshot != null) && (snap != biome_css)) {
if(snap != biome_css) {
biomebase = null;
biome_css = snap;
try {
if (biome_css instanceof SpoutChunkSnapshot) {
biome_css = ((SpoutChunkSnapshot)biome_css).chunk;
}
if(biome_css instanceof CraftChunkSnapshot) {
biomebase = (BiomeBase[]) biomesnapshot.get(biome_css);
}
} catch (IllegalArgumentException iax) {
} catch (IllegalAccessException e) {
if (biome_css instanceof SpoutChunkSnapshot) {
biome_css = ((SpoutChunkSnapshot)biome_css).chunk;
}
biomebase = helper.getBiomeBaseFromSnapshot(biome_css);
}
if(biomebase != null) {
bm = BiomeMap.byBiomeID(biomebase[bz << 4 | bx].id);
bm = BiomeMap.byBiomeID(helper.getBiomeBaseID(biomebase[bz << 4 | bx]));
}
else {
Biome bb = snap.getBiome(bx, bz);
@ -758,28 +730,6 @@ public class NewMapChunkCache implements MapChunkCache {
if(!init) {
use_spout = DynmapPlugin.plugin.hasSpout();
try {
unloadqueue = ChunkProviderServer.class.getField("unloadQueue");
Class cls = unloadqueue.getType();
String nm = cls.getName();
if (nm.equals("org.bukkit.craftbukkit.util.LongHashset")) {
queuecontainskey = unloadqueue.getType().getMethod("containsKey", new Class[] { int.class, int.class });
}
else {
unloadqueue = null;
}
} catch (NoSuchFieldException nsfx) {
unloadqueue = null;
} catch (NoSuchMethodException nsmx) {
unloadqueue = null;
}
try {
biomesnapshot = CraftChunkSnapshot.class.getDeclaredField("biome");
biomesnapshot.setAccessible(true);
} catch (NoSuchFieldException nsfx) {
biomesnapshot = null;
Log.warning("Unable to find biome field in ChunkSnapshot");
}
init = true;
}
}
@ -836,15 +786,8 @@ public class NewMapChunkCache implements MapChunkCache {
if(dw.isLoaded() == false)
return 0;
long t0 = System.nanoTime();
CraftWorld cw = (CraftWorld)w;
Object queue = null;
try {
if (unloadqueue != null) {
queue = unloadqueue.get(cw.getHandle().chunkProviderServer);
}
} catch (IllegalArgumentException iax) {
} catch (IllegalAccessException e) {
}
Object queue = helper.getUnloadQueue(helper.getNMSWorld(w));
int cnt = 0;
if(iterator == null)
iterator = chunks.listIterator();
@ -897,12 +840,7 @@ public class NewMapChunkCache implements MapChunkCache {
boolean didload = false;
boolean isunloadpending = false;
if (queue != null) {
try {
isunloadpending = (Boolean)queuecontainskey.invoke(queue, chunk.x, chunk.z);
} catch (IllegalAccessException iax) {
} catch (IllegalArgumentException e) {
} catch (InvocationTargetException e) {
}
isunloadpending = helper.isInUnloadQueue(queue, chunk.x, chunk.z);
}
if (isunloadpending) { /* Workaround: can't be pending if not loaded */
wasLoaded = true;
@ -958,62 +896,30 @@ public class NewMapChunkCache implements MapChunkCache {
}
/* 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);
Map tileents = helper.getTileEntitiesForChunk(c);
for(Object t : tileents.values()) {
int te_x = helper.getTileEntityX(t);
int te_y = helper.getTileEntityY(t);
int te_z = helper.getTileEntityZ(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) {
}
Object nbtcompound = helper.readTileEntityNBT(t);
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);
}
Object val = helper.getFieldValue(nbtcompound, id);
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);
tileData.put(getIndexInChunk(cx,te_y,cz), vlist);
}
}
}
@ -1036,8 +942,7 @@ public class NewMapChunkCache implements MapChunkCache {
/* It looks like bukkit "leaks" entities - they don't get removed from the world-level table
* when chunks are unloaded but not saved - removing them seems to do the trick */
if(!(didgenerate && do_save)) {
CraftChunk cc = (CraftChunk)c;
cc.getHandle().removeEntities();
helper.removeEntitiesFromChunk(c);
}
/* Since we only remember ones we loaded, and we're synchronous, no player has
* moved, so it must be safe (also prevent chunk leak, which appears to happen