Compare commits

...

42 Commits

Author SHA1 Message Date
Mike Primm b13c26c0d6 Switch to submodules 2014-10-12 17:32:38 -05:00
Mike Primm 3fd4ac7373 Update to fix Glowstone support 2014-09-13 21:17:37 -05:00
Mike Primm ac0f756fae More Glowstone fixes 2014-09-06 22:25:56 -05:00
Mike Primm 551f35f3f9 Add initial support for Glowstone server 2014-09-06 19:19:20 -05:00
Mike Primm ec9ebf2dbb Add well known 1.7 biomes only when appropriate version 2014-08-22 23:48:12 -05:00
Mike Primm 3702918a6f Add well known 1.7.x biomes only when version is appropriate 2014-08-22 23:15:57 -05:00
Mike Primm 8085221087 Add prefix setting for MySQL table names 2014-08-22 01:50:47 -05:00
mikeprimm 7de967f1c2 Merge pull request #1603 from KovuTheHusky/roundcoords
Add option to round coordinates to nearest integer
2014-08-20 18:10:10 -05:00
mikeprimm f6e127b7f0 Merge pull request #1601 from KovuTheHusky/master
Fix javadoc errors for building with Java SE 8
2014-08-20 18:08:20 -05:00
Mike Primm 22d1923ad5 Add support for 1.7.10 2014-07-09 22:20:33 -05:00
Mike Primm d8d3061696 Add config defaults for MySQL map storage 2014-06-08 21:59:32 -05:00
Kevin Breslin 14da080d52 Add option to round coordinates to nearest integer 2014-05-27 01:34:11 -04:00
Kevin Breslin 10ce166b54 Fix javadoc errors for building with Java SE 8 2014-05-26 22:37:53 -04:00
Mike Primm cb9f964348 Update default suffix 2014-05-10 14:36:50 -05:00
Mike Primm 9850a03945 More comments on storage config 2014-05-10 13:47:14 -05:00
Mike Primm 8abfae3d79 Add storage/type settings to control file tree vs sqlite storage 2014-05-10 00:42:02 -05:00
Mike Primm f486ad75f1 Bump to 2.0.0-SNAPSHOT 2014-05-05 00:30:03 -05:00
Mike Primm 54b3fb429c Switch to SNAPSHOT 2014-04-20 11:47:57 -05:00
Mike Primm 86547f8d78 Bump to 1.9.5 2014-04-20 11:09:49 -05:00
Mike Primm 8ec80937e3 Add plugin versions for sources and javadoc plugins 2014-04-17 08:59:38 -05:00
Mike Primm 0e5e602a90 Add plugin versions for javadocs and sources 2014-04-16 23:02:35 -05:00
Mike Primm 3239d539c0 Add sources and javadoc generation to POM 2014-04-16 22:28:29 -05:00
Mike Primm 05bd2544fd Switch to groupID us.dynmap (owned domain) - sonatype central repo prep 2014-04-16 19:46:47 -05:00
Mike Primm 252da2a5c6 Add exportpath, default-sign-set settings 2014-03-12 00:10:17 -05:00
Mike Primm 5d83ebf8aa Add sign change API to help with marker sign support on MCPC+ 2014-03-11 23:58:01 -05:00
Mike Primm 026cc72233 Bump to 1.9.4 2014-03-08 02:31:06 -06:00
Mike Primm 0d2cceea4b Add /dynmapexp command (for OBJ exporter support) 2014-02-24 00:27:05 -06:00
Mike Primm a1dfae7f79 Bump to 1.9.2 2014-02-06 08:37:24 -06:00
Mike Primm d6eb822b26 Rework chunk loading timing stats - simpler, more useful 2014-02-04 07:05:24 -06:00
Mike Primm d4f161ca99 Remove unneeded synchronized() 2014-02-03 22:29:00 -06:00
Mike Primm 376ec447ed Revert "Add more metrics to chunk loading (for testing)"
This reverts commit 926d2a3dbc.
2014-02-03 22:27:04 -06:00
Mike Primm 926d2a3dbc Add more metrics to chunk loading (for testing) 2014-02-03 21:36:43 -06:00
Mike Primm eeffa4f98d Add stubs for block unique ID support 2014-02-01 01:16:15 -06:00
Mike Primm 8350727a73 Fix inhabitedTime field lookup 2014-01-17 23:05:54 -06:00
Mike Primm 3b79890166 Add getInhabitedTime() 2014-01-17 17:40:39 -06:00
Mike Primm 17174c177c Handle textures loading from other mods 2014-01-11 23:41:23 -06:00
Mike Primm 07e7d53a93 Add debug option for dumping IDs of blocks with no render data 2014-01-06 21:41:12 -06:00
Mike Primm 76863aeb71 Add use-brightness-table setting, and support for world-specific brightness tables 2014-01-04 21:16:29 -06:00
Mike Primm f7d2dac826 Add permissions and help for /dynmap quiet command 2013-12-30 01:46:29 -06:00
Mike Primm 3cb7ba342c Add setting for periodic save of pending jobs 2013-12-30 01:45:17 -06:00
Mike Primm d2ab466dc0 Update server interface for mod-supplied texture/model files 2013-12-28 23:56:22 -06:00
Mike Primm d03ed7a461 Bump to 1.9.2 2013-12-24 10:52:17 -06:00
29 changed files with 1710 additions and 827 deletions
+56
View File
@@ -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>
@@ -22,48 +22,53 @@ 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;
/**
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
*/
public class NewMapChunkCache implements MapChunkCache {
public abstract class BaseMapChunkCache extends MapChunkCache {
private static boolean init = false;
private static boolean use_spout = false;
private World w;
private DynmapWorld dw;
protected World w;
protected DynmapWorld dw;
private int nsect;
private List<DynmapChunk> chunks;
private ListIterator<DynmapChunk> iterator;
private int x_min, x_max, z_min, z_max;
private int x_dim;
private boolean biome, biomeraw, highesty, blockdata;
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
private List<VisibilityLimit> visible_limits = null;
private List<VisibilityLimit> hidden_limits = null;
private boolean isempty = true;
protected List<DynmapChunk> chunks;
protected ListIterator<DynmapChunk> iterator;
protected int x_min;
private int x_max;
protected int z_min;
private int z_max;
protected int x_dim;
protected boolean biome;
protected boolean biomeraw;
protected boolean highesty;
protected boolean blockdata;
protected HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
protected List<VisibilityLimit> visible_limits = null;
protected List<VisibilityLimit> hidden_limits = null;
protected boolean isempty = true;
private int snapcnt;
private ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
private DynIntHashMap[] snaptile;
protected ChunkSnapshot[] snaparray; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
protected DynIntHashMap[] snaptile;
private byte[][] sameneighborbiomecnt;
private BiomeMap[][] biomemap;
private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */
protected long[] inhabitedTicks; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
private int chunks_read; /* Number of chunks actually loaded */
private int chunks_attempted; /* Number of chunks attempted to load */
private long total_loadtime; /* Total time loading chunks, in nanoseconds */
private long exceptions;
private static BukkitVersionHelper helper = BukkitVersionHelper.getHelper();
protected 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) {
protected static final int getIndexInChunk(int cx, int cy, int cz) {
return (cy << 8) | (cz << 4) | cx;
}
@@ -166,9 +171,6 @@ public class NewMapChunkCache implements MapChunkCache {
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) {
@@ -210,7 +212,6 @@ public class NewMapChunkCache implements MapChunkCache {
try {
return biomemap[x - x_base][z - z_base];
} catch (Exception ex) {
exceptions++;
return BiomeMap.NULL;
}
}
@@ -240,7 +241,6 @@ public class NewMapChunkCache implements MapChunkCache {
mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9);
}
} catch (Exception x) {
exceptions++;
mult = 0xFFFFFF;
}
return mult;
@@ -271,7 +271,6 @@ public class NewMapChunkCache implements MapChunkCache {
mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9);
}
} catch (Exception x) {
exceptions++;
mult = 0xFFFFFF;
}
return mult;
@@ -313,7 +312,6 @@ public class NewMapChunkCache implements MapChunkCache {
mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9);
}
} catch (Exception x) {
exceptions++;
mult = 0xFFFFFF;
}
return mult;
@@ -341,7 +339,6 @@ public class NewMapChunkCache implements MapChunkCache {
}
return ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9);
} catch (Exception x) {
exceptions++;
return 0xFFFFFF;
}
}
@@ -371,7 +368,6 @@ public class NewMapChunkCache implements MapChunkCache {
mult = ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9);
}
} catch (Exception x) {
exceptions++;
mult = 0xFFFFFF;
}
return mult;
@@ -593,6 +589,14 @@ public class NewMapChunkCache implements MapChunkCache {
int yoff, int zoff) {
return null;
}
@Override
public long getInhabitedTicks() {
try {
return inhabitedTicks[chunkindex];
} catch (Exception x) {
return 0;
}
}
}
private class OurEndMapIterator extends OurMapIterator {
@@ -680,68 +684,16 @@ public class NewMapChunkCache implements MapChunkCache {
return (sy < 4);
}
}
private static class SpoutChunkSnapshot implements ChunkSnapshot {
private ChunkSnapshot chunk;
private short[] customids;
private final int shiftx;
private final int shiftz;
SpoutChunkSnapshot(ChunkSnapshot chunk, short[] customids, int height) {
this.chunk = chunk;
this.customids = customids.clone();
int sx = 11;
int sz = 7; /* 128 high values */
while(height > 128) {
sx++;
sz++;
height = (height >> 1);
}
shiftx = sx;
shiftz = sz;
}
/* Need these for interface, but not used */
public final int getX() { return chunk.getX(); }
public final int getZ() { return chunk.getZ(); }
public final String getWorldName() { return chunk.getWorldName(); }
public final Biome getBiome(int x, int z) { return chunk.getBiome(x, z); }
public final double getRawBiomeTemperature(int x, int z) { return chunk.getRawBiomeTemperature(x, z); }
public final double getRawBiomeRainfall(int x, int z) { return chunk.getRawBiomeRainfall(x, z); }
public final long getCaptureFullTime() { return chunk.getCaptureFullTime(); }
public final int getBlockTypeId(int x, int y, int z) {
int id = customids[(x << shiftx) | (z << shiftz) | y];
if(id != 0) return id;
return chunk.getBlockTypeId(x, y, z);
}
public final int getBlockData(int x, int y, int z) {
return chunk.getBlockData(x, y, z);
}
public final int getBlockSkyLight(int x, int y, int z) {
return chunk.getBlockSkyLight(x, y, z);
}
public final int getBlockEmittedLight(int x, int y, int z) {
return chunk.getBlockEmittedLight(x, y, z);
}
public final int getHighestBlockYAt(int x, int z) {
return chunk.getHighestBlockYAt(x, z);
}
public boolean isSectionEmpty(int sy) {
return chunk.isSectionEmpty(sy);
}
}
private static final EmptyChunk EMPTY = new EmptyChunk();
private static final PlainChunk STONE = new PlainChunk(1);
private static final PlainChunk OCEAN = new PlainChunk(9);
protected static final EmptyChunk EMPTY = new EmptyChunk();
protected static final PlainChunk STONE = new PlainChunk(1);
protected static final PlainChunk OCEAN = new PlainChunk(9);
/**
* Construct empty cache
*/
public NewMapChunkCache() {
public BaseMapChunkCache() {
if(!init) {
use_spout = DynmapPlugin.plugin.hasSpout();
init = true;
}
}
@@ -779,199 +731,25 @@ public class NewMapChunkCache implements MapChunkCache {
snapcnt = x_dim * (z_max-z_min+1);
snaparray = new ChunkSnapshot[snapcnt];
inhabitedTicks = new long[snapcnt];
snaptile = new DynIntHashMap[snapcnt];
isSectionNotEmpty = new boolean[snapcnt][];
}
private ChunkSnapshot checkSpoutData(Chunk c, ChunkSnapshot ss) {
if(c instanceof SpoutChunk) {
SpoutChunk sc = (SpoutChunk)c;
short[] custids = sc.getCustomBlockIds();
if(custids != null) {
return new SpoutChunkSnapshot(ss, custids, c.getWorld().getMaxHeight());
}
}
return ss;
}
public int loadChunks(int max_to_load) {
if(dw.isLoaded() == false)
return 0;
long t0 = System.nanoTime();
Object queue = helper.getUnloadQueue(helper.getNMSWorld(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()) {
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;
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;
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;
continue;
}
chunks_attempted++;
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 */
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);
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) {
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++;
/* 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);
}
else if (isunloadpending) { /* Else, if loaded and unload is pending */
w.unloadChunkRequest(chunk.x, chunk.z); /* Request new unload */
}
}
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;
}
}
total_loadtime += System.nanoTime() - t0;
return cnt;
}
/**
* Test if done loading
* Loading call executed from main server thread - must
* @param max_to_load - maximum number to load at once
* @return number loaded
*/
public boolean isDoneLoading() {
if(dw.isLoaded() == false) {
isempty = true;
unloadChunks();
return true;
}
if(iterator != null)
return !iterator.hasNext();
return false;
}
public abstract int loadChunks(int max_to_load);
/**
* Test if done loading (no more loadChunks calls needed)
*/
public abstract boolean isDoneLoading();
/**
* Read call executed from off of main thread (if off thread loading is supported)
*/
public abstract int readChunks();
/**
* Test if all empty blocks
*/
@@ -979,7 +757,7 @@ public class NewMapChunkCache implements MapChunkCache {
return isempty;
}
/**
* Unload chunks
* Unload chunks (cleanup - if needed)
*/
public void unloadChunks() {
if(snaparray != null) {
@@ -987,8 +765,10 @@ public class NewMapChunkCache implements MapChunkCache {
snaparray[i] = null;
}
snaparray = null;
inhabitedTicks = null;
}
}
private void initSectionData(int idx) {
isSectionNotEmpty[idx] = new boolean[nsect + 1];
if(snaparray[idx] != EMPTY) {
@@ -1053,22 +833,6 @@ public class NewMapChunkCache implements MapChunkCache {
public DynmapWorld getWorld() {
return dw;
}
@Override
public int getChunksLoaded() {
return chunks_read;
}
@Override
public int getChunkLoadsAttempted() {
return chunks_attempted;
}
@Override
public long getTotalRuntimeNanos() {
return total_loadtime;
}
@Override
public long getExceptionCount() {
return exceptions;
}
static {
Biome[] b = Biome.values();
@@ -5,11 +5,13 @@ 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;
/**
@@ -21,6 +23,7 @@ public abstract class BukkitVersionHelper {
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. *");
@@ -35,6 +38,10 @@ public abstract class BukkitVersionHelper {
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();
}
@@ -64,14 +71,10 @@ public abstract class BukkitVersionHelper {
* 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);
public abstract Object getUnloadQueue(World world);
/**
* For testing unload queue for presence of givne chunk
*/
@@ -80,14 +83,14 @@ public abstract class BukkitVersionHelper {
* 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 inhabited ticks count from chunk
*/
public abstract long getInhabitedTicks(Chunk c);
/**
* Get tile entities map from chunk
*/
@@ -128,4 +131,12 @@ public abstract class BukkitVersionHelper {
* 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);
}
@@ -47,7 +47,7 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric {
nmsmaterial = getNMSClass("net.minecraft.server.Material");
blockbyid = getFieldNoFail(nmsblock, new String[] { "byId" }, nmsblockarray);
if (blockbyid == null) {
blockbyidfunc = getMethod(nmsblock, new String[] { "e" }, new Class[] { int.class });
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);
@@ -81,7 +81,11 @@ public class BukkitVersionHelperCB extends BukkitVersionHelperGeneric {
/** 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_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");
@@ -3,13 +3,17 @@ 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;
/**
@@ -51,6 +55,7 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
protected Class<?> nmschunk;
protected Method nmsc_removeentities;
protected Field nmsc_tileentities;
protected Field nmsc_inhabitedticks;
/** nbt classes */
protected Class<?> nbttagcompound;
protected Class<?> nbttagbyte;
@@ -78,6 +83,10 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
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;
@@ -98,6 +107,12 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
/* 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();
@@ -254,13 +269,13 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
}
/* Get net.minecraft.server.world for given world */
public Object getNMSWorld(World w) {
protected 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
public Object getUnloadQueue(World world) {
Object cps = getFieldValue(getNMSWorld(world), nmsw_chunkproviderserver, null); // Get chunkproviderserver
if(cps != null) {
return getFieldValue(cps, cps_unloadqueue, null);
}
@@ -278,12 +293,12 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
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;
}
// 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);
@@ -291,6 +306,21 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
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);
@@ -369,4 +399,31 @@ public abstract class BukkitVersionHelperGeneric extends BukkitVersionHelper {
}
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();
}
}
@@ -36,6 +36,20 @@ public class BukkitWorld extends DynmapWorld {
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
@@ -154,7 +168,7 @@ public class BukkitWorld extends DynmapWorld {
@Override
public MapChunkCache getChunkCache(List<DynmapChunk> chunks) {
if(isLoaded()) {
NewMapChunkCache c = new NewMapChunkCache();
LegacyMapChunkCache c = new LegacyMapChunkCache();
c.setChunks(this, chunks);
return c;
}
@@ -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;
}
}
@@ -14,9 +14,11 @@ import org.dynmap.utils.DynIntHashMap;
public class SnapshotCache {
public static class SnapshotRec {
public ChunkSnapshot ss;
public long inhabitedTicks;
public DynIntHashMap tileData;
};
public static SnapshotCache cache;
private CacheHashMap snapcache;
private ReferenceQueue<SnapshotRec> refqueue;
private long cache_attempts;
@@ -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
+53
View File
@@ -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;
}
}
+177
View File
@@ -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>
@@ -100,12 +100,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
private DynmapCore core;
private PermissionProvider permissions;
private String version;
public SnapshotCache sscache;
private boolean has_spout = false;
public PlayerList playerList;
private MapManager mapManager;
public static DynmapPlugin plugin;
public SpoutPluginBlocks spb;
public PluginManager pm;
private Metrics metrics;
private BukkitEnableCoreCallback enabCoreCB = new BukkitEnableCoreCallback();
@@ -167,26 +164,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
private class BukkitEnableCoreCallback extends DynmapCore.EnableCoreCallbacks {
@Override
public void configurationLoaded() {
/* Check for Spout */
if(detectSpout()) {
if(core.configuration.getBoolean("spout/enabled", true)) {
has_spout = true;
Log.info("Detected Spout");
if(spb == null) {
spb = new SpoutPluginBlocks(DynmapPlugin.this);
}
modsused.add("SpoutPlugin");
}
else {
Log.info("Detected Spout - Support Disabled");
}
}
if(!has_spout) { /* If not, clean up old spout texture, if needed */
File st = new File(core.getDataFolder(), "renderdata/spout-texture.txt");
if(st.exists())
st.delete();
}
File st = new File(core.getDataFolder(), "renderdata/spout-texture.txt");
if(st.exists())
st.delete();
}
}
@@ -216,10 +196,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
/**
* Server access abstraction class
*/
public class BukkitServer implements DynmapServerInterface {
/* Chunk load handling */
private Object loadlock = new Object();
public class BukkitServer extends DynmapServerInterface {
@Override
public int getBlockIDAt(String wname, int x, int y, int z) {
World w = getServer().getWorld(wname);
@@ -235,7 +212,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
@Override
public DynmapPlayer[] getOnlinePlayers() {
Player[] players = getServer().getOnlinePlayers();
Player[] players = helper.getOnlinePlayers();
DynmapPlayer[] dplay = new DynmapPlayer[players.length];
for(int i = 0; i < players.length; i++)
dplay[i] = new BukkitPlayer(players[i]);
@@ -344,7 +321,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
break;
case SIGN_CHANGE:
pm.registerEvents(new Listener() {
@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true)
@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
public void onSignChange(SignChangeEvent evt) {
Block b = evt.getBlock();
Location l = b.getLocation();
@@ -384,11 +361,11 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
@Override
public double getCacheHitRate() {
return sscache.getHitRate();
return SnapshotCache.cache.getHitRate();
}
@Override
public void resetCacheStats() {
sscache.resetStats();
SnapshotCache.cache.resetStats();
}
@Override
public DynmapWorld getWorldByName(String wname) {
@@ -430,7 +407,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
@Override
public MapChunkCache createMapChunkCache(DynmapWorld w, List<DynmapChunk> chunks,
boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) {
MapChunkCache c = w.getChunkCache(chunks);
BaseMapChunkCache c = (BaseMapChunkCache) w.getChunkCache(chunks);
if(c == null) { /* Can fail if not currently loaded */
return null;
}
@@ -461,20 +438,18 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public Boolean call() throws Exception {
boolean exhausted = true;
synchronized(loadlock) {
if (prev_tick != cur_tick) {
prev_tick = cur_tick;
cur_tick_starttime = System.nanoTime();
}
if(chunks_in_cur_tick > 0) {
boolean done = false;
while (!done) {
int cnt = chunks_in_cur_tick;
if (cnt > 5) cnt = 5;
chunks_in_cur_tick -= cc.loadChunks(cnt);
exhausted = (chunks_in_cur_tick == 0) || ((System.nanoTime() - cur_tick_starttime) > perTickLimit);
done = exhausted || cc.isDoneLoading();
}
if (prev_tick != cur_tick) {
prev_tick = cur_tick;
cur_tick_starttime = System.nanoTime();
}
if(chunks_in_cur_tick > 0) {
boolean done = false;
while (!done) {
int cnt = chunks_in_cur_tick;
if (cnt > 5) cnt = 5;
chunks_in_cur_tick -= cc.loadChunks(cnt);
exhausted = (chunks_in_cur_tick == 0) || ((System.nanoTime() - cur_tick_starttime) > perTickLimit);
done = exhausted || cc.isDoneLoading();
}
}
return exhausted;
@@ -499,6 +474,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
try { Thread.sleep(25); } catch (InterruptedException ix) {}
}
}
/* Finish reading chunks in requesting thread z*/
c.readChunks();
/* If cancelled due to world unload return nothing */
if(w.isLoaded() == false)
return null;
@@ -510,7 +487,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
@Override
public int getCurrentPlayers() {
return getServer().getOnlinePlayers().length;
return helper.getOnlinePlayers().length;
}
@Override
public boolean isModLoaded(String name) {
@@ -558,9 +535,17 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public String getServerIP() {
return Bukkit.getServer().getIp();
}
@Override
public File getModContainerFile(String mod) {
return null;
public Map<Integer, String> getBlockIDMap() {
String[] bsn = helper.getBlockShortNames();
HashMap<Integer, String> map = new HashMap<Integer, String>();
for (int i = 0; i < bsn.length; i++) {
if (bsn[i] != null) {
map.put(i, bsn[i]);
}
}
return map;
}
}
/**
@@ -631,7 +616,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
@Override
public int getHealth() {
if(player != null)
return player.getHealth();
return helper.getHealth(player);
else
return 0;
}
@@ -725,13 +710,15 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
}
public void loadExtraBiomes() {
public void loadExtraBiomes(String mcver) {
int cnt = 0;
BiomeMap.loadWellKnownByVersion(mcver);
/* Find array of biomes in biomebase */
Object[] biomelist = helper.getBiomeBaseList();
/* Loop through list, starting afer well known biomes */
for(int i = BiomeMap.LAST_WELL_KNOWN+1; i < biomelist.length; i++) {
/* Loop through list, skipping well known biomes */
for(int i = 0; i < biomelist.length; i++) {
if (!BiomeMap.byBiomeID(i).isDefault()) continue;
Object bb = biomelist[i];
if(bb != null) {
String id = helper.getBiomeBaseIDString(bb);
@@ -770,8 +757,18 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
PluginDescriptionFile pdfFile = this.getDescription();
version = pdfFile.getVersion();
/* Get MC version */
String bukkitver = getServer().getVersion();
String mcver = "1.0.0";
int idx = bukkitver.indexOf("(MC: ");
if(idx > 0) {
mcver = bukkitver.substring(idx+5);
idx = mcver.indexOf(")");
if(idx > 0) mcver = mcver.substring(0, idx);
}
/* Load extra biomes, if any */
loadExtraBiomes();
loadExtraBiomes(mcver);
/* Set up player login/quit event handler */
registerPlayerLoginListener();
@@ -800,17 +797,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
File dataDirectory = this.getDataFolder();
if(dataDirectory.exists() == false)
dataDirectory.mkdirs();
/* Get MC version */
String bukkitver = getServer().getVersion();
String mcver = "1.0.0";
int idx = bukkitver.indexOf("(MC: ");
if(idx > 0) {
mcver = bukkitver.substring(idx+5);
idx = mcver.indexOf(")");
if(idx > 0) mcver = mcver.substring(0, idx);
}
/* Instantiate core */
if(core == null)
core = new DynmapCore();
@@ -835,7 +822,6 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true)
public void onPluginEnabled(PluginEnableEvent evt) {
if (!readyToEnable()) {
spb.markPluginEnabled(evt.getPlugin());
if (readyToEnable()) { /* If we;re ready now, finish enable */
doEnable(); /* Finish enable */
}
@@ -860,25 +846,17 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
private boolean readyToEnable() {
if (spb != null) {
return spb.isReady();
}
return true;
}
private void doEnable() {
/* Prep spout support, if needed */
if(spb != null) {
spb.processSpoutBlocks(this, core);
}
/* Enable core */
if(!core.enableCore(enabCoreCB)) {
this.setEnabled(false);
return;
}
playerList = core.playerList;
sscache = new SnapshotCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache());
SnapshotCache.cache = new SnapshotCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache());
/* Get map manager from core */
mapManager = core.getMapManager();
@@ -912,9 +890,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
/* Disable core */
core.disableCore();
if(sscache != null) {
sscache.cleanup();
sscache = null;
if(SnapshotCache.cache != null) {
SnapshotCache.cache.cleanup();
SnapshotCache.cache = null;
}
Log.info("Disabled");
}
@@ -1097,7 +1075,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
if(btt.typeid == 9) btt.typeid = 8;
if((bt != btt.typeid) || (btt.data != w.getBlockAt(loc).getData())) {
String wn = getWorld(w).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), btt.trigger);
}
}
@@ -1165,7 +1143,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onBlockPlace(BlockPlaceEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockplace");
}
};
@@ -1180,7 +1158,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
if(b == null) return; /* Stupid mod workaround */
Location loc = b.getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockbreak");
}
};
@@ -1193,7 +1171,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onLeavesDecay(LeavesDecayEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
if(onleaves) {
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "leavesdecay");
}
@@ -1208,7 +1186,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onBlockBurn(BlockBurnEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
if(onburn) {
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockburn");
}
@@ -1272,14 +1250,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
String wn = getWorld(loc.getWorld()).getName();
int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ();
sscache.invalidateSnapshot(wn, x, y, z);
SnapshotCache.cache.invalidateSnapshot(wn, x, y, z);
if(onpiston)
mapManager.touch(wn, x, y, z, "pistonretract");
for(int i = 0; i < 2; i++) {
x += dir.getModX();
y += dir.getModY();
z += dir.getModZ();
sscache.invalidateSnapshot(wn, x, y, z);
SnapshotCache.cache.invalidateSnapshot(wn, x, y, z);
mapManager.touch(wn, x, y, z, "pistonretract");
}
}
@@ -1296,14 +1274,14 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
String wn = getWorld(loc.getWorld()).getName();
int x = loc.getBlockX(), y = loc.getBlockY(), z = loc.getBlockZ();
sscache.invalidateSnapshot(wn, x, y, z);
SnapshotCache.cache.invalidateSnapshot(wn, x, y, z);
if(onpiston)
mapManager.touch(wn, x, y, z, "pistonretract");
for(int i = 0; i < 1+event.getLength(); i++) {
x += dir.getModX();
y += dir.getModY();
z += dir.getModZ();
sscache.invalidateSnapshot(wn, x, y, z);
SnapshotCache.cache.invalidateSnapshot(wn, x, y, z);
mapManager.touch(wn, x, y, z, "pistonretract");
}
}
@@ -1317,7 +1295,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onBlockSpread(BlockSpreadEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockspread");
}
};
@@ -1330,7 +1308,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onBlockForm(BlockFormEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockform");
}
};
@@ -1343,7 +1321,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onBlockFade(BlockFadeEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockfade");
}
};
@@ -1358,7 +1336,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onBlockGrow(BlockGrowEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockgrow");
}
};
@@ -1371,7 +1349,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public void onBlockRedstone(BlockRedstoneEvent event) {
Location loc = event.getBlock().getLocation();
String wn = getWorld(loc.getWorld()).getName();
sscache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
SnapshotCache.cache.invalidateSnapshot(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
mapManager.touch(wn, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), "blockredstone");
}
};
@@ -1428,7 +1406,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
if(z < minz) minz = z;
if(z > maxz) maxz = z;
}
sscache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz);
SnapshotCache.cache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz);
if(onexplosion) {
mapManager.touchVolume(wname, minx, miny, minz, maxx, maxy, maxz, "entityexplode");
}
@@ -1475,7 +1453,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
if(z < minz) minz = z;
if(z > maxz) maxz = z;
}
sscache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz);
SnapshotCache.cache.invalidateSnapshot(wname, minx, miny, minz, maxx, maxy, maxz);
if(onstructuregrow) {
mapManager.touchVolume(wname, minx, miny, minz, maxx, maxy, maxz, "structuregrow");
}
@@ -1508,18 +1486,6 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
}
}
private boolean detectSpout() {
Plugin p = this.getServer().getPluginManager().getPlugin("Spout");
if(p != null) {
return p.isEnabled();
}
return false;
}
public boolean hasSpout() {
return has_spout;
}
@Override
public void assertPlayerInvisibility(String player, boolean is_invisible,
String plugin_id) {
@@ -1570,14 +1536,6 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
return 0;
}
});
features.addPlotter(new Metrics.Plotter("Spout") {
@Override
public int getValue() {
if(plugin.has_spout)
return 1;
return 0;
}
});
features.addPlotter(new Metrics.Plotter("Login Security") {
@Override
public int getValue() {
@@ -1646,4 +1604,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
// Failed to submit the stats :-(
}
}
@Override
public void processSignChange(int blkid, String world, int x, int y, int z,
String[] lines, String playerid) {
core.processSignChange(blkid, world, x, y, z, lines, playerid);
}
}
@@ -56,9 +56,9 @@ import java.util.logging.Level;
* <p> The metrics class obtains data about a plugin and submits statistics about it to the metrics backend. </p> <p>
* Public methods provided by this class: </p>
* <code>
* Graph createGraph(String name); <br/>
* void addCustomData(BukkitMetrics.Plotter plotter); <br/>
* void start(); <br/>
* Graph createGraph(String name); <br>
* void addCustomData(BukkitMetrics.Plotter plotter); <br>
* void start(); <br>
* </code>
*/
public class Metrics {
@@ -121,6 +121,8 @@ public class Metrics {
*/
private volatile BukkitTask task = null;
private BukkitVersionHelper helper;
public Metrics(final Plugin plugin) throws IOException {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null");
@@ -146,6 +148,8 @@ public class Metrics {
// Load the guid then
guid = configuration.getString("guid");
debug = configuration.getBoolean("debug", false);
helper = BukkitVersionHelper.getHelper();
}
/**
@@ -359,7 +363,7 @@ public class Metrics {
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
String pluginVersion = description.getVersion();
String serverVersion = Bukkit.getVersion();
int playersOnline = Bukkit.getServer().getOnlinePlayers().length;
int playersOnline = helper.getOnlinePlayers().length;
// END server software specific section -- all code below does not use any code outside of this class / Java

Some files were not shown because too many files have changed in this diff Show More