Compare commits

...

12 Commits

Author SHA1 Message Date
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
10 changed files with 106 additions and 61 deletions
+1 -1
View File
@@ -138,5 +138,5 @@
<version>2.10.1</version>
</dependency>
</dependencies>
<version>1.9.2</version>
<version>1.9.3</version>
</project>
@@ -88,6 +88,10 @@ public abstract class BukkitVersionHelper {
* 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
*/
@@ -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");
@@ -51,6 +51,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;
@@ -291,6 +292,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);
@@ -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
@@ -2,6 +2,7 @@ package org.dynmap.bukkit;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
@@ -217,10 +218,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);
@@ -462,20 +460,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;
@@ -559,14 +555,17 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public String getServerIP() {
return Bukkit.getServer().getIp();
}
@Override
public File getModContainerFile(String mod) {
return null;
}
@Override
public List<String> getModList() {
return Collections.emptyList();
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;
}
}
/**
@@ -27,7 +27,7 @@ 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 class NewMapChunkCache extends MapChunkCache {
private static boolean init = false;
private static boolean use_spout = false;
@@ -49,12 +49,7 @@ public class NewMapChunkCache implements MapChunkCache {
private byte[][] sameneighborbiomecnt;
private BiomeMap[][] biomemap;
private boolean[][] isSectionNotEmpty; /* Indexed by snapshot index, then by section index */
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 long[] inhabitedTicks; /* Index = (x-x_min) + ((z-z_min)*x_dim) */
private static BukkitVersionHelper helper = BukkitVersionHelper.getHelper();
@@ -210,7 +205,6 @@ public class NewMapChunkCache implements MapChunkCache {
try {
return biomemap[x - x_base][z - z_base];
} catch (Exception ex) {
exceptions++;
return BiomeMap.NULL;
}
}
@@ -240,7 +234,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 +264,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 +305,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 +332,6 @@ public class NewMapChunkCache implements MapChunkCache {
}
return ((raccum / 9) << 16) | ((gaccum / 9) << 8) | (baccum / 9);
} catch (Exception x) {
exceptions++;
return 0xFFFFFF;
}
}
@@ -371,7 +361,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 +582,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 {
@@ -779,6 +776,7 @@ 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][];
}
@@ -797,7 +795,6 @@ public class NewMapChunkCache implements MapChunkCache {
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;
@@ -808,6 +805,7 @@ public class NewMapChunkCache implements MapChunkCache {
//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) {
@@ -829,10 +827,12 @@ public class NewMapChunkCache implements MapChunkCache {
}
/* Check if cached chunk snapshot found */
ChunkSnapshot ss = null;
long inhabited_ticks = 0;
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;
inhabited_ticks = ssr.inhabitedTicks;
if(!vis) {
if(hidestyle == HiddenChunkStyle.FILL_STONE_PLAIN)
ss = STONE;
@@ -844,10 +844,11 @@ public class NewMapChunkCache implements MapChunkCache {
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;
}
chunks_attempted++;
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
boolean didload = false;
boolean isunloadpending = false;
@@ -870,6 +871,8 @@ public class NewMapChunkCache implements MapChunkCache {
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;
@@ -919,16 +922,18 @@ public class NewMapChunkCache implements MapChunkCache {
if(ss != null) {
ssr = new SnapshotRec();
ssr.ss = ss;
ssr.inhabitedTicks = inhabited_ticks;
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;
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) {
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,
@@ -936,10 +941,18 @@ public class NewMapChunkCache implements MapChunkCache {
* 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++;
}
@@ -955,7 +968,6 @@ public class NewMapChunkCache implements MapChunkCache {
isempty = false;
}
}
total_loadtime += System.nanoTime() - t0;
return cnt;
}
@@ -987,6 +999,7 @@ public class NewMapChunkCache implements MapChunkCache {
snaparray[i] = null;
}
snaparray = null;
inhabitedTicks = null;
}
}
private void initSectionData(int idx) {
@@ -1053,22 +1066,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();
@@ -14,6 +14,7 @@ import org.dynmap.utils.DynIntHashMap;
public class SnapshotCache {
public static class SnapshotRec {
public ChunkSnapshot ss;
public long inhabitedTicks;
public DynIntHashMap tileData;
};
+6
View File
@@ -219,6 +219,10 @@ enabletilehash: true
# Optional - enable smooth lighting by default on all maps supporting it (can be set per map as lighting option)
smooth-lighting: true
# Optional - use world provider lighting table (good for custom worlds with custom lighting curves, like nether)
# false=classic Dynmap lighting curve
use-brightness-table: true
# Optional - render specific block IDs using the texures and models of another block ID: can be used to hide/disguise specific
# blocks (e.g. make ores look like stone, hide chests) or to provide simple support for rendering unsupported custom blocks
block-id-alias:
@@ -441,3 +445,5 @@ verbose: false
# Enables debugging.
#debuggers:
# - class: org.dynmap.debug.LogDebugger
# Debug: dump blocks missing render data
dump-missing-blocks: false
+4
View File
@@ -116,6 +116,10 @@ commands:
/<command> mapset worldname:mapname attrib:value attrib:value - update given map on given world with given attributes
/<command> worldreset worldname - reset given world to default template for world type
/<command> worldreset worldname templatename - reset given world to given template
dynmapexp:
description: Map export commands
usage: |
/<command> shader <shadername> - Export material library for shader <shadername>
permissions:
dynmap.*: