Merge remote branch 'upstream/master'

This commit is contained in:
Mike Primm 2011-11-24 10:30:41 -06:00
commit e2ea48ed1b
13 changed files with 275 additions and 188 deletions

View File

@ -9,17 +9,23 @@ import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
public class ClientComponent extends Component {
private boolean disabled;
public ClientComponent(final DynmapPlugin plugin, final ConfigurationNode configuration) {
super(plugin, configuration);
plugin.events.addListener("buildclientconfiguration", new Event.Listener<JSONObject>() {
@Override
public void triggered(JSONObject root) {
buildClientConfiguration(root);
if(!disabled)
buildClientConfiguration(root);
}
});
}
protected void disableComponent() {
disabled = true;
}
protected void buildClientConfiguration(JSONObject root) {
JSONObject o = createClientConfiguration();
a(root, "components", o);

View File

@ -11,10 +11,13 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.dynmap.utils.BlockLightLevel;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
public class ClientUpdateComponent extends Component {
private BlockLightLevel bll = new BlockLightLevel();
public ClientUpdateComponent(final DynmapPlugin plugin, ConfigurationNode configuration) {
super(plugin, configuration);
plugin.events.addListener("buildclientupdate", new Event.Listener<ClientUpdateEvent>() {
@ -53,9 +56,14 @@ public class ClientUpdateComponent extends Component {
hide = true;
}
if(hideifunder < 15) {
/*TODO: when pull accepted for getSkyLightLevel(), switch to that */
if(pl.getWorld().getHighestBlockYAt(pl) > pl.getBlockY())
hide = true;
if(bll.isReady()) { /* If we can get real sky level */
if(bll.getSkyLightLevel(pl.getBlock()) <= hideifunder)
hide = true;
}
else {
if(pl.getWorld().getHighestBlockYAt(pl) > pl.getBlockY())
hide = true;
}
}
/* Don't leak player location for world not visible on maps, or if sendposition disbaled */

View File

@ -222,6 +222,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
permissions = new OpPermissions(new String[] { "fullrender", "cancelrender", "radiusrender", "resetstats", "reload", "purgequeue" });
dataDirectory = this.getDataFolder();
if(dataDirectory.exists() == false)
dataDirectory.mkdirs();
/* Initialize confguration.txt if needed */
File f = new File(this.getDataFolder(), "configuration.txt");
@ -432,7 +434,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onplace) {
mapManager.touch(loc);
mapManager.touch(loc, "blockplace");
}
}
@ -443,7 +445,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onbreak) {
mapManager.touch(loc);
mapManager.touch(loc, "blockbreak");
}
}
@ -454,7 +456,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onleaves) {
mapManager.touch(loc);
mapManager.touch(loc, "leavesdecay");
}
}
@ -465,7 +467,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onburn) {
mapManager.touch(loc);
mapManager.touch(loc, "blockburn");
}
}
@ -476,7 +478,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onblockform) {
mapManager.touch(loc);
mapManager.touch(loc, "blockform");
}
}
@ -487,7 +489,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onblockfade) {
mapManager.touch(loc);
mapManager.touch(loc, "blockfade");
}
}
@ -498,7 +500,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onblockspread) {
mapManager.touch(loc);
mapManager.touch(loc, "blockspread");
}
}
@ -516,7 +518,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
dir = BlockFace.NORTH;
}
if(onpiston) {
mapManager.touchVolume(loc, b.getRelative(dir, 2).getLocation());
mapManager.touchVolume(loc, b.getRelative(dir, 2).getLocation(), "pistonretract");
}
for(int i = 0; i < 2; i++) {
b = b.getRelative(dir, 1);
@ -537,7 +539,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
dir = BlockFace.NORTH;
}
if(onpiston) {
mapManager.touchVolume(loc, b.getRelative(dir, 1+event.getLength()).getLocation());
mapManager.touchVolume(loc, b.getRelative(dir, 1+event.getLength()).getLocation(), "pistonextend");
}
for(int i = 0; i < 1+event.getLength(); i++) {
b = b.getRelative(dir, 1);
@ -577,12 +579,12 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
PlayerListener playerTrigger = new PlayerListener() {
@Override
public void onPlayerJoin(PlayerJoinEvent event) {
mapManager.touch(event.getPlayer().getLocation());
mapManager.touch(event.getPlayer().getLocation(), "playerjoin");
}
@Override
public void onPlayerMove(PlayerMoveEvent event) {
mapManager.touch(event.getPlayer().getLocation());
mapManager.touch(event.getPlayer().getLocation(), "playermove");
}
};
@ -602,7 +604,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = b.getLocation();
mapManager.sscache.invalidateSnapshot(loc);
if(onexplosion) {
mapManager.touch(loc);
mapManager.touch(loc, "entityexplode");
}
}
}
@ -620,13 +622,13 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
/* Touch extreme corners */
int x = event.getChunk().getX() << 4;
int z = event.getChunk().getZ() << 4;
mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16));
mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16), "chunkload");
}
@Override
public void onChunkPopulate(ChunkPopulateEvent event) {
int x = event.getChunk().getX() << 4;
int z = event.getChunk().getZ() << 4;
mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16));
mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16), "chunkgenerate");
}
@Override
public void onWorldLoad(WorldLoadEvent event) {
@ -725,6 +727,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
"radiusrender",
"reload",
"stats",
"triggerstats",
"resetstats",
"sendtoweb",
"purgequeue" }));
@ -753,7 +756,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
if (c.equals("render") && checkPlayerPermission(sender,"render")) {
if (player != null) {
int invalidates = mapManager.touch(player.getLocation());
int invalidates = mapManager.touch(player.getLocation(), "render");
sender.sendMessage("Queued " + invalidates + " tiles" + (invalidates == 0
? " (world is not loaded?)"
: "..."));
@ -860,6 +863,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
mapManager.printStats(sender, null);
else
mapManager.printStats(sender, args[1]);
} else if (c.equals("triggerstats") && checkPlayerPermission(sender, "stats")) {
mapManager.printTriggerStats(sender);
} else if (c.equals("resetstats") && checkPlayerPermission(sender, "resetstats")) {
if(args.length == 1)
mapManager.resetStats(sender, null);
@ -1322,9 +1327,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public int triggerRenderOfVolume(Location l0, Location l1) {
if(mapManager != null) {
if(l1 == null)
return mapManager.touch(l0);
return mapManager.touch(l0, "api");
else
return mapManager.touchVolume(l0, l1);
return mapManager.touchVolume(l0, l1, "api");
}
return 0;
}

View File

@ -81,6 +81,14 @@ public class MapManager {
int transparentcnt;
}
private HashMap<String, TriggerStats> trigstats = new HashMap<String, TriggerStats>();
private static class TriggerStats {
long callsmade;
long callswithtiles;
long tilesqueued;
}
public DynmapWorld getWorld(String name) {
DynmapWorld world = worldsLookup.get(name);
return world;
@ -862,8 +870,8 @@ public class MapManager {
for(ConfigurationNode tile : tiles) {
MapTile mt = MapTile.restoreTile(w, tile); /* Restore tile, if possible */
if(mt != null) {
invalidateTile(mt);
cnt++;
if(invalidateTile(mt))
cnt++;
}
}
if(cnt > 0)
@ -916,7 +924,7 @@ public class MapManager {
}
}
public int touch(Location l) {
public int touch(Location l, String reason) {
DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null)
return 0;
@ -924,14 +932,26 @@ public class MapManager {
for (int i = 0; i < world.maps.size(); i++) {
MapTile[] tiles = world.maps.get(i).getTiles(l);
for (int j = 0; j < tiles.length; j++) {
invalidateTile(tiles[j]);
invalidates++;
if(invalidateTile(tiles[j]))
invalidates++;
}
}
if(reason != null) {
TriggerStats ts = trigstats.get(reason);
if(ts == null) {
ts = new TriggerStats();
trigstats.put(reason, ts);
}
ts.callsmade++;
if(invalidates > 0) {
ts.callswithtiles++;
ts.tilesqueued += invalidates;
}
}
return invalidates;
}
public int touchVolume(Location l0, Location l1) {
public int touchVolume(Location l0, Location l1, String reason) {
DynmapWorld world = getWorld(l0.getWorld().getName());
if (world == null)
return 0;
@ -939,16 +959,27 @@ public class MapManager {
for (int i = 0; i < world.maps.size(); i++) {
MapTile[] tiles = world.maps.get(i).getTiles(l0, l1);
for (int j = 0; j < tiles.length; j++) {
invalidateTile(tiles[j]);
invalidates++;
if(invalidateTile(tiles[j]))
invalidates++;
}
}
if(reason != null) {
TriggerStats ts = trigstats.get(reason);
if(ts == null) {
ts = new TriggerStats();
trigstats.put(reason, ts);
}
ts.callsmade++;
if(invalidates > 0) {
ts.callswithtiles++;
ts.tilesqueued += invalidates;
}
}
return invalidates;
}
public void invalidateTile(MapTile tile) {
if(tileQueue.push(tile))
Debug.debug("Invalidating tile " + tile.getFilename());
public boolean invalidateTile(MapTile tile) {
return tileQueue.push(tile);
}
public static boolean scheduleDelayedJob(Runnable job, long delay_in_msec) {
@ -1149,6 +1180,19 @@ public class MapManager {
act += wn + " ";
sender.sendMessage(" Active render jobs: " + act);
}
/**
* Print trigger statistics command
*/
public void printTriggerStats(CommandSender sender) {
sender.sendMessage("Render Trigger Statistics:");
synchronized(lock) {
for(String k: new TreeSet<String>(trigstats.keySet())) {
TriggerStats ts = trigstats.get(k);
sender.sendMessage(" " + k + ": calls=" + ts.callsmade + ", calls-adding-tiles=" + ts.callswithtiles + ", tiles-added=" + ts.tilesqueued);
}
}
}
/**
* Reset statistics
*/
@ -1163,6 +1207,12 @@ public class MapManager {
ms.updatedcnt = 0;
ms.transparentcnt = 0;
}
for(String k : trigstats.keySet()) {
TriggerStats ts = trigstats.get(k);
ts.callsmade = 0;
ts.callswithtiles = 0;
ts.tilesqueued = 0;
}
}
sscache.resetStats();
sender.sendMessage("Tile Render Statistics reset");

View File

@ -38,13 +38,7 @@ public abstract class MapTile {
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MapTile) {
MapTile t = (MapTile)obj;
return getFilename().equals(t.getFilename()) && getWorld().equals(t.getWorld());
}
return super.equals(obj);
}
public abstract boolean equals(Object obj);
public abstract String getKey();

View File

@ -81,7 +81,7 @@ public class KzedZoomedMapTile extends MapTile {
if (obj instanceof KzedZoomedMapTile) {
return ((KzedZoomedMapTile) obj).originalTile.equals(originalTile);
}
return super.equals(obj);
return false;
}

View File

@ -23,6 +23,7 @@ import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.config.Configuration;
import org.bukkit.util.config.ConfigurationNode;
import org.dynmap.Client;
@ -52,6 +53,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
private HashMap<String, MarkerSetImpl> markersets = new HashMap<String, MarkerSetImpl>();
private HashMap<String, List<Location>> pointaccum = new HashMap<String, List<Location>>();
private Server server;
private Plugin dynmap;
static MarkerAPIImpl api;
/* Built-in icons */
@ -154,6 +156,30 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
}
}
private boolean stop = false;
private Set<String> dirty_worlds = new HashSet<String>();
private boolean dirty_markers = false;
private class DoFileWrites implements Runnable {
public void run() {
if(stop)
return;
/* Write markers first - drives JSON updates too */
if(dirty_markers) {
doSaveMarkers();
dirty_markers = false;
}
/* Process any dirty worlds */
if(!dirty_worlds.isEmpty()) {
for(String world : dirty_worlds) {
writeMarkersFile(world);
}
dirty_worlds.clear();
}
server.getScheduler().scheduleSyncDelayedTask(dynmap, this, 20);
}
}
/**
* Singleton initializer
*/
@ -162,6 +188,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
api.cleanup(plugin);
}
api = new MarkerAPIImpl();
api.dynmap = plugin;
api.server = plugin.getServer();
/* Initialize persistence file name */
api.markerpersist = new File(plugin.getDataFolder(), "markers.yml");
@ -201,15 +228,27 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
/* Add listener so we update marker files for other worlds as they become active */
plugin.events.addListener("worldactivated", api);
api.scheduleWriteJob(); /* Start write job */
return api;
}
private void scheduleWriteJob() {
server.getScheduler().scheduleSyncDelayedTask(dynmap, new DoFileWrites(), 20);
}
/**
* Cleanup
*/
public void cleanup(DynmapPlugin plugin) {
plugin.events.removeListener("worldactivated", api);
stop = true;
if(dirty_markers) {
doSaveMarkers();
dirty_markers = false;
}
for(MarkerIconImpl icn : markericons.values())
icn.cleanup();
markericons.clear();
@ -348,6 +387,11 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
* Save persistence for markers
*/
static void saveMarkers() {
if(api != null) {
api.dirty_markers = true;
}
}
private void doSaveMarkers() {
if(api != null) {
Configuration conf = new Configuration(api.markerpersist); /* Make configuration object */
/* First, save icon definitions */
@ -386,7 +430,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
private void freshenMarkerFiles() {
if(MapManager.mapman != null) {
for(DynmapWorld w : MapManager.mapman.worlds) {
writeMarkersFile(w.world.getName());
dirty_worlds.add(w.world.getName());
}
}
}
@ -430,7 +474,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
static void markerUpdated(MarkerImpl marker, MarkerUpdate update) {
/* Freshen marker file for the world for this marker */
if(api != null)
api.writeMarkersFile(marker.getWorld());
api.dirty_worlds.add(marker.getWorld());
/* Enqueue client update */
if(MapManager.mapman != null)
MapManager.mapman.pushUpdate(marker.getWorld(), new MarkerUpdated(marker, update == MarkerUpdate.DELETED));
@ -443,7 +487,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
static void areaMarkerUpdated(AreaMarkerImpl marker, MarkerUpdate update) {
/* Freshen marker file for the world for this marker */
if(api != null)
api.writeMarkersFile(marker.getWorld());
api.dirty_worlds.add(marker.getWorld());
/* Enqueue client update */
if(MapManager.mapman != null)
MapManager.mapman.pushUpdate(marker.getWorld(), new AreaMarkerUpdated(marker, update == MarkerUpdate.DELETED));
@ -1381,7 +1425,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
/**
* Write markers file for given world
*/
public void writeMarkersFile(String wname) {
private void writeMarkersFile(String wname) {
Map<String, Object> markerdata = new HashMap<String, Object>();
File f = new File(markertiledir, "marker_" + wname + ".json");
@ -1465,7 +1509,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
@Override
public void triggered(DynmapWorld t) {
/* Update markers for now-active world */
writeMarkersFile(t.world.getName());
dirty_worlds.add(t.world.getName());
}
/* Remove icon */

View File

@ -52,11 +52,11 @@ public class MarkerSignManager {
set = v.substring(4);
evt.setLine(i, "");
}
else if(label.length() == 0) {
label = escapeMarkup(v);
}
else {
label = label + "<br/>" + escapeMarkup(v);
else if(v.length() > 0) {
if(label.length() > 0) {
label = label + "<br/>";
}
label = label + escapeMarkup(v);
}
}
/* Get the set and see if the marker is already defined */

View File

@ -25,15 +25,31 @@ public class RegionsComponent extends ClientComponent {
private FactionsConfigHandler factions;
private String regiontype;
private static String deprecated_ids[] = { "Residence", "Factions", "Towny", "WorldGuard" };
private static String deprecated_new_plugins[] = { "dynmap-residence", "Dynmap-Factions", "Dynmap-Towny", "Dynmap-WorldGuard" };
public RegionsComponent(final DynmapPlugin plugin, final ConfigurationNode configuration) {
super(plugin, configuration);
regiontype = configuration.getString("name", "WorldGuard");
/* Check if a deprecated component */
for(int i = 0; i < deprecated_ids.length; i++) {
if(regiontype.equals(deprecated_ids[i])) { /* If match */
/* See if new plugin is installed - disable if it is */
if(plugin.getServer().getPluginManager().getPlugin(deprecated_new_plugins[i]) != null) {
Log.info("Region component for '" + regiontype + "' disabled, replaced by '" + deprecated_new_plugins[i] + "' plugin, which is installed");
disableComponent();
return;
}
else {
Log.info("Region component for '" + regiontype + "' has been DEPRECATED - migrate to '" + deprecated_new_plugins[i] + "' plugin");
}
}
}
// For internal webserver.
String fname = configuration.getString("filename", "regions.yml");
regiontype = configuration.getString("name", "WorldGuard");
/* Load special handler for Towny */
if(regiontype.equals("Towny")) {
towny = new TownyConfigHandler(configuration);

View File

@ -0,0 +1,80 @@
package org.dynmap.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.bukkit.block.Block;
import org.dynmap.Log;
/**
* Wrapper for accessing raw light levels for given block
*/
public class BlockLightLevel {
private Method gethandle;
private Method getrawlight;
private Object enum_sky;
private Object enum_block;
private boolean ready;
@SuppressWarnings({ "unchecked", "rawtypes" })
public BlockLightLevel() {
/* Get CraftChunk.getChunkSnapshot(boolean,boolean,boolean) and CraftChunk.getHandle() */
try {
Class c = Class.forName("org.bukkit.craftbukkit.CraftChunk");
gethandle = c.getDeclaredMethod("getHandle", new Class[0]);
Class enumskyblock = Class.forName("net.minecraft.server.EnumSkyBlock");
Object[] enumvals = enumskyblock.getEnumConstants();
for(int i = 0; i < enumvals.length; i++) {
String ev = enumvals[i].toString();
if(ev.equals("Sky")) {
enum_sky = enumvals[i];
}
else if(ev.equals("Block")) {
enum_block = enumvals[i];
}
}
Class cc = Class.forName("net.minecraft.server.Chunk");
getrawlight = cc.getDeclaredMethod("a", new Class[] { enumskyblock, int.class, int.class, int.class });
} catch (ClassNotFoundException cnfx) {
} catch (NoSuchMethodException nsmx) {
}
if((gethandle != null) && (enum_sky != null) && (enum_block != null) && (getrawlight != null)) {
ready = true;
}
else {
Log.warning("Block raw light level API not available");
}
}
public boolean isReady() {
return ready;
}
public int getSkyLightLevel(Block b) {
try {
Object hand = gethandle.invoke(b.getChunk());
if(hand != null) {
Integer v = (Integer)getrawlight.invoke(hand, enum_sky, b.getX() & 0xF, b.getY() & 0x7F, b.getZ() & 0xF);
return v;
}
} catch (InvocationTargetException itx) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
return -1;
}
public int getBlockLightLevel(Block b) {
try {
Object hand = gethandle.invoke(b.getChunk());
if(hand != null) {
Integer v = (Integer)getrawlight.invoke(hand, enum_block, b.getX() & 0xF, b.getY() & 0x7F, b.getZ() & 0xF);
return v;
}
} catch (InvocationTargetException itx) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
return -1;
}
}

View File

@ -114,129 +114,6 @@ components:
# redirecturl: inactive.html
# #showmessage: 'You were inactive for too long.'
#- class: org.dynmap.regions.RegionsComponent
# type: regions
# name: WorldGuard
# useworldpath: true
# filename: regions.yml
# basenode: regions
# use3dregions: true
# regionstyle:
# strokeColor: "#FF0000"
# strokeOpacity: 0.8
# strokeWeight: 3
# fillColor: "#FF0000"
# fillOpacity: 0.35
# # Optional setting to limit which regions to show, by name - if commented out, all regions are shown
# visibleregions:
# - homebase
# - miningsite
# # Optional setting to hide specific regions, by name
# hiddenregions:
# - hiddenplace
# - secretsite
# # Optional per-region overrides for regionstyle (any defined replace those in regionstyle)
# customstyle:
# homebase:
# strokeColor: "#00FF00"
# # Optional - make layer hidden by default
# hidebydefault: true
# # Optional - ordering priority in layer menu (low goes before high - default is 0)
# layerprio: 1
#- class: org.dynmap.regions.RegionsComponent
# type: regions
# name: Residence
# useworldpath: false
# filename: res.yml
# basenode: Residences
# use3dregions: false
# infowindow: '<div class="infowindow"><span style="font-size:120%;">%regionname%</span><br /> Owner <span style="font-weight:bold;">%playerowners%</span><br />Flags<br /><span style="font-weight:bold;">%flags%</span></div>'
# regionstyle:
# strokeColor: "#FF0000"
# strokeOpacity: 0.8
# strokeWeight: 3
# fillColor: "#FF0000"
# fillOpacity: 0.35
# # Optional setting to limit which regions to show, by name - if commented out, all regions are shown
# visibleregions:
# - homebase
# - miningsite
# - area.subzone1
# # Optional setting to hide specific regions, by name
# hiddenregions:
# - hiddenplace
# - secretsite
# # Optional per-region overrides for regionstyle (any defined replace those in regionstyle)
# customstyle:
# homebase:
# strokeColor: "#00FF00"
# # Optional groups (subareas under a residence) overrides for regionstyle (any defined replace those in regionstyle)
# groupstyle:
# homebase:
# strokeColor: "#007F00"
# # Optional - make layer hidden by default
# hidebydefault: true
# # Optional - ordering priority in layer menu (low goes before high - default is 0)
# layerprio: 1
#- class: org.dynmap.regions.RegionsComponent
# type: regions
# name: Towny
# use3dregions: false
# infowindow: '<div class="infowindow"><span style="font-size:120%;">%regionname% (%nation%)</span><br /> Mayor <span style="font-weight:bold;">%playerowners%</span><br /> Associates <span style="font-weight:bold;">%playermanagers%</span><br/>Flags<br /><span style="font-weight:bold;">%flags%</span></div>'
# regionstyle:
# strokeColor: "#FF0000"
# strokeOpacity: 0.8
# strokeWeight: 3
# fillColor: "#FF0000"
# fillOpacity: 0.35
# # Optional setting to limit which regions to show, by name - if commented out, all regions are shown
# visibleregions:
# - homebase
# - miningsite
# # Optional setting to hide specific regions, by name
# hiddenregions:
# - hiddenplace
# - secretsite
# # Optional per-town overrides for regionstyle (any defined replace those in regionstyle)
# customstyle:
# homebase:
# strokeColor: "#00FF00"
# # Optional per-nation overrides for regionstyle (any defined replace those in regionstyle)
# groupstyle:
# MyNation:
# strokeColor: "#007F00"
# # Optional - make layer hidden by default
# hidebydefault: true
#- class: org.dynmap.regions.RegionsComponent
# type: regions
# name: Factions
# use3dregions: false
# infowindow: '<div class="infowindow"><span style="font-size:120%;">%regionname%</span><br />Flags<br /><span style="font-weight:bold;">%flags%</span></div>'
# regionstyle:
# strokeColor: "#FF0000"
# strokeOpacity: 0.8
# strokeWeight: 3
# fillColor: "#FF0000"
# fillOpacity: 0.35
# # Optional setting to limit which regions to show, by name - if commented out, all regions are shown
# visibleregions:
# - faction1
# - faction2
# # Optional setting to hide specific regions, by name
# hiddenregions:
# - hiddenfaction
# # Optional per-faction overrides for regionstyle (any defined replace those in regionstyle)
# customstyle:
# faction1:
# strokeColor: "#00FF00"
# # Optional - make layer hidden by default
# hidebydefault: true
# # Optional - ordering priority in layer menu (low goes before high - default is 0)
# layerprio: 1
#- class: org.dynmap.TestComponent
# stuff: "This is some configuration-value"
@ -281,7 +158,7 @@ enabletilehash: true
# Control behavior for new (1.9+) compass orientation (sunrise moved 90 degrees: east is now what used to be south)
# default is 'pre19' for 1.8 server (existing orientation), 'newrose' for 1.9+ (preserve maps, rotate rose)
# 'newnorth' is used to rotate maps and rose (requires fullrender of any HDMap map - same as 'newrose' for FlatMap or KzedMap)
#compass-mode: newnorth
compass-mode: newnorth
# Enable Industrial Craft 2 block rendering support
#ic2-support: true

View File

@ -8,7 +8,7 @@ commands:
description: Controls Dynmap.
usage: |
/<command> hide - hides the player from the map.
/<command> hide TheDude - hides the player 'TheDude' from the map.
/<command> hide TheDude - hides the player 'TheDude' on the map.
/<command> show - shows the player on the map.
/<command> show TheDude - shows the player 'TheDude' on the map.
/<command> render - Renders the tile at your location.
@ -21,6 +21,7 @@ commands:
/<command> cancelrender world - Cancels any active renders of world 'world'
/<command> stats - Show render statistics.
/<command> stats world - Show render statistics for maps on world 'world'.
/<command> triggerstats - Show render trigger statistics
/<command> resetstats - Reset render statistics.
/<command> resetstats world - Reset render statistics for maps on world 'world'.
/<command> sendtoweb msg - Send message to web users
@ -125,7 +126,7 @@ permissions:
description: Allows /dynmap reload
default: op
dynmap.stats:
description: Allows /dynmap stats or /dynmap stats <world>
description: Allows /dynmap stats, /dynmap stats <world>, or /dynmap triggerstats
default: true
dynmap.resetstats:
description: Allows /dynmap resetstats or /dynmap resetstats <world>

View File

@ -92,29 +92,35 @@ block:id=26,data=11,top=6135,bottom=6135,south=152,east=7151,west=151,transparen
# Bed - foot - pointing south
block:id=26,data=3,top=6134,bottom=6134,north=149,east=7150,west=150,transparency=TRANSPARENT
# Powered rail - heading east-west - unpowered
block:id=27,data=0,top=4163,bottom=4163,transparency=TRANSPARENT
# Powered rail - incline to east - unpowered
# Powered rail - incline to west - unpowered
block:id=27,data=0,data=4,data=5,top=4163,bottom=4163,allsides=4,transparency=TRANSPARENT
block:id=27,data=4,data=5,top=4163,bottom=4163,east=163,west=163,transparency=TRANSPARENT
# Powered rail - heading east-west - powered
block:id=27,data=8,top=4179,bottom=4179,transparency=TRANSPARENT
# Powered rail - incline to east - powered
# Powered rail - incline to west - powered
block:id=27,data=8,data=12,data=13,top=4179,bottom=4179,allsides=4,transparency=TRANSPARENT
block:id=27,data=12,data=13,top=4179,bottom=4179,east=179,west=179,transparency=TRANSPARENT
# Powered rail - heading north-south - unpowered
block:id=27,data=1,top=163,bottom=163,transparency=TRANSPARENT
# Powered rail - inclined to north - unpowered
# Powered rail - inclined to south - unpowered
block:id=27,data=1,data=2,data=3,top=163,bottom=163,allsides=4,transparency=TRANSPARENT
# Powered rail - heading north-sout - powered
block:id=27,data=2,data=3,top=163,bottom=163,north=163,south=163,transparency=TRANSPARENT
# Powered rail - heading north-south - powered
block:id=27,data=9,top=179,bottom=179,transparency=TRANSPARENT
# Powered rail - inclined to north - powered
# Powered rail - inclined to south - powered
block:id=27,data=9,data=10,data=11,top=179,bottom=179,allsides=4,transparency=TRANSPARENT
block:id=27,data=10,data=11,top=179,bottom=179,north=179,south=179,transparency=TRANSPARENT
# Detector rail - heading east-west
block:id=28,data=0,top=4195,bottom=4195,transparency=TRANSPARENT
# Detector rail - incline to east
# Detector rail - incline to west
block:id=28,data=0,data=4,data=5,top=4195,bottom=4195,allsides=4,transparency=TRANSPARENT
block:id=28,data=4,data=5,top=4195,bottom=4195,east=195,west=195,transparency=TRANSPARENT
# Detector rail - heading north-south
block:id=28,data=1,top=195,bottom=195,transparency=TRANSPARENT
# Detector rail - incline to north
# Detector rail - incline to south
block:id=28,data=1,data=2,data=3,top=195,bottom=195,allsides=4,transparency=TRANSPARENT
block:id=28,data=2,data=3,top=195,bottom=195,north=195,south=195,transparency=TRANSPARENT
# Sticky piston - facing down
block:id=29,data=0,top=109,bottom=106,allsides=5108
# Sticky piston - facing up
@ -377,7 +383,7 @@ block:id=66,data=0,top=4128,bottom=4128,transparency=TRANSPARENT
# Rail - incline to west
block:id=66,data=4,data=5,top=4128,bottom=4128,east=128,west=128,transparency=TRANSPARENT
# Rail - heading north-south
block:id=66,data=1,top=128,bottom=128,allsides=4,transparency=TRANSPARENT
block:id=66,data=1,top=128,bottom=128,transparency=TRANSPARENT
# Rail - incline to north
# Rail - incline to south
block:id=66,data=2,data=3,top=128,bottom=128,north=128,south=128,transparency=TRANSPARENT