mirror of
https://github.com/encounter/dynmap.git
synced 2026-03-30 11:08:39 -07:00
Compare commits
154 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b13c26c0d6 | |||
| 3fd4ac7373 | |||
| ac0f756fae | |||
| 551f35f3f9 | |||
| ec9ebf2dbb | |||
| 3702918a6f | |||
| 8085221087 | |||
| 7de967f1c2 | |||
| f6e127b7f0 | |||
| 22d1923ad5 | |||
| d8d3061696 | |||
| 14da080d52 | |||
| 10ce166b54 | |||
| cb9f964348 | |||
| 9850a03945 | |||
| 8abfae3d79 | |||
| f486ad75f1 | |||
| 54b3fb429c | |||
| 86547f8d78 | |||
| 8ec80937e3 | |||
| 0e5e602a90 | |||
| 3239d539c0 | |||
| 05bd2544fd | |||
| 252da2a5c6 | |||
| 5d83ebf8aa | |||
| 026cc72233 | |||
| 0d2cceea4b | |||
| a1dfae7f79 | |||
| d6eb822b26 | |||
| d4f161ca99 | |||
| 376ec447ed | |||
| 926d2a3dbc | |||
| eeffa4f98d | |||
| 8350727a73 | |||
| 3b79890166 | |||
| 17174c177c | |||
| 07e7d53a93 | |||
| 76863aeb71 | |||
| f7d2dac826 | |||
| 3cb7ba342c | |||
| d2ab466dc0 | |||
| d03ed7a461 | |||
| c8469d7aba | |||
| e7c92096b2 | |||
| 0c9d397144 | |||
| b4a3b61c11 | |||
| 564c38b44a | |||
| 664e7da659 | |||
| 9046212a47 | |||
| b6ee68c9b0 | |||
| 7854568d88 | |||
| f1c9417237 | |||
| 336f8302c4 | |||
| d8ccc26109 | |||
| d396046249 | |||
| 1793d910d4 | |||
| f0f881d126 | |||
| 5482ddaa89 | |||
| 47455eb912 | |||
| 32a1c20fd0 | |||
| b85c38e3a7 | |||
| 5bc4de6a8b | |||
| 2d20fd11f7 | |||
| 6a4bb59d60 | |||
| ab45edb82c | |||
| 4f6bc05180 | |||
| 076681e188 | |||
| b7abfe7c06 | |||
| 3a88ac66a6 | |||
| d3b9367794 | |||
| 666840fc8b | |||
| 62f4c12147 | |||
| 4b3f2280b6 | |||
| df55606023 | |||
| 6fc5fddd44 | |||
| dea285c160 | |||
| 204641a4b0 | |||
| d4aaa1d1fd | |||
| fe83a7d1cc | |||
| d4e24e9d26 | |||
| 734937884a | |||
| 3efe3c3d3d | |||
| 46ab344197 | |||
| 9270ce853d | |||
| 04a2019e9d | |||
| 8daf95891d | |||
| 5396d0b823 | |||
| a2ab8c4f2f | |||
| e7efbe193a | |||
| 99ea38d02a | |||
| 7c6e660cf0 | |||
| bcd0acec33 | |||
| 7e07bff71f | |||
| 2d95548d25 | |||
| 3ac67ce2c5 | |||
| 0d25fd2edc | |||
| bee16ef331 | |||
| bf16d18371 | |||
| e57634ebb3 | |||
| 55a5aacfce | |||
| e6fe29f0c5 | |||
| 34712e27f0 | |||
| 6a5eebcc00 | |||
| c8b1f71949 | |||
| dc11ef3507 | |||
| d0bbb78e98 | |||
| 9144bff25b | |||
| 18325c2b33 | |||
| f1a686eaf8 | |||
| b3c32456ca | |||
| be16ac089f | |||
| 44a8bfa38d | |||
| 443d64f7da | |||
| 9ad5a7e4f7 | |||
| 3483b19cef | |||
| 44c5d51c4e | |||
| 56d1bcf3eb | |||
| f43027f02f | |||
| bd12420edd | |||
| 3c01aff411 | |||
| 4d664de250 | |||
| 278fa36f94 | |||
| 1a2f63bcfb | |||
| 344d9bf1c9 | |||
| 70b27b8034 | |||
| abe7fc8405 | |||
| 4fa62993f4 | |||
| 08a920694b | |||
| 4bdb331eb0 | |||
| cb7c9061e8 | |||
| 29cb155534 | |||
| ada85ed960 | |||
| bfb12aa0f3 | |||
| 3342977a92 | |||
| 07cbd84d44 | |||
| da5e2cf24a | |||
| c6d345d8f1 | |||
| 3a57261120 | |||
| a39f99cab8 | |||
| f0885abea2 | |||
| 2b17cb215b | |||
| 68f0c17f70 | |||
| a20e55beab | |||
| 413542fe61 | |||
| a250732d31 | |||
| 07f2496f2f | |||
| 2f6e52261c | |||
| a117987840 | |||
| cbb8cc061e | |||
| c03365d574 | |||
| 827f18b8e0 | |||
| 1603015631 | |||
| c2d97ba3d5 | |||
| 418b175923 |
@@ -0,0 +1,56 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapBukkitBase</artifactId>
|
||||||
|
<name>DynmapBukkitBase</name>
|
||||||
|
<url>http://github.com/webbukkit/dynmap/</url>
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub</system>
|
||||||
|
<url>https://github.com/webbukkit/dynmap/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.0.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<releases>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
</snapshots>
|
||||||
|
<id>bukkit-repo</id>
|
||||||
|
<url>http://repo.bukkit.org/content/repositories/releases/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<releases>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
</snapshots>
|
||||||
|
<id>dynmap-repo</id>
|
||||||
|
<url>http://repo.mikeprimm.com/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>Bukkit</artifactId>
|
||||||
|
<version>1.7.10-R0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapCore</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
+215
-452
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,142 @@
|
|||||||
|
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.bukkit.entity.Player;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for isolation of bukkit version specific issues
|
||||||
|
*/
|
||||||
|
public abstract class BukkitVersionHelper {
|
||||||
|
|
||||||
|
private static BukkitVersionHelper helper = null;
|
||||||
|
|
||||||
|
public static final BukkitVersionHelper getHelper() {
|
||||||
|
if(helper == null) {
|
||||||
|
Log.info("version=" + Bukkit.getServer().getVersion());
|
||||||
|
if(Bukkit.getServer().getVersion().contains("MCPC")) {
|
||||||
|
Log.severe("*********************************************************************************");
|
||||||
|
Log.severe("* MCPC-Plus is no longer supported via the Bukkit version of Dynmap. *");
|
||||||
|
Log.severe("* Install the appropriate Forge version of Dynmap. *");
|
||||||
|
Log.severe("* Add the DynmapCBBridge plugin to enable support for Dynmap-compatible plugins *");
|
||||||
|
Log.severe("*********************************************************************************");
|
||||||
|
}
|
||||||
|
else if(Bukkit.getServer().getVersion().contains("BukkitForge")) {
|
||||||
|
Log.severe("*********************************************************************************");
|
||||||
|
Log.severe("* BukkitForge is not supported via the Bukkit version of Dynmap. *");
|
||||||
|
Log.severe("* Install the appropriate Forge version of Dynmap. *");
|
||||||
|
Log.severe("* Add the DynmapCBBridge plugin to enable support for Dynmap-compatible plugins *");
|
||||||
|
Log.severe("*********************************************************************************");
|
||||||
|
}
|
||||||
|
else if(Bukkit.getServer().getClass().getName().contains("GlowServer")) {
|
||||||
|
Log.info("Loading Glowstone support");
|
||||||
|
helper = new BukkitVersionHelperGlowstone();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
helper = new BukkitVersionHelperCB();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return helper;
|
||||||
|
}
|
||||||
|
protected BukkitVersionHelper() {
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get list of defined biomebase objects
|
||||||
|
*/
|
||||||
|
public abstract Object[] getBiomeBaseList();
|
||||||
|
/**
|
||||||
|
* Get temperature from biomebase
|
||||||
|
*/
|
||||||
|
public abstract float getBiomeBaseTemperature(Object bb);
|
||||||
|
/**
|
||||||
|
* Get humidity from biomebase
|
||||||
|
*/
|
||||||
|
public abstract float getBiomeBaseHumidity(Object bb);
|
||||||
|
/**
|
||||||
|
* Get ID string from biomebase
|
||||||
|
*/
|
||||||
|
public abstract String getBiomeBaseIDString(Object bb);
|
||||||
|
/**
|
||||||
|
* Get ID from biomebase
|
||||||
|
*/
|
||||||
|
public abstract int getBiomeBaseID(Object bb);
|
||||||
|
/**
|
||||||
|
* Get unload queue for given NMS world
|
||||||
|
*/
|
||||||
|
public abstract Object getUnloadQueue(World world);
|
||||||
|
/**
|
||||||
|
* For testing unload queue for presence of givne chunk
|
||||||
|
*/
|
||||||
|
public abstract boolean isInUnloadQueue(Object unloadqueue, int x, int z);
|
||||||
|
/**
|
||||||
|
* Read raw biome ID from snapshot
|
||||||
|
*/
|
||||||
|
public abstract Object[] getBiomeBaseFromSnapshot(ChunkSnapshot css);
|
||||||
|
/**
|
||||||
|
* Remove entities from given chunk
|
||||||
|
*/
|
||||||
|
public abstract void removeEntitiesFromChunk(Chunk c);
|
||||||
|
/**
|
||||||
|
* Get inhabited ticks count from chunk
|
||||||
|
*/
|
||||||
|
public abstract long getInhabitedTicks(Chunk c);
|
||||||
|
/**
|
||||||
|
* Get tile entities map from chunk
|
||||||
|
*/
|
||||||
|
public abstract Map getTileEntitiesForChunk(Chunk c);
|
||||||
|
/**
|
||||||
|
* Get X coordinate of tile entity
|
||||||
|
*/
|
||||||
|
public abstract int getTileEntityX(Object te);
|
||||||
|
/**
|
||||||
|
* Get Y coordinate of tile entity
|
||||||
|
*/
|
||||||
|
public abstract int getTileEntityY(Object te);
|
||||||
|
/**
|
||||||
|
* Get Z coordinate of tile entity
|
||||||
|
*/
|
||||||
|
public abstract int getTileEntityZ(Object te);
|
||||||
|
/**
|
||||||
|
* Read tile entity NBT
|
||||||
|
*/
|
||||||
|
public abstract Object readTileEntityNBT(Object te);
|
||||||
|
/**
|
||||||
|
* Get field value from NBT compound
|
||||||
|
*/
|
||||||
|
public abstract Object getFieldValue(Object nbt, String field);
|
||||||
|
/**
|
||||||
|
* Unload chunk no save needed
|
||||||
|
*/
|
||||||
|
public abstract void unloadChunkNoSave(World w, Chunk c, int cx, int cz);
|
||||||
|
/**
|
||||||
|
* Get block short name list
|
||||||
|
*/
|
||||||
|
public abstract String[] getBlockShortNames();
|
||||||
|
/**
|
||||||
|
* Get biome name list
|
||||||
|
*/
|
||||||
|
public abstract String[] getBiomeNames();
|
||||||
|
/**
|
||||||
|
* Get block material index list
|
||||||
|
*/
|
||||||
|
public abstract int[] getBlockMaterialMap();
|
||||||
|
/**
|
||||||
|
* Get list of online players
|
||||||
|
*/
|
||||||
|
public abstract Player[] getOnlinePlayers();
|
||||||
|
/**
|
||||||
|
* Get player health
|
||||||
|
*/
|
||||||
|
public abstract int getHealth(Player p);
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
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.Map;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
import org.dynmap.common.BiomeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for isolation of bukkit version specific issues
|
||||||
|
*/
|
||||||
|
public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric {
|
||||||
|
private Class<?> nmsblock;
|
||||||
|
private Class<?> nmsblockarray;
|
||||||
|
private Class<?> nmsmaterial;
|
||||||
|
private Field blockbyid;
|
||||||
|
private Field blockname;
|
||||||
|
private Field material;
|
||||||
|
private Method blockbyidfunc; // 1.7+ method for getting block by id
|
||||||
|
|
||||||
|
BukkitVersionHelperCB() {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected String getNMSPackage() {
|
||||||
|
Server srv = Bukkit.getServer();
|
||||||
|
/* Get getHandle() method */
|
||||||
|
try {
|
||||||
|
Method m = srv.getClass().getMethod("getHandle");
|
||||||
|
Object scm = m.invoke(srv); /* And use it to get SCM (nms object) */
|
||||||
|
return scm.getClass().getPackage().getName();
|
||||||
|
} catch (Exception x) {
|
||||||
|
Log.severe("Error finding net.minecraft.server packages");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void loadNMS() {
|
||||||
|
// Get block fields
|
||||||
|
nmsblock = getNMSClass("net.minecraft.server.Block");
|
||||||
|
nmsblockarray = getNMSClass("[Lnet.minecraft.server.Block;");
|
||||||
|
nmsmaterial = getNMSClass("net.minecraft.server.Material");
|
||||||
|
blockbyid = getFieldNoFail(nmsblock, new String[] { "byId" }, nmsblockarray);
|
||||||
|
if (blockbyid == null) {
|
||||||
|
blockbyidfunc = getMethod(nmsblock, new String[] { "getById", "e" }, new Class[] { int.class });
|
||||||
|
}
|
||||||
|
blockname = getPrivateField(nmsblock, new String[] { "name", "b" }, String.class);
|
||||||
|
material = getPrivateField(nmsblock, new String[] { "material" }, nmsmaterial);
|
||||||
|
|
||||||
|
/* Set up biomebase fields */
|
||||||
|
biomebase = getNMSClass("net.minecraft.server.BiomeBase");
|
||||||
|
biomebasearray = getNMSClass("[Lnet.minecraft.server.BiomeBase;");
|
||||||
|
biomebaselist = getPrivateField(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", "af" }, String.class);
|
||||||
|
biomebaseid = getField(biomebase, new String[] { "id" }, int.class);
|
||||||
|
/* n.m.s.World */
|
||||||
|
nmsworld = getNMSClass("net.minecraft.server.WorldServer");
|
||||||
|
chunkprovserver = getNMSClass("net.minecraft.server.ChunkProviderServer");
|
||||||
|
nmsw_chunkproviderserver = getField(nmsworld, new String[] { "chunkProviderServer" }, chunkprovserver);
|
||||||
|
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
|
||||||
|
cps_unloadqueue = getFieldNoFail(chunkprovserver, new String[] { "unloadQueue" }, longhashset);
|
||||||
|
if(cps_unloadqueue == null) {
|
||||||
|
Log.info("Unload queue not found - default to unload all chunks");
|
||||||
|
}
|
||||||
|
/** 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);
|
||||||
|
nmsc_inhabitedticks = getFieldNoFail(nmschunk, new String[] { "s", "q" }, long.class);
|
||||||
|
if (nmsc_inhabitedticks == null) {
|
||||||
|
Log.info("inhabitedTicks field not found - inhabited shader not functional");
|
||||||
|
}
|
||||||
|
/** 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 = getPrivateField(nbttagbyte, new String[] { "data" }, byte.class);
|
||||||
|
nbttagshort_val = getPrivateField(nbttagshort, new String[] { "data" }, short.class);
|
||||||
|
nbttagint_val = getPrivateField(nbttagint, new String[] { "data" }, int.class);
|
||||||
|
nbttaglong_val = getPrivateField(nbttaglong, new String[] { "data" }, long.class);
|
||||||
|
nbttagfloat_val = getPrivateField(nbttagfloat, new String[] { "data" }, float.class);
|
||||||
|
nbttagdouble_val = getPrivateField(nbttagdouble, new String[] { "data" }, double.class);
|
||||||
|
nbttagbytearray_val = getPrivateField(nbttagbytearray, new String[] { "data" }, byte[].class);
|
||||||
|
nbttagstring_val = getPrivateField(nbttagstring, new String[] { "data" }, String.class);
|
||||||
|
nbttagintarray_val = getPrivateField(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);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void unloadChunkNoSave(World w, Chunk c, int cx, int cz) {
|
||||||
|
this.removeEntitiesFromChunk(c);
|
||||||
|
w.unloadChunk(cx, cz, false, false);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get block short name list
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String[] getBlockShortNames() {
|
||||||
|
try {
|
||||||
|
String[] names = new String[4096];
|
||||||
|
if (blockbyid != null) {
|
||||||
|
Object[] byid = (Object[])blockbyid.get(nmsblock);
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
if (byid[i] != null) {
|
||||||
|
names[i] = (String)blockname.get(byid[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
Object blk = blockbyidfunc.invoke(nmsblock, i);
|
||||||
|
if (blk != null) {
|
||||||
|
names[i] = (String)blockname.get(blk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
}
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get biome name list
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String[] getBiomeNames() {
|
||||||
|
String[] names;
|
||||||
|
/* Find array of biomes in biomebase */
|
||||||
|
Object[] biomelist = getBiomeBaseList();
|
||||||
|
names = new String[biomelist.length];
|
||||||
|
/* Loop through list, starting afer well known biomes */
|
||||||
|
for(int i = 0; i < biomelist.length; i++) {
|
||||||
|
Object bb = biomelist[i];
|
||||||
|
if(bb != null) {
|
||||||
|
names[i] = getBiomeBaseIDString(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get block material index list
|
||||||
|
*/
|
||||||
|
public int[] getBlockMaterialMap() {
|
||||||
|
try {
|
||||||
|
int[] map = new int[4096];
|
||||||
|
if (blockbyid != null) {
|
||||||
|
Object[] byid = (Object[])blockbyid.get(nmsblock);
|
||||||
|
ArrayList<Object> mats = new ArrayList<Object>();
|
||||||
|
for (int i = 0; i < map.length; i++) {
|
||||||
|
if (byid[i] != null) {
|
||||||
|
Object mat = (Object)material.get(byid[i]);
|
||||||
|
if (mat != null) {
|
||||||
|
map[i] = mats.indexOf(mat);
|
||||||
|
if (map[i] < 0) {
|
||||||
|
map[i] = mats.size();
|
||||||
|
mats.add(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ArrayList<Object> mats = new ArrayList<Object>();
|
||||||
|
for (int i = 0; i < map.length; i++) {
|
||||||
|
Object blk = blockbyidfunc.invoke(nmsblock, i);
|
||||||
|
if (blk != null) {
|
||||||
|
Object mat = (Object)material.get(blk);
|
||||||
|
if (mat != null) {
|
||||||
|
map[i] = mats.indexOf(mat);
|
||||||
|
if (map[i] < 0) {
|
||||||
|
map[i] = mats.size();
|
||||||
|
mats.add(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
}
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,429 @@
|
|||||||
|
package org.dynmap.bukkit;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
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.bukkit.entity.Player;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
private static final Object[] nullargs = new Object[0];
|
||||||
|
private static final Map nullmap = Collections.emptyMap();
|
||||||
|
|
||||||
|
/** CraftChunkSnapshot */
|
||||||
|
private Class<?> craftchunksnapshot;
|
||||||
|
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;
|
||||||
|
protected Method lhs_containskey;
|
||||||
|
/** n.m.s.Chunk */
|
||||||
|
protected Class<?> nmschunk;
|
||||||
|
protected Method nmsc_removeentities;
|
||||||
|
protected Field nmsc_tileentities;
|
||||||
|
protected Field nmsc_inhabitedticks;
|
||||||
|
/** 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;
|
||||||
|
/** Server */
|
||||||
|
protected Method server_getonlineplayers;
|
||||||
|
/** Player */
|
||||||
|
protected Method player_gethealth;
|
||||||
|
|
||||||
|
BukkitVersionHelperGeneric() {
|
||||||
|
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 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");
|
||||||
|
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]);
|
||||||
|
|
||||||
|
/** Server */
|
||||||
|
server_getonlineplayers = getMethod(Server.class, new String[] { "getOnlinePlayers" }, new Class[0]);
|
||||||
|
/** Player */
|
||||||
|
player_gethealth = getMethod(Player.class, new String[] { "getHealth" }, new Class[0]);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get private field
|
||||||
|
*/
|
||||||
|
protected 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;
|
||||||
|
}
|
||||||
|
protected 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
|
||||||
|
*/
|
||||||
|
protected 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 */
|
||||||
|
protected Object getNMSWorld(World w) {
|
||||||
|
return callMethod(w, cw_gethandle, nullargs, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get unload queue for given NMS world */
|
||||||
|
public Object getUnloadQueue(World world) {
|
||||||
|
Object cps = getFieldValue(getNMSWorld(world), 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public int getHealth(Player p) {
|
||||||
|
Object health = callMethod(p, player_gethealth, nullargs, null);
|
||||||
|
if (health instanceof Integer) {
|
||||||
|
return (Integer) health;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ((Double) health).intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,451 @@
|
|||||||
|
package org.dynmap.bukkit;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collection;
|
||||||
|
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.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class BukkitVersionHelperGlowstone extends BukkitVersionHelper {
|
||||||
|
private Method rawbiome;
|
||||||
|
private Method server_getonlineplayers;
|
||||||
|
|
||||||
|
public BukkitVersionHelperGlowstone() {
|
||||||
|
try {
|
||||||
|
Class<?> c = Class.forName("net.glowstone.GlowChunkSnapshot");
|
||||||
|
rawbiome = c.getMethod("getRawBiomes", new Class[0]);
|
||||||
|
|
||||||
|
/** Server */
|
||||||
|
server_getonlineplayers = Server.class.getMethod("getOnlinePlayers", new Class[0]);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
}
|
||||||
|
if ((rawbiome == null) && (server_getonlineplayers == null)) {
|
||||||
|
throw new IllegalArgumentException("Error initializing dynmap - Glowstone version incompatible!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getBiomeBaseList() {
|
||||||
|
return new Object[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getBiomeBaseTemperature(Object bb) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getBiomeBaseHumidity(Object bb) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBiomeBaseIDString(Object bb) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBiomeBaseID(Object bb) {
|
||||||
|
if (bb != null)
|
||||||
|
return (Integer) bb;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getUnloadQueue(World world) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInUnloadQueue(Object unloadqueue, int x, int z) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] getBiomeBaseFromSnapshot(ChunkSnapshot css) {
|
||||||
|
Integer b[] = new Integer[256];
|
||||||
|
byte[] rb = null;
|
||||||
|
try {
|
||||||
|
rb = (byte[]) rawbiome.invoke(css, new Object[0]);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
}
|
||||||
|
if (rb != null) {
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
b[i] = Integer.valueOf(255 & (int)rb[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeEntitiesFromChunk(Chunk c) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getInhabitedTicks(Chunk c) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map getTileEntitiesForChunk(Chunk c) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTileEntityX(Object te) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTileEntityY(Object te) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTileEntityZ(Object te) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object readTileEntityNBT(Object te) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getFieldValue(Object nbt, String field) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unloadChunkNoSave(World w, Chunk c, int cx, int cz) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBlockShortNames() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String[] bnames = {
|
||||||
|
"Ocean",
|
||||||
|
"Plains",
|
||||||
|
"Desert",
|
||||||
|
"Extreme Hills",
|
||||||
|
"Forest",
|
||||||
|
"Taiga",
|
||||||
|
"Swampland",
|
||||||
|
"River",
|
||||||
|
"Hell",
|
||||||
|
"Sky",
|
||||||
|
"FrozenOcean",
|
||||||
|
"FrozenRiver",
|
||||||
|
"Ice Plains",
|
||||||
|
"Ice Mountains",
|
||||||
|
"MushroomIsland",
|
||||||
|
"MushroomIslandShore",
|
||||||
|
"Beach",
|
||||||
|
"DesertHills",
|
||||||
|
"ForestHills",
|
||||||
|
"TaigaHills",
|
||||||
|
"Extreme Hills Edge",
|
||||||
|
"Jungle",
|
||||||
|
"JungleHills",
|
||||||
|
"JungleEdge",
|
||||||
|
"Deep Ocean",
|
||||||
|
"Stone Beach",
|
||||||
|
"Cold Beach",
|
||||||
|
"Birch Forest",
|
||||||
|
"Birch Forest Hills",
|
||||||
|
"Roofed Forest",
|
||||||
|
"Cold Taiga",
|
||||||
|
"Cold Taiga Hills",
|
||||||
|
"Mega Taiga",
|
||||||
|
"Mega Taiga Hills",
|
||||||
|
"Extreme Hills+",
|
||||||
|
"Savanna",
|
||||||
|
"Savanna Plateau",
|
||||||
|
"Mesa",
|
||||||
|
"Mesa Plateau F",
|
||||||
|
"Mesa Plateau",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"Sunflower Plains",
|
||||||
|
"Desert M",
|
||||||
|
"Extreme Hills M",
|
||||||
|
"Flower Forest",
|
||||||
|
"Taiga M",
|
||||||
|
"Swampland M",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"Ice Plains Spikes",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"Jungle M",
|
||||||
|
null,
|
||||||
|
"JungleEdge M",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"Birch Forest M",
|
||||||
|
"Birch Forest Hills M",
|
||||||
|
"Roofed Forest M",
|
||||||
|
"Cold Taiga M",
|
||||||
|
null,
|
||||||
|
"Mega Spruce Taiga",
|
||||||
|
"Mega Spruce Taiga",
|
||||||
|
"Extreme Hills+ M",
|
||||||
|
"Savanna M",
|
||||||
|
"Savanna Plateau M",
|
||||||
|
"Mesa (Bryce)",
|
||||||
|
"Mesa Plateau F M",
|
||||||
|
"Mesa Plateau M",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBiomeNames() {
|
||||||
|
return bnames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getBlockMaterialMap() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of online players
|
||||||
|
*/
|
||||||
|
public Player[] getOnlinePlayers() {
|
||||||
|
Object players;
|
||||||
|
try {
|
||||||
|
players = server_getonlineplayers.invoke(Bukkit.getServer(), new Object[0]);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
}
|
||||||
|
return new Player[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHealth(Player p) {
|
||||||
|
return (int) p.getHealth();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
package org.dynmap.bukkit;
|
||||||
|
/**
|
||||||
|
* Bukkit specific implementation of DynmapWorld
|
||||||
|
*/
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.permissions.Permission;
|
||||||
|
import org.bukkit.permissions.PermissionDefault;
|
||||||
|
import org.dynmap.DynmapChunk;
|
||||||
|
import org.dynmap.DynmapLocation;
|
||||||
|
import org.dynmap.DynmapWorld;
|
||||||
|
import org.dynmap.utils.MapChunkCache;
|
||||||
|
import org.dynmap.utils.TileFlags;
|
||||||
|
|
||||||
|
public class BukkitWorld extends DynmapWorld {
|
||||||
|
private World world;
|
||||||
|
private World.Environment env;
|
||||||
|
private boolean skylight;
|
||||||
|
private DynmapLocation spawnloc = new DynmapLocation();
|
||||||
|
|
||||||
|
public BukkitWorld(World w) {
|
||||||
|
this(w.getName(), w.getMaxHeight(), w.getSeaLevel(), w.getEnvironment());
|
||||||
|
setWorldLoaded(w);
|
||||||
|
new Permission("dynmap.world." + getName(), "Dynmap access for world " + getName(), PermissionDefault.OP);
|
||||||
|
}
|
||||||
|
public BukkitWorld(String name, int height, int sealevel, World.Environment env) {
|
||||||
|
super(name, height, sealevel);
|
||||||
|
world = null;
|
||||||
|
this.env = env;
|
||||||
|
skylight = (env == World.Environment.NORMAL);
|
||||||
|
new Permission("dynmap.world." + getName(), "Dynmap access for world " + getName(), PermissionDefault.OP);
|
||||||
|
// Generate non-default environment lighting table
|
||||||
|
switch (env) {
|
||||||
|
case NETHER:
|
||||||
|
{
|
||||||
|
float f = 0.1F;
|
||||||
|
for (int i = 0; i <= 15; ++i) {
|
||||||
|
float f1 = 1.0F - (float)i / 15.0F;
|
||||||
|
this.setBrightnessTableEntry(i, (1.0F - f1) / (f1 * 3.0F + 1.0F) * (1.0F - f) + f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set world online
|
||||||
|
* @param w - loaded world
|
||||||
|
*/
|
||||||
|
public void setWorldLoaded(World w) {
|
||||||
|
world = w;
|
||||||
|
env = world.getEnvironment();
|
||||||
|
skylight = (env == World.Environment.NORMAL);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set world unloaded
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setWorldUnloaded() {
|
||||||
|
getSpawnLocation(); /* Remember spawn location before unload */
|
||||||
|
world = null;
|
||||||
|
}
|
||||||
|
/* Test if world is nether */
|
||||||
|
@Override
|
||||||
|
public boolean isNether() {
|
||||||
|
return env == World.Environment.NETHER;
|
||||||
|
}
|
||||||
|
/* Get world spawn location */
|
||||||
|
@Override
|
||||||
|
public DynmapLocation getSpawnLocation() {
|
||||||
|
if(world != null) {
|
||||||
|
Location sloc = world.getSpawnLocation();
|
||||||
|
spawnloc.x = sloc.getBlockX();
|
||||||
|
spawnloc.y = sloc.getBlockY();
|
||||||
|
spawnloc.z = sloc.getBlockZ();
|
||||||
|
spawnloc.world = normalizeWorldName(sloc.getWorld().getName());
|
||||||
|
}
|
||||||
|
return spawnloc;
|
||||||
|
}
|
||||||
|
/* Get world time */
|
||||||
|
@Override
|
||||||
|
public long getTime() {
|
||||||
|
if(world != null) {
|
||||||
|
return world.getTime();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* World is storming */
|
||||||
|
@Override
|
||||||
|
public boolean hasStorm() {
|
||||||
|
if(world != null) {
|
||||||
|
return world.hasStorm();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* World is thundering */
|
||||||
|
@Override
|
||||||
|
public boolean isThundering() {
|
||||||
|
if(world != null) {
|
||||||
|
return world.isThundering();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* World is loaded */
|
||||||
|
@Override
|
||||||
|
public boolean isLoaded() {
|
||||||
|
return (world != null);
|
||||||
|
}
|
||||||
|
/* Get light level of block */
|
||||||
|
@Override
|
||||||
|
public int getLightLevel(int x, int y, int z) {
|
||||||
|
if(world != null) {
|
||||||
|
return world.getBlockAt(x, y, z).getLightLevel();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Get highest Y coord of given location */
|
||||||
|
@Override
|
||||||
|
public int getHighestBlockYAt(int x, int z) {
|
||||||
|
if(world != null) {
|
||||||
|
return world.getHighestBlockYAt(x, z);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Test if sky light level is requestable */
|
||||||
|
@Override
|
||||||
|
public boolean canGetSkyLightLevel() {
|
||||||
|
return skylight && (world != null);
|
||||||
|
}
|
||||||
|
/* Return sky light level */
|
||||||
|
@Override
|
||||||
|
public int getSkyLightLevel(int x, int y, int z) {
|
||||||
|
if(world != null) {
|
||||||
|
return world.getBlockAt(x, y, z).getLightFromSky();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get world environment ID (lower case - normal, the_end, nether)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getEnvironment() {
|
||||||
|
return env.name().toLowerCase();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get map chunk cache for world
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MapChunkCache getChunkCache(List<DynmapChunk> chunks) {
|
||||||
|
if(isLoaded()) {
|
||||||
|
LegacyMapChunkCache c = new LegacyMapChunkCache();
|
||||||
|
c.setChunks(this, chunks);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return false if unimplemented
|
||||||
|
@Override
|
||||||
|
public int getChunkMap(TileFlags map) {
|
||||||
|
map.clear();
|
||||||
|
if (world == null) return -1;
|
||||||
|
int cnt = 0;
|
||||||
|
// Mark loaded chunks
|
||||||
|
for(Chunk c : world.getLoadedChunks()) {
|
||||||
|
map.setFlag(c.getX(), c.getZ(), true);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
File f = world.getWorldFolder();
|
||||||
|
File regiondir = new File(f, "region");
|
||||||
|
File[] lst = regiondir.listFiles();
|
||||||
|
if(lst != null) {
|
||||||
|
byte[] hdr = new byte[4096];
|
||||||
|
for(File rf : lst) {
|
||||||
|
if(!rf.getName().endsWith(".mca")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] parts = rf.getName().split("\\.");
|
||||||
|
if((!parts[0].equals("r")) && (parts.length != 4)) continue;
|
||||||
|
|
||||||
|
RandomAccessFile rfile = null;
|
||||||
|
int x = 0, z = 0;
|
||||||
|
try {
|
||||||
|
x = Integer.parseInt(parts[1]);
|
||||||
|
z = Integer.parseInt(parts[2]);
|
||||||
|
rfile = new RandomAccessFile(rf, "r");
|
||||||
|
rfile.read(hdr, 0, hdr.length);
|
||||||
|
} catch (IOException iox) {
|
||||||
|
Arrays.fill(hdr, (byte)0);
|
||||||
|
} catch (NumberFormatException nfx) {
|
||||||
|
Arrays.fill(hdr, (byte)0);
|
||||||
|
} finally {
|
||||||
|
if(rfile != null) {
|
||||||
|
try { rfile.close(); } catch (IOException iox) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 1024; i++) {
|
||||||
|
int v = hdr[4*i] | hdr[4*i + 1] | hdr[4*i + 2] | hdr[4*i + 3];
|
||||||
|
if (v == 0) continue;
|
||||||
|
int xx = (x << 5) | (i & 0x1F);
|
||||||
|
int zz = (z << 5) | ((i >> 5) & 0x1F);
|
||||||
|
if (!map.setFlag(xx, zz, true)) {
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
package org.dynmap.bukkit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.ChunkSnapshot;
|
||||||
|
import org.dynmap.DynmapChunk;
|
||||||
|
import org.dynmap.DynmapCore;
|
||||||
|
import org.dynmap.DynmapWorld;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
import org.dynmap.bukkit.SnapshotCache.SnapshotRec;
|
||||||
|
import org.dynmap.common.BiomeMap;
|
||||||
|
import org.dynmap.hdmap.HDBlockModels;
|
||||||
|
import org.dynmap.renderer.RenderPatchFactory;
|
||||||
|
import org.dynmap.utils.DynIntHashMap;
|
||||||
|
import org.dynmap.utils.MapChunkCache;
|
||||||
|
import org.dynmap.utils.MapIterator;
|
||||||
|
import org.dynmap.utils.BlockStep;
|
||||||
|
import org.dynmap.utils.VisibilityLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
|
||||||
|
*/
|
||||||
|
public class LegacyMapChunkCache extends BaseMapChunkCache {
|
||||||
|
@Override
|
||||||
|
public int loadChunks(int max_to_load) {
|
||||||
|
if(dw.isLoaded() == false)
|
||||||
|
return 0;
|
||||||
|
Object queue = helper.getUnloadQueue(w);
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
if(iterator == null)
|
||||||
|
iterator = chunks.listIterator();
|
||||||
|
|
||||||
|
DynmapCore.setIgnoreChunkLoads(true);
|
||||||
|
//boolean isnormral = w.getEnvironment() == Environment.NORMAL;
|
||||||
|
// 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 */
|
||||||
|
ChunkSnapshot ss = null;
|
||||||
|
long inhabited_ticks = 0;
|
||||||
|
DynIntHashMap tileData = null;
|
||||||
|
SnapshotRec ssr = SnapshotCache.cache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
|
||||||
|
if(ssr != null) {
|
||||||
|
ss = ssr.ss;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
int idx = (chunk.x-x_min) + (chunk.z - z_min)*x_dim;
|
||||||
|
snaparray[idx] = ss;
|
||||||
|
snaptile[idx] = ssr.tileData;
|
||||||
|
inhabitedTicks[idx] = inhabited_ticks;
|
||||||
|
|
||||||
|
endChunkLoad(startTime, ChunkStats.CACHED_SNAPSHOT_HIT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
|
||||||
|
boolean didload = false;
|
||||||
|
boolean isunloadpending = false;
|
||||||
|
if (queue != null) {
|
||||||
|
isunloadpending = helper.isInUnloadQueue(queue, chunk.x, chunk.z);
|
||||||
|
}
|
||||||
|
if (isunloadpending) { /* Workaround: can't be pending if not loaded */
|
||||||
|
wasLoaded = true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
didload = w.loadChunk(chunk.x, chunk.z, false);
|
||||||
|
} catch (Throwable t) { /* Catch chunk error from Bukkit */
|
||||||
|
Log.warning("Bukkit error loading chunk " + chunk.x + "," + chunk.z + " on " + w.getName());
|
||||||
|
if(!wasLoaded) { /* If wasn't loaded, we loaded it if it now is */
|
||||||
|
didload = w.isChunkLoaded(chunk.x, chunk.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If it did load, make cache of it */
|
||||||
|
if(didload) {
|
||||||
|
tileData = new DynIntHashMap();
|
||||||
|
|
||||||
|
Chunk c = w.getChunkAt(chunk.x, chunk.z); /* Get the chunk */
|
||||||
|
/* Get inhabited ticks count */
|
||||||
|
inhabited_ticks = helper.getInhabitedTicks(c);
|
||||||
|
if(!vis) {
|
||||||
|
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
||||||
|
ss = STONE;
|
||||||
|
else if(hidestyle == HiddenChunkStyle.FILL_OCEAN)
|
||||||
|
ss = OCEAN;
|
||||||
|
else
|
||||||
|
ss = EMPTY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(blockdata || highesty) {
|
||||||
|
ss = c.getChunkSnapshot(highesty, biome, biomeraw);
|
||||||
|
/* Get tile entity data */
|
||||||
|
List<Object> vals = new ArrayList<Object>();
|
||||||
|
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) {
|
||||||
|
Object nbtcompound = helper.readTileEntityNBT(t);
|
||||||
|
|
||||||
|
vals.clear();
|
||||||
|
for(String id: te_fields) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ss = w.getEmptyChunkSnapshot(chunk.x, chunk.z, biome, biomeraw);
|
||||||
|
if(ss != null) {
|
||||||
|
ssr = new SnapshotRec();
|
||||||
|
ssr.ss = ss;
|
||||||
|
ssr.inhabitedTicks = inhabited_ticks;
|
||||||
|
ssr.tileData = tileData;
|
||||||
|
SnapshotCache.cache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int chunkIndex = (chunk.x-x_min) + (chunk.z - z_min)*x_dim;
|
||||||
|
snaparray[chunkIndex] = ss;
|
||||||
|
snaptile[chunkIndex] = tileData;
|
||||||
|
inhabitedTicks[chunkIndex] = inhabited_ticks;
|
||||||
|
|
||||||
|
/* If wasn't loaded before, we need to do unload */
|
||||||
|
if (!wasLoaded) {
|
||||||
|
/* 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
|
||||||
|
* because isChunkInUse defined "in use" as being within 256 blocks of a player,
|
||||||
|
* while the actual in-use chunk area for a player where the chunks are managed
|
||||||
|
* by the MC base server is 21x21 (or about a 160 block radius).
|
||||||
|
* Also, if we did generate it, need to save it */
|
||||||
|
helper.unloadChunkNoSave(w, c, chunk.x, chunk.z);
|
||||||
|
endChunkLoad(startTime, ChunkStats.UNLOADED_CHUNKS);
|
||||||
|
}
|
||||||
|
else if (isunloadpending) { /* Else, if loaded and unload is pending */
|
||||||
|
w.unloadChunkRequest(chunk.x, chunk.z); /* Request new unload */
|
||||||
|
endChunkLoad(startTime, ChunkStats.LOADED_CHUNKS);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
endChunkLoad(startTime, ChunkStats.LOADED_CHUNKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
endChunkLoad(startTime, ChunkStats.UNGENERATED_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;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test if done loading
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isDoneLoading() {
|
||||||
|
if(dw.isLoaded() == false) {
|
||||||
|
isempty = true;
|
||||||
|
unloadChunks();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(iterator != null)
|
||||||
|
return !iterator.hasNext();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int readChunks() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
-12
@@ -3,20 +3,30 @@ package org.dynmap.bukkit;
|
|||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
import java.lang.ref.ReferenceQueue;
|
import java.lang.ref.ReferenceQueue;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.LinkedHashMap;
|
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 long inhabitedTicks;
|
||||||
|
public DynIntHashMap tileData;
|
||||||
|
};
|
||||||
|
public static SnapshotCache cache;
|
||||||
|
|
||||||
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 boolean softref;
|
||||||
|
|
||||||
private static class CacheRec {
|
private static class CacheRec {
|
||||||
WeakReference<ChunkSnapshot> ref;
|
Reference<SnapshotRec> ref;
|
||||||
boolean hasbiome;
|
boolean hasbiome;
|
||||||
boolean hasrawbiome;
|
boolean hasrawbiome;
|
||||||
boolean hasblockdata;
|
boolean hasblockdata;
|
||||||
@@ -26,12 +36,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<Reference<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<Reference<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);
|
||||||
@@ -45,9 +55,10 @@ public class SnapshotCache {
|
|||||||
/**
|
/**
|
||||||
* Create snapshot cache
|
* Create snapshot cache
|
||||||
*/
|
*/
|
||||||
public SnapshotCache(int max_size) {
|
public SnapshotCache(int max_size, boolean softref) {
|
||||||
snapcache = new CacheHashMap(max_size);
|
snapcache = new CacheHashMap(max_size);
|
||||||
refqueue = new ReferenceQueue<ChunkSnapshot>();
|
refqueue = new ReferenceQueue<SnapshotRec>();
|
||||||
|
this.softref = softref;
|
||||||
}
|
}
|
||||||
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 +94,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 +123,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 +132,10 @@ 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);
|
if (softref)
|
||||||
|
rec.ref = new SoftReference<SnapshotRec>(ss, refqueue);
|
||||||
|
else
|
||||||
|
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 +146,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) {
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#Generated by Maven
|
||||||
|
#Fri Sep 19 23:52:48 CDT 2014
|
||||||
|
version=2.0.0-SNAPSHOT
|
||||||
|
groupId=us.dynmap
|
||||||
|
artifactId=DynmapBukkitBase
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapBukkit_1_7_10</artifactId>
|
||||||
|
<name>DynmapBukkit_1_7_10</name>
|
||||||
|
<url>http://github.com/webbukkit/dynmap/</url>
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub</system>
|
||||||
|
<url>https://github.com/webbukkit/dynmap/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.0.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<releases>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
</snapshots>
|
||||||
|
<id>dynmap-repo</id>
|
||||||
|
<url>http://repo.mikeprimm.com/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>Bukkit</artifactId>
|
||||||
|
<version>1.7.10-R0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapCore</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>CraftBukkit</artifactId>
|
||||||
|
<version>1.7.10-R0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,414 @@
|
|||||||
|
package org.dynmap.bukkit;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.server.v1_7_R4.ChunkProviderServer;
|
||||||
|
import net.minecraft.server.v1_7_R4.ChunkRegionLoader;
|
||||||
|
import net.minecraft.server.v1_7_R4.IChunkLoader;
|
||||||
|
import net.minecraft.server.v1_7_R4.NBTTagCompound;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
|
||||||
|
import org.bukkit.ChunkSnapshot;
|
||||||
|
import org.dynmap.DynmapChunk;
|
||||||
|
import org.dynmap.DynmapCore;
|
||||||
|
import org.dynmap.DynmapWorld;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
import org.dynmap.bukkit.BaseMapChunkCache;
|
||||||
|
import org.dynmap.bukkit.SnapshotCache;
|
||||||
|
import org.dynmap.bukkit.SnapshotCache.SnapshotRec;
|
||||||
|
import org.dynmap.common.BiomeMap;
|
||||||
|
import org.dynmap.hdmap.HDBlockModels;
|
||||||
|
import org.dynmap.renderer.RenderPatchFactory;
|
||||||
|
import org.dynmap.utils.DynIntHashMap;
|
||||||
|
import org.dynmap.utils.MapChunkCache;
|
||||||
|
import org.dynmap.utils.MapIterator;
|
||||||
|
import org.dynmap.utils.BlockStep;
|
||||||
|
import org.dynmap.utils.VisibilityLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
|
||||||
|
*/
|
||||||
|
public class V1_7_10_MapChunkCache extends BaseMapChunkCache {
|
||||||
|
private boolean doneLoad = false;
|
||||||
|
private ChunkProviderServer cps;
|
||||||
|
private ChunkRegionLoader loader;
|
||||||
|
private static boolean didInit = false;
|
||||||
|
private static Field loaderField = null;
|
||||||
|
|
||||||
|
public V1_7_10_MapChunkCache() {
|
||||||
|
if (!didInit) {
|
||||||
|
try {
|
||||||
|
loaderField = ChunkProviderServer.class.getField("f");
|
||||||
|
} catch (NoSuchFieldException nsfx) {
|
||||||
|
Log.info("Error finding chunk loader");
|
||||||
|
loaderField = null;
|
||||||
|
}
|
||||||
|
didInit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVisibleChunk(DynmapChunk chunk) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vis;
|
||||||
|
}
|
||||||
|
private boolean isInCache(DynmapChunk chunk, int idx, boolean vis) {
|
||||||
|
SnapshotRec ssr = SnapshotCache.cache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
|
||||||
|
if(ssr != null) {
|
||||||
|
ChunkSnapshot ss = ssr.ss;
|
||||||
|
if(!vis) {
|
||||||
|
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
||||||
|
ss = STONE;
|
||||||
|
else if(hidestyle == HiddenChunkStyle.FILL_OCEAN)
|
||||||
|
ss = OCEAN;
|
||||||
|
else
|
||||||
|
ss = EMPTY;
|
||||||
|
}
|
||||||
|
snaparray[idx] = ss;
|
||||||
|
snaptile[idx] = ssr.tileData;
|
||||||
|
inhabitedTicks[idx] = ssr.inhabitedTicks;
|
||||||
|
}
|
||||||
|
return (ssr != null);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int loadChunks(int max_to_load) {
|
||||||
|
if(dw.isLoaded() == false)
|
||||||
|
return 0;
|
||||||
|
Object queue = helper.getUnloadQueue(w);
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
Iterator<DynmapChunk> iterator = chunks.listIterator();
|
||||||
|
|
||||||
|
//boolean isnormral = w.getEnvironment() == Environment.NORMAL;
|
||||||
|
// Load the required chunks.
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
DynmapChunk chunk = iterator.next();
|
||||||
|
int idx = (chunk.x - x_min) + ((chunk.z - z_min) * x_dim);
|
||||||
|
|
||||||
|
if (snaparray[idx] != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boolean vis = isVisibleChunk(chunk);
|
||||||
|
/* Check if cached chunk snapshot found */
|
||||||
|
if (isInCache(chunk, idx, vis)) {
|
||||||
|
endChunkLoad(startTime, ChunkStats.CACHED_SNAPSHOT_HIT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ChunkSnapshot ss = null;
|
||||||
|
long inhabited_ticks = 0;
|
||||||
|
DynIntHashMap tileData = null;
|
||||||
|
// See if chunk already loaded
|
||||||
|
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
|
||||||
|
boolean isunloadpending = false;
|
||||||
|
if (queue != null) {
|
||||||
|
isunloadpending = helper.isInUnloadQueue(queue, chunk.x, chunk.z);
|
||||||
|
}
|
||||||
|
// If loaded, and not being unloaded, read live chunk
|
||||||
|
if (wasLoaded && (!isunloadpending)) {
|
||||||
|
tileData = new DynIntHashMap();
|
||||||
|
|
||||||
|
Chunk c = w.getChunkAt(chunk.x, chunk.z); /* Get the chunk */
|
||||||
|
/* Get inhabited ticks count */
|
||||||
|
inhabited_ticks = helper.getInhabitedTicks(c);
|
||||||
|
if(!vis) {
|
||||||
|
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
|
||||||
|
ss = STONE;
|
||||||
|
else if(hidestyle == HiddenChunkStyle.FILL_OCEAN)
|
||||||
|
ss = OCEAN;
|
||||||
|
else
|
||||||
|
ss = EMPTY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(blockdata || highesty) {
|
||||||
|
ss = c.getChunkSnapshot(highesty, biome, biomeraw);
|
||||||
|
/* Get tile entity data */
|
||||||
|
List<Object> vals = new ArrayList<Object>();
|
||||||
|
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) {
|
||||||
|
Object nbtcompound = helper.readTileEntityNBT(t);
|
||||||
|
|
||||||
|
vals.clear();
|
||||||
|
for(String id: te_fields) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ss = w.getEmptyChunkSnapshot(chunk.x, chunk.z, biome, biomeraw);
|
||||||
|
if(ss != null) {
|
||||||
|
SnapshotRec ssr = new SnapshotRec();
|
||||||
|
ssr.ss = ss;
|
||||||
|
ssr.inhabitedTicks = inhabited_ticks;
|
||||||
|
ssr.tileData = tileData;
|
||||||
|
SnapshotCache.cache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int chunkIndex = (chunk.x-x_min) + (chunk.z - z_min)*x_dim;
|
||||||
|
snaparray[chunkIndex] = ss;
|
||||||
|
snaptile[chunkIndex] = tileData;
|
||||||
|
inhabitedTicks[chunkIndex] = inhabited_ticks;
|
||||||
|
|
||||||
|
endChunkLoad(startTime, ChunkStats.LOADED_CHUNKS);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
endChunkLoad(startTime, ChunkStats.UNGENERATED_CHUNKS);
|
||||||
|
}
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
doneLoad = true;
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test if done loading
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isDoneLoading() {
|
||||||
|
return doneLoad;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int readChunks() {
|
||||||
|
if(dw.isLoaded() == false)
|
||||||
|
return 0;
|
||||||
|
Object queue = helper.getUnloadQueue(w);
|
||||||
|
cps = ((CraftWorld) w).getHandle().chunkProviderServer;
|
||||||
|
try {
|
||||||
|
IChunkLoader cloader = (IChunkLoader) loaderField.get(cps);
|
||||||
|
if (cloader instanceof ChunkRegionLoader) {
|
||||||
|
loader = (ChunkRegionLoader) cloader;
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException iax) {
|
||||||
|
} catch (IllegalAccessException ixx) {
|
||||||
|
}
|
||||||
|
if (loader == null) {
|
||||||
|
Log.warning("Unable to find usable chunk loader");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int cnt = 0;
|
||||||
|
Iterator<DynmapChunk> iterator = chunks.listIterator();
|
||||||
|
|
||||||
|
//boolean isnormral = w.getEnvironment() == Environment.NORMAL;
|
||||||
|
// Load the required chunks.
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
DynmapChunk chunk = iterator.next();
|
||||||
|
int idx = (chunk.x - x_min) + ((chunk.z - z_min) * x_dim);
|
||||||
|
if (snaparray[idx] != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boolean vis = isVisibleChunk(chunk);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// Finish up any chunks that didn't get loaded or read
|
||||||
|
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 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NBTTagCompound readChunk(int x, int z) {
|
||||||
|
try {
|
||||||
|
List<?> chunkstoremove = null;
|
||||||
|
Set<?> pendingcoords = null;
|
||||||
|
LinkedHashMap<?,?> pendingsavesmcpc = null;
|
||||||
|
|
||||||
|
if (pendingAnvilChunksMCPC != null) {
|
||||||
|
pendingsavesmcpc = (LinkedHashMap<?,?>)pendingAnvilChunksMCPC.get(acl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chunkstoremove = (List<?>)chunksToRemove.get(acl);
|
||||||
|
pendingcoords = (Set<?>)pendingAnvilChunksCoordinates.get(acl);
|
||||||
|
}
|
||||||
|
Object synclock = syncLockObject.get(acl);
|
||||||
|
|
||||||
|
NBTTagCompound rslt = null;
|
||||||
|
ChunkCoordIntPair coord = new ChunkCoordIntPair(x, z);
|
||||||
|
|
||||||
|
synchronized (synclock) {
|
||||||
|
if (pendingAnvilChunksMCPC != null) {
|
||||||
|
Object rec = pendingsavesmcpc.get(coord);
|
||||||
|
if(rec != null) {
|
||||||
|
if (chunkCoord == null) {
|
||||||
|
Field[] f = rec.getClass().getDeclaredFields();
|
||||||
|
for(Field ff : f) {
|
||||||
|
if((chunkCoord == null) && (ff.getType().equals(ChunkCoordIntPair.class))) {
|
||||||
|
chunkCoord = ff;
|
||||||
|
}
|
||||||
|
else if((nbtTag == null) && (ff.getType().equals(NBTTagCompound.class))) {
|
||||||
|
nbtTag = ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rslt = (NBTTagCompound)nbtTag.get(rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (pendingcoords.contains(coord)) {
|
||||||
|
for (int i = 0; i < chunkstoremove.size(); i++) {
|
||||||
|
Object o = chunkstoremove.get(i);
|
||||||
|
if (chunkCoord == null) {
|
||||||
|
Field[] f = o.getClass().getDeclaredFields();
|
||||||
|
for(Field ff : f) {
|
||||||
|
if((chunkCoord == null) && (ff.getType().equals(ChunkCoordIntPair.class))) {
|
||||||
|
chunkCoord = ff;
|
||||||
|
}
|
||||||
|
else if((nbtTag == null) && (ff.getType().equals(NBTTagCompound.class))) {
|
||||||
|
nbtTag = ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChunkCoordIntPair occ = (ChunkCoordIntPair)chunkCoord.get(o);
|
||||||
|
|
||||||
|
if (occ.equals(coord)) {
|
||||||
|
rslt = (NBTTagCompound)nbtTag.get(o);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rslt == null) {
|
||||||
|
DataInputStream str = RegionFileCache.getChunkInputStream(acl.chunkSaveLocation, x, z);
|
||||||
|
|
||||||
|
if (str == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
rslt = CompressedStreamTools.read(str);
|
||||||
|
}
|
||||||
|
if(rslt != null)
|
||||||
|
rslt = rslt.getCompoundTag("Level");
|
||||||
|
return rslt;
|
||||||
|
} catch (Exception exc) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getNBTValue(NBTBase v) {
|
||||||
|
Object val = null;
|
||||||
|
switch(v.getId()) {
|
||||||
|
case 1: // Byte
|
||||||
|
val = Byte.valueOf(((NBTTagByte)v).func_150290_f());
|
||||||
|
break;
|
||||||
|
case 2: // Short
|
||||||
|
val = Short.valueOf(((NBTTagShort)v).func_150289_e());
|
||||||
|
break;
|
||||||
|
case 3: // Int
|
||||||
|
val = Integer.valueOf(((NBTTagInt)v).func_150287_d());
|
||||||
|
break;
|
||||||
|
case 4: // Long
|
||||||
|
val = Long.valueOf(((NBTTagLong)v).func_150291_c());
|
||||||
|
break;
|
||||||
|
case 5: // Float
|
||||||
|
val = Float.valueOf(((NBTTagFloat)v).func_150288_h());
|
||||||
|
break;
|
||||||
|
case 6: // Double
|
||||||
|
val = Double.valueOf(((NBTTagDouble)v).func_150286_g());
|
||||||
|
break;
|
||||||
|
case 7: // Byte[]
|
||||||
|
val = ((NBTTagByteArray)v).func_150292_c();
|
||||||
|
break;
|
||||||
|
case 8: // String
|
||||||
|
val = ((NBTTagString)v).func_150285_a_();
|
||||||
|
break;
|
||||||
|
case 9: // List
|
||||||
|
NBTTagList tl = (NBTTagList) v;
|
||||||
|
ArrayList<Object> vlist = new ArrayList<Object>();
|
||||||
|
int type = tl.func_150303_d();
|
||||||
|
for (int i = 0; i < tl.tagCount(); i++) {
|
||||||
|
switch (type) {
|
||||||
|
case 5:
|
||||||
|
float fv = tl.func_150308_e(i);
|
||||||
|
vlist.add(fv);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
double dv = tl.func_150309_d(i);
|
||||||
|
vlist.add(dv);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
String sv = tl.getStringTagAt(i);
|
||||||
|
vlist.add(sv);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
NBTTagCompound tc = tl.getCompoundTagAt(i);
|
||||||
|
vlist.add(getNBTValue(tc));
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
int[] ia = tl.func_150306_c(i);
|
||||||
|
vlist.add(ia);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = vlist;
|
||||||
|
break;
|
||||||
|
case 10: // Map
|
||||||
|
NBTTagCompound tc = (NBTTagCompound) v;
|
||||||
|
HashMap<String, Object> vmap = new HashMap<String, Object>();
|
||||||
|
for (Object t : tc.func_150296_c()) {
|
||||||
|
String st = (String) t;
|
||||||
|
NBTBase tg = tc.getTag(st);
|
||||||
|
vmap.put(st, getNBTValue(tg));
|
||||||
|
}
|
||||||
|
val = vmap;
|
||||||
|
break;
|
||||||
|
case 11: // Int[]
|
||||||
|
val = ((NBTTagIntArray)v).func_150302_c();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+177
@@ -0,0 +1,177 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>dynmap</artifactId>
|
||||||
|
<name>dynmap</name>
|
||||||
|
<properties>
|
||||||
|
<timestamp>${maven.build.timestamp}</timestamp>
|
||||||
|
<maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<BUILD_NUMBER>Dev${timestamp}</BUILD_NUMBER>
|
||||||
|
</properties>
|
||||||
|
<url>http://github.com/webbukkit/dynmap/</url>
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub</system>
|
||||||
|
<url>https://github.com/webbukkit/dynmap/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
<build>
|
||||||
|
<directory>../target</directory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<includes>
|
||||||
|
<include>*.yml</include>
|
||||||
|
<include>*.txt</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>false</filtering>
|
||||||
|
<excludes>
|
||||||
|
<exclude>*.yml</exclude>
|
||||||
|
<exclude>*.txt</exclude>
|
||||||
|
</excludes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.0.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>1.5</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactSet>
|
||||||
|
<includes>
|
||||||
|
<include>us.dynmap:dynmap-api:jar:*</include>
|
||||||
|
<include>us.dynmap:DynmapCore:jar:*</include>
|
||||||
|
<include>us.dynmap:DynmapBukkitBase:jar:*</include>
|
||||||
|
</includes>
|
||||||
|
</artifactSet>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>2.2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.9.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<releases>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
</snapshots>
|
||||||
|
<id>bukkit-repo</id>
|
||||||
|
<url>http://repo.bukkit.org/content/repositories/releases/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<releases>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
</snapshots>
|
||||||
|
<id>dynmap-repo</id>
|
||||||
|
<url>http://repo.mikeprimm.com/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.nijikokun.bukkit</groupId>
|
||||||
|
<artifactId>Permissions</artifactId>
|
||||||
|
<version>3.1.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>Bukkit</artifactId>
|
||||||
|
<version>1.7.10-R0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>dynmap-api</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapCore</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ru.tehkode</groupId>
|
||||||
|
<artifactId>PermissionsEx</artifactId>
|
||||||
|
<version>1.19.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.bananaco</groupId>
|
||||||
|
<artifactId>bPermissions</artifactId>
|
||||||
|
<version>2.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.platymuus.bukkit.permissions</groupId>
|
||||||
|
<artifactId>PermissionsBukkit</artifactId>
|
||||||
|
<version>1.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.anjocaido</groupId>
|
||||||
|
<artifactId>EssentialsGroupManager</artifactId>
|
||||||
|
<version>2.10.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapSpigot</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapBukkitBase</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>us.dynmap</groupId>
|
||||||
|
<artifactId>DynmapBukkit_1_7_10</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
</project>
|
||||||
@@ -7,15 +7,7 @@
|
|||||||
<fileSets>
|
<fileSets>
|
||||||
<fileSet>
|
<fileSet>
|
||||||
<directory>${project.build.directory}/core</directory>
|
<directory>${project.build.directory}/core</directory>
|
||||||
<outputDirectory>/dynmap</outputDirectory>
|
<outputDirectory>/dynmap</outputDirectory></fileSet>
|
||||||
<excludes>
|
|
||||||
<exclude>web/version.js</exclude></excludes></fileSet>
|
|
||||||
<fileSet>
|
|
||||||
<directory>${project.build.directory}/core/web</directory>
|
|
||||||
<outputDirectory>/dynmap/web</outputDirectory>
|
|
||||||
<includes>
|
|
||||||
<include>version.js</include></includes>
|
|
||||||
<filtered>true</filtered></fileSet>
|
|
||||||
<fileSet>
|
<fileSet>
|
||||||
<directory>${project.basedir}</directory>
|
<directory>${project.basedir}</directory>
|
||||||
<outputDirectory>/dynmap</outputDirectory>
|
<outputDirectory>/dynmap</outputDirectory>
|
||||||
+476
-240
File diff suppressed because it is too large
Load Diff
+109
-81
@@ -25,7 +25,6 @@
|
|||||||
* authors and contributors and should not be interpreted as representing official policies,
|
* authors and contributors and should not be interpreted as representing official policies,
|
||||||
* either expressed or implied, of anybody else.
|
* either expressed or implied, of anybody else.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.dynmap.bukkit;
|
package org.dynmap.bukkit;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@@ -33,6 +32,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
|||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -53,16 +53,12 @@ import java.util.UUID;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p> The metrics class obtains data about a plugin and submits statistics about it to the metrics backend. </p> <p>
|
||||||
* The metrics class obtains data about a plugin and submits statistics about it to the metrics backend.
|
* Public methods provided by this class: </p>
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Public methods provided by this class:
|
|
||||||
* </p>
|
|
||||||
* <code>
|
* <code>
|
||||||
* Graph createGraph(String name); <br/>
|
* Graph createGraph(String name); <br>
|
||||||
* void addCustomData(Metrics.Plotter plotter); <br/>
|
* void addCustomData(BukkitMetrics.Plotter plotter); <br>
|
||||||
* void start(); <br/>
|
* void start(); <br>
|
||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
public class Metrics {
|
public class Metrics {
|
||||||
@@ -70,69 +66,63 @@ public class Metrics {
|
|||||||
/**
|
/**
|
||||||
* The current revision number
|
* The current revision number
|
||||||
*/
|
*/
|
||||||
private final static int REVISION = 5;
|
private final static int REVISION = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base url of the metrics domain
|
* The base url of the metrics domain
|
||||||
*/
|
*/
|
||||||
private static final String BASE_URL = "http://mcstats.org";
|
private static final String BASE_URL = "http://mcstats.org";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The url used to report a server's status
|
* The url used to report a server's status
|
||||||
*/
|
*/
|
||||||
private static final String REPORT_URL = "/report/%s";
|
private static final String REPORT_URL = "/report/%s";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The separator to use for custom data. This MUST NOT change unless you are hosting your own
|
* The separator to use for custom data. This MUST NOT change unless you are hosting your own version of metrics and
|
||||||
* version of metrics and want to change it.
|
* want to change it.
|
||||||
*/
|
*/
|
||||||
private static final String CUSTOM_DATA_SEPARATOR = "~~";
|
private static final String CUSTOM_DATA_SEPARATOR = "~~";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interval of time to ping (in minutes)
|
* Interval of time to ping (in minutes)
|
||||||
*/
|
*/
|
||||||
private static final int PING_INTERVAL = 10;
|
private static final int PING_INTERVAL = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The plugin this metrics submits for
|
* The plugin this metrics submits for
|
||||||
*/
|
*/
|
||||||
private final Plugin plugin;
|
private final Plugin plugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All of the custom graphs to submit to metrics
|
* All of the custom graphs to submit to metrics
|
||||||
*/
|
*/
|
||||||
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
|
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default graph, used for addCustomData when you don't want a specific graph
|
* The default graph, used for addCustomData when you don't want a specific graph
|
||||||
*/
|
*/
|
||||||
private final Graph defaultGraph = new Graph("Default");
|
private final Graph defaultGraph = new Graph("Default");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The plugin configuration file
|
* The plugin configuration file
|
||||||
*/
|
*/
|
||||||
private final YamlConfiguration configuration;
|
private final YamlConfiguration configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The plugin configuration file
|
* The plugin configuration file
|
||||||
*/
|
*/
|
||||||
private final File configurationFile;
|
private final File configurationFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique server id
|
* Unique server id
|
||||||
*/
|
*/
|
||||||
private final String guid;
|
private final String guid;
|
||||||
|
/**
|
||||||
|
* Debug mode
|
||||||
|
*/
|
||||||
|
private final boolean debug;
|
||||||
/**
|
/**
|
||||||
* Lock for synchronization
|
* Lock for synchronization
|
||||||
*/
|
*/
|
||||||
private final Object optOutLock = new Object();
|
private final Object optOutLock = new Object();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of the scheduled task
|
* The scheduled task
|
||||||
*/
|
*/
|
||||||
private volatile int taskId = -1;
|
private volatile BukkitTask task = null;
|
||||||
|
|
||||||
|
private BukkitVersionHelper helper;
|
||||||
|
|
||||||
public Metrics(final Plugin plugin) throws IOException {
|
public Metrics(final Plugin plugin) throws IOException {
|
||||||
if (plugin == null) {
|
if (plugin == null) {
|
||||||
throw new IllegalArgumentException("Plugin cannot be null");
|
throw new IllegalArgumentException("Plugin cannot be null");
|
||||||
@@ -147,6 +137,7 @@ public class Metrics {
|
|||||||
// add some defaults
|
// add some defaults
|
||||||
configuration.addDefault("opt-out", false);
|
configuration.addDefault("opt-out", false);
|
||||||
configuration.addDefault("guid", UUID.randomUUID().toString());
|
configuration.addDefault("guid", UUID.randomUUID().toString());
|
||||||
|
configuration.addDefault("debug", false);
|
||||||
|
|
||||||
// Do we need to create the file?
|
// Do we need to create the file?
|
||||||
if (configuration.get("guid", null) == null) {
|
if (configuration.get("guid", null) == null) {
|
||||||
@@ -156,11 +147,14 @@ public class Metrics {
|
|||||||
|
|
||||||
// Load the guid then
|
// Load the guid then
|
||||||
guid = configuration.getString("guid");
|
guid = configuration.getString("guid");
|
||||||
|
debug = configuration.getBoolean("debug", false);
|
||||||
|
|
||||||
|
helper = BukkitVersionHelper.getHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct and create a Graph that can be used to separate specific plotters to their own graphs
|
* Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
|
||||||
* on the metrics website. Plotters can be added to the graph object returned.
|
* website. Plotters can be added to the graph object returned.
|
||||||
*
|
*
|
||||||
* @param name The name of the graph
|
* @param name The name of the graph
|
||||||
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
|
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
|
||||||
@@ -181,7 +175,7 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a Graph object to Metrics that represents data for the plugin that should be sent to the backend
|
* Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend
|
||||||
*
|
*
|
||||||
* @param graph The name of the graph
|
* @param graph The name of the graph
|
||||||
*/
|
*/
|
||||||
@@ -211,9 +205,9 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send
|
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
|
||||||
* the initial data to the metrics backend, and then after that it will post in increments of
|
* initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
|
||||||
* PING_INTERVAL * 1200 ticks.
|
* ticks.
|
||||||
*
|
*
|
||||||
* @return True if statistics measuring is running, otherwise false.
|
* @return True if statistics measuring is running, otherwise false.
|
||||||
*/
|
*/
|
||||||
@@ -225,12 +219,13 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Is metrics already running?
|
// Is metrics already running?
|
||||||
if (taskId >= 0) {
|
if (task != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin hitting the server with glorious data
|
// Begin hitting the server with glorious data
|
||||||
taskId = plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() {
|
try {
|
||||||
|
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
|
||||||
|
|
||||||
private boolean firstPost = true;
|
private boolean firstPost = true;
|
||||||
|
|
||||||
@@ -239,11 +234,11 @@ public class Metrics {
|
|||||||
// This has to be synchronized or it can collide with the disable method.
|
// This has to be synchronized or it can collide with the disable method.
|
||||||
synchronized (optOutLock) {
|
synchronized (optOutLock) {
|
||||||
// Disable Task, if it is running and the server owner decided to opt-out
|
// Disable Task, if it is running and the server owner decided to opt-out
|
||||||
if (isOptOut() && taskId > 0) {
|
if (isOptOut() && task != null) {
|
||||||
plugin.getServer().getScheduler().cancelTask(taskId);
|
task.cancel();
|
||||||
taskId = -1;
|
task = null;
|
||||||
// Tell all plotters to stop gathering information.
|
// Tell all plotters to stop gathering information.
|
||||||
for (Graph graph : graphs){
|
for (Graph graph : graphs) {
|
||||||
graph.onOptOut();
|
graph.onOptOut();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,10 +253,16 @@ public class Metrics {
|
|||||||
// Each post thereafter will be a ping
|
// Each post thereafter will be a ping
|
||||||
firstPost = false;
|
firstPost = false;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
|
if (debug) {
|
||||||
|
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0, PING_INTERVAL * 1200);
|
}, 0, PING_INTERVAL * 1200);
|
||||||
|
} catch (NoSuchMethodError nsme) {
|
||||||
|
// Handle deprecated scheduler API stupidity
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -273,15 +274,19 @@ public class Metrics {
|
|||||||
* @return true if metrics should be opted out of it
|
* @return true if metrics should be opted out of it
|
||||||
*/
|
*/
|
||||||
public boolean isOptOut() {
|
public boolean isOptOut() {
|
||||||
synchronized(optOutLock) {
|
synchronized (optOutLock) {
|
||||||
try {
|
try {
|
||||||
// Reload the metrics file
|
// Reload the metrics file
|
||||||
configuration.load(getConfigFile());
|
configuration.load(getConfigFile());
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
if (debug) {
|
||||||
|
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (InvalidConfigurationException ex) {
|
} catch (InvalidConfigurationException ex) {
|
||||||
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
if (debug) {
|
||||||
|
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return configuration.getBoolean("opt-out", false);
|
return configuration.getBoolean("opt-out", false);
|
||||||
@@ -289,30 +294,30 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
|
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws java.io.IOException
|
||||||
*/
|
*/
|
||||||
public void enable() throws IOException {
|
public void enable() throws IOException {
|
||||||
// This has to be synchronized or it can collide with the check in the task.
|
// This has to be synchronized or it can collide with the check in the task.
|
||||||
synchronized (optOutLock) {
|
synchronized (optOutLock) {
|
||||||
// Check if the server owner has already set opt-out, if not, set it.
|
// Check if the server owner has already set opt-out, if not, set it.
|
||||||
if (isOptOut()) {
|
if (isOptOut()) {
|
||||||
configuration.set("opt-out", false);
|
configuration.set("opt-out", false);
|
||||||
configuration.save(configurationFile);
|
configuration.save(configurationFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable Task, if it is not running
|
// Enable Task, if it is not running
|
||||||
if (taskId < 0) {
|
if (task == null) {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
|
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws java.io.IOException
|
||||||
*/
|
*/
|
||||||
public void disable() throws IOException {
|
public void disable() throws IOException {
|
||||||
// This has to be synchronized or it can collide with the check in the task.
|
// This has to be synchronized or it can collide with the check in the task.
|
||||||
@@ -324,9 +329,9 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable Task, if it is running
|
// Disable Task, if it is running
|
||||||
if (taskId > 0) {
|
if (task != null) {
|
||||||
this.plugin.getServer().getScheduler().cancelTask(taskId);
|
task.cancel();
|
||||||
taskId = -1;
|
task = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,17 +357,45 @@ public class Metrics {
|
|||||||
* Generic method that posts a plugin to the metrics website
|
* Generic method that posts a plugin to the metrics website
|
||||||
*/
|
*/
|
||||||
private void postPlugin(final boolean isPing) throws IOException {
|
private void postPlugin(final boolean isPing) throws IOException {
|
||||||
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
// Server software specific section
|
||||||
final PluginDescriptionFile description = plugin.getDescription();
|
PluginDescriptionFile description = plugin.getDescription();
|
||||||
|
String pluginName = description.getName();
|
||||||
|
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
|
||||||
|
String pluginVersion = description.getVersion();
|
||||||
|
String serverVersion = Bukkit.getVersion();
|
||||||
|
int playersOnline = helper.getOnlinePlayers().length;
|
||||||
|
|
||||||
|
// END server software specific section -- all code below does not use any code outside of this class / Java
|
||||||
|
|
||||||
// Construct the post data
|
// Construct the post data
|
||||||
final StringBuilder data = new StringBuilder();
|
final StringBuilder data = new StringBuilder();
|
||||||
|
|
||||||
|
// The plugin's description file containg all of the plugin data such as name, version, author, etc
|
||||||
data.append(encode("guid")).append('=').append(encode(guid));
|
data.append(encode("guid")).append('=').append(encode(guid));
|
||||||
encodeDataPair(data, "version", description.getVersion());
|
encodeDataPair(data, "version", pluginVersion);
|
||||||
encodeDataPair(data, "server", Bukkit.getVersion());
|
encodeDataPair(data, "server", serverVersion);
|
||||||
encodeDataPair(data, "players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length));
|
encodeDataPair(data, "players", Integer.toString(playersOnline));
|
||||||
encodeDataPair(data, "revision", String.valueOf(REVISION));
|
encodeDataPair(data, "revision", String.valueOf(REVISION));
|
||||||
|
|
||||||
|
// New data as of R6
|
||||||
|
String osname = System.getProperty("os.name");
|
||||||
|
String osarch = System.getProperty("os.arch");
|
||||||
|
String osversion = System.getProperty("os.version");
|
||||||
|
String java_version = System.getProperty("java.version");
|
||||||
|
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
|
// normalize os arch .. amd64 -> x86_64
|
||||||
|
if (osarch.equals("amd64")) {
|
||||||
|
osarch = "x86_64";
|
||||||
|
}
|
||||||
|
|
||||||
|
encodeDataPair(data, "osname", osname);
|
||||||
|
encodeDataPair(data, "osarch", osarch);
|
||||||
|
encodeDataPair(data, "osversion", osversion);
|
||||||
|
encodeDataPair(data, "cores", Integer.toString(coreCount));
|
||||||
|
encodeDataPair(data, "online-mode", Boolean.toString(onlineMode));
|
||||||
|
encodeDataPair(data, "java_version", java_version);
|
||||||
|
|
||||||
// If we're pinging, append it
|
// If we're pinging, append it
|
||||||
if (isPing) {
|
if (isPing) {
|
||||||
encodeDataPair(data, "ping", "true");
|
encodeDataPair(data, "ping", "true");
|
||||||
@@ -393,7 +426,7 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the url
|
// Create the url
|
||||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(plugin.getDescription().getName())));
|
URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(pluginName)));
|
||||||
|
|
||||||
// Connect to the website
|
// Connect to the website
|
||||||
URLConnection connection;
|
URLConnection connection;
|
||||||
@@ -456,8 +489,8 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first
|
* <p>Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first key/value pair
|
||||||
* key/value pair MUST be included manually, e.g:</p>
|
* MUST be included manually, e.g:</p>
|
||||||
* <code>
|
* <code>
|
||||||
* StringBuffer data = new StringBuffer();
|
* StringBuffer data = new StringBuffer();
|
||||||
* data.append(encode("guid")).append('=').append(encode(guid));
|
* data.append(encode("guid")).append('=').append(encode(guid));
|
||||||
@@ -488,11 +521,10 @@ public class Metrics {
|
|||||||
public static class Graph {
|
public static class Graph {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The graph's name, alphanumeric and spaces only :)
|
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
|
||||||
* If it does not comply to the above when submitted, it is rejected
|
* rejected
|
||||||
*/
|
*/
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The set of plotters that are contained within this graph
|
* The set of plotters that are contained within this graph
|
||||||
*/
|
*/
|
||||||
@@ -532,7 +564,7 @@ public class Metrics {
|
|||||||
/**
|
/**
|
||||||
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph
|
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph
|
||||||
*
|
*
|
||||||
* @return an unmodifiable {@link Set} of the plotter objects
|
* @return an unmodifiable {@link java.util.Set} of the plotter objects
|
||||||
*/
|
*/
|
||||||
public Set<Plotter> getPlotters() {
|
public Set<Plotter> getPlotters() {
|
||||||
return Collections.unmodifiableSet(plotters);
|
return Collections.unmodifiableSet(plotters);
|
||||||
@@ -554,11 +586,10 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the server owner decides to opt-out of Metrics while the server is running.
|
* Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
|
||||||
*/
|
*/
|
||||||
protected void onOptOut() {
|
protected void onOptOut() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -588,10 +619,9 @@ public class Metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current value for the plotted point. Since this function defers to an external function
|
* Get the current value for the plotted point. Since this function defers to an external function it may or may
|
||||||
* it may or may not return immediately thus cannot be guaranteed to be thread friendly or safe.
|
* not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
|
||||||
* This function can be called from any thread so care should be taken when accessing resources
|
* from any thread so care should be taken when accessing resources that need to be synchronized.
|
||||||
* that need to be synchronized.
|
|
||||||
*
|
*
|
||||||
* @return the current value for the point to be plotted.
|
* @return the current value for the point to be plotted.
|
||||||
*/
|
*/
|
||||||
@@ -626,7 +656,5 @@ public class Metrics {
|
|||||||
final Plotter plotter = (Plotter) object;
|
final Plotter plotter = (Plotter) object;
|
||||||
return plotter.name.equals(name) && plotter.getValue() == getValue();
|
return plotter.name.equals(name) && plotter.getValue() == getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user