diff --git a/configuration.txt b/configuration.txt index 6d36d4ec..3bbb840f 100644 --- a/configuration.txt +++ b/configuration.txt @@ -21,7 +21,7 @@ components: type: timeofdayclock showdigitalclock: true #showweather: true - #- class: org.dynmap.ClientComponent + #- class: org.dynmap.regions.RegionsComponent # type: regions # name: WorldGuard # useworldpath: true diff --git a/src/main/java/org/dynmap/ClientComponent.java b/src/main/java/org/dynmap/ClientComponent.java index d8972d2c..112bf5ea 100644 --- a/src/main/java/org/dynmap/ClientComponent.java +++ b/src/main/java/org/dynmap/ClientComponent.java @@ -14,15 +14,24 @@ public class ClientComponent extends Component { super(plugin, configuration); plugin.events.addListener("buildclientconfiguration", new Event.Listener() { @Override - public void triggered(JSONObject t) { - JSONObject o = convertMap(configuration); - o.remove("class"); - a(t, "components", o); + public void triggered(JSONObject root) { + buildClientConfiguration(root); } }); } - JSONObject convertMap(Map m) { + protected void buildClientConfiguration(JSONObject root) { + JSONObject o = createClientConfiguration(); + a(root, "components", o); + } + + protected JSONObject createClientConfiguration() { + JSONObject o = convertMap(configuration); + o.remove("class"); + return o; + } + + protected static final JSONObject convertMap(Map m) { JSONObject o = new JSONObject(); for(Map.Entry entry : m.entrySet()) { s(o, entry.getKey(), convert(entry.getValue())); @@ -30,7 +39,7 @@ public class ClientComponent extends Component { return o; } - JSONArray convertList(List l) { + protected static final JSONArray convertList(List l) { JSONArray o = new JSONArray(); for(Object entry : l) { o.add(convert(entry)); @@ -38,7 +47,7 @@ public class ClientComponent extends Component { return o; } - Object convert(Object o) { + protected static final Object convert(Object o) { if (o instanceof Map) { return convertMap((Map)o); } else if (o instanceof List) { diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index fc6a9c27..4f99209b 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -38,13 +38,14 @@ import org.dynmap.debug.Debugger; import org.dynmap.permissions.NijikokunPermissions; import org.dynmap.permissions.OpPermissions; import org.dynmap.permissions.PermissionProvider; +import org.dynmap.regions.RegionHandler; import org.dynmap.web.HttpServer; import org.dynmap.web.Json; import org.dynmap.web.handlers.ClientConfigurationHandler; import org.dynmap.web.handlers.ClientUpdateHandler; import org.dynmap.web.handlers.FilesystemHandler; -import org.dynmap.web.handlers.RegionHandler; import org.dynmap.web.handlers.SendMessageHandler; +import org.json.simple.JSONObject; public class DynmapPlugin extends JavaPlugin { public HttpServer webServer = null; @@ -83,11 +84,6 @@ public class DynmapPlugin extends JavaPlugin { loadDebuggers(); - // Load components. - for(Component component : configuration.createInstances("components", new Class[] { DynmapPlugin.class }, new Object[] { this })) { - componentManager.add(component); - } - tilesDirectory = getFile(configuration.getString("tilespath", "web/tiles")); if (!tilesDirectory.isDirectory() && !tilesDirectory.mkdirs()) { Log.warning("Could not create directory for tiles ('" + tilesDirectory + "')."); @@ -120,9 +116,16 @@ public class DynmapPlugin extends JavaPlugin { enabledTriggers.add((String) trigger); } } + + // Load components. + for(Component component : configuration.createInstances("components", new Class[] { DynmapPlugin.class }, new Object[] { this })) { + componentManager.add(component); + } registerEvents(); + startWebserver(); + /* Print version info */ PluginDescriptionFile pdfFile = this.getDescription(); Log.info("version " + pdfFile.getVersion() + " is enabled" ); @@ -146,20 +149,12 @@ public class DynmapPlugin extends JavaPlugin { webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web")))); webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory)); webServer.handlers.put("/up/", new ClientUpdateHandler(mapManager, playerList, getServer(), configuration.getBoolean("health-in-json", false))); - webServer.handlers.put("/up/configuration", new ClientConfigurationHandler(this, configuration.getNode("web"))); - /* See if regions configuration branch is present */ - for(ConfigurationNode type : configuration.getNodes("web/components")) { - if(type.getString("type").equalsIgnoreCase("regions")) { - String fname = type.getString("filename", "regions.yml"); - fname = "/standalone/" + fname.substring(0, fname.lastIndexOf('.')) + "_"; /* Find our path base */ - webServer.handlers.put(fname + "*", new RegionHandler(type)); - } - } + webServer.handlers.put("/up/configuration", new ClientConfigurationHandler(this)); - if (configuration.getNode("web").getBoolean("allowwebchat", false)) { + if (configuration.getBoolean("allowwebchat", false)) { SendMessageHandler messageHandler = new SendMessageHandler() {{ - maximumMessageInterval = (configuration.getNode("web").getInteger("webchat-interval", 1) * 1000); - spamMessage = "\""+configuration.getNode("web").getString("spammessage", "You may only chat once every %interval% seconds.")+"\""; + maximumMessageInterval = (configuration.getInteger("webchat-interval", 1) * 1000); + spamMessage = "\""+configuration.getString("spammessage", "You may only chat once every %interval% seconds.")+"\""; onMessageReceived.addListener(new Listener() { @Override public void triggered(Message t) { @@ -170,13 +165,14 @@ public class DynmapPlugin extends JavaPlugin { webServer.handlers.put("/up/sendmessage", messageHandler); } - + } + + public void startWebserver() { try { webServer.startServer(); } catch (IOException e) { - Log.severe("Failed to start WebServer on " + bindAddress + ":" + port + "!"); + Log.severe("Failed to start WebServer on " + webServer.getAddress() + ":" + webServer.getPort() + "!"); } - } public void onDisable() { @@ -259,7 +255,7 @@ public class DynmapPlugin extends JavaPlugin { } // To announce when players have joined/quit/chatted. - if (configuration.getNode("web").getBoolean("allowchat", false)) { + if (configuration.getBoolean("allowchat", false)) { // To handle webchat. PlayerListener playerListener = new DynmapPlayerChatListener(this); //getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, playerListener, Priority.Normal, this); @@ -397,7 +393,8 @@ public class DynmapPlugin extends JavaPlugin { private void jsonConfig() { File outputFile; - ConfigurationNode clientConfig = configuration.getNode("web"); + JSONObject clientConfiguration = new JSONObject(); + events.trigger("buildclientconfiguration", clientConfiguration); File webpath = new File(configuration.getString("webpath", "web"), "standalone/dynmap_config.json"); if (webpath.isAbsolute()) outputFile = webpath; @@ -406,7 +403,7 @@ public class DynmapPlugin extends JavaPlugin { try { FileOutputStream fos = new FileOutputStream(outputFile); - fos.write(Json.stringifyJson(clientConfig).getBytes()); + fos.write(clientConfiguration.toJSONString().getBytes()); fos.close(); } catch (FileNotFoundException ex) { Log.severe("Exception while writing JSON-configuration-file.", ex); diff --git a/src/main/java/org/dynmap/HeroChatHandler.java b/src/main/java/org/dynmap/HeroChatHandler.java index e53c0abf..8c3ddac7 100644 --- a/src/main/java/org/dynmap/HeroChatHandler.java +++ b/src/main/java/org/dynmap/HeroChatHandler.java @@ -239,15 +239,13 @@ public class HeroChatHandler { public HeroChatHandler(ConfigurationNode cfg, DynmapPlugin plugin, Server server) { /* If we're enabling hero chat support */ - if (cfg.getNode("web").getBoolean("enableherochat", false)) { + if (cfg.getBoolean("enableherochat", false)) { Log.info("HeroChat support configured"); this.plugin = plugin; /* Now, get the monitored channel list */ - hcchannels = cfg.getStrings("web/herochatchannels", - DEF_CHANNELS); + hcchannels = cfg.getStrings("herochatchannels", DEF_CHANNELS); /* And get channel to send web messages */ - hcwebinputchannel = cfg.getNode("web").getString( - "herochatwebchannel", DEF_CHANNEL); + hcwebinputchannel = cfg.getString("herochatwebchannel", DEF_CHANNEL); Plugin hc = server.getPluginManager().getPlugin("HeroChat"); if(hc != null) { activateHeroChat(hc); diff --git a/src/main/java/org/dynmap/JsonTimerTask.java b/src/main/java/org/dynmap/JsonTimerTask.java index 622ab177..bc1dd83e 100644 --- a/src/main/java/org/dynmap/JsonTimerTask.java +++ b/src/main/java/org/dynmap/JsonTimerTask.java @@ -33,11 +33,6 @@ class JsonTimerTask extends TimerTask { this.server = this.plugin.getServer(); this.mapManager = this.plugin.getMapManager(); this.configuration = config; - for(ConfigurationNode type : configuration.getNode("web").getNodes("components")) - if(type.getString("type").equalsIgnoreCase("regions")) { - this.regions = type; - break; - } } public void run() { @@ -79,16 +74,13 @@ class JsonTimerTask extends TimerTask { } //Handles Updates - for (World world : this.server.getWorlds()) { - //Parse region file for multi world style - if (regions != null) - if (regions.getBoolean("useworldpath", false)) - parseRegionFile(world.getName() + "/" + regions.getString("filename", "regions.yml"), regions.getString("filename", "regions.yml").replace(".", "_" + world.getName() + ".yml")); - + for (DynmapWorld dynmapWorld : plugin.mapManager.worlds.values()) { + World world = dynmapWorld.world; current = System.currentTimeMillis(); Client.Update update = new Client.Update(); - + WorldUpdate worldUpdate = new WorldUpdate(dynmapWorld, update); + plugin.events.trigger("buildingupdate", worldUpdate); update.timestamp = current; update.servertime = world.getTime() % 24000; update.hasStorm = world.hasStorm(); @@ -105,6 +97,8 @@ class JsonTimerTask extends TimerTask { update.updates = mapManager.getWorldUpdates(world.getName(), current - (jsonInterval + 10000)); + plugin.events.trigger("buildupdate", worldUpdate); + File webWorldPath = new File(this.configuration.getString("webpath", "web"), "standalone/dynmap_" + world.getName() + ".json"); if (webWorldPath.isAbsolute()) outputFile = webWorldPath; @@ -120,51 +114,10 @@ class JsonTimerTask extends TimerTask { } catch (IOException ioe) { Log.severe("Exception while writing JSON-file.", ioe); } + plugin.events.trigger("updatewritten", worldUpdate); } lastTimestamp = System.currentTimeMillis(); - - //Parse regions file for non worlds style - if (regions != null) - if (!regions.getBoolean("useworldpath", false)) - parseRegionFile(regions.getString("filename", "regions.yml"), regions.getString("filename", "regions.yml")); - } - - //handles parsing and writing region json files - private void parseRegionFile(String regionFile, String outputFileName) - { - File outputFile; - org.bukkit.util.config.Configuration regionConfig = null; - if(regions.getBoolean("useworldpath", false)) - { - if(new File("plugins/"+regions.getString("name", "WorldGuard"), regionFile).exists()) - regionConfig = new org.bukkit.util.config.Configuration(new File("plugins/"+regions.getString("name", "WorldGuard"), regionFile)); - else if(new File("plugins/"+regions.getString("name", "WorldGuard")+"/worlds", regionFile).exists()) - regionConfig = new org.bukkit.util.config.Configuration(new File("plugins/"+regions.getString("name", "WorldGuard")+"/worlds", regionFile)); - } - else - regionConfig = new org.bukkit.util.config.Configuration(new File("plugins/"+regions.getString("name", "WorldGuard"), regionFile)); - //File didn't exist - if(regionConfig == null) - return; - regionConfig.load(); - - outputFileName = outputFileName.substring(0, outputFileName.lastIndexOf("."))+".json"; - - File webWorldPath = new File(this.configuration.getString("webpath", "web")+"/standalone/", outputFileName); - Map regionData = (Map) regionConfig.getProperty(regions.getString("basenode", "regions")); - if (webWorldPath.isAbsolute()) - outputFile = webWorldPath; - else { - outputFile = new File(plugin.getDataFolder(), webWorldPath.toString()); - } - try { - FileOutputStream fos = new FileOutputStream(outputFile); - fos.write(Json.stringifyJson(regionData).getBytes()); - fos.close(); - } catch (FileNotFoundException ex) { - Log.severe("Exception while writing JSON-file.", ex); - } catch (IOException ioe) { - Log.severe("Exception while writing JSON-file.", ioe); - } + + plugin.events.trigger("updateswritten", null); } } diff --git a/src/main/java/org/dynmap/WorldUpdate.java b/src/main/java/org/dynmap/WorldUpdate.java new file mode 100644 index 00000000..947bd40d --- /dev/null +++ b/src/main/java/org/dynmap/WorldUpdate.java @@ -0,0 +1,11 @@ +package org.dynmap; + +public class WorldUpdate { + public DynmapWorld world; + public Client.Update update; + + public WorldUpdate(DynmapWorld world, Client.Update update) { + this.world = world; + this.update = update; + } +} diff --git a/src/main/java/org/dynmap/web/handlers/RegionHandler.java b/src/main/java/org/dynmap/regions/RegionHandler.java similarity index 97% rename from src/main/java/org/dynmap/web/handlers/RegionHandler.java rename to src/main/java/org/dynmap/regions/RegionHandler.java index f1b42bae..a8bc8f64 100644 --- a/src/main/java/org/dynmap/web/handlers/RegionHandler.java +++ b/src/main/java/org/dynmap/regions/RegionHandler.java @@ -1,4 +1,4 @@ -package org.dynmap.web.handlers; +package org.dynmap.regions; import java.io.File; import java.io.FileNotFoundException; @@ -11,6 +11,8 @@ import org.dynmap.ConfigurationNode; import org.dynmap.web.HttpRequest; import org.dynmap.web.HttpResponse; import org.dynmap.web.Json; +import org.dynmap.web.handlers.FileHandler; + import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; diff --git a/src/main/java/org/dynmap/regions/RegionsComponent.java b/src/main/java/org/dynmap/regions/RegionsComponent.java new file mode 100644 index 00000000..bd21d5d2 --- /dev/null +++ b/src/main/java/org/dynmap/regions/RegionsComponent.java @@ -0,0 +1,86 @@ +package org.dynmap.regions; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; + +import org.bukkit.World; +import org.dynmap.ClientComponent; +import org.dynmap.ConfigurationNode; +import org.dynmap.DynmapPlugin; +import org.dynmap.Event; +import org.dynmap.Log; +import org.dynmap.WorldUpdate; +import org.dynmap.web.Json; + +public class RegionsComponent extends ClientComponent { + + public RegionsComponent(final DynmapPlugin plugin, final ConfigurationNode configuration) { + super(plugin, configuration); + + // For internal webserver. + String fname = configuration.getString("filename", "regions.yml"); + plugin.webServer.handlers.put("/standalone/" + fname.substring(0, fname.lastIndexOf('.')) + "_*", new RegionHandler(configuration)); + + // For external webserver. + //Parse region file for multi world style + if (configuration.getBoolean("useworldpath", false)) { + plugin.events.addListener("updatewritten", new Event.Listener() { + @Override + public void triggered(WorldUpdate t) { + World world = t.world.world; + parseRegionFile(world.getName() + "/" + configuration.getString("filename", "regions.yml"), configuration.getString("filename", "regions.yml").replace(".", "_" + world.getName() + ".yml")); + } + }); + } else { + plugin.events.addListener("updateswritten", new Event.Listener() { + @Override + public void triggered(Object t) { + parseRegionFile(configuration.getString("filename", "regions.yml"), configuration.getString("filename", "regions.yml")); + } + }); + } + } + + //handles parsing and writing region json files + private void parseRegionFile(String regionFile, String outputFileName) + { + File outputFile; + org.bukkit.util.config.Configuration regionConfig = null; + if(configuration.getBoolean("useworldpath", false)) + { + if(new File("plugins/"+configuration.getString("name", "WorldGuard"), regionFile).exists()) + regionConfig = new org.bukkit.util.config.Configuration(new File("plugins/"+configuration.getString("name", "WorldGuard"), regionFile)); + else if(new File("plugins/"+configuration.getString("name", "WorldGuard")+"/worlds", regionFile).exists()) + regionConfig = new org.bukkit.util.config.Configuration(new File("plugins/"+configuration.getString("name", "WorldGuard")+"/worlds", regionFile)); + } + else + regionConfig = new org.bukkit.util.config.Configuration(new File("plugins/"+configuration.getString("name", "WorldGuard"), regionFile)); + //File didn't exist + if(regionConfig == null) + return; + regionConfig.load(); + + outputFileName = outputFileName.substring(0, outputFileName.lastIndexOf("."))+".json"; + + File webWorldPath = new File(this.configuration.getString("webpath", "web")+"/standalone/", outputFileName); + Map regionData = (Map) regionConfig.getProperty(configuration.getString("basenode", "regions")); + if (webWorldPath.isAbsolute()) + outputFile = webWorldPath; + else { + outputFile = new File(plugin.getDataFolder(), webWorldPath.toString()); + } + try { + FileOutputStream fos = new FileOutputStream(outputFile); + fos.write(Json.stringifyJson(regionData).getBytes()); + fos.close(); + } catch (FileNotFoundException ex) { + Log.severe("Exception while writing JSON-file.", ex); + } catch (IOException ioe) { + Log.severe("Exception while writing JSON-file.", ioe); + } + } + +} diff --git a/src/main/java/org/dynmap/web/HttpServer.java b/src/main/java/org/dynmap/web/HttpServer.java index 8ada63e0..f9330942 100644 --- a/src/main/java/org/dynmap/web/HttpServer.java +++ b/src/main/java/org/dynmap/web/HttpServer.java @@ -28,6 +28,14 @@ public class HttpServer extends Thread { this.port = port; } + public InetAddress getAddress() { + return bindAddress; + } + + public int getPort() { + return port; + } + public void startServer() throws IOException { sock = new ServerSocket(port, 50, bindAddress); /* 5 too low - more than a couple users during render will get connect errors on some tile loads */ listeningThread = this; diff --git a/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java b/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java index 9a0c0d89..84d1d790 100644 --- a/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java +++ b/src/main/java/org/dynmap/web/handlers/ClientConfigurationHandler.java @@ -13,11 +13,9 @@ import org.json.simple.JSONObject; public class ClientConfigurationHandler implements HttpHandler { private DynmapPlugin plugin; - private Map configuration; private byte[] cachedConfiguration = null; - public ClientConfigurationHandler(DynmapPlugin plugin, Map configuration) { + public ClientConfigurationHandler(DynmapPlugin plugin) { this.plugin = plugin; - this.configuration = configuration; } @Override public void handle(String path, HttpRequest request, HttpResponse response) throws Exception {