From fb01f6ecf7ef393480eaa5febc7941d94360b1f0 Mon Sep 17 00:00:00 2001 From: Jason Booth Date: Wed, 9 Feb 2011 11:35:09 -0600 Subject: [PATCH 1/8] New config to Disable Webserver New feature and config to output JSON to file --- configuration.txt | 9 +++ src/main/java/org/dynmap/DynmapPlugin.java | 88 ++++++++++++++++------ 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/configuration.txt b/configuration.txt index 0c880ec7..c8190d3d 100755 --- a/configuration.txt +++ b/configuration.txt @@ -15,6 +15,15 @@ webserver-bindaddress: 0.0.0.0 # The TCP-port the webserver will listen on. webserver-port: 8123 +# Disables Webserver portion of Dynmap (Advanced users only) +disable-webserver: true + +# Writes JSON to file in the webpath +jsonfile: true + +# How often the json file gets written to(in seconds) +jsonfile-interval: 1000 + disabledcommands: - fullrender diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index e3aab1ea..b660d14a 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -1,11 +1,14 @@ package org.dynmap; import java.io.File; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Map; import java.util.logging.Logger; +import java.util.Timer; import org.bukkit.Server; import org.bukkit.World; @@ -22,6 +25,7 @@ import org.dynmap.web.HttpServer; import org.dynmap.web.handlers.ClientConfigurationHandler; import org.dynmap.web.handlers.ClientUpdateHandler; import org.dynmap.web.handlers.FilesystemHandler; +import org.dynmap.web.Json; public class DynmapPlugin extends JavaPlugin { @@ -32,6 +36,8 @@ public class DynmapPlugin extends JavaPlugin { private PlayerList playerList; private Configuration configuration; + private Timer timer; + private BukkitPlayerDebugger debugger = new BukkitPlayerDebugger(this); public static File dataRoot; @@ -64,31 +70,43 @@ public class DynmapPlugin extends JavaPlugin { mapManager = new MapManager(getWorld(), debugger, configuration); mapManager.startManager(); - InetAddress bindAddress; - { - String address = configuration.getString("webserver-bindaddress", "0.0.0.0"); - try { - bindAddress = address.equals("0.0.0.0") - ? null - : InetAddress.getByName(address); - } catch (UnknownHostException e) { - bindAddress = null; - } - } - int port = configuration.getInt("webserver-port", 8123); + if(!configuration.getBoolean("disable-webserver", true)) { + InetAddress bindAddress; + { + String address = configuration.getString("webserver-bindaddress", "0.0.0.0"); + try { + bindAddress = address.equals("0.0.0.0") + ? null + : InetAddress.getByName(address); + } catch (UnknownHostException e) { + bindAddress = null; + } + } + int port = configuration.getInt("webserver-port", 8123); - webServer = new HttpServer(bindAddress, port); - webServer.handlers.put("/", new FilesystemHandler(mapManager.webDirectory)); - webServer.handlers.put("/tiles/", new FilesystemHandler(mapManager.tileDirectory)); - webServer.handlers.put("/up/", new ClientUpdateHandler(mapManager, playerList, getWorld())); - webServer.handlers.put("/up/configuration", new ClientConfigurationHandler((Map) configuration.getProperty("web"))); + webServer = new HttpServer(bindAddress, port); + webServer.handlers.put("/", new FilesystemHandler(mapManager.webDirectory)); + webServer.handlers.put("/tiles/", new FilesystemHandler(mapManager.tileDirectory)); + webServer.handlers.put("/up/", new ClientUpdateHandler(mapManager, playerList, getWorld())); + webServer.handlers.put("/up/configuration", new ClientConfigurationHandler((Map) configuration.getProperty("web"))); - try { - webServer.startServer(); - } catch (IOException e) { - log.severe("Failed to start WebServer on " + bindAddress + ":" + port + "!"); - } + try { + webServer.startServer(); + } catch (IOException e) { + log.severe("Failed to start WebServer on " + bindAddress + ":" + port + "!"); + } + } + else + System.out.println("WebServer Disabled"); + if(configuration.getBoolean("jsonfile", false)) { + jsonConfig(); + int jsonInterval = configuration.getInt("jsonfile", 1) * 1000; + timer = new Timer(); + timer.scheduleAtFixedRate(new JsonTimerTask(this, configuration), jsonInterval, jsonInterval); + } + else + System.out.println("JsonFile Writing Disabled"); registerEvents(); } @@ -111,4 +129,30 @@ public class DynmapPlugin extends JavaPlugin { getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, playerListener, Priority.Normal, this); getServer().getPluginManager().registerEvent(Event.Type.PLAYER_CHAT, playerListener, Priority.Normal, this); } + + private void jsonConfig() + { + File outputFile; + Map clientConfig = (Map) configuration.getProperty("web"); + File webpath = new File(configuration.getString("webpath", "web"), "dynmap_config.json"); + if(webpath.isAbsolute()) + outputFile = webpath; + else + outputFile = new File(DynmapPlugin.dataRoot, webpath.toString()); + + try + { + FileOutputStream fos = new FileOutputStream(outputFile); + fos.write(Json.stringifyJson(clientConfig).getBytes()); + fos.close(); + } + catch(FileNotFoundException ex) + { + System.out.println("FileNotFoundException : " + ex); + } + catch(IOException ioe) + { + System.out.println("IOException : " + ioe); + } + } } From 2f6930bc17b937b50746ef22070a1384e1190dca Mon Sep 17 00:00:00 2001 From: Jason Booth Date: Wed, 9 Feb 2011 11:57:46 -0600 Subject: [PATCH 2/8] Removed System debug messages. Added missing JsonTimerTask.java --- src/main/java/org/dynmap/DynmapPlugin.java | 5 +- src/main/java/org/dynmap/JsonTimerTask.java | 71 +++++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/dynmap/JsonTimerTask.java diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index b660d14a..5c907ebc 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -96,8 +96,6 @@ public class DynmapPlugin extends JavaPlugin { log.severe("Failed to start WebServer on " + bindAddress + ":" + port + "!"); } } - else - System.out.println("WebServer Disabled"); if(configuration.getBoolean("jsonfile", false)) { jsonConfig(); @@ -105,8 +103,7 @@ public class DynmapPlugin extends JavaPlugin { timer = new Timer(); timer.scheduleAtFixedRate(new JsonTimerTask(this, configuration), jsonInterval, jsonInterval); } - else - System.out.println("JsonFile Writing Disabled"); + registerEvents(); } diff --git a/src/main/java/org/dynmap/JsonTimerTask.java b/src/main/java/org/dynmap/JsonTimerTask.java new file mode 100644 index 00000000..af85fc04 --- /dev/null +++ b/src/main/java/org/dynmap/JsonTimerTask.java @@ -0,0 +1,71 @@ +package org.dynmap; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.List; +import java.util.TimerTask; +import org.bukkit.Location; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.util.config.Configuration; +import org.dynmap.web.Json; + +class JsonTimerTask extends TimerTask +{ + private final DynmapPlugin plugin; + private Server server; + private PlayerList playerList; + private MapManager mapManager; + private Configuration configuration; + + public JsonTimerTask(DynmapPlugin instance, Configuration config) + { + this.plugin = instance; + this.server = this.plugin.getServer(); + this.playerList = new PlayerList(this.server); + this.mapManager = this.plugin.getMapManager(); + this.configuration = config; + } + + public void run() { + long current = System.currentTimeMillis(); + + Client.Update update = new Client.Update(); + update.timestamp = current; + update.servertime = ((World)this.server.getWorlds().get(0)).getTime(); + + Player[] players = this.playerList.getVisiblePlayers(); + update.players = new Client.Player[players.length]; + for (int i = 0; i < players.length; i++) { + Player p = players[i]; + update.players[i] = new Client.Player(p.getName(), p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ()); + } + update.updates = this.mapManager.updateQueue.getUpdatedObjects(current - 10L); + + File webpath = new File(this.configuration.getString("webpath", "web"), "dynmap.json"); + File outputFile; + if (webpath.isAbsolute()) + outputFile = webpath; + else { + outputFile = new File(DynmapPlugin.dataRoot, webpath.toString()); + } + try + { + FileOutputStream fos = new FileOutputStream(outputFile); + fos.write(Json.stringifyJson(update).getBytes()); + fos.close(); + } + catch (FileNotFoundException ex) + { + System.out.println("FileNotFoundException : " + ex); + } + catch (IOException ioe) + { + System.out.println("IOException : " + ioe); + } + } +} \ No newline at end of file From 3c1bde109214a80a62bc16cc5abc23f7f58211b0 Mon Sep 17 00:00:00 2001 From: Jason Booth Date: Thu, 17 Feb 2011 09:33:27 -0600 Subject: [PATCH 3/8] Updated JsonTimerTask.java to be Multi-World Compatible --- src/main/java/org/dynmap/JsonTimerTask.java | 75 ++++++++++++--------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/dynmap/JsonTimerTask.java b/src/main/java/org/dynmap/JsonTimerTask.java index af85fc04..a49f9852 100644 --- a/src/main/java/org/dynmap/JsonTimerTask.java +++ b/src/main/java/org/dynmap/JsonTimerTask.java @@ -32,40 +32,49 @@ class JsonTimerTask extends TimerTask } public void run() { - long current = System.currentTimeMillis(); + for(World world : this.server.getWorlds()) + { + long current = System.currentTimeMillis(); - Client.Update update = new Client.Update(); - update.timestamp = current; - update.servertime = ((World)this.server.getWorlds().get(0)).getTime(); + Client.Update update = new Client.Update(); + update.timestamp = current; + update.servertime = world.getTime(); - Player[] players = this.playerList.getVisiblePlayers(); - update.players = new Client.Player[players.length]; - for (int i = 0; i < players.length; i++) { - Player p = players[i]; - update.players[i] = new Client.Player(p.getName(), p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ()); - } - update.updates = this.mapManager.updateQueue.getUpdatedObjects(current - 10L); + update.timestamp = current; + update.servertime = world.getTime() % 24000; - File webpath = new File(this.configuration.getString("webpath", "web"), "dynmap.json"); - File outputFile; - if (webpath.isAbsolute()) - outputFile = webpath; - else { - outputFile = new File(DynmapPlugin.dataRoot, webpath.toString()); - } - try - { - FileOutputStream fos = new FileOutputStream(outputFile); - fos.write(Json.stringifyJson(update).getBytes()); - fos.close(); - } - catch (FileNotFoundException ex) - { - System.out.println("FileNotFoundException : " + ex); - } - catch (IOException ioe) - { - System.out.println("IOException : " + ioe); - } - } + + Player[] players = playerList.getVisiblePlayers(); + update.players = new Client.Player[players.length]; + for(int i=0;i Date: Thu, 17 Feb 2011 09:38:08 -0600 Subject: [PATCH 4/8] Changed disable-webserver and jsonfile to default false --- configuration.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration.txt b/configuration.txt index d567b2c2..865f9196 100755 --- a/configuration.txt +++ b/configuration.txt @@ -16,10 +16,10 @@ webserver-bindaddress: 0.0.0.0 webserver-port: 8123 # Disables Webserver portion of Dynmap (Advanced users only) -disable-webserver: true +disable-webserver: false # Writes JSON to file in the webpath -jsonfile: true +jsonfile: false # How often the json file gets written to(in seconds) jsonfile-interval: 1000 From 77d9a8886896bf3d17f1f9b1c4cc84611a7e1834 Mon Sep 17 00:00:00 2001 From: Jason Booth Date: Thu, 17 Feb 2011 09:45:32 -0600 Subject: [PATCH 5/8] Fixed timer to be stopped onDisabled if it was started --- src/main/java/org/dynmap/DynmapPlugin.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index bd5f84ef..f5aada1b 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -130,6 +130,11 @@ public class DynmapPlugin extends JavaPlugin { webServer.shutdown(); webServer = null; } + + if(timer != null) { + timer.cancel(); + } + Debug.clearDebuggers(); } From 3916c363ae973921959258a2ce033c9f6553d906 Mon Sep 17 00:00:00 2001 From: Jason Booth Date: Thu, 17 Feb 2011 10:05:07 -0600 Subject: [PATCH 6/8] Fixed jsontimer-interval config not being used. Change JsonTimerTask.java to use jsontimer-interval+10 to allow a buffer for late/delayed client requests(to prevent updated tiles info to be missing) --- src/main/java/org/dynmap/DynmapPlugin.java | 2 +- src/main/java/org/dynmap/JsonTimerTask.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index f5aada1b..2b97fba4 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -115,7 +115,7 @@ public class DynmapPlugin extends JavaPlugin { if(configuration.getBoolean("jsonfile", false)) { jsonConfig(); - int jsonInterval = configuration.getInt("jsonfile", 1) * 1000; + int jsonInterval = configuration.getInt("jsonfile-interval", 1) * 1000; timer = new Timer(); timer.scheduleAtFixedRate(new JsonTimerTask(this, configuration), jsonInterval, jsonInterval); } diff --git a/src/main/java/org/dynmap/JsonTimerTask.java b/src/main/java/org/dynmap/JsonTimerTask.java index a49f9852..104a29d4 100644 --- a/src/main/java/org/dynmap/JsonTimerTask.java +++ b/src/main/java/org/dynmap/JsonTimerTask.java @@ -52,7 +52,7 @@ class JsonTimerTask extends TimerTask update.players[i] = new Client.Player(p.getName(), pl.getWorld().getName(), pl.getX(), pl.getY(), pl.getZ()); } - update.updates = mapManager.getWorldUpdates(world.getName(), current - 10L); + update.updates = mapManager.getWorldUpdates(world.getName(), current - (configuration.getInt("jsonfile-interval", 1) + 10)); File webpath = new File(this.configuration.getString("webpath", "web"), "dynmap_"+world.getName()+".json"); File outputFile; From 13099587e0a50e34b3774a090fac39de4eb67ca2 Mon Sep 17 00:00:00 2001 From: Jason Booth Date: Thu, 17 Feb 2011 11:14:37 -0600 Subject: [PATCH 7/8] Fixed mistake with map updates only pulling interval+10 instead of interval+10000 --- src/main/java/org/dynmap/JsonTimerTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/dynmap/JsonTimerTask.java b/src/main/java/org/dynmap/JsonTimerTask.java index 104a29d4..23d3745c 100644 --- a/src/main/java/org/dynmap/JsonTimerTask.java +++ b/src/main/java/org/dynmap/JsonTimerTask.java @@ -52,7 +52,7 @@ class JsonTimerTask extends TimerTask update.players[i] = new Client.Player(p.getName(), pl.getWorld().getName(), pl.getX(), pl.getY(), pl.getZ()); } - update.updates = mapManager.getWorldUpdates(world.getName(), current - (configuration.getInt("jsonfile-interval", 1) + 10)); + update.updates = mapManager.getWorldUpdates(world.getName(), current - (configuration.getInt("jsonfile-interval", 1) + 10000)); File webpath = new File(this.configuration.getString("webpath", "web"), "dynmap_"+world.getName()+".json"); File outputFile; From 6ab82174a58294ed3d8786ee10be3a8e65853b8f Mon Sep 17 00:00:00 2001 From: Jason Booth Date: Sat, 19 Feb 2011 18:55:01 -0600 Subject: [PATCH 8/8] Added timestamp support to Update Tiles and Chat. New web config to handle for jsonfile method Modified webclient to handle timestamps to prevent duplication. Removed duplicate code in JsonTimerTask.java --- configuration.txt | 3 +++ src/main/java/org/dynmap/Client.java | 8 ++++++-- src/main/java/org/dynmap/DynmapPlayerListener.java | 2 +- src/main/java/org/dynmap/JsonTimerTask.java | 2 -- src/main/java/org/dynmap/MapManager.java | 2 +- web/map.js | 10 +++++++--- 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/configuration.txt b/configuration.txt index 865f9196..e56127e9 100755 --- a/configuration.txt +++ b/configuration.txt @@ -42,6 +42,9 @@ web: # Interval the browser should poll for updates. updaterate: 2000 + # Handles the clientside updates differently only enable if using jsonfile + jsonfile: false + showchatballoons: true showplayerfacesonmap: true showplayerfacesinmenu: true diff --git a/src/main/java/org/dynmap/Client.java b/src/main/java/org/dynmap/Client.java index d27f3e0b..ae9e7036 100644 --- a/src/main/java/org/dynmap/Client.java +++ b/src/main/java/org/dynmap/Client.java @@ -27,19 +27,23 @@ public class Client { public String type = "chat"; public String playerName; public String message; + public long timestamp; - public ChatMessage(String playerName, String message) { + public ChatMessage(String playerName, String message, long timestamp) { this.playerName = playerName; this.message = message; + this.timestamp = timestamp; } } public static class Tile { public String type = "tile"; public String name; + public long timestamp; - public Tile(String name) { + public Tile(String name, long timestamp) { this.name = name; + this.timestamp = timestamp; } } } diff --git a/src/main/java/org/dynmap/DynmapPlayerListener.java b/src/main/java/org/dynmap/DynmapPlayerListener.java index 7f30456a..ddac3dc2 100644 --- a/src/main/java/org/dynmap/DynmapPlayerListener.java +++ b/src/main/java/org/dynmap/DynmapPlayerListener.java @@ -67,6 +67,6 @@ public class DynmapPlayerListener extends PlayerListener { * Relevant event details */ public void onPlayerChat(PlayerChatEvent event) { - mgr.pushUpdate(new Client.ChatMessage(event.getPlayer().getName(), event.getMessage())); + mgr.pushUpdate(new Client.ChatMessage(event.getPlayer().getName(), event.getMessage(), System.currentTimeMillis())); } } \ No newline at end of file diff --git a/src/main/java/org/dynmap/JsonTimerTask.java b/src/main/java/org/dynmap/JsonTimerTask.java index 23d3745c..99d34d4f 100644 --- a/src/main/java/org/dynmap/JsonTimerTask.java +++ b/src/main/java/org/dynmap/JsonTimerTask.java @@ -37,8 +37,6 @@ class JsonTimerTask extends TimerTask long current = System.currentTimeMillis(); Client.Update update = new Client.Update(); - update.timestamp = current; - update.servertime = world.getTime(); update.timestamp = current; update.servertime = world.getTime() % 24000; diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index 4c172e1d..1bf76b16 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -159,7 +159,7 @@ public class MapManager { public boolean render(MapTile tile) { boolean result = tile.getMap().render(tile, getTileFile(tile)); - pushUpdate(tile.getWorld(), new Client.Tile(tile.getFilename())); + pushUpdate(tile.getWorld(), new Client.Tile(tile.getFilename(), System.currentTimeMillis())); return result; } diff --git a/web/map.js b/web/map.js index fc86da18..c0823464 100644 --- a/web/map.js +++ b/web/map.js @@ -221,7 +221,6 @@ DynMap.prototype = { $.getJSON(me.options.updateUrl + "world/" + me.world + "/" + me.lasttimestamp, function(update) { me.alertbox.hide(); - me.lasttimestamp = update.timestamp; me.clock.setTime(update.servertime); var typeVisibleMap = {}; @@ -243,12 +242,16 @@ DynMap.prototype = { $.each(update.updates, function(index, update) { swtch(update.type, { tile: function() { - me.onTileUpdated(update.name); + + if(me.lasttimestamp <= update.timestamp || !me.options.jsonfile) + me.onTileUpdated(update.name); }, chat: function() { if (!me.options.showchatballoons) return; - me.onPlayerChat(update.playerName, update.message); + + if(me.lasttimestamp <= update.timestamp || !me.options.jsonfile) + me.onPlayerChat(update.playerName, update.message); } }, function(type) { console.log('Unknown type ', value, '!'); @@ -265,6 +268,7 @@ DynMap.prototype = { delete me.markers[m]; } } + me.lasttimestamp = update.timestamp; setTimeout(function() { me.update(); }, me.options.updaterate); }, function(request, statusText, ex) { me.alertbox