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

View File

@ -11,10 +11,13 @@ import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.dynmap.utils.BlockLightLevel;
import org.json.simple.JSONArray; import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
public class ClientUpdateComponent extends Component { public class ClientUpdateComponent extends Component {
private BlockLightLevel bll = new BlockLightLevel();
public ClientUpdateComponent(final DynmapPlugin plugin, ConfigurationNode configuration) { public ClientUpdateComponent(final DynmapPlugin plugin, ConfigurationNode configuration) {
super(plugin, configuration); super(plugin, configuration);
plugin.events.addListener("buildclientupdate", new Event.Listener<ClientUpdateEvent>() { plugin.events.addListener("buildclientupdate", new Event.Listener<ClientUpdateEvent>() {
@ -53,10 +56,15 @@ public class ClientUpdateComponent extends Component {
hide = true; hide = true;
} }
if(hideifunder < 15) { if(hideifunder < 15) {
/*TODO: when pull accepted for getSkyLightLevel(), switch to that */ 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()) if(pl.getWorld().getHighestBlockYAt(pl) > pl.getBlockY())
hide = true; hide = true;
} }
}
/* Don't leak player location for world not visible on maps, or if sendposition disbaled */ /* Don't leak player location for world not visible on maps, or if sendposition disbaled */
DynmapWorld pworld = MapManager.mapman.worldsLookup.get(p.getWorld().getName()); DynmapWorld pworld = MapManager.mapman.worldsLookup.get(p.getWorld().getName());

View File

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

View File

@ -81,6 +81,14 @@ public class MapManager {
int transparentcnt; 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) { public DynmapWorld getWorld(String name) {
DynmapWorld world = worldsLookup.get(name); DynmapWorld world = worldsLookup.get(name);
return world; return world;
@ -862,7 +870,7 @@ public class MapManager {
for(ConfigurationNode tile : tiles) { for(ConfigurationNode tile : tiles) {
MapTile mt = MapTile.restoreTile(w, tile); /* Restore tile, if possible */ MapTile mt = MapTile.restoreTile(w, tile); /* Restore tile, if possible */
if(mt != null) { if(mt != null) {
invalidateTile(mt); if(invalidateTile(mt))
cnt++; cnt++;
} }
} }
@ -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()); DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null) if (world == null)
return 0; return 0;
@ -924,14 +932,26 @@ public class MapManager {
for (int i = 0; i < world.maps.size(); i++) { for (int i = 0; i < world.maps.size(); i++) {
MapTile[] tiles = world.maps.get(i).getTiles(l); MapTile[] tiles = world.maps.get(i).getTiles(l);
for (int j = 0; j < tiles.length; j++) { for (int j = 0; j < tiles.length; j++) {
invalidateTile(tiles[j]); if(invalidateTile(tiles[j]))
invalidates++; 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; return invalidates;
} }
public int touchVolume(Location l0, Location l1) { public int touchVolume(Location l0, Location l1, String reason) {
DynmapWorld world = getWorld(l0.getWorld().getName()); DynmapWorld world = getWorld(l0.getWorld().getName());
if (world == null) if (world == null)
return 0; return 0;
@ -939,16 +959,27 @@ public class MapManager {
for (int i = 0; i < world.maps.size(); i++) { for (int i = 0; i < world.maps.size(); i++) {
MapTile[] tiles = world.maps.get(i).getTiles(l0, l1); MapTile[] tiles = world.maps.get(i).getTiles(l0, l1);
for (int j = 0; j < tiles.length; j++) { for (int j = 0; j < tiles.length; j++) {
invalidateTile(tiles[j]); if(invalidateTile(tiles[j]))
invalidates++; 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; return invalidates;
} }
public void invalidateTile(MapTile tile) { public boolean invalidateTile(MapTile tile) {
if(tileQueue.push(tile)) return tileQueue.push(tile);
Debug.debug("Invalidating tile " + tile.getFilename());
} }
public static boolean scheduleDelayedJob(Runnable job, long delay_in_msec) { public static boolean scheduleDelayedJob(Runnable job, long delay_in_msec) {
@ -1149,6 +1180,19 @@ public class MapManager {
act += wn + " "; act += wn + " ";
sender.sendMessage(" Active render jobs: " + act); 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 * Reset statistics
*/ */
@ -1163,6 +1207,12 @@ public class MapManager {
ms.updatedcnt = 0; ms.updatedcnt = 0;
ms.transparentcnt = 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(); sscache.resetStats();
sender.sendMessage("Tile Render Statistics reset"); sender.sendMessage("Tile Render Statistics reset");

View File

@ -38,13 +38,7 @@ public abstract class MapTile {
} }
@Override @Override
public boolean equals(Object obj) { public abstract 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 String getKey(); public abstract String getKey();

View File

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

View File

@ -52,11 +52,11 @@ public class MarkerSignManager {
set = v.substring(4); set = v.substring(4);
evt.setLine(i, ""); evt.setLine(i, "");
} }
else if(label.length() == 0) { else if(v.length() > 0) {
label = escapeMarkup(v); if(label.length() > 0) {
label = label + "<br/>";
} }
else { label = label + escapeMarkup(v);
label = label + "<br/>" + escapeMarkup(v);
} }
} }
/* Get the set and see if the marker is already defined */ /* 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 FactionsConfigHandler factions;
private String regiontype; 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) { public RegionsComponent(final DynmapPlugin plugin, final ConfigurationNode configuration) {
super(plugin, 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. // For internal webserver.
String fname = configuration.getString("filename", "regions.yml"); String fname = configuration.getString("filename", "regions.yml");
regiontype = configuration.getString("name", "WorldGuard");
/* Load special handler for Towny */ /* Load special handler for Towny */
if(regiontype.equals("Towny")) { if(regiontype.equals("Towny")) {
towny = new TownyConfigHandler(configuration); 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 # redirecturl: inactive.html
# #showmessage: 'You were inactive for too long.' # #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 #- class: org.dynmap.TestComponent
# stuff: "This is some configuration-value" # 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) # 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) # 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) # '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 # Enable Industrial Craft 2 block rendering support
#ic2-support: true #ic2-support: true

View File

@ -8,7 +8,7 @@ commands:
description: Controls Dynmap. description: Controls Dynmap.
usage: | usage: |
/<command> hide - hides the player from the map. /<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 - shows the player on the map.
/<command> show TheDude - shows the player 'TheDude' on the map. /<command> show TheDude - shows the player 'TheDude' on the map.
/<command> render - Renders the tile at your location. /<command> render - Renders the tile at your location.
@ -21,6 +21,7 @@ commands:
/<command> cancelrender world - Cancels any active renders of world 'world' /<command> cancelrender world - Cancels any active renders of world 'world'
/<command> stats - Show render statistics. /<command> stats - Show render statistics.
/<command> stats world - Show render statistics for maps on world 'world'. /<command> stats world - Show render statistics for maps on world 'world'.
/<command> triggerstats - Show render trigger statistics
/<command> resetstats - Reset render statistics. /<command> resetstats - Reset render statistics.
/<command> resetstats world - Reset render statistics for maps on world 'world'. /<command> resetstats world - Reset render statistics for maps on world 'world'.
/<command> sendtoweb msg - Send message to web users /<command> sendtoweb msg - Send message to web users
@ -125,7 +126,7 @@ permissions:
description: Allows /dynmap reload description: Allows /dynmap reload
default: op default: op
dynmap.stats: dynmap.stats:
description: Allows /dynmap stats or /dynmap stats <world> description: Allows /dynmap stats, /dynmap stats <world>, or /dynmap triggerstats
default: true default: true
dynmap.resetstats: dynmap.resetstats:
description: Allows /dynmap resetstats or /dynmap resetstats <world> 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 # Bed - foot - pointing south
block:id=26,data=3,top=6134,bottom=6134,north=149,east=7150,west=150,transparency=TRANSPARENT block:id=26,data=3,top=6134,bottom=6134,north=149,east=7150,west=150,transparency=TRANSPARENT
# Powered rail - heading east-west - unpowered # 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 east - unpowered
# Powered rail - incline to west - 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 # 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 east - powered
# Powered rail - incline to west - 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 # 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 north - unpowered
# Powered rail - inclined to south - unpowered # Powered rail - inclined to south - unpowered
block:id=27,data=1,data=2,data=3,top=163,bottom=163,allsides=4,transparency=TRANSPARENT block:id=27,data=2,data=3,top=163,bottom=163,north=163,south=163,transparency=TRANSPARENT
# Powered rail - heading north-sout - powered # 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 north - powered
# Powered rail - inclined to south - 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 # 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 east
# Detector rail - incline to west # 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 # 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 north
# Detector rail - incline to south # 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 # Sticky piston - facing down
block:id=29,data=0,top=109,bottom=106,allsides=5108 block:id=29,data=0,top=109,bottom=106,allsides=5108
# Sticky piston - facing up # Sticky piston - facing up
@ -377,7 +383,7 @@ block:id=66,data=0,top=4128,bottom=4128,transparency=TRANSPARENT
# Rail - incline to west # Rail - incline to west
block:id=66,data=4,data=5,top=4128,bottom=4128,east=128,west=128,transparency=TRANSPARENT block:id=66,data=4,data=5,top=4128,bottom=4128,east=128,west=128,transparency=TRANSPARENT
# Rail - heading north-south # 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 north
# Rail - incline to south # Rail - incline to south
block:id=66,data=2,data=3,top=128,bottom=128,north=128,south=128,transparency=TRANSPARENT block:id=66,data=2,data=3,top=128,bottom=128,north=128,south=128,transparency=TRANSPARENT