Compare commits

...

70 Commits

Author SHA1 Message Date
Mike Primm 7c6e660cf0 Add supporting code to help with CTM support (block names, biome names) 2013-04-18 01:20:59 -05:00
Mike Primm bcd0acec33 Bump to 1.7 2013-04-07 21:34:37 -05:00
Mike Primm 7e07bff71f Remove MCPC-Plus support from Bukkit version - add notice to use Forge 2013-03-29 21:46:06 -05:00
Mike Primm 2d95548d25 Add default setting for initial zoomout validate option 2013-03-26 23:50:54 -05:00
Mike Primm 3ac67ce2c5 Update for new API listener 2013-03-20 23:59:50 -05:00
Mike Primm 0d25fd2edc Make sure chunk unload queue is processed quickly enough on MCPC 2013-03-18 20:30:13 -05:00
Mike Primm bee16ef331 Switch MCPC+ to using unloadChunkRequest - unloadChunk() seems to not clean up properly 2013-03-17 23:43:11 -05:00
Mike Primm bf16d18371 Bump to 1.6 2013-03-02 16:00:58 -06:00
Mike Primm e57634ebb3 Add BukkitForge handler - doesn't work right due to BukkitForge API bugs 2013-03-01 23:51:45 -06:00
Mike Primm 55a5aacfce Drop autogenerate option 2013-02-24 20:24:05 -06:00
mikeprimm e6fe29f0c5 Merge pull request #1148 from dejavecu/master
Added support of round visibility limits
2013-02-24 16:15:16 -08:00
Mike Primm 34712e27f0 Put in some protextion logic for apparently broken SpoutPlugin 2013-02-24 18:04:20 -06:00
dejavecu 6a5eebcc00 Added support of round visibility limits 2013-02-16 03:59:07 +04:00
Mike Primm c8b1f71949 Add settings for image update command exits 2013-02-03 17:11:35 -06:00
Mike Primm dc11ef3507 Bump to 1.5 2013-01-29 13:52:25 -06:00
Mike Primm d0bbb78e98 Add upgrade version check 2013-01-29 11:49:22 -06:00
Mike Primm 9144bff25b Add support for MCPC-Plus 2013-01-21 23:54:13 -06:00
Mike Primm 18325c2b33 Switch version check to core version 2013-01-15 11:33:51 -06:00
Mike Primm f1a686eaf8 Hack to work around broken jenkins 2013-01-15 08:45:49 -06:00
Mike Primm b3c32456ca Revert "Test to try to fix jenkins f-up"
This reverts commit 3483b19cef.
2013-01-15 08:23:31 -06:00
Mike Primm be16ac089f Revert "Revert - no help"
This reverts commit 9ad5a7e4f7.
2013-01-15 08:23:11 -06:00
Mike Primm 44a8bfa38d Revert "Try to workaround Jenkins/Maven packaging issue"
This reverts commit 443d64f7da.
2013-01-15 08:22:55 -06:00
Mike Primm 443d64f7da Try to workaround Jenkins/Maven packaging issue 2013-01-15 08:17:31 -06:00
Mike Primm 9ad5a7e4f7 Revert - no help 2013-01-15 03:31:33 -06:00
Mike Primm 3483b19cef Test to try to fix jenkins f-up 2013-01-15 03:26:03 -06:00
Mike Primm 44c5d51c4e Fix v1.2.5 support, broken by API change in metrics 2013-01-15 00:30:08 -06:00
Mike Primm 56d1bcf3eb Show details on execution exceptions - better info on cause 2013-01-11 15:59:55 -06:00
Mike Primm f43027f02f Add tileupdatedelay setting, compute more accurate bounding box for new chunks 2013-01-08 00:10:53 -06:00
Mike Primm bd12420edd Add option to hide players on map that have invisibility potion effects 2013-01-03 21:58:58 -06:00
Mike Primm 3c01aff411 Drop obsolete file 2013-01-02 21:25:17 -06:00
Mike Primm 4d664de250 Bump to 1.4 2012-12-31 15:58:32 -06:00
Mike Primm 278fa36f94 Add call needed for sign block checks 2012-12-31 12:29:28 -06:00
Mike Primm 1a2f63bcfb Switch weather display to be on by default 2012-12-30 11:23:21 -06:00
Mike Primm 344d9bf1c9 Add support for configuing which proxy addresses to trust X-Forwarded-For from 2012-12-30 11:03:28 -06:00
Mike Primm 70b27b8034 Remove debug message 2012-12-30 10:14:05 -06:00
Mike Primm abe7fc8405 Update metrics agent 2012-12-30 09:17:35 -06:00
Mike Primm 4fa62993f4 Scrub system dependencies - shifted to repository 2012-12-24 15:10:24 -06:00
Mike Primm 08a920694b Switch to new repo 2012-12-24 14:52:00 -06:00
Mike Primm 4bdb331eb0 Switch mod use to features graph - doesn't look like we get a 3rd one.. 2012-12-17 21:55:23 -06:00
Mike Primm cb7c9061e8 Update stats to collect mod usage data 2012-12-17 21:08:39 -06:00
Mike Primm 29cb155534 Revert "Fix to bukkit API 1.2.5 - avoid accidental breaks of backward compat"
This reverts commit ada85ed960.
2012-12-16 17:12:09 -06:00
Mike Primm ada85ed960 Fix to bukkit API 1.2.5 - avoid accidental breaks of backward compat 2012-12-16 15:02:19 -06:00
Mike Primm bfb12aa0f3 Bump to 1.3 2012-12-10 22:52:02 -06:00
Mike Primm 3342977a92 Add cyrillic setting back in to configuration.txt 2012-12-10 00:21:58 -06:00
Mike Primm 07cbd84d44 Combine support for pre 1.4.5 versions and new 1.4.x packaging crud 2012-12-09 22:28:21 -06:00
Mike Primm da5e2cf24a Add transparent-leaves setting : workaround for borked lighting in some SpoutPlugin versions 2012-12-09 13:04:44 -06:00
Mike Primm c6d345d8f1 Add tile entity data collection 2012-11-22 00:50:55 -06:00
Mike Primm 3a57261120 First pass of custom renderer support 2012-11-19 15:56:55 -06:00
Mike Primm a39f99cab8 Back to 1.2 2012-11-16 18:46:34 -06:00
Mike Primm f0885abea2 Back to 1.1 for patch 2012-11-16 18:39:44 -06:00
Mike Primm 2b17cb215b Bump to 1.2 2012-11-16 18:06:22 -06:00
Mike Primm 68f0c17f70 Support world loading/unloading - allow viewing while world unloaded 2012-11-10 23:47:40 -06:00
Mike Primm a20e55beab Add support for handling custom biomes (ExtraBiomes XL) 2012-11-09 21:01:11 -06:00
Mike Primm 413542fe61 Add permissions.jar to project - not on repo anymore 2012-11-08 14:25:32 -06:00
Mike Primm a250732d31 Bump to v1.1 2012-10-29 22:37:55 -05:00
Mike Primm 07f2496f2f Bump to 1.00 2012-10-21 12:32:58 -05:00
Mike Primm 2f6e52261c Cleanup unused methods, speed up world lookup 2012-10-17 19:42:37 -05:00
Mike Primm a117987840 Handle multiple mod names 2012-10-15 08:24:10 -05:00
Mike Primm cbb8cc061e Add support for automatic enabling of mod-specific blocks and textures 2012-10-15 01:19:18 -05:00
Mike Primm c03365d574 Correct setting for TubeStuff support 2012-10-14 21:02:37 -05:00
Mike Primm 827f18b8e0 Support delaying dynmap start to allow Spout blocks to be registered 2012-10-05 00:10:32 -05:00
Mike Primm 1603015631 Handle new CancellationExceptions being thrown by Bukkit Scheduler 2012-09-03 20:43:30 -05:00
Mike Primm c2d97ba3d5 Keep metrics from nagging if mcstats.org is offline 2012-08-27 21:03:55 -05:00
Mike Primm 418b175923 Bump to 0.90 2012-08-26 22:07:56 -05:00
Mike Primm fdc14b413d Add ee2-support setting for Equivalent Exchange 2 support 2012-08-25 22:55:48 -05:00
Mike Primm e6d509c3e6 Add some more feature metrics 2012-08-24 22:37:48 -05:00
Mike Primm b10ec3a331 Add support for ExtraBiomesXL Bunyan blocks 2012-08-24 01:28:46 -05:00
Mike Primm 9f8617d81d Add mcstats.org reporting 2012-08-24 00:07:06 -05:00
Mike Primm 265e037b74 Add setting for enabling ExtraBiomesXL rendering support 2012-08-20 00:17:00 -05:00
Mike Primm f50e73180c Back to 0.80 2012-08-19 19:34:45 -05:00
16 changed files with 1960 additions and 301 deletions
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-6
View File
@@ -1,6 +0,0 @@
dynmap.render # Render current chunk
dynmap.fullrender # Issue a full render
dynmap.hide.self # Hide self from map
dynmap.hide.others # Hide others from map
dynmap.show.self # Reveal self on map
dynmap.show.others # Reveal others on map
+14 -19
View File
@@ -2,11 +2,10 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.dynmap</groupId>
<artifactId>dynmap</artifactId>
<version>0.70.3</version>
<name>dynmap</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<BUILD_NUMBER>dev</BUILD_NUMBER>
<BUILD_NUMBER>Dev</BUILD_NUMBER>
</properties>
<url>http://github.com/webbukkit/dynmap/</url>
<issueManagement>
@@ -120,22 +119,28 @@
</releases>
<snapshots>
</snapshots>
<id>spout-repo</id>
<url>http://repo.spout.org</url>
<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>[2.5.4,)</version>
<version>3.1.6</version>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>[1.2.5-R4.0,1.7)</version>
<type>jar</type>
<scope>compile</scope>
<version>1.3.2-R3.0</version>
</dependency>
<dependency>
<groupId>org.dynmap</groupId>
@@ -162,27 +167,17 @@
<groupId>ru.tehkode</groupId>
<artifactId>PermissionsEx</artifactId>
<version>1.19.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/PermissionsEx.jar</systemPath>
</dependency>
<dependency>
<groupId>de.bananaco</groupId>
<artifactId>bPermissions</artifactId>
<version>2.9.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/bpermissions.jar</systemPath>
</dependency>
<dependency>
<groupId>com.platymuus.bukkit.permissions</groupId>
<artifactId>PermissionsBukkit</artifactId>
<version>1.6</version>
<scope>system</scope>
<systemPath>${project.basedir}/PermissionsBukkit.jar</systemPath>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.2.5-R5.1-SNAPSHOT</version>
</dependency>
</dependencies>
<version>1.7</version>
</project>
+1 -9
View File
@@ -7,15 +7,7 @@
<fileSets>
<fileSet>
<directory>${project.build.directory}/core</directory>
<outputDirectory>/dynmap</outputDirectory>
<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>
<outputDirectory>/dynmap</outputDirectory></fileSet>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory>/dynmap</outputDirectory>
@@ -0,0 +1,127 @@
package org.dynmap.bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Server;
import org.bukkit.World;
import org.dynmap.Log;
/**
* Helper for isolation of bukkit version specific issues
*/
public abstract class BukkitVersionHelper {
private static BukkitVersionHelper helper = null;
public static final BukkitVersionHelper getHelper() {
if(helper == null) {
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 {
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 net.minecraft.server.world for given world
*/
public abstract Object getNMSWorld(World w);
/**
* Get unload queue for given NMS world
*/
public abstract Object getUnloadQueue(Object nmsworld);
/**
* 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);
/**
* Test if normal chunk snapshot
*/
public abstract boolean isCraftChunkSnapshot(ChunkSnapshot css);
/**
* Remove entities from given chunk
*/
public abstract void removeEntitiesFromChunk(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();
}
@@ -0,0 +1,146 @@
package org.dynmap.bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
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 Field blockbyid;
private Field blockname;
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;");
blockbyid = getField(nmsblock, new String[] { "byId" }, nmsblockarray);
blockname = getPrivateField(nmsblock, new String[] { "name" }, String.class);
/* Set up biomebase fields */
biomebase = getNMSClass("net.minecraft.server.BiomeBase");
biomebasearray = getNMSClass("[Lnet.minecraft.server.BiomeBase;");
biomebaselist = getField(biomebase, new String[] { "biomes" }, biomebasearray);
biomebasetemp = getField(biomebase, new String[] { "temperature", "F" }, float.class);
biomebasehumi = getField(biomebase, new String[] { "humidity", "G" }, float.class);
biomebaseidstring = getField(biomebase, new String[] { "y" }, String.class);
biomebaseid = getField(biomebase, new String[] { "id" }, int.class);
/* 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);
/** nbt classes */
nbttagcompound = getNMSClass("net.minecraft.server.NBTTagCompound");
nbttagbyte = getNMSClass("net.minecraft.server.NBTTagByte");
nbttagshort = getNMSClass("net.minecraft.server.NBTTagShort");
nbttagint = getNMSClass("net.minecraft.server.NBTTagInt");
nbttaglong = getNMSClass("net.minecraft.server.NBTTagLong");
nbttagfloat = getNMSClass("net.minecraft.server.NBTTagFloat");
nbttagdouble = getNMSClass("net.minecraft.server.NBTTagDouble");
nbttagbytearray = getNMSClass("net.minecraft.server.NBTTagByteArray");
nbttagstring = getNMSClass("net.minecraft.server.NBTTagString");
nbttagintarray = getNMSClass("net.minecraft.server.NBTTagIntArray");
compound_get = getMethod(nbttagcompound, new String[] { "get" }, new Class[] { String.class });
nbttagbyte_val = getField(nbttagbyte, new String[] { "data" }, byte.class);
nbttagshort_val = getField(nbttagshort, new String[] { "data" }, short.class);
nbttagint_val = getField(nbttagint, new String[] { "data" }, int.class);
nbttaglong_val = getField(nbttaglong, new String[] { "data" }, long.class);
nbttagfloat_val = getField(nbttagfloat, new String[] { "data" }, float.class);
nbttagdouble_val = getField(nbttagdouble, new String[] { "data" }, double.class);
nbttagbytearray_val = getField(nbttagbytearray, new String[] { "data" }, byte[].class);
nbttagstring_val = getField(nbttagstring, new String[] { "data" }, String.class);
nbttagintarray_val = getField(nbttagintarray, new String[] { "data" }, int[].class);
/** Tile entity */
nms_tileentity = getNMSClass("net.minecraft.server.TileEntity");
nmst_readnbt = getMethod(nms_tileentity, new String[] { "b" }, new Class[] { nbttagcompound });
nmst_x = getField(nms_tileentity, new String[] { "x" }, int.class);
nmst_y = getField(nms_tileentity, new String[] { "y" }, int.class);
nmst_z = getField(nms_tileentity, new String[] { "z" }, int.class);
}
@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 {
Object[] byid = (Object[])blockbyid.get(nmsblock);
String[] names = new String[byid.length];
for (int i = 0; i < names.length; i++) {
if (byid[i] != null) {
names[i] = (String)blockname.get(byid[i]);
}
}
return names;
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException 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;
}
}
@@ -0,0 +1,372 @@
package org.dynmap.bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Server;
import org.bukkit.World;
import org.dynmap.Log;
/**
* Helper for isolation of bukkit version specific issues
*/
public 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;
/** 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;
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]);
/* 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 */
public Object getNMSWorld(World w) {
return callMethod(w, cw_gethandle, nullargs, null);
}
/* Get unload queue for given NMS world */
public Object getUnloadQueue(Object nmsworld) {
Object cps = getFieldValue(nmsworld, nmsw_chunkproviderserver, null); // Get chunkproviderserver
if(cps != null) {
return getFieldValue(cps, cps_unloadqueue, null);
}
return null;
}
/* For testing unload queue for presence of givne chunk */
public boolean isInUnloadQueue(Object unloadqueue, int x, int z) {
if(unloadqueue != null) {
return (Boolean)callMethod(unloadqueue, lhs_containskey, new Object[] { x, z }, true);
}
return true;
}
public Object[] getBiomeBaseFromSnapshot(ChunkSnapshot css) {
return (Object[])getFieldValue(css, ccss_biome, null);
}
public boolean isCraftChunkSnapshot(ChunkSnapshot css) {
if(craftchunksnapshot != null) {
return craftchunksnapshot.isAssignableFrom(css.getClass());
}
return false;
}
/** Remove entities from given chunk */
public void removeEntitiesFromChunk(Chunk c) {
Object omsc = callMethod(c, cc_gethandle, nullargs, null);
if(omsc != null) {
callMethod(omsc, nmsc_removeentities, nullargs, null);
}
}
/** Get tile entities map from chunk */
public Map getTileEntitiesForChunk(Chunk c) {
Object omsc = callMethod(c, cc_gethandle, nullargs, null);
if(omsc != null) {
return (Map)getFieldValue(omsc, nmsc_tileentities, nullmap);
}
return nullmap;
}
/**
* Get X coordinate of tile entity
*/
public int getTileEntityX(Object te) {
return (Integer)getFieldValue(te, nmst_x, 0);
}
/**
* Get Y coordinate of tile entity
*/
public int getTileEntityY(Object te) {
return (Integer)getFieldValue(te, nmst_y, 0);
}
/**
* Get Z coordinate of tile entity
*/
public int getTileEntityZ(Object te) {
return (Integer)getFieldValue(te, nmst_z, 0);
}
/**
* Read tile entity NBT
*/
public Object readTileEntityNBT(Object te) {
if(nbttagcompound == null) return null;
Object nbt = null;
try {
nbt = nbttagcompound.newInstance();
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
if(nbt != null) {
callMethod(te, nmst_readnbt, new Object[] { nbt }, null);
}
return nbt;
}
/**
* Get field value from NBT compound
*/
public Object getFieldValue(Object nbt, String field) {
Object val = callMethod(nbt, compound_get, new Object[] { field }, null);
if(val == null) return null;
Class<?> valcls = val.getClass();
if(valcls.equals(nbttagbyte)) {
return getFieldValue(val, nbttagbyte_val, null);
}
else if(valcls.equals(nbttagshort)) {
return getFieldValue(val, nbttagshort_val, null);
}
else if(valcls.equals(nbttagint)) {
return getFieldValue(val, nbttagint_val, null);
}
else if(valcls.equals(nbttaglong)) {
return getFieldValue(val, nbttaglong_val, null);
}
else if(valcls.equals(nbttagfloat)) {
return getFieldValue(val, nbttagfloat_val, null);
}
else if(valcls.equals(nbttagdouble)) {
return getFieldValue(val, nbttagdouble_val, null);
}
else if(valcls.equals(nbttagbytearray)) {
return getFieldValue(val, nbttagbytearray_val, null);
}
else if(valcls.equals(nbttagstring)) {
return getFieldValue(val, nbttagstring_val, null);
}
else if(valcls.equals(nbttagintarray)) {
return getFieldValue(val, nbttagintarray_val, null);
}
return null;
}
}
@@ -17,13 +17,36 @@ public class BukkitWorld extends DynmapWorld {
private World world;
private World.Environment env;
private boolean skylight;
private DynmapLocation spawnloc = new DynmapLocation();
public BukkitWorld(World w) {
super(w.getName(), w.getMaxHeight(), w.getSeaLevel());
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);
}
/**
* Set world online
* @param w - loaded world
*/
public void setWorldLoaded(World w) {
world = w;
env = world.getEnvironment();
skylight = (env == World.Environment.NORMAL);
new Permission("dynmap.world." + getName(), "Dynmap access for world " + getName(), PermissionDefault.OP);
}
/**
* Set world unloaded
*/
@Override
public void setWorldUnloaded() {
getSpawnLocation(); /* Remember spawn location before unload */
world = null;
}
/* Test if world is nether */
@Override
@@ -33,26 +56,44 @@ public class BukkitWorld extends DynmapWorld {
/* Get world spawn location */
@Override
public DynmapLocation getSpawnLocation() {
DynmapLocation dloc = new DynmapLocation();
Location sloc = world.getSpawnLocation();
dloc.x = sloc.getBlockX(); dloc.y = sloc.getBlockY();
dloc.z = sloc.getBlockZ(); dloc.world = normalizeWorldName(sloc.getWorld().getName());
return dloc;
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() {
return world.getTime();
if(world != null) {
return world.getTime();
}
else {
return -1;
}
}
/* World is storming */
@Override
public boolean hasStorm() {
return world.hasStorm();
if(world != null) {
return world.hasStorm();
}
else {
return false;
}
}
/* World is thundering */
@Override
public boolean isThundering() {
return world.isThundering();
if(world != null) {
return world.isThundering();
}
else {
return false;
}
}
/* World is loaded */
@Override
@@ -62,22 +103,37 @@ public class BukkitWorld extends DynmapWorld {
/* Get light level of block */
@Override
public int getLightLevel(int x, int y, int z) {
return world.getBlockAt(x, y, z).getLightLevel();
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) {
return world.getHighestBlockYAt(x, 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;
return skylight && (world != null);
}
/* Return sky light level */
@Override
public int getSkyLightLevel(int x, int y, int z) {
return world.getBlockAt(x, y, z).getLightFromSky();
if(world != null) {
return world.getBlockAt(x, y, z).getLightFromSky();
}
else {
return -1;
}
}
/**
* Get world environment ID (lower case - normal, the_end, nether)
@@ -91,9 +147,14 @@ public class BukkitWorld extends DynmapWorld {
*/
@Override
public MapChunkCache getChunkCache(List<DynmapChunk> chunks) {
NewMapChunkCache c = new NewMapChunkCache();
c.setChunks(this, chunks);
return c;
if(isLoaded()) {
NewMapChunkCache c = new NewMapChunkCache();
c.setChunks(this, chunks);
return c;
}
else {
return null;
}
}
public World getWorld() {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,30 +1,27 @@
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.Arrays;
import java.util.List;
import java.util.ListIterator;
import net.minecraft.server.ChunkProviderServer;
import java.util.Map;
import org.bukkit.World;
import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftChunk;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.util.LongHashset;
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;
import org.getspout.spoutapi.block.SpoutChunk;
/**
@@ -32,9 +29,7 @@ import org.getspout.spoutapi.block.SpoutChunk;
*/
public class NewMapChunkCache implements MapChunkCache {
private static boolean init = false;
private static boolean use_spout = false;
private static Field unloadqueue = null;
private static Method queuecontainskey = null;
private static boolean use_spout = false;
private World w;
private DynmapWorld dw;
@@ -47,10 +42,9 @@ public class NewMapChunkCache implements MapChunkCache {
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
private List<VisibilityLimit> visible_limits = null;
private List<VisibilityLimit> hidden_limits = null;
private boolean do_generate = false;
private boolean do_save = false;
private boolean isempty = true;
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
private DynIntHashMap[] snaptile;
private byte[][] sameneighborbiomecnt;
private BiomeMap[][] biomemap;
private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */
@@ -61,11 +55,17 @@ public class NewMapChunkCache implements MapChunkCache {
private long exceptions;
private static BukkitVersionHelper helper = BukkitVersionHelper.getHelper();
private static final BlockStep unstep[] = { BlockStep.X_MINUS, BlockStep.Y_MINUS, BlockStep.Z_MINUS,
BlockStep.X_PLUS, BlockStep.Y_PLUS, BlockStep.Z_PLUS };
private static BiomeMap[] biome_to_bmap;
private static final int getIndexInChunk(int cx, int cy, int cz) {
return (cy << 8) | (cz << 4) | cx;
}
/**
* Iterator for traversing map chunk cache (base is for non-snapshot)
*/
@@ -145,15 +145,31 @@ public class NewMapChunkCache implements MapChunkCache {
sameneighborbiomecnt[i] = new byte[z_size];
biomemap[i] = new BiomeMap[z_size];
}
Object[] biomebase = null;
ChunkSnapshot biome_css = null;
for(int i = 0; i < x_size; i++) {
initialize(i + x_base, 64, z_base);
for(int j = 0; j < z_size; j++) {
Biome bb = snap.getBiome(bx, bz);
BiomeMap bm;
if(bb == null)
bm = BiomeMap.NULL;
else
bm = biome_to_bmap[bb.ordinal()];
if(snap != biome_css) {
biomebase = null;
biome_css = snap;
if (biome_css instanceof SpoutChunkSnapshot) {
biome_css = ((SpoutChunkSnapshot)biome_css).chunk;
}
biomebase = helper.getBiomeBaseFromSnapshot(biome_css);
}
if(biomebase != null) {
bm = BiomeMap.byBiomeID(helper.getBiomeBaseID(biomebase[bz << 4 | bx]));
}
else {
Biome bb = snap.getBiome(bx, bz);
if(bb == null)
bm = BiomeMap.NULL;
else
bm = biome_to_bmap[bb.ordinal()];
}
biomemap[i][j] = bm;
int cnt = 0;
if(i > 0) {
@@ -517,6 +533,53 @@ public class NewMapChunkCache implements MapChunkCache {
return !isSectionNotEmpty[chunkindex][y >> 4];
}
}
@Override
public RenderPatchFactory getPatchFactory() {
return HDBlockModels.getPatchDefinitionFactory();
}
@Override
public Object getBlockTileEntityField(String fieldId) {
try {
int idx = getIndexInChunk(bx,y,bz);
Object[] vals = (Object[])snaptile[chunkindex].get(idx);
for (int i = 0; i < vals.length; i += 2) {
if (vals[i].equals(fieldId)) {
return vals[i+1];
}
}
} catch (Exception x) {
}
return null;
}
@Override
public int getBlockTypeIDAt(int xoff, int yoff, int zoff) {
int xx = this.x + xoff;
int yy = this.y + yoff;
int zz = this.z + zoff;
int idx = ((xx >> 4) - x_min) + (((zz >> 4) - z_min) * x_dim);
try {
return snaparray[idx].getBlockTypeId(xx & 0xF, yy, zz & 0xF);
} catch (Exception x) {
return 0;
}
}
@Override
public int getBlockDataAt(int xoff, int yoff, int zoff) {
int xx = this.x + xoff;
int yy = this.y + yoff;
int zz = this.z + zoff;
int idx = ((xx >> 4) - x_min) + (((zz >> 4) - z_min) * x_dim);
try {
return snaparray[idx].getBlockData(xx & 0xF, yy, zz & 0xF);
} catch (Exception x) {
return 0;
}
}
@Override
public Object getBlockTileEntityFieldAt(String fieldId, int xoff,
int yoff, int zoff) {
return null;
}
}
private class OurEndMapIterator extends OurMapIterator {
@@ -666,27 +729,15 @@ public class NewMapChunkCache implements MapChunkCache {
if(!init) {
use_spout = DynmapPlugin.plugin.hasSpout();
try {
unloadqueue = ChunkProviderServer.class.getField("unloadQueue");
Class cls = unloadqueue.getType();
String nm = cls.getName();
if (nm.equals("org.bukkit.craftbukkit.util.LongHashset")) {
queuecontainskey = unloadqueue.getType().getMethod("containsKey", new Class[] { int.class, int.class });
}
else {
unloadqueue = null;
}
} catch (NoSuchFieldException nsfx) {
unloadqueue = null;
} catch (NoSuchMethodException nsmx) {
unloadqueue = null;
}
init = true;
}
}
public void setChunks(BukkitWorld dw, List<DynmapChunk> chunks) {
this.dw = dw;
this.w = dw.getWorld();
if(this.w == null) {
this.chunks = new ArrayList<DynmapChunk>();
}
nsect = dw.worldheight >> 4;
this.chunks = chunks;
/* Compute range */
@@ -713,8 +764,10 @@ public class NewMapChunkCache implements MapChunkCache {
x_dim = x_max - x_min + 1;
}
snaparray = new ChunkSnapshot[x_dim * (z_max-z_min+1)];
isSectionNotEmpty = new boolean[x_dim * (z_max-z_min+1)][];
int snapcnt = x_dim * (z_max-z_min+1);
snaparray = new ChunkSnapshot[snapcnt];
snaptile = new DynIntHashMap[snapcnt];
isSectionNotEmpty = new boolean[snapcnt][];
}
private ChunkSnapshot checkSpoutData(Chunk c, ChunkSnapshot ss) {
@@ -729,16 +782,11 @@ public class NewMapChunkCache implements MapChunkCache {
}
public int loadChunks(int max_to_load) {
if(dw.isLoaded() == false)
return 0;
long t0 = System.nanoTime();
CraftWorld cw = (CraftWorld)w;
Object queue = null;
try {
if (unloadqueue != null) {
queue = unloadqueue.get(cw.getHandle().chunkProviderServer);
}
} catch (IllegalArgumentException iax) {
} catch (IllegalAccessException e) {
}
Object queue = helper.getUnloadQueue(helper.getNMSWorld(w));
int cnt = 0;
if(iterator == null)
iterator = chunks.listIterator();
@@ -752,7 +800,7 @@ public class NewMapChunkCache implements MapChunkCache {
if(visible_limits != null) {
vis = false;
for(VisibilityLimit limit : visible_limits) {
if((chunk.x >= limit.x0) && (chunk.x <= limit.x1) && (chunk.z >= limit.z0) && (chunk.z <= limit.z1)) {
if (limit.doIntersectChunk(chunk.x, chunk.z)) {
vis = true;
break;
}
@@ -760,15 +808,18 @@ public class NewMapChunkCache implements MapChunkCache {
}
if(vis && (hidden_limits != null)) {
for(VisibilityLimit limit : hidden_limits) {
if((chunk.x >= limit.x0) && (chunk.x <= limit.x1) && (chunk.z >= limit.z0) && (chunk.z <= limit.z1)) {
if (limit.doIntersectChunk(chunk.x, chunk.z)) {
vis = false;
break;
}
}
}
/* Check if cached chunk snapshot found */
ChunkSnapshot ss = DynmapPlugin.plugin.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
if(ss != null) {
ChunkSnapshot ss = null;
DynIntHashMap tileData = null;
SnapshotRec ssr = DynmapPlugin.plugin.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
if(ssr != null) {
ss = ssr.ss;
if(!vis) {
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
ss = STONE;
@@ -777,7 +828,10 @@ public class NewMapChunkCache implements MapChunkCache {
else
ss = EMPTY;
}
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
int idx = (chunk.x-x_min) + (chunk.z - z_min)*x_dim;
snaparray[idx] = ss;
snaptile[idx] = ssr.tileData;
continue;
}
chunks_attempted++;
@@ -785,12 +839,7 @@ public class NewMapChunkCache implements MapChunkCache {
boolean didload = false;
boolean isunloadpending = false;
if (queue != null) {
try {
isunloadpending = (Boolean)queuecontainskey.invoke(queue, chunk.x, chunk.z);
} catch (IllegalAccessException iax) {
} catch (IllegalArgumentException e) {
} catch (InvocationTargetException e) {
}
isunloadpending = helper.isInUnloadQueue(queue, chunk.x, chunk.z);
}
if (isunloadpending) { /* Workaround: can't be pending if not loaded */
wasLoaded = true;
@@ -809,11 +858,10 @@ public class NewMapChunkCache implements MapChunkCache {
}
}
boolean didgenerate = false;
/* If we didn't load, and we're supposed to generate, do it */
if((!didload) && do_generate && vis)
didgenerate = didload = w.loadChunk(chunk.x, chunk.z, true);
/* If it did load, make cache of it */
if(didload) {
tileData = new DynIntHashMap();
Chunk c = w.getChunkAt(chunk.x, chunk.z); /* Get the chunk */
/* Test if chunk isn't populated */
boolean populated = true;
@@ -842,30 +890,58 @@ public class NewMapChunkCache implements MapChunkCache {
if(use_spout) {
ss = checkSpoutData(c, ss);
}
/* 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) {
DynmapPlugin.plugin.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ss, blockdata, biome, biomeraw, highesty);
ssr = new SnapshotRec();
ssr.ss = ss;
ssr.tileData = tileData;
DynmapPlugin.plugin.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty);
}
}
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
snaptile[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = tileData;
/* If wasn't loaded before, we need to do unload */
if (!wasLoaded) {
chunks_read++;
/* It looks like bukkit "leaks" entities - they don't get removed from the world-level table
* when chunks are unloaded but not saved - removing them seems to do the trick */
if(!(didgenerate && do_save)) {
CraftChunk cc = (CraftChunk)c;
cc.getHandle().removeEntities();
}
/* 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 */
w.unloadChunk(chunk.x, chunk.z, didgenerate && do_save, false);
helper.unloadChunkNoSave(w, c, chunk.x, chunk.z);
}
else if (isunloadpending) { /* Else, if loaded and unload is pending */
w.unloadChunkRequest(chunk.x, chunk.z); /* Request new unload */
@@ -893,6 +969,11 @@ public class NewMapChunkCache implements MapChunkCache {
* Test if done loading
*/
public boolean isDoneLoading() {
if(dw.isLoaded() == false) {
isempty = true;
unloadChunks();
return true;
}
if(iterator != null)
return !iterator.hasNext();
return false;
@@ -914,45 +995,6 @@ public class NewMapChunkCache implements MapChunkCache {
snaparray = null;
}
}
/**
* Get block ID at coordinates
*/
public int getBlockTypeID(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockTypeId(x & 0xF, y, z & 0xF);
}
/**
* Get block data at coordiates
*/
public byte getBlockData(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return (byte)ss.getBlockData(x & 0xF, y, z & 0xF);
}
/* Get sky light level
*/
public int getBlockSkyLight(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockSkyLight(x & 0xF, y, z & 0xF);
}
/* Get emitted light level
*/
public int getBlockEmittedLight(int x, int y, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockEmittedLight(x & 0xF, y, z & 0xF);
}
public BiomeMap getBiome(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
Biome b = ss.getBiome(x & 0xF, z & 0xF);
return (b != null)?biome_to_bmap[b.ordinal()]:null;
}
public double getRawBiomeTemperature(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getRawBiomeTemperature(x & 0xF, z & 0xF);
}
public double getRawBiomeRainfall(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getRawBiomeRainfall(x & 0xF, z & 0xF);
}
private void initSectionData(int idx) {
isSectionNotEmpty[idx] = new boolean[nsect + 1];
if(snaparray[idx] != EMPTY) {
@@ -985,39 +1027,15 @@ public class NewMapChunkCache implements MapChunkCache {
public void setHiddenFillStyle(HiddenChunkStyle style) {
this.hidestyle = style;
}
/**
* Set autogenerate - must be done after at least one visible range has been set
*/
public void setAutoGenerateVisbileRanges(DynmapWorld.AutoGenerateOption generateopt) {
if((generateopt != DynmapWorld.AutoGenerateOption.NONE) && ((visible_limits == null) || (visible_limits.size() == 0))) {
Log.severe("Cannot setAutoGenerateVisibleRanges() without visible ranges defined");
return;
}
this.do_generate = (generateopt != DynmapWorld.AutoGenerateOption.NONE);
this.do_save = (generateopt == DynmapWorld.AutoGenerateOption.PERMANENT);
}
/**
* Add visible area limit - can be called more than once
* Needs to be set before chunks are loaded
* Coordinates are block coordinates
*/
public void setVisibleRange(VisibilityLimit lim) {
VisibilityLimit limit = new VisibilityLimit();
if(lim.x0 > lim.x1) {
limit.x0 = (lim.x1 >> 4); limit.x1 = ((lim.x0+15) >> 4);
}
else {
limit.x0 = (lim.x0 >> 4); limit.x1 = ((lim.x1+15) >> 4);
}
if(lim.z0 > lim.z1) {
limit.z0 = (lim.z1 >> 4); limit.z1 = ((lim.z0+15) >> 4);
}
else {
limit.z0 = (lim.z0 >> 4); limit.z1 = ((lim.z1+15) >> 4);
}
if(visible_limits == null)
visible_limits = new ArrayList<VisibilityLimit>();
visible_limits.add(limit);
visible_limits.add(lim);
}
/**
* Add hidden area limit - can be called more than once
@@ -1025,22 +1043,9 @@ public class NewMapChunkCache implements MapChunkCache {
* Coordinates are block coordinates
*/
public void setHiddenRange(VisibilityLimit lim) {
VisibilityLimit limit = new VisibilityLimit();
if(lim.x0 > lim.x1) {
limit.x0 = (lim.x1 >> 4); limit.x1 = ((lim.x0+15) >> 4);
}
else {
limit.x0 = (lim.x0 >> 4); limit.x1 = ((lim.x1+15) >> 4);
}
if(lim.z0 > lim.z1) {
limit.z0 = (lim.z1 >> 4); limit.z1 = ((lim.z0+15) >> 4);
}
else {
limit.z0 = (lim.z0 >> 4); limit.z1 = ((lim.z1+15) >> 4);
}
if(hidden_limits == null)
hidden_limits = new ArrayList<VisibilityLimit>();
hidden_limits.add(limit);
hidden_limits.add(lim);
}
@Override
public boolean setChunkDataTypes(boolean blockdata, boolean biome, boolean highestblocky, boolean rawbiome) {
@@ -8,15 +8,21 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.bukkit.ChunkSnapshot;
import org.dynmap.utils.DynIntHashMap;
public class SnapshotCache {
public static class SnapshotRec {
public ChunkSnapshot ss;
public DynIntHashMap tileData;
};
private CacheHashMap snapcache;
private ReferenceQueue<ChunkSnapshot> refqueue;
private ReferenceQueue<SnapshotRec> refqueue;
private long cache_attempts;
private long cache_success;
private static class CacheRec {
WeakReference<ChunkSnapshot> ref;
WeakReference<SnapshotRec> ref;
boolean hasbiome;
boolean hasrawbiome;
boolean hasblockdata;
@@ -26,12 +32,12 @@ public class SnapshotCache {
@SuppressWarnings("serial")
public class CacheHashMap extends LinkedHashMap<String, CacheRec> {
private int limit;
private IdentityHashMap<WeakReference<ChunkSnapshot>, String> reverselookup;
private IdentityHashMap<WeakReference<SnapshotRec>, String> reverselookup;
public CacheHashMap(int lim) {
super(16, (float)0.75, true);
limit = lim;
reverselookup = new IdentityHashMap<WeakReference<ChunkSnapshot>, String>();
reverselookup = new IdentityHashMap<WeakReference<SnapshotRec>, String>();
}
protected boolean removeEldestEntry(Map.Entry<String, CacheRec> last) {
boolean remove = (size() >= limit);
@@ -47,7 +53,7 @@ public class SnapshotCache {
*/
public SnapshotCache(int max_size) {
snapcache = new CacheHashMap(max_size);
refqueue = new ReferenceQueue<ChunkSnapshot>();
refqueue = new ReferenceQueue<SnapshotRec>();
}
private String getKey(String w, int cx, int cz) {
return w + ":" + cx + ":" + cz;
@@ -83,11 +89,11 @@ public class SnapshotCache {
/**
* 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) {
String key = getKey(w, chunkx, chunkz);
processRefQueue();
ChunkSnapshot ss = null;
SnapshotRec ss = null;
CacheRec rec = snapcache.get(key);
if(rec != null) {
ss = rec.ref.get();
@@ -112,7 +118,7 @@ public class SnapshotCache {
/**
* 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) {
String key = getKey(w, chunkx, chunkz);
processRefQueue();
@@ -121,7 +127,7 @@ public class SnapshotCache {
rec.hasbiome = biome;
rec.hasrawbiome = biomeraw;
rec.hashighesty = highesty;
rec.ref = new WeakReference<ChunkSnapshot>(ss, refqueue);
rec.ref = new WeakReference<SnapshotRec>(ss, refqueue);
CacheRec prevrec = snapcache.put(key, rec);
if(prevrec != null) {
snapcache.reverselookup.remove(prevrec.ref);
@@ -132,7 +138,7 @@ public class SnapshotCache {
* Process reference queue
*/
private void processRefQueue() {
Reference<? extends ChunkSnapshot> ref;
Reference<? extends SnapshotRec> ref;
while((ref = refqueue.poll()) != null) {
String k = snapcache.reverselookup.remove(ref);
if(k != null) {
@@ -9,6 +9,7 @@ import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import javax.imageio.ImageIO;
@@ -33,7 +34,29 @@ import org.getspout.spoutapi.material.MaterialData;
public class SpoutPluginBlocks {
private Field textXPosField; /* float[][] textXPos */
private Field textYPosField; /* float[][] textYPos */
private HashSet<String> plugins_pending = new HashSet<String>();
public SpoutPluginBlocks(Plugin plugin) {
/* First, see if any spout plugins that need to be enabled */
for(Plugin p : plugin.getServer().getPluginManager().getPlugins()) {
List<String> dep = p.getDescription().getDepend();
if((dep != null) && (dep.contains("Spout"))) {
Log.info("Found Spout plugin: " + p.getName());
if(p.isEnabled() == false) {
plugins_pending.add(p.getName());
}
}
}
}
public boolean isReady() {
return plugins_pending.isEmpty();
}
public void markPluginEnabled(Plugin p) {
plugins_pending.remove(p.getName());
}
private boolean initSpoutAccess() {
boolean success = false;
try {
@@ -73,17 +96,6 @@ public class SpoutPluginBlocks {
/* Process spout blocks - return true if something changed */
public boolean processSpoutBlocks(DynmapPlugin plugin, DynmapCore core) {
/* First, see if any spout plugins that need to be enabled */
for(Plugin p : plugin.getServer().getPluginManager().getPlugins()) {
List<String> dep = p.getDescription().getDepend();
if((dep != null) && (dep.contains("Spout"))) {
Log.info("Found Spout plugin: " + p.getName());
if(p.isEnabled() == false) {
plugin.getPluginLoader().enablePlugin(p);
}
}
}
File datadir = core.getDataFolder();
if(textYPosField == null) {
if(initSpoutAccess() == false)
@@ -103,7 +115,12 @@ public class SpoutPluginBlocks {
/* Loop through blocks - try to freshen files, if needed */
for(CustomBlock b : cb) {
BlockDesign bd = b.getBlockDesign();
String blkid = bd.getTexturePlugin() + "." + fixIDString(b.getName());
if(bd == null) continue;
String txtplug = bd.getTexturePlugin();
if(txtplug == null) continue;
String blkname = b.getName();
if(blkname == null) continue;
String blkid = txtplug + "." + fixIDString(blkname);
/* If not GenericCubiodBlockDesign, we don't handle it */
if((bd instanceof GenericCuboidBlockDesign) == false) {
Log.info("Block " + blkid + " not suppored - only cubiod blocks");
+31 -33
View File
@@ -42,11 +42,13 @@ components:
hideifsneaking: false
# If true, player positions/status is protected (login with ID with dynmap.playermarkers.seeall permission required for info other than self)
protected-player-info: false
# If true, hide players with invisibility potion effects active
hide-if-invisiblity-potion: true
#- class: org.dynmap.JsonFileClientUpdateComponent
# writeinterval: 1
# sendhealth: true
# sendposition: true
# allowwebchat: false
# allowwebchat: true
# webchat-interval: 5
# hidewebchatip: false
# includehiddenplayers: false
@@ -62,6 +64,7 @@ components:
# webchat-permissions: false
# # Limit length of single chat messages
# chatlengthlimit: 256
# hide-if-invisiblity-potion: true
- class: org.dynmap.SimpleWebChatComponent
allowchat: true
@@ -131,7 +134,7 @@ components:
- class: org.dynmap.ClientComponent
type: timeofdayclock
showdigitalclock: true
#showweather: true
showweather: true
# Mouse pointer world coordinate display
- class: org.dynmap.ClientComponent
type: coord
@@ -183,6 +186,14 @@ saverestorepending: true
# Zoom-out tile update period - how often to scan for and process tile updates into zoom-out tiles (in seconds)
zoomoutperiod: 30
# Control whether zoom out tiles are validated on startup (can be needed if zoomout processing is interrupted, but can be expensive on large maps)
initial-zoomout-validate: true
# Default delay on processing of updated tiles, in seconds. This can reduce potentially expensive re-rendering
# of frequently updated tiles (such as due to machines, pistons, quarries or other automation). Values can
# also be set on individual worlds and individual maps.
tileupdatedelay: 30
# Tile hashing is used to minimize tile file updates when no changes have occurred - set to false to disable
enabletilehash: true
@@ -201,8 +212,10 @@ image-format: png
# use-generated-textures: if true, use generated textures (same as client); false is static water/lava textures
# correct-water-lighting: if true, use corrected water lighting (same as client); false is legacy water (darker)
# transparent-leaves: if true, leaves are transparent (lighting-wise): false is needed for some Spout versions that break lighting on leaf blocks
use-generated-textures: true
correct-water-lighting: true
transparent-leaves: true
# Control loading of player faces (if set to false, skins are never fetched)
#fetchskins: false
@@ -218,37 +231,6 @@ skin-url: "http://s3.amazonaws.com/MinecraftSkins/%player%.png"
# 'newnorth' is used to rotate maps and rose (requires fullrender of any HDMap map - same as 'newrose' for FlatMap or KzedMap)
compass-mode: newnorth
### Mod block support ###
# Enable Industrial Craft 2 block rendering support (core, Advanced Machines, Charging Bench, Power Converters, Compact Solars, Nuclear Control)
#ic2-support: true
#ic2-advancesmachines-support: true
#ic2-chargingbench-support: true
#ic2-powerconverters-support: true
#ic2-compactsolars-support: true
#ic2-nuclearcontrol-support: true
# Enable BuildCraft block rendering support
#buildcraft-support: true
# Enable RedPower2 block rendering support
#redpower2-support: true
# Enable NetherOres block rendering support
#netherores-support: true
# Enable RailCraft block rendering support
#railcraft-support: true
# Enable Kaevator's Superslopes block rendering support
#superslopes-support: true
# Enabled ComputerCraft block rendering support
#computercraft-support: true
# Enabled LC Trees++ block rendering support
#lctrees-support: true
# Enable Forestry block rending support
#forestry-support: true
# Enable IronCheck block rendering support
#ironchest-support: true
# Enable TubeCraft block rendering support
#tubecraft-support: true
# Enable Ender Storage block rendering support
#enderstorage-support: true
render-triggers:
#- playermove
#- playerjoin
@@ -330,6 +312,11 @@ grayplayerswhenhidden: true
# Access-Control-Allow-Origin: "my-domain.com"
# X-Custom-Header-Of-Mine: "MyHeaderValue"
# Trusted proxies for web server - which proxy addresses are trusted to supply valid X-Forwarded-For fields
trusted-proxies:
- "127.0.0.1"
- "0:0:0:0:0:0:0:1"
joinmessage: "%playername% joined"
quitmessage: "%playername% quit"
spammessage: "You may only chat once every %interval% seconds."
@@ -353,6 +340,9 @@ defaultmap: flat
# If true, make persistent record of IP addresses used by player logins, to support web IP to player matching
persist-ids-by-ip: true
# If true, map text to cyrillic
cyrillic-support: false
# Messages to customize
msg:
maptypes: "Map Types"
@@ -386,6 +376,14 @@ spout:
# to clean cached textures and force reload on next startup)
use-existing-textures: true
# Customization commands - allows scripts to be run before/after certain events
custom-commands:
image-updates:
# Command run just before any image file is written or updated: run with single parameter with fully qualified file name
preupdatecommand: ""
# Command run just after any image file is written or updated: run with single parameter with fully qualified file name
postupdatecommand: ""
# Set to true to enable verbose startup messages - can help with debugging map configuration problems
# Set to false for a much quieter startup log
verbose: false