Changed the way templates and world-configuration are handled.

This commit is contained in:
FrozenCow 2011-05-24 02:13:43 +02:00
parent de0ad58344
commit 108e9d24c4
8 changed files with 174 additions and 148 deletions

View File

@ -111,9 +111,10 @@ defaultworld: world
# template world - this is used for worlds that exist but aren't defined in the worlds section.
# Also, it supplies the "maps" section for worlds lacking a maps section, and the "center"
# for worlds lacking a "center" section.
template:
templates:
# Template for normal world
normal:
enabled: true
center:
x: 0
y: 64
@ -151,6 +152,7 @@ template:
maximumheight: 127
# Nether world template
nether:
enabled: true
center:
x: 0
y: 64
@ -169,18 +171,18 @@ template:
prefix: nt
maximumheight: 127
colorscheme: default
# This list of worlds will be hidden - they will not be automatically initialized by templates
hiddenworlds:
- MyHiddenWorld
- AnotherHiddenWorld
# The maptypes Dynmap will use to render.
worlds:
# Worlds can be handled by templates, based on world type
# To override, provide name and title here. Any other sections that are provided will
# be used instead of the template's value (center, maps).
# You can override the properties of the template by specifying them in this section
# for example 'Title: "My Awesome World"'
#- name: world
# title: "World"
# Use 'enabled: false' to disable a certain world.
# enabled: false
# Use 'template: mycustomtemplate' to use the properties specified in the template 'mycustomtemplate' to this world. Default it is set to the environment-name (normal or nether).
# template: mycustomtemplate
# Rest of comes from template - uncomment to tailor for world specifically
# center:
# x: 0

View File

@ -19,9 +19,12 @@ public class ClientConfigurationComponent extends Component {
s(t, "joinmessage", c.getString("joinmessage", "%playername% joined"));
s(t, "quitmessage", c.getString("quitmessage", "%playername% quit"));
s(t, "spammessage", c.getString("spammessage", "You may only chat once every %interval% seconds."));
s(t, "defaultzoom", c.getInteger("defaultzoom", 0));
for(ConfigurationNode wn : plugin.configuration.getNodes("worlds")) {
DynmapWorld world = plugin.mapManager.getWorld(wn.getString("name"));
DynmapWorld defaultWorld = null;
for(DynmapWorld world : plugin.mapManager.getWorlds()) {
if (defaultWorld == null) defaultWorld = world;
ConfigurationNode wn = world.configuration;
JSONObject wo = new JSONObject();
s(wo, "name", wn.getString("name"));
s(wo, "title", wn.getString("title"));
@ -34,6 +37,7 @@ public class ClientConfigurationComponent extends Component {
mt.buildClientConfiguration(wo);
}
}
s(t, "defaultworld", c.getString("defaultworld", defaultWorld == null ? "world" : defaultWorld.world.getName()));
}
});
}

View File

