2018-08-08 08:39:51 +02:00
|
|
|
package org.dynmap.bukkit.helper;
|
2013-01-22 06:54:13 +01:00
|
|
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
import java.lang.reflect.Method;
|
2018-02-14 02:11:16 +01:00
|
|
|
import java.nio.charset.Charset;
|
2014-07-10 05:20:33 +02:00
|
|
|
import java.util.Collection;
|
2013-01-22 06:54:13 +01:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Map;
|
2016-06-12 04:38:50 +02:00
|
|
|
import java.util.Set;
|
2014-07-10 05:20:33 +02:00
|
|
|
|
2013-01-22 06:54:13 +01:00
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
import org.bukkit.Chunk;
|
|
|
|
import org.bukkit.ChunkSnapshot;
|
|
|
|
import org.bukkit.Server;
|
|
|
|
import org.bukkit.World;
|
2014-07-10 05:20:33 +02:00
|
|
|
import org.bukkit.entity.Player;
|
2013-01-22 06:54:13 +01:00
|
|
|
import org.dynmap.Log;
|
2018-02-14 02:11:16 +01:00
|
|
|
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
|
|
|
|
|
|
|
import com.google.common.base.Charsets;
|
|
|
|
import com.google.common.collect.ForwardingMultimap;
|
|
|
|
import com.google.common.collect.Iterables;
|
|
|
|
import com.google.gson.Gson;
|
|
|
|
import com.google.gson.GsonBuilder;
|
|
|
|
import com.google.gson.JsonParseException;
|
2013-01-22 06:54:13 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper for isolation of bukkit version specific issues
|
|
|
|
*/
|
|
|
|
public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
|
|
|
|
private String obc_package; // Package used for org.bukkit.craftbukkit
|
|
|
|
protected String nms_package; // Package used for net.minecraft.server
|
|
|
|
private boolean failed;
|
2015-02-15 19:40:30 +01:00
|
|
|
protected static final Object[] nullargs = new Object[0];
|
2016-05-23 07:35:58 +02:00
|
|
|
protected static final Class<?>[] nulltypes = new Class[0];
|
|
|
|
private static final Map<?, ?> nullmap = Collections.emptyMap();
|
2013-01-22 06:54:13 +01:00
|
|
|
|
|
|
|
/** CraftChunkSnapshot */
|
2018-08-08 08:39:51 +02:00
|
|
|
protected Class<?> craftchunksnapshot;
|
2013-01-22 06:54:13 +01:00
|
|
|
private Field ccss_biome;
|
|
|
|
/** CraftChunk */
|
|
|
|
private Class<?> craftchunk;
|
|
|
|
private Method cc_gethandle;
|
|
|
|
/** CraftWorld */
|
|
|
|
private Class<?> craftworld;
|
|
|
|
private Method cw_gethandle;
|
|
|
|
|
|
|
|
/** BiomeBase related helpers */
|
|
|
|
protected Class<?> biomebase;
|
|
|
|
protected Class<?> biomebasearray;
|
|
|
|
protected Field biomebaselist;
|
|
|
|
protected Field biomebasetemp;
|
|
|
|
protected Field biomebasehumi;
|
|
|
|
protected Field biomebaseidstring;
|
|
|
|
protected Field biomebaseid;
|
|
|
|
/** n.m.s.World */
|
|
|
|
protected Class<?> nmsworld;
|
|
|
|
protected Class<?> chunkprovserver;
|
|
|
|
protected Class<?> longhashset;
|
|
|
|
protected Field nmsw_chunkproviderserver;
|
|
|
|
protected Field cps_unloadqueue;
|
2016-06-10 08:14:06 +02:00
|
|
|
protected boolean cps_unloadqueue_isSet;
|
2013-01-22 06:54:13 +01:00
|
|
|
protected Method lhs_containskey;
|
|
|
|
/** n.m.s.Chunk */
|
|
|
|
protected Class<?> nmschunk;
|
|
|
|
protected Field nmsc_tileentities;
|
2014-01-18 00:40:39 +01:00
|
|
|
protected Field nmsc_inhabitedticks;
|
2013-01-22 06:54:13 +01:00
|
|
|
/** nbt classes */
|
|
|
|
protected Class<?> nbttagcompound;
|
|
|
|
protected Class<?> nbttagbyte;
|
|
|
|
protected Class<?> nbttagshort;
|
|
|
|
protected Class<?> nbttagint;
|
|
|
|
protected Class<?> nbttaglong;
|
|
|
|
protected Class<?> nbttagfloat;
|
|
|
|
protected Class<?> nbttagdouble;
|
|
|
|
protected Class<?> nbttagbytearray;
|
|
|
|
protected Class<?> nbttagstring;
|
|
|
|
protected Class<?> nbttagintarray;
|
|
|
|
protected Method compound_get;
|
|
|
|
protected Field nbttagbyte_val;
|
|
|
|
protected Field nbttagshort_val;
|
|
|
|
protected Field nbttagint_val;
|
|
|
|
protected Field nbttaglong_val;
|
|
|
|
protected Field nbttagfloat_val;
|
|
|
|
protected Field nbttagdouble_val;
|
|
|
|
protected Field nbttagbytearray_val;
|
|
|
|
protected Field nbttagstring_val;
|
|
|
|
protected Field nbttagintarray_val;
|
|
|
|
/** Tile entity */
|
|
|
|
protected Class<?> nms_tileentity;
|
|
|
|
protected Method nmst_readnbt;
|
|
|
|
protected Field nmst_x;
|
|
|
|
protected Field nmst_y;
|
|
|
|
protected Field nmst_z;
|
2014-11-28 18:08:44 +01:00
|
|
|
protected Method nmst_getposition;
|
|
|
|
/** BlockPosition */
|
|
|
|
protected Class<?> nms_blockposition;
|
|
|
|
protected Method nmsbp_getx;
|
|
|
|
protected Method nmsbp_gety;
|
|
|
|
protected Method nmsbp_getz;
|
|
|
|
|
2014-07-10 05:20:33 +02:00
|
|
|
/** Server */
|
|
|
|
protected Method server_getonlineplayers;
|
|
|
|
/** Player */
|
|
|
|
protected Method player_gethealth;
|
2018-02-14 02:11:16 +01:00
|
|
|
// CraftPlayer
|
|
|
|
private Class<?> obc_craftplayer;
|
|
|
|
private Method obcplayer_getprofile;
|
|
|
|
// GameProfile
|
|
|
|
private Class<?> cma_gameprofile;
|
|
|
|
private Method cmaprofile_getproperties;
|
|
|
|
// Property
|
|
|
|
private Class<?> cma_property;
|
|
|
|
private Method cmaproperty_getvalue;
|
2013-01-22 06:54:13 +01:00
|
|
|
|
2018-08-08 08:39:51 +02:00
|
|
|
protected BukkitVersionHelperGeneric() {
|
2013-01-22 06:54:13 +01:00
|
|
|
failed = false;
|
|
|
|
/* Look up base classname for bukkit server - tells us OBC package */
|
|
|
|
obc_package = Bukkit.getServer().getClass().getPackage().getName();
|
|
|
|
/* Get NMS package */
|
|
|
|
nms_package = getNMSPackage();
|
|
|
|
if(nms_package == null) {
|
|
|
|
failed = true;
|
|
|
|
}
|
|
|
|
/* Craftworld fields */
|
|
|
|
craftworld = getOBCClass("org.bukkit.craftbukkit.CraftWorld");
|
|
|
|
cw_gethandle = getMethod(craftworld, new String[] { "getHandle" }, new Class[0]);
|
|
|
|
/* CraftChunkSnapshot */
|
|
|
|
craftchunksnapshot = getOBCClass("org.bukkit.craftbukkit.CraftChunkSnapshot");
|
2016-04-02 06:55:53 +02:00
|
|
|
biomebasearray = getNMSClass("[Lnet.minecraft.server.BiomeBase;");
|
2013-01-22 06:54:13 +01:00
|
|
|
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]);
|
2014-07-10 05:20:33 +02:00
|
|
|
|
|
|
|
/** Server */
|
|
|
|
server_getonlineplayers = getMethod(Server.class, new String[] { "getOnlinePlayers" }, new Class[0]);
|
|
|
|
/** Player */
|
|
|
|
player_gethealth = getMethod(Player.class, new String[] { "getHealth" }, new Class[0]);
|
2018-02-14 02:11:16 +01:00
|
|
|
|
|
|
|
// CraftPlayer
|
|
|
|
obc_craftplayer = getOBCClass("org.bukkit.craftbukkit.entity.CraftPlayer");
|
|
|
|
obcplayer_getprofile = getMethod(obc_craftplayer, new String[] { "getProfile" }, new Class[0]);
|
|
|
|
// GameProfile
|
|
|
|
cma_gameprofile = getOBCClass("com.mojang.authlib.GameProfile");
|
|
|
|
cmaprofile_getproperties = getMethod(cma_gameprofile, new String[] { "getProperties" }, new Class[0]);
|
|
|
|
// Property
|
|
|
|
cma_property = getOBCClass("com.mojang.authlib.properties.Property");
|
|
|
|
cmaproperty_getvalue = getMethod(cma_property, new String[] { "getValue" }, new Class[0]);
|
|
|
|
|
2013-01-22 06:54:13 +01:00
|
|
|
/* Get NMS classes and fields */
|
|
|
|
if(!failed)
|
|
|
|
loadNMS();
|
|
|
|
|
|
|
|
if(failed)
|
|
|
|
throw new IllegalArgumentException("Error initializing dynmap - bukkit version incompatible!");
|
|
|
|
}
|
|
|
|
|
|
|
|
protected abstract void loadNMS();
|
|
|
|
|
|
|
|
protected abstract String getNMSPackage();
|
|
|
|
|
|
|
|
protected Class<?> getOBCClass(String classname) {
|
|
|
|
return getClassByName(classname, "org.bukkit.craftbukkit", obc_package, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected Class<?> getOBCClassNoFail(String classname) {
|
|
|
|
return getClassByName(classname, "org.bukkit.craftbukkit", obc_package, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected Class<?> getNMSClass(String classname) {
|
|
|
|
return getClassByName(classname, "net.minecraft.server", nms_package, false);
|
|
|
|
}
|
2015-02-15 19:40:30 +01:00
|
|
|
|
|
|
|
protected Class<?> getNMSClassNoFail(String classname) {
|
|
|
|
return getClassByName(classname, "net.minecraft.server", nms_package, true);
|
|
|
|
}
|
|
|
|
|
2013-01-22 06:54:13 +01:00
|
|
|
protected 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
|
|
|
|
*/
|
|
|
|
protected Field getField(Class<?> cls, String[] ids, Class<?> type) {
|
|
|
|
return getField(cls, ids, type, false);
|
|
|
|
}
|
|
|
|
protected 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;
|
|
|
|
}
|
2016-03-02 05:40:52 +01:00
|
|
|
/**
|
|
|
|
* Get private field
|
|
|
|
*/
|
|
|
|
protected Field getPrivateFieldNoFail(Class<?> cls, String[] ids, Class<?> type) {
|
|
|
|
return getPrivateField(cls, ids, type, true);
|
|
|
|
}
|
2013-01-22 06:54:13 +01:00
|
|
|
/**
|
|
|
|
* Get private field
|
|
|
|
*/
|
2013-04-18 08:20:59 +02:00
|
|
|
protected Field getPrivateField(Class<?> cls, String[] ids, Class<?> type) {
|
2016-03-02 05:40:52 +01:00
|
|
|
return getPrivateField(cls, ids, type, false);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get private field
|
|
|
|
*/
|
|
|
|
protected Field getPrivateField(Class<?> cls, String[] ids, Class<?> type, boolean nofail) {
|
2013-01-22 06:54:13 +01:00
|
|
|
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) {
|
|
|
|
}
|
|
|
|
}
|
2016-03-02 05:40:52 +01:00
|
|
|
if (!nofail) {
|
|
|
|
Log.severe("Unable to find field " + ids[0] + " for " + cls.getName());
|
|
|
|
failed = true;
|
|
|
|
}
|
2013-01-22 06:54:13 +01:00
|
|
|
return null;
|
|
|
|
}
|
2013-03-19 02:30:13 +01:00
|
|
|
protected Object getFieldValue(Object obj, Field field, Object def) {
|
2013-01-22 06:54:13 +01:00
|
|
|
if((obj != null) && (field != null)) {
|
|
|
|
try {
|
|
|
|
return field.get(obj);
|
|
|
|
} catch (IllegalArgumentException e) {
|
2016-04-02 06:55:53 +02:00
|
|
|
System.out.println(String.format("IllegalArgExc(%s,%s)", obj.toString(), field.toString()));
|
2013-01-22 06:54:13 +01:00
|
|
|
} catch (IllegalAccessException e) {
|
2016-04-02 06:55:53 +02:00
|
|
|
System.out.println(String.format("IllegalAccessExc(%s,%s)", obj.toString(), field.toString()));
|
2013-01-22 06:54:13 +01:00
|
|
|
}
|
|
|
|
}
|
2016-04-02 06:55:53 +02:00
|
|
|
else {
|
|
|
|
System.out.println(String.format("NullArg(%s,%s)", (obj != null)?obj.toString():"null", (field != null)?field.toString():"null"));
|
|
|
|
}
|
2013-01-22 06:54:13 +01:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get method
|
|
|
|
*/
|
2016-05-23 07:35:58 +02:00
|
|
|
protected Method getMethod(Class<?> cls, String[] ids, Class<?>[] args) {
|
2013-01-22 06:54:13 +01:00
|
|
|
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;
|
|
|
|
}
|
2016-05-23 07:35:58 +02:00
|
|
|
protected Method getMethodNoFail(Class<?> cls, String[] ids, Class<?>[] args) {
|
2014-11-28 18:08:44 +01:00
|
|
|
if(cls == null) return null;
|
|
|
|
for(String id : ids) {
|
|
|
|
try {
|
|
|
|
return cls.getMethod(id, args);
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
} catch (NoSuchMethodException e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2015-02-15 19:40:30 +01:00
|
|
|
protected Object callMethod(Object obj, Method meth, Object[] args, Object def) {
|
2013-01-22 06:54:13 +01:00
|
|
|
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 */
|
2014-09-07 02:19:20 +02:00
|
|
|
protected Object getNMSWorld(World w) {
|
2013-01-22 06:54:13 +01:00
|
|
|
return callMethod(w, cw_gethandle, nullargs, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get unload queue for given NMS world */
|
2014-09-07 02:19:20 +02:00
|
|
|
public Object getUnloadQueue(World world) {
|
|
|
|
Object cps = getFieldValue(getNMSWorld(world), nmsw_chunkproviderserver, null); // Get chunkproviderserver
|
2016-04-03 02:01:04 +02:00
|
|
|
if ((cps != null) && (cps_unloadqueue != null)) {
|
2013-01-22 06:54:13 +01:00
|
|
|
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) {
|
2016-06-12 04:38:50 +02:00
|
|
|
if (cps_unloadqueue_isSet)
|
|
|
|
return ((Set) unloadqueue).contains(Long.valueOf((long)x & 0xFFFFFFFF | ((long)z & 0xFFFFFFFF) << 32));
|
2013-01-22 06:54:13 +01:00
|
|
|
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);
|
|
|
|
}
|
2014-09-07 02:19:20 +02:00
|
|
|
// public boolean isCraftChunkSnapshot(ChunkSnapshot css) {
|
|
|
|
// if(craftchunksnapshot != null) {
|
|
|
|
// return craftchunksnapshot.isAssignableFrom(css.getClass());
|
|
|
|
// }
|
|
|
|
// return false;
|
|
|
|
// }
|
2016-03-29 02:20:06 +02:00
|
|
|
|
2014-01-18 00:40:39 +01:00
|
|
|
/**
|
|
|
|
* Get inhabited ticks count from chunk
|
|
|
|
*/
|
|
|
|
private static final Long zero = new Long(0);
|
|
|
|
public long getInhabitedTicks(Chunk c) {
|
|
|
|
if (nmsc_inhabitedticks == null) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
Object omsc = callMethod(c, cc_gethandle, nullargs, null);
|
|
|
|
if(omsc != null) {
|
|
|
|
return (Long)getFieldValue(omsc, nmsc_inhabitedticks, zero);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-22 06:54:13 +01:00
|
|
|
/** Get tile entities map from chunk */
|
2016-05-23 07:35:58 +02:00
|
|
|
public Map<?, ?> getTileEntitiesForChunk(Chunk c) {
|
2013-01-22 06:54:13 +01:00
|
|
|
Object omsc = callMethod(c, cc_gethandle, nullargs, null);
|
|
|
|
if(omsc != null) {
|
2016-05-23 07:35:58 +02:00
|
|
|
return (Map<?, ?>)getFieldValue(omsc, nmsc_tileentities, nullmap);
|
2013-01-22 06:54:13 +01:00
|
|
|
}
|
|
|
|
return nullmap;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get X coordinate of tile entity
|
|
|
|
*/
|
|
|
|
public int getTileEntityX(Object te) {
|
2014-11-28 18:08:44 +01:00
|
|
|
if (nmst_getposition == null) {
|
|
|
|
return (Integer)getFieldValue(te, nmst_x, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Object pos = callMethod(te, nmst_getposition, nullargs, null);
|
|
|
|
return (Integer) callMethod(pos, nmsbp_getx, nullargs, null);
|
|
|
|
}
|
2013-01-22 06:54:13 +01:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get Y coordinate of tile entity
|
|
|
|
*/
|
|
|
|
public int getTileEntityY(Object te) {
|
2014-11-28 18:08:44 +01:00
|
|
|
if (nmst_getposition == null) {
|
|
|
|
return (Integer)getFieldValue(te, nmst_y, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Object pos = callMethod(te, nmst_getposition, nullargs, null);
|
|
|
|
return (Integer) callMethod(pos, nmsbp_gety, nullargs, null);
|
|
|
|
}
|
2013-01-22 06:54:13 +01:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get Z coordinate of tile entity
|
|
|
|
*/
|
|
|
|
public int getTileEntityZ(Object te) {
|
2014-11-28 18:08:44 +01:00
|
|
|
if (nmst_getposition == null) {
|
|
|
|
return (Integer)getFieldValue(te, nmst_z, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Object pos = callMethod(te, nmst_getposition, nullargs, null);
|
|
|
|
return (Integer) callMethod(pos, nmsbp_getz, nullargs, null);
|
|
|
|
}
|
2013-01-22 06:54:13 +01:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
2014-07-10 05:20:33 +02:00
|
|
|
/**
|
|
|
|
* Get list of online players
|
|
|
|
*/
|
|
|
|
public Player[] getOnlinePlayers() {
|
|
|
|
Object players = callMethod(Bukkit.getServer(), server_getonlineplayers, nullargs, null);
|
|
|
|
if (players instanceof Player[]) { /* Pre 1.7.10 */
|
|
|
|
return (Player[]) players;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
Collection<? extends Player> p = (Collection<? extends Player>) players;
|
|
|
|
return p.toArray(new Player[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get player health
|
|
|
|
*/
|
2014-10-13 16:41:14 +02:00
|
|
|
@Override
|
|
|
|
public double getHealth(Player p) {
|
2014-07-10 05:20:33 +02:00
|
|
|
Object health = callMethod(p, player_gethealth, nullargs, null);
|
|
|
|
if (health instanceof Integer) {
|
|
|
|
return (Integer) health;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return ((Double) health).intValue();
|
|
|
|
}
|
|
|
|
}
|
2018-02-14 02:11:16 +01:00
|
|
|
|
|
|
|
private static final Gson gson = new GsonBuilder().create();
|
|
|
|
|
|
|
|
public class TexturesPayload {
|
|
|
|
public long timestamp;
|
|
|
|
public String profileId;
|
|
|
|
public String profileName;
|
|
|
|
public boolean isPublic;
|
|
|
|
public Map<String, ProfileTexture> textures;
|
|
|
|
|
|
|
|
}
|
|
|
|
public class ProfileTexture {
|
|
|
|
public String url;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get skin URL for player
|
|
|
|
* @param player
|
|
|
|
*/
|
|
|
|
public String getSkinURL(Player player) {
|
|
|
|
String url = null;
|
|
|
|
Object profile = callMethod(player, obcplayer_getprofile, nullargs, null);
|
|
|
|
if (profile != null) {
|
|
|
|
Object propmap = callMethod(profile, cmaprofile_getproperties, nullargs, null);
|
|
|
|
if ((propmap != null) && (propmap instanceof ForwardingMultimap)) {
|
|
|
|
ForwardingMultimap<String, Object> fmm = (ForwardingMultimap<String, Object>) propmap;
|
|
|
|
Collection<Object> txt = fmm.get("textures");
|
|
|
|
Object textureProperty = Iterables.getFirst(fmm.get("textures"), null);
|
|
|
|
if (textureProperty != null) {
|
|
|
|
String val = (String) callMethod(textureProperty, cmaproperty_getvalue, nullargs, null);
|
|
|
|
if (val != null) {
|
|
|
|
TexturesPayload result = null;
|
|
|
|
try {
|
|
|
|
String json = new String(Base64Coder.decode(val), Charsets.UTF_8);
|
|
|
|
result = gson.fromJson(json, TexturesPayload.class);
|
|
|
|
} catch (JsonParseException e) {
|
|
|
|
}
|
|
|
|
if ((result != null) && (result.textures != null) && (result.textures.containsKey("SKIN"))) {
|
|
|
|
url = result.textures.get("SKIN").url;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
2014-07-10 05:20:33 +02:00
|
|
|
|
2013-01-22 06:54:13 +01:00
|
|
|
}
|