Merge remote branch 'origin/master'
@ -4,6 +4,8 @@ import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.json.simple.JSONAware;
|
||||
import org.json.simple.JSONStreamAware;
|
||||
|
||||
@ -77,4 +79,8 @@ public class Client {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ComponentMessage extends Update {
|
||||
public String type = "component";
|
||||
/* Each subclass must provide 'ctype' string for component 'type' */
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ import org.dynmap.debug.Debug;
|
||||
import org.dynmap.debug.Debugger;
|
||||
import org.dynmap.hdmap.HDBlockModels;
|
||||
import org.dynmap.hdmap.TexturePack;
|
||||
import org.dynmap.markers.MarkerAPI;
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl;
|
||||
import org.dynmap.permissions.BukkitPermissions;
|
||||
import org.dynmap.permissions.NijikokunPermissions;
|
||||
import org.dynmap.permissions.OpPermissions;
|
||||
@ -85,6 +87,8 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
|
||||
private HashMap<Event.Type, List<Listener>> event_handlers = new HashMap<Event.Type, List<Listener>>();
|
||||
|
||||
private MarkerAPIImpl markerapi;
|
||||
|
||||
public static File dataDirectory;
|
||||
public static File tilesDirectory;
|
||||
|
||||
@ -208,6 +212,7 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
permissions = new OpPermissions(new String[] { "fullrender", "cancelrender", "radiusrender", "resetstats", "reload" });
|
||||
|
||||
dataDirectory = this.getDataFolder();
|
||||
|
||||
/* Load block models */
|
||||
HDBlockModels.loadModels(dataDirectory);
|
||||
/* Load texture mappings */
|
||||
@ -278,11 +283,11 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
if (!configuration.getBoolean("disable-webserver", false)) {
|
||||
startWebserver();
|
||||
}
|
||||
|
||||
|
||||
/* Print version info */
|
||||
PluginDescriptionFile pdfFile = this.getDescription();
|
||||
Log.info("version " + pdfFile.getVersion() + " is enabled" );
|
||||
|
||||
|
||||
events.<Object>trigger("initialized", null);
|
||||
}
|
||||
|
||||
@ -360,7 +365,10 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
ll.clear(); /* Empty list - we use presence of list to remember that we've registered with Bukkit */
|
||||
}
|
||||
playerfacemgr = null;
|
||||
|
||||
if(markerapi != null) {
|
||||
markerapi.cleanup(this);
|
||||
markerapi = null;
|
||||
}
|
||||
Debug.clearDebuggers();
|
||||
}
|
||||
|
||||
@ -640,6 +648,9 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
|
||||
if(cmd.getName().equalsIgnoreCase("dmarker")) {
|
||||
return MarkerAPIImpl.onCommand(this, sender, cmd, commandLabel, args);
|
||||
}
|
||||
if (!cmd.getName().equalsIgnoreCase("dynmap"))
|
||||
return false;
|
||||
Player player = null;
|
||||
@ -768,7 +779,7 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkPlayerPermission(CommandSender sender, String permission) {
|
||||
public boolean checkPlayerPermission(CommandSender sender, String permission) {
|
||||
if (!(sender instanceof Player) || sender.isOp()) {
|
||||
return true;
|
||||
} else if (!permissions.has(sender, permission.toLowerCase())) {
|
||||
@ -1163,4 +1174,24 @@ public class DynmapPlugin extends JavaPlugin {
|
||||
}
|
||||
ll.add(listener);
|
||||
}
|
||||
/**
|
||||
* ** This is the public API for other plugins to use for accessing the Marker API **
|
||||
* This method can return null if the 'markers' component has not been configured -
|
||||
* a warning message will be issued to the server.log in this event.
|
||||
*
|
||||
* @return MarkerAPI, or null if not configured
|
||||
*/
|
||||
public MarkerAPI getMarkerAPI() {
|
||||
if(markerapi == null) {
|
||||
Log.warning("Marker API has been requested, but is not enabled. Uncomment or add 'markers' component to configuration.txt.");
|
||||
}
|
||||
return markerapi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register markers API - used by component to supply marker API to plugin
|
||||
*/
|
||||
public void registerMarkerAPI(MarkerAPIImpl api) {
|
||||
markerapi = api;
|
||||
}
|
||||
}
|
||||
|
@ -790,7 +790,8 @@ public class MapManager {
|
||||
|
||||
public void pushUpdate(String worldName, Object update) {
|
||||
DynmapWorld world = getWorld(worldName);
|
||||
world.updates.pushUpdate(update);
|
||||
if(world != null)
|
||||
world.updates.pushUpdate(update);
|
||||
}
|
||||
|
||||
public Object[] getWorldUpdates(String worldName, long since) {
|
||||
|
26
src/main/java/org/dynmap/MarkersComponent.java
Normal file
@ -0,0 +1,26 @@
|
||||
package org.dynmap;
|
||||
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl;
|
||||
|
||||
/**
|
||||
* Markers component - ties in the component system, both on the server and client
|
||||
*/
|
||||
public class MarkersComponent extends ClientComponent {
|
||||
private MarkerAPIImpl api;
|
||||
public MarkersComponent(DynmapPlugin plugin, ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
/* Register API with plugin */
|
||||
api = MarkerAPIImpl.initializeMarkerAPI(plugin);
|
||||
plugin.registerMarkerAPI(api);
|
||||
|
||||
}
|
||||
@Override
|
||||
public void dispose() {
|
||||
if(api != null) {
|
||||
/* Clean up API registered with plugin */
|
||||
plugin.registerMarkerAPI(null);
|
||||
api.cleanup(this.plugin);
|
||||
api = null;
|
||||
}
|
||||
}
|
||||
}
|
74
src/main/java/org/dynmap/markers/Marker.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.dynmap.markers;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
/**
|
||||
* This defines the public interface to a marker object, for use with the MarkerAPI
|
||||
*/
|
||||
public interface Marker {
|
||||
/**
|
||||
* Get ID of the marker (unique string within the MarkerSet)
|
||||
* @return id of marker
|
||||
*/
|
||||
public String getMarkerID();
|
||||
/**
|
||||
* Get the marker set for the marker
|
||||
* @return marker set
|
||||
*/
|
||||
public MarkerSet getMarkerSet();
|
||||
/**
|
||||
* Delete the marker
|
||||
*/
|
||||
public void deleteMarker();
|
||||
/**
|
||||
* Get marker's world ID
|
||||
* @return world id
|
||||
*/
|
||||
public String getWorld();
|
||||
/**
|
||||
* Get marker's X coordinate
|
||||
* @return x coordinate
|
||||
*/
|
||||
public int getX();
|
||||
/**
|
||||
* Get marker's Y coordinate
|
||||
* @return y coordinate
|
||||
*/
|
||||
public int getY();
|
||||
/**
|
||||
* Get marker's Z coordinate
|
||||
* @return z coordinate
|
||||
*/
|
||||
public int getZ();
|
||||
/**
|
||||
* Update the marker's location
|
||||
* @param worldid - world ID
|
||||
* @param x - x coord
|
||||
* @param y - y coord
|
||||
* @param z - z coord
|
||||
*/
|
||||
public void setLocation(String worldid, int x, int y, int z);
|
||||
/**
|
||||
* Get the marker's icon
|
||||
* @return marker icon
|
||||
*/
|
||||
public MarkerIcon getMarkerIcon();
|
||||
/**
|
||||
* Set the marker's icon
|
||||
* @param icon - new marker icon
|
||||
* @return true if new marker icon set, false if not allowed
|
||||
*/
|
||||
public boolean setMarkerIcon(MarkerIcon icon);
|
||||
/**
|
||||
* Test if marker is persistent
|
||||
*/
|
||||
public boolean isPersistentMarker();
|
||||
/**
|
||||
* Get the marker's label
|
||||
*/
|
||||
public String getLabel();
|
||||
/**
|
||||
* Update the marker's label
|
||||
*/
|
||||
public void setLabel(String lbl);
|
||||
}
|
50
src/main/java/org/dynmap/markers/MarkerAPI.java
Normal file
@ -0,0 +1,50 @@
|
||||
package org.dynmap.markers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This defines the public interface to the MarkerAPI (as retrieved by the getMarkerAPI() method in the DynmapPlugin class).
|
||||
*/
|
||||
public interface MarkerAPI {
|
||||
/**
|
||||
* Get set of defined marker sets
|
||||
* @return set of marker sets
|
||||
*/
|
||||
public Set<MarkerSet> getMarkerSets();
|
||||
/**
|
||||
* Find marker set by ID
|
||||
* @param id - ID of marker set
|
||||
* @return marker set, or null if not found
|
||||
*/
|
||||
public MarkerSet getMarkerSet(String id);
|
||||
/**
|
||||
* Create marker set
|
||||
* @param id - ID for marker set (must be unique among marker set - limit to alphanumerics, periods, underscores)
|
||||
* @param lbl - Label for marker set
|
||||
* @param iconlimit - set of allowed marker icons (if null, any marker icon can be used in set)
|
||||
* @param persistent - if true, set is persistent (and can contain persistent markers)
|
||||
* @return marker set, or null if failed to be created
|
||||
*/
|
||||
public MarkerSet createMarkerSet(String id, String lbl, Set<MarkerIcon> iconlimit, boolean persistent);
|
||||
/**
|
||||
* Get set of defined marker icons
|
||||
* @return set of marker icons
|
||||
*/
|
||||
public Set<MarkerIcon> getMarkerIcons();
|
||||
/**
|
||||
* Find marker icon by ID
|
||||
* @param id - ID of marker icon
|
||||
* @return marker icon, or null if not found
|
||||
*/
|
||||
public MarkerIcon getMarkerIcon(String id);
|
||||
/**
|
||||
* Register a new marker icon
|
||||
* @param id - ID of marker icon (must be unique among marker icons - letters, numbers, periods, underscores only)
|
||||
* @param label - label for marker icon
|
||||
* @param marker_png - stream containing PNG encoded icon for marker (will be read and copied)
|
||||
* @return marker icon object, or null if failed
|
||||
*/
|
||||
public MarkerIcon createMarkerIcon(String id, String label, InputStream marker_png);
|
||||
}
|
26
src/main/java/org/dynmap/markers/MarkerIcon.java
Normal file
@ -0,0 +1,26 @@
|
||||
package org.dynmap.markers;
|
||||
|
||||
/**
|
||||
* This defines the public interface to a marker icon, for use with the MarkerAPI
|
||||
*/
|
||||
public interface MarkerIcon {
|
||||
/** Default marker icon - always exists */
|
||||
public static final String DEFAULT = "default";
|
||||
|
||||
|
||||
/**
|
||||
* Get ID of the marker icon (unique among marker icons)
|
||||
* @return ID
|
||||
*/
|
||||
public String getMarkerIconID();
|
||||
/**
|
||||
* Get label for marker icon (descriptive - for helping select icon, or for legend/key)
|
||||
* @return icon label
|
||||
*/
|
||||
public String getMarkerIconLabel();
|
||||
/**
|
||||
* Is builtin marker
|
||||
* @return true
|
||||
*/
|
||||
public boolean isBuiltIn();
|
||||
}
|
83
src/main/java/org/dynmap/markers/MarkerSet.java
Normal file
@ -0,0 +1,83 @@
|
||||
package org.dynmap.markers;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This defines the public interface to a marker set object, for use with the MarkerAPI.
|
||||
* This represents a logical set of markers, which are presented as a labelled layer on the web UI.
|
||||
* Marker sets can be created as persistent or non-persistent, but only persistent marker sets can contain persistent markers.
|
||||
*/
|
||||
public interface MarkerSet {
|
||||
public static final String DEFAULT = "markers"; /* Default set - always exists */
|
||||
|
||||
/**
|
||||
* Get set of all markers currently in the set
|
||||
* @return set of markers (set is copy - safe to iterate)
|
||||
*/
|
||||
public Set<Marker> getMarkers();
|
||||
/**
|
||||
* Create a new marker in the marker set
|
||||
*
|
||||
* @param id - ID of the marker - must be unique within the set: if null, unique ID is generated
|
||||
* @param label - Label for the marker
|
||||
* @param world - world ID
|
||||
* @param x - x coord
|
||||
* @param y - y coord
|
||||
* @param z - z coord
|
||||
* @param icon - Icon for the marker
|
||||
* @param is_persistent - if true, marker is persistent (saved and reloaded on restart). If set is not persistent, this must be false.
|
||||
* @return created marker, or null if cannot be created.
|
||||
*/
|
||||
public Marker createMarker(String id, String label, String world, int x, int y, int z, MarkerIcon icon, boolean is_persistent);
|
||||
/**
|
||||
* Get marker by ID
|
||||
* @param id - ID of the marker
|
||||
* @return marker, or null if cannot be found
|
||||
*/
|
||||
public Marker findMarker(String id);
|
||||
/**
|
||||
* Get ID of marker set - unique among marker sets
|
||||
* @return ID
|
||||
*/
|
||||
public String getMarkerSetID();
|
||||
/**
|
||||
* Get label for marker set
|
||||
* @return label
|
||||
*/
|
||||
public String getMarkerSetLabel();
|
||||
/**
|
||||
* Update label for marker set
|
||||
* @param lbl - label for marker set
|
||||
*/
|
||||
public void setMarketSetLabel(String lbl);
|
||||
/**
|
||||
* Test if marker set is persistent
|
||||
* @return true if the set is persistent
|
||||
*/
|
||||
public boolean isMarkerSetPersistent();
|
||||
/**
|
||||
* Get marker icons allowed in set (if restricted)
|
||||
* @return set of allowed marker icons
|
||||
*/
|
||||
public Set<MarkerIcon> getAllowedMarkerIcons();
|
||||
/**
|
||||
* Add marker icon to allowed set (must have been created restricted)
|
||||
* @param icon - icon to be added
|
||||
*/
|
||||
public void addAllowedMarkerIcon(MarkerIcon icon);
|
||||
/**
|
||||
* Test if marker icon is allowed
|
||||
* @param icon - marker icon
|
||||
* @return true if allowed, false if not
|
||||
*/
|
||||
public boolean isAllowedMarkerIcon(MarkerIcon icon);
|
||||
/**
|
||||
* Get distinct set of marker icons used by set (based on markers currently in set)
|
||||
* @return set of marker icons
|
||||
*/
|
||||
public Set<MarkerIcon> getMarkerIconsInUse();
|
||||
/**
|
||||
* Delete marker set
|
||||
*/
|
||||
public void deleteMarkerSet();
|
||||
}
|
514
src/main/java/org/dynmap/markers/impl/MarkerAPIImpl.java
Normal file
@ -0,0 +1,514 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.config.Configuration;
|
||||
import org.bukkit.util.config.ConfigurationNode;
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.ClientUpdateEvent;
|
||||
import org.dynmap.DynmapPlugin;
|
||||
import org.dynmap.DynmapWorld;
|
||||
import org.dynmap.Event;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.Client.ComponentMessage;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerAPI;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.dynmap.web.Json;
|
||||
|
||||
/**
|
||||
* Implementation class for MarkerAPI - should not be called directly
|
||||
*/
|
||||
public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
|
||||
private File markerpersist;
|
||||
private File markerdir; /* Local store for markers (internal) */
|
||||
private File markertiledir; /* Marker directory for web server (under tiles) */
|
||||
private HashMap<String, MarkerIconImpl> markericons = new HashMap<String, MarkerIconImpl>();
|
||||
private HashMap<String, MarkerSetImpl> markersets = new HashMap<String, MarkerSetImpl>();
|
||||
|
||||
private Server server;
|
||||
static MarkerAPIImpl api;
|
||||
|
||||
/* Built-in icons */
|
||||
private static final String[] builtin_icons = {
|
||||
"anchor", "bank", "basket", "beer", "bighouse", "blueflag", "bomb", "bookshelf", "bricks", "bronzemedal", "bronzestar",
|
||||
"building", "cake", "camera", "cart", "caution", "chest", "church", "coins", "comment", "compass", "construction",
|
||||
"cross", "cup", "cutlery", "default", "diamond", "dog", "door", "down", "drink", "exclamation", "factory",
|
||||
"fire", "flower", "gear", "goldmedal", "goldstar", "greenflag", "hammer", "heart", "house", "key", "king",
|
||||
"left", "lightbulb", "lighthouse", "lock", "orangeflag", "pin", "pinkflag", "pirateflag", "pointdown", "pointleft",
|
||||
"pointright", "pointup", "purpleflag", "queen", "redflag", "right", "ruby", "scales", "skull", "shield", "sign",
|
||||
"silvermedal", "silverstar", "star", "sun", "temple", "theater", "tornado", "tower", "tree", "truck", "up",
|
||||
"walk", "warning", "world", "wrench", "yellowflag"
|
||||
};
|
||||
|
||||
/* Component messages for client updates */
|
||||
public static class MarkerComponentMessage extends ComponentMessage {
|
||||
public String ctype = "markers";
|
||||
}
|
||||
|
||||
public static class MarkerUpdated extends MarkerComponentMessage {
|
||||
public String msg;
|
||||
public int x, y, z;
|
||||
public String id;
|
||||
public String label;
|
||||
public String icon;
|
||||
public String set;
|
||||
|
||||
public MarkerUpdated(Marker m, boolean deleted) {
|
||||
this.id = m.getMarkerID();
|
||||
this.label = m.getLabel();
|
||||
this.x = m.getX();
|
||||
this.y = m.getY();
|
||||
this.z = m.getZ();
|
||||
this.set = m.getMarkerSet().getMarkerSetID();
|
||||
this.icon = m.getMarkerIcon().getMarkerIconID();
|
||||
if(deleted)
|
||||
msg = "markerdeleted";
|
||||
else
|
||||
msg = "markerupdated";
|
||||
}
|
||||
}
|
||||
|
||||
public static class MarkerSetUpdated extends MarkerComponentMessage {
|
||||
public String msg;
|
||||
public String id;
|
||||
public String label;
|
||||
public MarkerSetUpdated(MarkerSet markerset, boolean deleted) {
|
||||
this.id = markerset.getMarkerSetID();
|
||||
this.label = markerset.getMarkerSetLabel();
|
||||
if(deleted)
|
||||
msg = "setdeleted";
|
||||
else
|
||||
msg = "setupdated";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton initializer
|
||||
*/
|
||||
public static MarkerAPIImpl initializeMarkerAPI(DynmapPlugin plugin) {
|
||||
if(api != null) {
|
||||
api.cleanup(plugin);
|
||||
}
|
||||
api = new MarkerAPIImpl();
|
||||
api.server = plugin.getServer();
|
||||
/* Initialize persistence file name */
|
||||
api.markerpersist = new File(plugin.getDataFolder(), "markers.yml");
|
||||
/* Load persistence */
|
||||
api.loadMarkers();
|
||||
/* Fill in default icons and sets, if needed */
|
||||
for(int i = 0; i < builtin_icons.length; i++) {
|
||||
String id = builtin_icons[i];
|
||||
if(api.getMarkerIcon(id) == null) {
|
||||
api.createBuiltinMarkerIcon(id, id);
|
||||
}
|
||||
}
|
||||
if(api.getMarkerSet(MarkerSet.DEFAULT) == null) {
|
||||
api.createMarkerSet(MarkerSet.DEFAULT, "Markers", null, true);
|
||||
}
|
||||
/* Build paths for markers */
|
||||
api.markerdir = new File(plugin.getDataFolder(), "markers");
|
||||
if(api.markerdir.mkdirs() == false) { /* Create directory if needed */
|
||||
Log.severe("Error creating markers directory - " + api.markerdir.getPath());
|
||||
}
|
||||
api.markertiledir = new File(DynmapPlugin.tilesDirectory, "_markers_");
|
||||
if(api.markertiledir.mkdirs() == false) { /* Create directory if needed */
|
||||
Log.severe("Error creating markers directory - " + api.markertiledir.getPath());
|
||||
}
|
||||
/* Now publish marker files to the tiles directory */
|
||||
for(MarkerIcon ico : api.getMarkerIcons()) {
|
||||
api.publishMarkerIcon(ico);
|
||||
}
|
||||
/* Freshen files */
|
||||
api.freshenMarkerFiles();
|
||||
/* Add listener so we update marker files for other worlds as they become active */
|
||||
plugin.events.addListener("worldactivated", api);
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*/
|
||||
public void cleanup(DynmapPlugin plugin) {
|
||||
plugin.events.removeListener("worldactivated", api);
|
||||
|
||||
for(MarkerIconImpl icn : markericons.values())
|
||||
icn.cleanup();
|
||||
markericons.clear();
|
||||
for(MarkerSetImpl set : markersets.values())
|
||||
set.cleanup();
|
||||
markersets.clear();
|
||||
}
|
||||
|
||||
private MarkerIcon createBuiltinMarkerIcon(String id, String label) {
|
||||
if(markericons.containsKey(id)) return null; /* Exists? */
|
||||
MarkerIconImpl ico = new MarkerIconImpl(id, label, true);
|
||||
markericons.put(id, ico); /* Add to set */
|
||||
return ico;
|
||||
}
|
||||
|
||||
private void publishMarkerIcon(MarkerIcon ico) {
|
||||
byte[] buf = new byte[512];
|
||||
InputStream in = null;
|
||||
File infile = new File(markerdir, ico.getMarkerIconID() + ".png"); /* Get source file name */
|
||||
File outfile = new File(markertiledir, ico.getMarkerIconID() + ".png"); /* Destination */
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(outfile);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Cannot write marker to tilespath - " + outfile.getPath());
|
||||
return;
|
||||
}
|
||||
if(ico.isBuiltIn()) {
|
||||
in = getClass().getResourceAsStream("/markers/" + ico.getMarkerIconID() + ".png");
|
||||
}
|
||||
else if(infile.canRead()) { /* If it exists and is readable */
|
||||
try {
|
||||
in = new FileInputStream(infile);
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Error opening marker " + infile.getPath() + " - " + iox);
|
||||
}
|
||||
}
|
||||
if(in == null) { /* Not found, use default marker */
|
||||
in = getClass().getResourceAsStream("/markers/marker.png");
|
||||
if(in == null)
|
||||
return;
|
||||
}
|
||||
/* Copy to destination */
|
||||
try {
|
||||
int len;
|
||||
while((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Error writing marker to tilespath - " + outfile.getPath());
|
||||
} finally {
|
||||
if(in != null) try { in.close(); } catch (IOException x){}
|
||||
if(out != null) try { out.close(); } catch (IOException x){}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MarkerSet> getMarkerSets() {
|
||||
return new HashSet<MarkerSet>(markersets.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerSet getMarkerSet(String id) {
|
||||
return markersets.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerSet createMarkerSet(String id, String lbl, Set<MarkerIcon> iconlimit, boolean persistent) {
|
||||
if(markersets.containsKey(id)) return null; /* Exists? */
|
||||
|
||||
MarkerSetImpl set = new MarkerSetImpl(id, lbl, iconlimit, persistent);
|
||||
|
||||
markersets.put(id, set); /* Add to list */
|
||||
if(persistent) {
|
||||
saveMarkers();
|
||||
}
|
||||
markerSetUpdated(set, MarkerUpdate.CREATED); /* Notify update */
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MarkerIcon> getMarkerIcons() {
|
||||
return new HashSet<MarkerIcon>(markericons.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerIcon getMarkerIcon(String id) {
|
||||
return markericons.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerIcon createMarkerIcon(String id, String label, InputStream marker_png) {
|
||||
if(markericons.containsKey(id)) return null; /* Exists? */
|
||||
MarkerIconImpl ico = new MarkerIconImpl(id, label, false);
|
||||
/* Copy icon resource into marker directory */
|
||||
File f = new File(markerdir, id + ".png");
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
byte[] buf = new byte[512];
|
||||
int len;
|
||||
fos = new FileOutputStream(f);
|
||||
while((len = marker_png.read(buf)) > 0) {
|
||||
fos.write(buf, 0, len);
|
||||
}
|
||||
} catch (IOException iox) {
|
||||
Log.severe("Error copying marker - " + f.getPath());
|
||||
return null;
|
||||
} finally {
|
||||
if(fos != null) try { fos.close(); } catch (IOException x) {}
|
||||
}
|
||||
markericons.put(id, ico); /* Add to set */
|
||||
|
||||
/* Publish the marker */
|
||||
publishMarkerIcon(ico);
|
||||
|
||||
saveMarkers(); /* Save results */
|
||||
|
||||
return ico;
|
||||
}
|
||||
|
||||
static MarkerIconImpl getMarkerIconImpl(String id) {
|
||||
if(api != null) {
|
||||
return api.markericons.get(id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save persistence for markers
|
||||
*/
|
||||
static void saveMarkers() {
|
||||
if(api != null) {
|
||||
Configuration conf = new Configuration(api.markerpersist); /* Make configuration object */
|
||||
/* First, save icon definitions */
|
||||
HashMap<String, Object> icons = new HashMap<String,Object>();
|
||||
for(String id : api.markericons.keySet()) {
|
||||
MarkerIconImpl ico = api.markericons.get(id);
|
||||
Map<String,Object> dat = ico.getPersistentData();
|
||||
if(dat != null) {
|
||||
icons.put(id, dat);
|
||||
}
|
||||
}
|
||||
conf.setProperty("icons", icons);
|
||||
/* Then, save persistent sets */
|
||||
HashMap<String, Object> sets = new HashMap<String, Object>();
|
||||
for(String id : api.markersets.keySet()) {
|
||||
MarkerSetImpl set = api.markersets.get(id);
|
||||
if(set.isMarkerSetPersistent()) {
|
||||
Map<String, Object> dat = set.getPersistentData();
|
||||
if(dat != null) {
|
||||
sets.put(id, dat);
|
||||
}
|
||||
}
|
||||
}
|
||||
conf.setProperty("sets", sets);
|
||||
/* And write it out */
|
||||
if(!conf.save())
|
||||
Log.severe("Error writing markers - " + api.markerpersist.getPath());
|
||||
/* Refresh JSON files */
|
||||
api.freshenMarkerFiles();
|
||||
}
|
||||
}
|
||||
|
||||
private void freshenMarkerFiles() {
|
||||
if(MapManager.mapman != null) {
|
||||
for(DynmapWorld w : MapManager.mapman.worlds) {
|
||||
writeMarkersFile(w.world.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load persistence
|
||||
*/
|
||||
private boolean loadMarkers() {
|
||||
Configuration conf = new Configuration(api.markerpersist); /* Make configuration object */
|
||||
conf.load(); /* Load persistence */
|
||||
/* Get icons */
|
||||
Map<String,ConfigurationNode> icons = conf.getNodes("icons");
|
||||
if(icons == null) return false;
|
||||
for(String id : icons.keySet()) {
|
||||
MarkerIconImpl ico = new MarkerIconImpl(id);
|
||||
if(ico.loadPersistentData(icons.get(id))) {
|
||||
markericons.put(id, ico);
|
||||
}
|
||||
}
|
||||
/* Get marker sets */
|
||||
Map<String,ConfigurationNode> sets = conf.getNodes("sets");
|
||||
if(sets != null) {
|
||||
for(String id: sets.keySet()) {
|
||||
MarkerSetImpl set = new MarkerSetImpl(id);
|
||||
if(set.loadPersistentData(sets.get(id))) {
|
||||
markersets.put(id, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum MarkerUpdate { CREATED, UPDATED, DELETED };
|
||||
|
||||
/**
|
||||
* Signal marker update
|
||||
* @param marker - updated marker
|
||||
* @param update - type of update
|
||||
*/
|
||||
static void markerUpdated(MarkerImpl marker, MarkerUpdate update) {
|
||||
Log.info("markerUpdated(" + marker.getMarkerID() + "," + update + ")");
|
||||
/* Freshen marker file for the world for this marker */
|
||||
if(api != null)
|
||||
api.writeMarkersFile(marker.getWorld());
|
||||
/* Enqueue client update */
|
||||
if(MapManager.mapman != null)
|
||||
MapManager.mapman.pushUpdate(marker.getWorld(), new MarkerUpdated(marker, update == MarkerUpdate.DELETED));
|
||||
}
|
||||
/**
|
||||
* Signal marker set update
|
||||
* @param markerset - updated marker set
|
||||
* @param update - type of update
|
||||
*/
|
||||
static void markerSetUpdated(MarkerSetImpl markerset, MarkerUpdate update) {
|
||||
Log.info("markerSetUpdated(" + markerset.getMarkerSetID() + "," + update + ")");
|
||||
/* Freshen all marker files */
|
||||
if(api != null)
|
||||
api.freshenMarkerFiles();
|
||||
/* Enqueue client update */
|
||||
if(MapManager.mapman != null)
|
||||
MapManager.mapman.pushUpdate(new MarkerSetUpdated(markerset, update == MarkerUpdate.DELETED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove marker set
|
||||
*/
|
||||
static void removeMarkerSet(MarkerSetImpl markerset) {
|
||||
if(api != null) {
|
||||
api.markersets.remove(markerset.getMarkerSetID()); /* Remove set from list */
|
||||
if(markerset.isMarkerSetPersistent()) { /* If persistent */
|
||||
MarkerAPIImpl.saveMarkers(); /* Drive save */
|
||||
}
|
||||
markerSetUpdated(markerset, MarkerUpdate.DELETED); /* Signal delete of set */
|
||||
}
|
||||
}
|
||||
|
||||
private static final Set<String> commands = new HashSet<String>(Arrays.asList(new String[] {
|
||||
"add", "update", "delete", "list"
|
||||
}));
|
||||
|
||||
public static boolean onCommand(DynmapPlugin plugin, CommandSender sender, Command cmd, String commandLabel, String[] args) {
|
||||
if(api == null) {
|
||||
sender.sendMessage("Markers component is not enabled.");
|
||||
return false;
|
||||
}
|
||||
if(args.length == 0)
|
||||
return false;
|
||||
Player player = null;
|
||||
if (sender instanceof Player)
|
||||
player = (Player) sender;
|
||||
/* Check if valid command */
|
||||
String c = args[0];
|
||||
if (!commands.contains(c)) {
|
||||
return false;
|
||||
}
|
||||
/* Process commands */
|
||||
if(c.equals("add") && plugin.checkPlayerPermission(sender, "marker.add")) {
|
||||
if(player == null) {
|
||||
sender.sendMessage("Command can only be used by player");
|
||||
}
|
||||
else if(args.length > 1) {
|
||||
String lbl = args[1];
|
||||
if(lbl.charAt(0) == '"') { /* Starts with doublequote */
|
||||
lbl = lbl.substring(1); /* Trim it off */
|
||||
int idx = 2;
|
||||
while(lbl.indexOf('"') < 0) {
|
||||
if(idx < args.length) {
|
||||
lbl = lbl + " " + args[idx];
|
||||
idx++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
idx = lbl.indexOf('"');
|
||||
if(idx >= 0) lbl = lbl.substring(0, idx);
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
/* Add new marker (generic ID and default set) */
|
||||
MarkerSet set = api.getMarkerSet(MarkerSet.DEFAULT);
|
||||
MarkerIcon ico = api.getMarkerIcon(MarkerIcon.DEFAULT);
|
||||
Marker m = set.createMarker(null, lbl, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), ico, true);
|
||||
if(m == null) {
|
||||
sender.sendMessage("Error creating marker");
|
||||
}
|
||||
else {
|
||||
sender.sendMessage("Added marker id='" + m.getMarkerID() + "' (" + m.getLabel() + ") to marker set " + set.getMarkerSetID());
|
||||
}
|
||||
}
|
||||
else {
|
||||
sender.sendMessage("Marker label required");
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write markers file for given world
|
||||
*/
|
||||
public void writeMarkersFile(String wname) {
|
||||
Map<String, Object> markerdata = new HashMap<String, Object>();
|
||||
|
||||
File f = new File(markertiledir, "marker_" + wname + ".json");
|
||||
|
||||
Map<String, Object> worlddata = new HashMap<String, Object>();
|
||||
worlddata.put("timestamp", Long.valueOf(System.currentTimeMillis())); /* Add timestamp */
|
||||
|
||||
for(MarkerSet ms : markersets.values()) {
|
||||
HashMap<String, Object> msdata = new HashMap<String, Object>();
|
||||
msdata.put("label", ms.getMarkerSetLabel());
|
||||
HashMap<String, Object> markers = new HashMap<String, Object>();
|
||||
for(Marker m : ms.getMarkers()) {
|
||||
if(m.getWorld().equals(wname) == false) continue;
|
||||
|
||||
HashMap<String, Object> mdata = new HashMap<String, Object>();
|
||||
mdata.put("x", m.getX());
|
||||
mdata.put("y", m.getY());
|
||||
mdata.put("z", m.getZ());
|
||||
mdata.put("icon", m.getMarkerIcon().getMarkerIconID());
|
||||
mdata.put("label", m.getLabel());
|
||||
/* Add to markers */
|
||||
markers.put(m.getMarkerID(), mdata);
|
||||
}
|
||||
msdata.put("markers", markers); /* Add markers to set data */
|
||||
|
||||
markerdata.put(ms.getMarkerSetID(), msdata); /* Add marker set data to world marker data */
|
||||
}
|
||||
worlddata.put("sets", markerdata);
|
||||
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(f);
|
||||
fos.write(Json.stringifyJson(worlddata).getBytes());
|
||||
} catch (FileNotFoundException ex) {
|
||||
Log.severe("Exception while writing JSON-file.", ex);
|
||||
} catch (IOException ioe) {
|
||||
Log.severe("Exception while writing JSON-file.", ioe);
|
||||
} finally {
|
||||
if(fos != null) try { fos.close(); } catch (IOException x) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggered(DynmapWorld t) {
|
||||
/* Update markers for now-active world */
|
||||
writeMarkersFile(t.world.getName());
|
||||
}
|
||||
}
|
71
src/main/java/org/dynmap/markers/impl/MarkerIconImpl.java
Normal file
@ -0,0 +1,71 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.util.config.ConfigurationNode;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
|
||||
class MarkerIconImpl implements MarkerIcon {
|
||||
private String iconid;
|
||||
private String label;
|
||||
private boolean is_builtin;
|
||||
|
||||
MarkerIconImpl(String id) {
|
||||
iconid = id;
|
||||
label = id;
|
||||
is_builtin = false;
|
||||
}
|
||||
|
||||
MarkerIconImpl(String id, String lbl, boolean is_builtin) {
|
||||
iconid = id;
|
||||
if(lbl != null)
|
||||
label = lbl;
|
||||
else
|
||||
label = id;
|
||||
this.is_builtin = is_builtin;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerIconID() {
|
||||
return iconid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerIconLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltIn() {
|
||||
return is_builtin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration node to be saved
|
||||
* @return node
|
||||
*/
|
||||
Map<String, Object> getPersistentData() {
|
||||
if(is_builtin)
|
||||
return null;
|
||||
|
||||
HashMap<String, Object> node = new HashMap<String, Object>();
|
||||
node.put("label", label);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
boolean loadPersistentData(ConfigurationNode node) {
|
||||
if(is_builtin)
|
||||
return false;
|
||||
|
||||
label = node.getString("label", iconid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
179
src/main/java/org/dynmap/markers/impl/MarkerImpl.java
Normal file
@ -0,0 +1,179 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.config.ConfigurationNode;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl.MarkerUpdate;
|
||||
|
||||
class MarkerImpl implements Marker {
|
||||
private String markerid;
|
||||
private String label;
|
||||
private MarkerSetImpl markerset;
|
||||
private int x, y, z;
|
||||
private String world;
|
||||
private MarkerIconImpl icon;
|
||||
private boolean ispersistent;
|
||||
|
||||
/**
|
||||
* Create marker
|
||||
* @param id - marker ID
|
||||
* @param lbl - label
|
||||
* @param world - world id
|
||||
* @param x - x coord
|
||||
* @param y - y coord
|
||||
* @param z - z coord
|
||||
* @param icon - marker icon
|
||||
* @param persistent - true if persistent
|
||||
*/
|
||||
MarkerImpl(String id, String lbl, String world, int x, int y, int z, MarkerIconImpl icon, boolean persistent, MarkerSetImpl set) {
|
||||
markerid = id;
|
||||
if(lbl != null)
|
||||
label = lbl;
|
||||
else
|
||||
label = id;
|
||||
this.x = x; this.y = y; this.z = z;
|
||||
this.world = world;
|
||||
this.icon = icon;
|
||||
ispersistent = persistent;
|
||||
markerset = set;
|
||||
}
|
||||
/**
|
||||
* Make bare marker - used for persistence load
|
||||
* @param id - marker ID
|
||||
* @param set - marker set
|
||||
*/
|
||||
MarkerImpl(String id, MarkerSetImpl set) {
|
||||
markerid = id;
|
||||
markerset = set;
|
||||
label = id;
|
||||
x = z = 0; y = 64; world = "world";
|
||||
icon = MarkerAPIImpl.getMarkerIconImpl(MarkerIcon.DEFAULT);
|
||||
}
|
||||
/**
|
||||
* Load marker from configuration node
|
||||
* @param node - configuration node
|
||||
*/
|
||||
boolean loadPersistentData(ConfigurationNode node) {
|
||||
label = node.getString("label", markerid);
|
||||
x = node.getInt("x", 0);
|
||||
y = node.getInt("y", 64);
|
||||
z = node.getInt("z", 0);
|
||||
world = node.getString("world", "world");
|
||||
icon = MarkerAPIImpl.getMarkerIconImpl(node.getString("icon", MarkerIcon.DEFAULT));
|
||||
ispersistent = true; /* Loaded from config, so must be */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
icon = null;
|
||||
markerset = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerID() {
|
||||
return markerid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerSet getMarkerSet() {
|
||||
return markerset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMarker() {
|
||||
markerset.removeMarker(this); /* Remove from our marker set (notified by set) */
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkerIcon getMarkerIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMarkerIcon(MarkerIcon icon) {
|
||||
if(!(icon instanceof MarkerIconImpl)) {
|
||||
return false;
|
||||
}
|
||||
/* Check if icons restricted for this set */
|
||||
Set<MarkerIcon> icns = markerset.getAllowedMarkerIcons();
|
||||
if((icns != null) && (icns.contains(icon) == false)) {
|
||||
return false;
|
||||
}
|
||||
this.icon = (MarkerIconImpl)icon;
|
||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistentMarker() {
|
||||
return ispersistent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabel(String lbl) {
|
||||
label = lbl;
|
||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration node to be saved
|
||||
* @return node
|
||||
*/
|
||||
Map<String, Object> getPersistentData() {
|
||||
if(!ispersistent) /* Nothing if not persistent */
|
||||
return null;
|
||||
HashMap<String, Object> node = new HashMap<String, Object>();
|
||||
node.put("label", label);
|
||||
node.put("x", Integer.valueOf(x));
|
||||
node.put("y", Integer.valueOf(y));
|
||||
node.put("z", Integer.valueOf(z));
|
||||
node.put("world", world);
|
||||
node.put("icon", icon.getMarkerIconID());
|
||||
|
||||
return node;
|
||||
}
|
||||
@Override
|
||||
public String getWorld() {
|
||||
return world;
|
||||
}
|
||||
@Override
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
@Override
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
@Override
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
@Override
|
||||
public void setLocation(String worldid, int x, int y, int z) {
|
||||
this.world = worldid;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
}
|
228
src/main/java/org/dynmap/markers/impl/MarkerSetImpl.java
Normal file
@ -0,0 +1,228 @@
|
||||
package org.dynmap.markers.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.config.ConfigurationNode;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.markers.Marker;
|
||||
import org.dynmap.markers.MarkerIcon;
|
||||
import org.dynmap.markers.MarkerSet;
|
||||
import org.dynmap.markers.impl.MarkerAPIImpl.MarkerUpdate;
|
||||
|
||||
class MarkerSetImpl implements MarkerSet {
|
||||
private HashMap<String, MarkerImpl> markers = new HashMap<String, MarkerImpl>();
|
||||
private String setid;
|
||||
private String label;
|
||||
private HashMap<String, MarkerIconImpl> allowedicons = null;
|
||||
|
||||
private boolean ispersistent;
|
||||
|
||||
MarkerSetImpl(String id) {
|
||||
setid = id;
|
||||
label = id;
|
||||
}
|
||||
|
||||
MarkerSetImpl(String id, String lbl, Set<MarkerIcon> iconlimit, boolean persistent) {
|
||||
setid = id;
|
||||
if(lbl != null)
|
||||
label = lbl;
|
||||
else
|
||||
label = id;
|
||||
if(iconlimit != null) {
|
||||
allowedicons = new HashMap<String, MarkerIconImpl>();
|
||||
for(MarkerIcon ico : iconlimit) {
|
||||
if(ico instanceof MarkerIconImpl) {
|
||||
allowedicons.put(ico.getMarkerIconID(), (MarkerIconImpl)ico);
|
||||
}
|
||||
}
|
||||
}
|
||||
ispersistent = persistent;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
for(MarkerImpl m : markers.values())
|
||||
m.cleanup();
|
||||
markers.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Marker> getMarkers() {
|
||||
return new HashSet<Marker>(markers.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Marker createMarker(String id, String label, String world, int x, int y, int z, MarkerIcon icon, boolean is_persistent) {
|
||||
if(id == null) { /* If not defined, generate unique one */
|
||||
int i = 0;
|
||||
do {
|
||||
i++;
|
||||
id = "marker_" + i;
|
||||
} while(markers.containsKey(id));
|
||||
}
|
||||
if(markers.containsKey(id)) return null; /* Duplicate ID? */
|
||||
if(!(icon instanceof MarkerIconImpl)) return null;
|
||||
/* If limited icons, and this isn't valid one, quit */
|
||||
if((allowedicons != null) && (allowedicons.containsKey(icon.getMarkerIconID()) == false)) return null;
|
||||
/* Create marker */
|
||||
is_persistent = is_persistent && this.ispersistent;
|
||||
MarkerImpl marker = new MarkerImpl(id, label, world, x, y, z, (MarkerIconImpl)icon, is_persistent, this);
|
||||
markers.put(id, marker); /* Add to set */
|
||||
if(is_persistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
|
||||
MarkerAPIImpl.markerUpdated(marker, MarkerUpdate.CREATED); /* Signal create */
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Marker findMarker(String id) {
|
||||
return markers.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerSetID() {
|
||||
return setid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMarkerSetLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarketSetLabel(String lbl) {
|
||||
label = lbl;
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMarkerSetPersistent() {
|
||||
return ispersistent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MarkerIcon> getAllowedMarkerIcons() {
|
||||
if(allowedicons != null)
|
||||
return new HashSet<MarkerIcon>(allowedicons.values());
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllowedMarkerIcon(MarkerIcon icon) {
|
||||
if(!(icon instanceof MarkerIconImpl)) return;
|
||||
if(allowedicons == null) return;
|
||||
allowedicons.put(icon.getMarkerIconID(), (MarkerIconImpl)icon);
|
||||
MarkerAPIImpl.markerSetUpdated(this, MarkerUpdate.UPDATED);
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowedMarkerIcon(MarkerIcon icon) {
|
||||
if(allowedicons == null) return true;
|
||||
return allowedicons.containsKey(icon.getMarkerIconID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MarkerIcon> getMarkerIconsInUse() {
|
||||
HashSet<String> ids = new HashSet<String>();
|
||||
HashSet<MarkerIcon> icons = new HashSet<MarkerIcon>();
|
||||
for(Marker m : markers.values()) {
|
||||
MarkerIcon mi = m.getMarkerIcon();
|
||||
if(!ids.contains(mi.getMarkerIconID())) {
|
||||
ids.add(mi.getMarkerIconID());
|
||||
icons.add(mi);
|
||||
}
|
||||
}
|
||||
return icons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMarkerSet() {
|
||||
MarkerAPIImpl.removeMarkerSet(this); /* Remove from top level sets (notification from there) */
|
||||
if(ispersistent)
|
||||
MarkerAPIImpl.saveMarkers();
|
||||
cleanup();
|
||||
}
|
||||
/**
|
||||
* Remove marker from set
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
void removeMarker(MarkerImpl marker) {
|
||||
markers.remove(marker.getMarkerID()); /* Remove from set */
|
||||
if(ispersistent && marker.isPersistentMarker()) { /* If persistent */
|
||||
MarkerAPIImpl.saveMarkers(); /* Drive save */
|
||||
}
|
||||
MarkerAPIImpl.markerUpdated(marker, MarkerUpdate.DELETED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration node to be saved
|
||||
* @return node
|
||||
*/
|
||||
Map<String, Object> getPersistentData() {
|
||||
if(!ispersistent) /* Nothing if not persistent */
|
||||
return null;
|
||||
HashMap<String, Object> node = new HashMap<String, Object>();
|
||||
for(String id : markers.keySet()) {
|
||||
MarkerImpl m = markers.get(id);
|
||||
if(m.isPersistentMarker()) {
|
||||
node.put(id, m.getPersistentData());
|
||||
}
|
||||
}
|
||||
/* Make top level node */
|
||||
HashMap<String, Object> setnode = new HashMap<String, Object>();
|
||||
setnode.put("label", label);
|
||||
if(allowedicons != null) {
|
||||
ArrayList<String> allowed = new ArrayList<String>(allowedicons.keySet());
|
||||
setnode.put("allowedicons", allowed);
|
||||
}
|
||||
setnode.put("markers", node);
|
||||
return setnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load marker from configuration node
|
||||
* @param node - configuration node
|
||||
*/
|
||||
boolean loadPersistentData(ConfigurationNode node) {
|
||||
label = node.getString("label", setid); /* Get label */
|
||||
ConfigurationNode markernode = node.getNode("markers");
|
||||
if(markernode != null) {
|
||||
for(String id : markernode.getKeys()) {
|
||||
MarkerImpl marker = new MarkerImpl(id, this); /* Make and load marker */
|
||||
if(marker.loadPersistentData(markernode.getNode(id))) {
|
||||
markers.put(id, marker);
|
||||
}
|
||||
else {
|
||||
Log.info("Error loading marker '" + id + "' for set '" + setid + "'");
|
||||
marker.cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
List<String> allowed = node.getStringList("allowedicons", null);
|
||||
if(allowed != null) {
|
||||
for(String id : allowed) {
|
||||
MarkerIconImpl icon = MarkerAPIImpl.getMarkerIconImpl(id);
|
||||
if(icon != null)
|
||||
allowedicons.put(id, icon);
|
||||
else
|
||||
Log.info("Error loading allowed icon '" + id + "' for set '" + setid + "'");
|
||||
}
|
||||
}
|
||||
ispersistent = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -40,6 +40,10 @@ components:
|
||||
# #- Trade
|
||||
# #- Haggle
|
||||
|
||||
# Note: this component is needed for the dmarker commands, and for the Marker API to be available to other plugins
|
||||
- class: org.dynmap.MarkersComponent
|
||||
type: markers
|
||||
|
||||
- class: org.dynmap.ClientComponent
|
||||
type: chat
|
||||
- class: org.dynmap.ClientComponent
|
||||
|
BIN
src/main/resources/markers/anchor.png
Normal file
After Width: | Height: | Size: 831 B |
BIN
src/main/resources/markers/bank.png
Normal file
After Width: | Height: | Size: 771 B |
BIN
src/main/resources/markers/basket.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
src/main/resources/markers/beer.png
Normal file
After Width: | Height: | Size: 609 B |
BIN
src/main/resources/markers/bighouse.png
Normal file
After Width: | Height: | Size: 756 B |
BIN
src/main/resources/markers/blueflag.png
Normal file
After Width: | Height: | Size: 726 B |
BIN
src/main/resources/markers/bomb.png
Normal file
After Width: | Height: | Size: 871 B |
BIN
src/main/resources/markers/bookshelf.png
Normal file
After Width: | Height: | Size: 719 B |
BIN
src/main/resources/markers/bricks.png
Normal file
After Width: | Height: | Size: 959 B |
BIN
src/main/resources/markers/bronzemedal.png
Normal file
After Width: | Height: | Size: 657 B |
BIN
src/main/resources/markers/bronzestar.png
Normal file
After Width: | Height: | Size: 692 B |
BIN
src/main/resources/markers/building.png
Normal file
After Width: | Height: | Size: 630 B |
BIN
src/main/resources/markers/cake.png
Normal file
After Width: | Height: | Size: 792 B |
BIN
src/main/resources/markers/camera.png
Normal file
After Width: | Height: | Size: 729 B |
BIN
src/main/resources/markers/cart.png
Normal file
After Width: | Height: | Size: 745 B |
BIN
src/main/resources/markers/caution.png
Normal file
After Width: | Height: | Size: 543 B |
BIN
src/main/resources/markers/chest.png
Normal file
After Width: | Height: | Size: 476 B |
BIN
src/main/resources/markers/church.png
Normal file
After Width: | Height: | Size: 608 B |
BIN
src/main/resources/markers/coins.png
Normal file
After Width: | Height: | Size: 672 B |
BIN
src/main/resources/markers/comment.png
Normal file
After Width: | Height: | Size: 695 B |
BIN
src/main/resources/markers/compass.png
Normal file
After Width: | Height: | Size: 906 B |
BIN
src/main/resources/markers/construction.png
Normal file
After Width: | Height: | Size: 654 B |
BIN
src/main/resources/markers/cross.png
Normal file
After Width: | Height: | Size: 473 B |
BIN
src/main/resources/markers/cup.png
Normal file
After Width: | Height: | Size: 724 B |
BIN
src/main/resources/markers/cutlery.png
Normal file
After Width: | Height: | Size: 584 B |
BIN
src/main/resources/markers/default.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
src/main/resources/markers/diamond.png
Normal file
After Width: | Height: | Size: 555 B |
BIN
src/main/resources/markers/dog.png
Normal file
After Width: | Height: | Size: 879 B |
BIN
src/main/resources/markers/door.png
Normal file
After Width: | Height: | Size: 606 B |
BIN
src/main/resources/markers/down.png
Normal file
After Width: | Height: | Size: 381 B |
BIN
src/main/resources/markers/drink.png
Normal file
After Width: | Height: | Size: 773 B |
BIN
src/main/resources/markers/exclamation.png
Normal file
After Width: | Height: | Size: 732 B |
BIN
src/main/resources/markers/factory.png
Normal file
After Width: | Height: | Size: 710 B |
BIN
src/main/resources/markers/fire.png
Normal file
After Width: | Height: | Size: 637 B |
BIN
src/main/resources/markers/flower.png
Normal file
After Width: | Height: | Size: 920 B |
BIN
src/main/resources/markers/gear.png
Normal file
After Width: | Height: | Size: 777 B |
BIN
src/main/resources/markers/goldmedal.png
Normal file
After Width: | Height: | Size: 664 B |
BIN
src/main/resources/markers/goldstar.png
Normal file
After Width: | Height: | Size: 699 B |
BIN
src/main/resources/markers/greenflag.png
Normal file
After Width: | Height: | Size: 722 B |
BIN
src/main/resources/markers/hammer.png
Normal file
After Width: | Height: | Size: 814 B |
BIN
src/main/resources/markers/heart.png
Normal file
After Width: | Height: | Size: 742 B |
BIN
src/main/resources/markers/house.png
Normal file
After Width: | Height: | Size: 727 B |
BIN
src/main/resources/markers/key.png
Normal file
After Width: | Height: | Size: 664 B |
BIN
src/main/resources/markers/king.png
Normal file
After Width: | Height: | Size: 691 B |
BIN
src/main/resources/markers/left.png
Normal file
After Width: | Height: | Size: 371 B |
BIN
src/main/resources/markers/lightbulb.png
Normal file
After Width: | Height: | Size: 685 B |
BIN
src/main/resources/markers/lighthouse.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
src/main/resources/markers/lock.png
Normal file
After Width: | Height: | Size: 689 B |
BIN
src/main/resources/markers/orangeflag.png
Normal file
After Width: | Height: | Size: 709 B |
BIN
src/main/resources/markers/pin.png
Normal file
After Width: | Height: | Size: 521 B |
BIN
src/main/resources/markers/pinkflag.png
Normal file
After Width: | Height: | Size: 711 B |
BIN
src/main/resources/markers/pirateflag.png
Normal file
After Width: | Height: | Size: 753 B |
BIN
src/main/resources/markers/pointdown.png
Normal file
After Width: | Height: | Size: 659 B |
BIN
src/main/resources/markers/pointleft.png
Normal file
After Width: | Height: | Size: 617 B |
BIN
src/main/resources/markers/pointright.png
Normal file
After Width: | Height: | Size: 620 B |
BIN
src/main/resources/markers/pointup.png
Normal file
After Width: | Height: | Size: 637 B |
BIN
src/main/resources/markers/purpleflag.png
Normal file
After Width: | Height: | Size: 744 B |
BIN
src/main/resources/markers/queen.png
Normal file
After Width: | Height: | Size: 694 B |
BIN
src/main/resources/markers/redflag.png
Normal file
After Width: | Height: | Size: 737 B |
BIN
src/main/resources/markers/right.png
Normal file
After Width: | Height: | Size: 363 B |
BIN
src/main/resources/markers/ruby.png
Normal file
After Width: | Height: | Size: 568 B |
BIN
src/main/resources/markers/scales.png
Normal file
After Width: | Height: | Size: 664 B |
BIN
src/main/resources/markers/shield.png
Normal file
After Width: | Height: | Size: 704 B |
BIN
src/main/resources/markers/sign.png
Normal file
After Width: | Height: | Size: 650 B |
BIN
src/main/resources/markers/silvermedal.png
Normal file
After Width: | Height: | Size: 635 B |
BIN
src/main/resources/markers/silverstar.png
Normal file
After Width: | Height: | Size: 717 B |
BIN
src/main/resources/markers/skull.png
Normal file
After Width: | Height: | Size: 798 B |
BIN
src/main/resources/markers/star.png
Normal file
After Width: | Height: | Size: 611 B |
BIN
src/main/resources/markers/sun.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
src/main/resources/markers/temple.png
Normal file
After Width: | Height: | Size: 627 B |
BIN
src/main/resources/markers/theater.png
Normal file
After Width: | Height: | Size: 815 B |
BIN
src/main/resources/markers/tornado.png
Normal file
After Width: | Height: | Size: 854 B |
BIN
src/main/resources/markers/tower.png
Normal file
After Width: | Height: | Size: 747 B |
BIN
src/main/resources/markers/tree.png
Normal file
After Width: | Height: | Size: 716 B |
BIN
src/main/resources/markers/truck.png
Normal file
After Width: | Height: | Size: 623 B |
BIN
src/main/resources/markers/up.png
Normal file
After Width: | Height: | Size: 391 B |
BIN
src/main/resources/markers/walk.png
Normal file
After Width: | Height: | Size: 700 B |
BIN
src/main/resources/markers/warning.png
Normal file
After Width: | Height: | Size: 652 B |
BIN
src/main/resources/markers/world.png
Normal file
After Width: | Height: | Size: 910 B |
BIN
src/main/resources/markers/wrench.png
Normal file
After Width: | Height: | Size: 660 B |
BIN
src/main/resources/markers/yellowflag.png
Normal file
After Width: | Height: | Size: 671 B |
@ -23,6 +23,11 @@ commands:
|
||||
/<command> stats world - Show render statistics for maps on world 'world'.
|
||||
/<command> resetstats - Reset render statistics.
|
||||
/<command> resetstats world - Reset render statistics for maps on world 'world'.
|
||||
dmarker:
|
||||
description: Manipulate map markers
|
||||
usage: |
|
||||
/<command> add <label> - add new marker at current location (use double-quotes if spaces needed)
|
||||
|
||||
permissions:
|
||||
dynmap.*:
|
||||
description: Gives access to all dynmap functions
|
||||
@ -39,6 +44,7 @@ permissions:
|
||||
dynmap.reload: true
|
||||
dynmap.stats: true
|
||||
dynmap.resetstats: true
|
||||
dynmap.marker.add: true
|
||||
dynmap.render:
|
||||
description: Allows /dynmap render command
|
||||
default: true
|
||||
@ -72,3 +78,7 @@ permissions:
|
||||
dynmap.resetstats:
|
||||
description: Allows /dynmap resetstats or /dynmap resetstats <world>
|
||||
default: op
|
||||
dynmap.marker.add:
|
||||
description: Allows /dmarker add
|
||||
default: op
|
||||
|
@ -499,6 +499,9 @@ DynMap.prototype = {
|
||||
},
|
||||
playerquit: function() {
|
||||
$(me).trigger('playerquit', [ update.playerName ]);
|
||||
},
|
||||
component: function() {
|
||||
$(me).trigger('component.' + update.ctype, [ update ]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
34
web/js/markers.js
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
var dynmapmarkersets = {};
|
||||
|
||||
componentconstructors['markers'] = function(dynmap, configuration) {
|
||||
var me = this;
|
||||
|
||||
function loadmarkers(world) {
|
||||
dynmapmarkersets = {};
|
||||
$.getJSON(dynmap.options.tileUrl+'_markers_/marker_'+world+'.json', function(data) {
|
||||
var ts = data.timestamp;
|
||||
$.each(data.sets, function(name, markerset) {
|
||||
dynmapmarkersets[name] = markerset;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(dynmap).bind('component.markers', function(event, msg) {
|
||||
console.log('got marker event - ' + msg.ctype + ', ' + msg.msg);
|
||||
});
|
||||
|
||||
// Remove marker on start of map change
|
||||
$(dynmap).bind('mapchanging', function(event) {
|
||||
});
|
||||
// Remove marker on map change - let update place it again
|
||||
$(dynmap).bind('mapchanged', function(event) {
|
||||
});
|
||||
// Load markers for new world
|
||||
$(dynmap).bind('worldchanged', function(event) {
|
||||
loadmarkers(this.world.name);
|
||||
});
|
||||
|
||||
loadmarkers(dynmap.world.name);
|
||||
|
||||
};
|
@ -9,12 +9,44 @@ function createMinecraftHead(player,size,completed,failed) {
|
||||
faceImage.src = dynmap.options.tileUrl + 'faces/' + size + 'x' + size + '/' + player + '.png';
|
||||
}
|
||||
|
||||
var playerHeads = {};
|
||||
|
||||
function getMinecraftHead(player,size,completed) {
|
||||
createMinecraftHead(player, size, completed, function() {
|
||||
console.error('Failed to retrieve face of "', player, '" with size "', size, '"!')
|
||||
});
|
||||
var key = player + '.' + size;
|
||||
var head = playerHeads[key];
|
||||
// Synchronous
|
||||
if (!completed) {
|
||||
return (!head || head.working) ? null : head;
|
||||
}
|
||||
|
||||
// Asynchronous
|
||||
if (!head) {
|
||||
playerHeads[key] = { working: true, hooks: [{f:completed}] };
|
||||
createMinecraftHead(player, size, function(head) {
|
||||
hooks = playerHeads[key].hooks;
|
||||
playerHeads[key] = head;
|
||||
var i;
|
||||
for(i=0;i<hooks.length;i++) {
|
||||
hooks[i].f(head);
|
||||
}
|
||||
head.working = false;
|
||||
}, function() {
|
||||
|
||||
});
|
||||
} else if (head.working) {
|
||||
//console.log('Other process working on head of ',player,', will add myself to hooks...');
|
||||
head.hooks[head.hooks.length] = {f:completed};
|
||||
} else {
|
||||
completed(head);
|
||||
}
|
||||
}
|
||||
|
||||
//function getMinecraftHead(player,size,completed) {
|
||||
// createMinecraftHead(player, size, completed, function() {
|
||||
// console.error('Failed to retrieve face of "', player, '" with size "', size, '"!')
|
||||
// });
|
||||
//}
|
||||
|
||||
function getMinecraftTime(servertime) {
|
||||
servertime = parseInt(servertime);
|
||||
var day = servertime >= 0 && servertime < 13700;
|
||||
|