@ -10,6 +10,11 @@ import java.util.Set;
public class ConfigurationNode implements Map<String, Object> {
public Map<String, Object> entries;
public ConfigurationNode() {
entries = new HashMap<String, Object>();
}
public ConfigurationNode(org.bukkit.util.config.ConfigurationNode node) {
entries = new HashMap<String, Object>();
for(String key : node.getKeys(null)) {
@ -18,6 +23,9 @@ public class ConfigurationNode implements Map<String, Object> {
}
public ConfigurationNode(Map<String, Object> map) {
if (map == null) {
throw new IllegalArgumentException();
}
entries = map;
}
@ -152,6 +160,28 @@ public class ConfigurationNode implements Map<String, Object> {
return nodes;
}
public void extend(Map<String, Object> other) {
if (other != null)
extendMap(this, other);
}
private final static void extendMap(Map<String, Object> left, Map<String, Object> right) {
ConfigurationNode original = new ConfigurationNode(left);
for(Map.Entry<String, Object> entry : right.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof Map<?, ?>) {
ConfigurationNode subnode = original.getNode(key);
if (subnode == null) {
original.put(key, subnode = new ConfigurationNode());
}
extendMap(subnode, (Map<String, Object>)value);
} else {
original.put(key, value);
}
}
}
public <T> T createInstance(Class<?>[] constructorParameters, Object[] constructorArguments) {
String typeName = getString("class");
try {

View File

@ -74,8 +74,6 @@ public class DynmapPlugin extends JavaPlugin {
org.bukkit.util.config.Configuration bukkitConfiguration = new org.bukkit.util.config.Configuration(new File(this.getDataFolder(), "configuration.txt"));
bukkitConfiguration.load();
configuration = new ConfigurationNode(bukkitConfiguration);
processWorldTemplates(configuration);
loadDebuggers();
@ -150,20 +148,24 @@ public class DynmapPlugin extends JavaPlugin {
@Override
public void onDisable() {
int componentCount = componentManager.components.size();
for(Component component : componentManager.components) {
component.dispose();
if (componentManager != null) {
int componentCount = componentManager.components.size();
for(Component component : componentManager.components) {
component.dispose();
}
componentManager.clear();
Log.info("Unloaded " + componentCount + " components.");
}
componentManager.clear();
Log.info("Unloaded " + componentCount + " components.");
mapManager.stopRendering();
if (mapManager != null) {
mapManager.stopRendering();
}
if (webServer != null) {
webServer.shutdown();
webServer = null;
}
Debug.clearDebuggers();
}
@ -344,10 +346,7 @@ public class DynmapPlugin extends JavaPlugin {
}
} else if (c.equals("reload") && checkPlayerPermission(sender, "reload")) {
sender.sendMessage("Reloading Dynmap...");
is_reload = true;
onDisable();
onEnable();
is_reload = false;
reload();
sender.sendMessage("Dynmap reloaded");
return true;
}
@ -365,86 +364,67 @@ public class DynmapPlugin extends JavaPlugin {
}
return true;
}
/* Prepare for sky worlds... */
private static final String[] templateworldtypes = { "normal", "nether" };
private static final Environment[] templateworldenv = { Environment.NORMAL, Environment.NETHER };
private void processWorldTemplates(ConfigurationNode node) {
ConfigurationNode template = node.getNode("template");
if(template == null)
return;
List<ConfigurationNode> worlds = node.getNodes("worlds");
boolean worldsupdated = false;
/* Initialize even if no worlds section */
if(worlds == null) {
worlds = new ArrayList<ConfigurationNode>();
worldsupdated = true;
}
List<String> hiddenworlds = node.getStrings("hiddenworlds", Collections.EMPTY_LIST);
/* Iternate by world type - so that order in templateworldtypes drives our default order */
for(int wtype = 0; wtype < templateworldtypes.length; wtype++) {
ConfigurationNode typetemplate = template.getNode(templateworldtypes[wtype]);
if(typetemplate == null)
continue;
for(World w : getServer().getWorlds()) { /* Roll through worlds */
String wn = w.getName();
/* Skip processing on hidden worlds */
if(hiddenworlds.contains(wn))
continue;
/* Find node for this world, if any */
ConfigurationNode world = null;
int index;
for(index = 0; index < worlds.size(); index++) {
ConfigurationNode ww = worlds.get(index);
if(wn.equals(ww.getString("name", ""))) {
world = ww;
break;
}
}
/* Check type of world - skip if not right for current template */
if(w.getEnvironment() != templateworldenv[wtype])
continue;
/* World not found - need to use template */
if(world == null) {
ConfigurationNode newworldnode = new ConfigurationNode(new HashMap<String,Object>(typetemplate)); /* Copy it */
newworldnode.put("name", w.getName());
newworldnode.put("title", w.getName());
worlds.add(newworldnode);
worldsupdated = true;
Log.info("World '" + w.getName() + "' configuration inherited from template");
}
else { /* Else, definition is there, but may be incomplete */
boolean wupd = false;
List<ConfigurationNode> tempmaps = typetemplate.getList("maps");
if((tempmaps != null) && (world.get("maps") == null)) { /* World with no maps section */
world.put("maps", tempmaps);
Log.info("World '" + w.getName() + "' configuration inherited maps from template");
wupd = true;
}
ConfigurationNode tempcenter = typetemplate.getNode("center");
if((tempcenter != null) && (world.get("center") == null)) { /* World with no center */
world.put("center", new ConfigurationNode(new HashMap<String,Object>(tempcenter)));
Log.info("World '" + w.getName() + "' configuration inherited center from template");
wupd = true;
}
if(world.getString("title", null) == null) {
world.put("title", w.getName());
wupd = true;
}
if(wupd) {
worldsupdated = true;
worlds.set(index, world);
}
}
public ConfigurationNode getWorldConfiguration(World world) {
ConfigurationNode finalConfiguration = new ConfigurationNode();
finalConfiguration.put("name", world.getName());
finalConfiguration.put("title", world.getName());
ConfigurationNode worldConfiguration = getWorldConfigurationNode(world.getName());
// Get the template.
ConfigurationNode templateConfiguration = null;
if (worldConfiguration != null) {
String templateName = worldConfiguration.getString("template");
if (templateName != null) {
templateConfiguration = getTemplateConfigurationNode(templateName);
}
}
if(worldsupdated) {
node.put("worlds", worlds);
// Template not found, using default template.
if (templateConfiguration == null) {
templateConfiguration = getDefaultTemplateConfigurationNode(world);
}
// Merge the finalConfiguration, templateConfiguration and worldConfiguration.
finalConfiguration.extend(templateConfiguration);
finalConfiguration.extend(worldConfiguration);
Log.info("Configuration of world " + world.getName());
for(Map.Entry<String, Object> e : finalConfiguration.entrySet()) {
Log.info(e.getKey() + ": " + e.getValue());
}
return finalConfiguration;
}
public boolean isReload() {
return is_reload;
private ConfigurationNode getDefaultTemplateConfigurationNode(World world) {
Environment environment = world.getEnvironment();
String environmentName = environment.name().toLowerCase();
Log.info("Using environment as template: " + environmentName);
return getTemplateConfigurationNode(environmentName);
}
private ConfigurationNode getWorldConfigurationNode(String worldName) {
for(ConfigurationNode worldNode : configuration.getNodes("worlds")) {
if (worldName.equals(worldNode.getString("name"))) {
return worldNode;
}
}
return new ConfigurationNode();
}
private ConfigurationNode getTemplateConfigurationNode(String templateName) {
ConfigurationNode templatesNode = configuration.getNode("templates");
if (templatesNode != null) {
return templatesNode.getNode(templateName);
}
return null;
}
public void reload() {
PluginManager pluginManager = getServer().getPluginManager();
pluginManager.disablePlugin(this);
pluginManager.enablePlugin(this);
}
}

View File

@ -9,4 +9,5 @@ public class DynmapWorld {
public World world;
public List<MapType> maps = new ArrayList<MapType>();
public UpdateQueue updates = new UpdateQueue();
public ConfigurationNode configuration;
}

View File

@ -57,6 +57,12 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
writeConfiguration();
}
});
plugin.events.addListener("worldactivated", new Event.Listener<DynmapWorld>() {
@Override
public void triggered(DynmapWorld t) {
writeConfiguration();
}
});
}
protected File getStandaloneFile(String filename) {
@ -87,7 +93,7 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
protected void writeUpdates() {
File outputFile;
//Handles Updates
for (DynmapWorld dynmapWorld : plugin.mapManager.worlds.values()) {
for (DynmapWorld dynmapWorld : plugin.mapManager.getWorlds()) {
World world = dynmapWorld.world;
JSONObject update = new JSONObject();

View File

@ -1,9 +1,12 @@
package org.dynmap;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.bukkit.Chunk;
@ -17,8 +20,8 @@ public class MapManager {
public AsynchronousQueue<MapTile> tileQueue;
public AsynchronousQueue<ImageWriter> writeQueue;
public Map<String, DynmapWorld> worlds = new HashMap<String, DynmapWorld>();
public Map<String, DynmapWorld> inactiveworlds = new HashMap<String, DynmapWorld>();
public List<DynmapWorld> worlds = new ArrayList<DynmapWorld>();
public Map<String, DynmapWorld> worldsLookup = new HashMap<String, DynmapWorld>();
private BukkitScheduler scheduler;
private DynmapPlugin plug_in;
private double timeslice_interval = 0.0;
@ -35,13 +38,14 @@ public class MapManager {
}
public DynmapWorld getWorld(String name) {
DynmapWorld world = worlds.get(name);
if(world == null) {
world = inactiveworlds.get(name);
}
DynmapWorld world = worldsLookup.get(name);
return world;
}
public Collection<DynmapWorld> getWorlds() {
return worlds;
}
private class FullWorldRenderState implements Runnable {
DynmapWorld world; /* Which world are we rendering */
Location loc; /* Start location */
@ -64,7 +68,7 @@ public class MapManager {
/* Single tile render - used for incremental renders */
FullWorldRenderState(MapTile t) {
world = worlds.get(t.getWorld().getName());
world = getWorld(t.getWorld().getName());
tile0 = t;
}
@ -136,7 +140,7 @@ public class MapManager {
}
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration) {
plug_in = plugin;
mapman = this;
this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() {
@ -157,42 +161,18 @@ public class MapManager {
timeslice_interval = configuration.getDouble("timesliceinterval", 0.5);
for(ConfigurationNode worldConfiguration : configuration.getNodes("worlds")) {
String worldName = worldConfiguration.getString("name");
DynmapWorld world = new DynmapWorld();
Event.Listener<MapTile> invalitateListener = new Event.Listener<MapTile>() {
@Override
public void triggered(MapTile t) {
invalidateTile(t);
}
};
Log.info("Loading maps of world '" + worldName + "'...");
for(MapType map : worldConfiguration.<MapType>createInstances("maps", new Class<?>[0], new Object[0])) {
map.onTileInvalidated.addListener(invalitateListener);
world.maps.add(map);
}
Log.info("Loaded " + world.maps.size() + " maps of world '" + worldName + "'.");
inactiveworlds.put(worldName, world);
World bukkitWorld = plugin.getServer().getWorld(worldName);
if (bukkitWorld != null)
activateWorld(bukkitWorld);
}
scheduler = plugin.getServer().getScheduler();
plug_in = plugin;
tileQueue.start();
writeQueue.start();
for (World world : plug_in.getServer().getWorlds()) {
activateWorld(world);
}
}
void renderFullWorld(Location l) {
DynmapWorld world = worlds.get(l.getWorld().getName());
DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null) {
Log.severe("Could not render: world '" + l.getWorld().getName() + "' not defined in configuration.");
return;
@ -211,21 +191,36 @@ public class MapManager {
}
public void activateWorld(World w) {
DynmapWorld world = inactiveworlds.get(w.getName());
if (world == null) {
world = worlds.get(w.getName());
} else {
inactiveworlds.remove(w.getName());
ConfigurationNode worldConfiguration = plug_in.getWorldConfiguration(w);
if (!worldConfiguration.getBoolean("enabled", false)) {
Log.info("World '" + w.getName() + "' disabled");
return;
}
if (world != null) {
world.world = w;
worlds.put(w.getName(), world);
Log.info("Activated world '" + w.getName() + "' in Dynmap.");
String worldName = w.getName();
Event.Listener<MapTile> invalitateListener = new Event.Listener<MapTile>() {
@Override
public void triggered(MapTile t) {
invalidateTile(t);
}
};
DynmapWorld dynmapWorld = new DynmapWorld();
dynmapWorld.world = w;
dynmapWorld.configuration = worldConfiguration;
Log.info("Loading maps of world '" + worldName + "'...");
for(MapType map : worldConfiguration.<MapType>createInstances("maps", new Class<?>[0], new Object[0])) {
map.onTileInvalidated.addListener(invalitateListener);
dynmapWorld.maps.add(map);
}
Log.info("Loaded " + dynmapWorld.maps.size() + " maps of world '" + worldName + "'.");
worlds.add(dynmapWorld);
worldsLookup.put(w.getName(), dynmapWorld);
plug_in.events.trigger("worldactivated", dynmapWorld);
}
public int touch(Location l) {
DynmapWorld world = worlds.get(l.getWorld().getName());
DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null)
return 0;
int invalidates = 0;
@ -276,7 +271,7 @@ public class MapManager {
}
public void pushUpdate(Object update) {
for(DynmapWorld world : worlds.values()) {
for(DynmapWorld world : getWorlds()) {
world.updates.pushUpdate(update);
}
}
@ -286,12 +281,12 @@ public class MapManager {
}
public void pushUpdate(String worldName, Object update) {
DynmapWorld world = worlds.get(worldName);
DynmapWorld world = getWorld(worldName);
world.updates.pushUpdate(update);
}
public Object[] getWorldUpdates(String worldName, long since) {
DynmapWorld world = worlds.get(worldName);
DynmapWorld world = getWorld(worldName);
if (world == null)
return new Object[0];
return world.updates.getUpdatedObjects(since);

View File

@ -5,6 +5,8 @@ import java.util.Date;
import java.util.Map;
import org.dynmap.DynmapPlugin;
import org.dynmap.DynmapWorld;
import org.dynmap.Event;
import org.dynmap.web.HttpHandler;
import org.dynmap.web.HttpRequest;
import org.dynmap.web.HttpResponse;
@ -16,6 +18,12 @@ public class ClientConfigurationHandler implements HttpHandler {
private byte[] cachedConfiguration = null;
public ClientConfigurationHandler(DynmapPlugin plugin) {
this.plugin = plugin;
plugin.events.addListener("worldactivated", new Event.Listener<DynmapWorld>() {
@Override
public void triggered(DynmapWorld t) {
cachedConfiguration = null;
}
});
}
@Override
public void handle(String path, HttpRequest request, HttpResponse response) throws Exception {