Complete first drop of /dmarker commands and client support

This commit is contained in:
Mike Primm 2011-09-04 23:40:00 -05:00
parent 9f8ab5da03
commit f0db205eb9
9 changed files with 304 additions and 59 deletions

View File

@ -29,17 +29,17 @@ public interface Marker {
* Get marker's X coordinate
* @return x coordinate
*/
public int getX();
public double getX();
/**
* Get marker's Y coordinate
* @return y coordinate
*/
public int getY();
public double getY();
/**
* Get marker's Z coordinate
* @return z coordinate
*/
public int getZ();
public double getZ();
/**
* Update the marker's location
* @param worldid - world ID
@ -47,7 +47,7 @@ public interface Marker {
* @param y - y coord
* @param z - z coord
*/
public void setLocation(String worldid, int x, int y, int z);
public void setLocation(String worldid, double x, double y, double z);
/**
* Get the marker's icon
* @return marker icon

View File

@ -28,7 +28,7 @@ public interface MarkerSet {
* @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);
public Marker createMarker(String id, String label, String world, double x, double y, double z, MarkerIcon icon, boolean is_persistent);
/**
* Get marker by ID
* @param id - ID of the marker

View File

@ -68,7 +68,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
public static class MarkerUpdated extends MarkerComponentMessage {
public String msg;
public int x, y, z;
public double x, y, z;
public String id;
public String label;
public String icon;
@ -115,26 +115,29 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
/* Initialize persistence file name */
api.markerpersist = new File(plugin.getDataFolder(), "markers.yml");
api.markerpersist_old = new File(plugin.getDataFolder(), "markers.yml.old");
/* 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);
}
api.createBuiltinMarkerIcon(id, id);
}
/* Load persistence */
api.loadMarkers();
/* Initialize default marker set, if needed */
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());
if(api.markerdir.isDirectory() == false) {
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());
if(api.markertiledir.isDirectory() == false) {
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()) {
@ -403,9 +406,63 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
}
private static final Set<String> commands = new HashSet<String>(Arrays.asList(new String[] {
"add", "update", "delete", "list"
"add", "movehere", "update", "delete", "list", "icons"
}));
/* Parse argument strings : handle 'attrib=value' and quoted strings */
private static Map<String,String> parseArgs(String[] args, CommandSender snd) {
HashMap<String,String> rslt = new HashMap<String,String>();
/* Build command line, so we can parse our way - make sure there is trailing space */
String cmdline = "";
for(int i = 1; i < args.length; i++) {
cmdline += args[i] + " ";
}
boolean inquote = false;
StringBuilder sb = new StringBuilder();
String varid = null;
for(int i = 0; i < cmdline.length(); i++) {
char c = cmdline.charAt(i);
if(inquote) { /* If in quote, accumulate until end or another quote */
if(c == '\"') { /* End quote */
inquote = false;
if(varid == null) { /* No varid? */
rslt.put("label", sb.toString());
}
else {
rslt.put(varid, sb.toString());
varid = null;
}
sb.setLength(0);
}
else {
sb.append(c);
}
}
else if(c == '=') { /* var=value */
varid = sb.toString(); /* Save variable ID */
sb.setLength(0);
}
else if(c == ' ') { /* Ending space? */
if(varid == null) { /* No varid? */
rslt.put("label", sb.toString());
}
else {
rslt.put(varid, sb.toString());
varid = null;
}
sb.setLength(0);
}
else {
sb.append(c);
}
}
if(inquote) { /* If still in quote, syntax error */
snd.sendMessage("Error: unclosed doublequote");
return null;
}
return rslt;
}
public static boolean onCommand(DynmapPlugin plugin, CommandSender sender, Command cmd, String commandLabel, String[] args) {
if(api == null) {
sender.sendMessage("Markers component is not enabled.");
@ -427,38 +484,172 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener<DynmapWorld> {
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);
}
/* Parse arguements */
Map<String,String> parms = parseArgs(args, sender);
if(parms == null) return true;
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);
/* Fill in defaults for missing parameters */
if(parms.get("icon") == null) {
parms.put("icon", MarkerIcon.DEFAULT);
}
if(parms.get("set") == null) {
parms.put("set", MarkerSet.DEFAULT);
}
/* Add new marker */
MarkerSet set = api.getMarkerSet(parms.get("set"));
if(set == null) {
sender.sendMessage("Error: invalid marker set - " + parms.get("set"));
return true;
}
MarkerIcon ico = api.getMarkerIcon(parms.get("icon"));
if(ico == null) {
sender.sendMessage("Error: invalid icon - " + parms.get("icon"));
return true;
}
Marker m = set.createMarker(parms.get("id"), parms.get("label"),
loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ(), 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());
sender.sendMessage("Added marker id='" + m.getMarkerID() + "' (" + m.getLabel() + ") to set '" + set.getMarkerSetID() + "'");
}
}
else {
sender.sendMessage("Marker label required");
}
}
/* Update position of bookmark - must have ID parameter */
else if(c.equals("movehere") && plugin.checkPlayerPermission(sender, "marker.movehere")) {
if(player == null) {
sender.sendMessage("Command can only be used by player");
}
else if(args.length > 1) {
/* Parse arguements */
Map<String,String> parms = parseArgs(args, sender);
if(parms == null) return true;
if(parms.get("id") == null) {
sender.sendMessage("id=<marker-id> required");
return true;
}
if(parms.get("set") == null) {
parms.put("set", MarkerSet.DEFAULT);
}
MarkerSet set = api.getMarkerSet(parms.get("set"));
if(set == null) {
sender.sendMessage("Error: invalid marker set - " + parms.get("set"));
return true;
}
Marker marker = set.findMarker(parms.get("id"));
if(marker == null) { /* No marker */
sender.sendMessage("Error: marker not found - " + parms.get("id"));
return true;
}
Location loc = player.getLocation();
marker.setLocation(loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ());
sender.sendMessage("Updated location of marker id=" + parms.get("id") + " (" + marker.getLabel() + ")");
}
else {
sender.sendMessage("id=<marker-id> required");
}
}
/* Update other attributes of marker - must have ID parameter */
else if(c.equals("update") && plugin.checkPlayerPermission(sender, "marker.update")) {
if(args.length > 1) {
/* Parse arguements */
Map<String,String> parms = parseArgs(args, sender);
if(parms == null) return true;
if(parms.get("id") == null) {
sender.sendMessage("id=<marker-id> required");
return true;
}
if(parms.get("set") == null) {
parms.put("set", MarkerSet.DEFAULT);
}
MarkerSet set = api.getMarkerSet(parms.get("set"));
if(set == null) {
sender.sendMessage("Error: invalid marker set - " + parms.get("set"));
return true;
}
Marker marker = set.findMarker(parms.get("id"));
if(marker == null) { /* No marker */
sender.sendMessage("Error: marker not found - " + parms.get("id"));
return true;
}
if(parms.get("label") != null) { /* Label set? */
marker.setLabel(parms.get("label"));
}
if(parms.get("icon") != null) {
MarkerIcon ico = api.getMarkerIcon(parms.get("icon"));
if(ico == null) {
sender.sendMessage("Error: invalid icon - " + parms.get("icon"));
return true;
}
marker.setMarkerIcon(ico);
}
sender.sendMessage("Updated marker id=" + parms.get("id") + " (" + marker.getLabel() + ")");
}
else {
sender.sendMessage("id=<marker-id> required");
}
}
/* Delete marker - must have ID parameter */
else if(c.equals("delete") && plugin.checkPlayerPermission(sender, "marker.delete")) {
if(args.length > 1) {
/* Parse arguements */
Map<String,String> parms = parseArgs(args, sender);
if(parms == null) return true;
if(parms.get("id") == null) {
sender.sendMessage("id=<marker-id> required");
return true;
}
if(parms.get("set") == null) {
parms.put("set", MarkerSet.DEFAULT);
}
MarkerSet set = api.getMarkerSet(parms.get("set"));
if(set == null) {
sender.sendMessage("Error: invalid marker set - " + parms.get("set"));
return true;
}
Marker marker = set.findMarker(parms.get("id"));
if(marker == null) { /* No marker */
sender.sendMessage("Error: marker not found - " + parms.get("id"));
return true;
}
marker.deleteMarker();
sender.sendMessage("Deleted marker id=" + parms.get("id"));
}
else {
sender.sendMessage("id=<marker-id> required");
}
}
/* List markers */
else if(c.equals("list") && plugin.checkPlayerPermission(sender, "marker.list")) {
/* Parse arguements */
Map<String,String> parms = parseArgs(args, sender);
if(parms == null) return true;
if(parms.get("set") == null) {
parms.put("set", MarkerSet.DEFAULT);
}
MarkerSet set = api.getMarkerSet(parms.get("set"));
if(set == null) {
sender.sendMessage("Error: invalid marker set - " + parms.get("set"));
return true;
}
Set<Marker> markers = set.getMarkers();
for(Marker m : markers) {
sender.sendMessage(m.getMarkerID() + ": label=\"" + m.getLabel() + "\", set=" + m.getMarkerSet().getMarkerSetID() +
", world=" + m.getWorld() + ", x=" + m.getX() + ", y=" + m.getY() + ", z=" + m.getZ());
}
}
/* List icons */
else if(c.equals("icons") && plugin.checkPlayerPermission(sender, "marker.icons")) {
Set<MarkerIcon> icons = api.getMarkerIcons();
for(MarkerIcon ico : icons) {
sender.sendMessage(ico.getMarkerIconID() + ": label=\"" + ico.getMarkerIconLabel() + "\", builtin=" + ico.isBuiltIn());
}
}
else {
return false;
}

View File

@ -15,7 +15,7 @@ class MarkerImpl implements Marker {
private String markerid;
private String label;
private MarkerSetImpl markerset;
private int x, y, z;
private double x, y, z;
private String world;
private MarkerIconImpl icon;
private boolean ispersistent;
@ -31,7 +31,7 @@ class MarkerImpl implements Marker {
* @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) {
MarkerImpl(String id, String lbl, String world, double x, double y, double z, MarkerIconImpl icon, boolean persistent, MarkerSetImpl set) {
markerid = id;
if(lbl != null)
label = lbl;
@ -61,9 +61,9 @@ class MarkerImpl implements Marker {
*/
boolean loadPersistentData(ConfigurationNode node) {
label = node.getString("label", markerid);
x = node.getInt("x", 0);
y = node.getInt("y", 64);
z = node.getInt("z", 0);
x = node.getDouble("x", 0);
y = node.getDouble("y", 64);
z = node.getDouble("z", 0);
world = node.getString("world", "world");
icon = MarkerAPIImpl.getMarkerIconImpl(node.getString("icon", MarkerIcon.DEFAULT));
ispersistent = true; /* Loaded from config, so must be */
@ -142,9 +142,9 @@ class MarkerImpl implements Marker {
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("x", Double.valueOf(x));
node.put("y", Double.valueOf(y));
node.put("z", Double.valueOf(z));
node.put("world", world);
node.put("icon", icon.getMarkerIconID());
@ -155,19 +155,19 @@ class MarkerImpl implements Marker {
return world;
}
@Override
public int getX() {
public double getX() {
return x;
}
@Override
public int getY() {
public double getY() {
return y;
}
@Override
public int getZ() {
public double getZ() {
return z;
}
@Override
public void setLocation(String worldid, int x, int y, int z) {
public void setLocation(String worldid, double x, double y, double z) {
this.world = worldid;
this.x = x;
this.y = y;

View File

@ -57,7 +57,7 @@ class MarkerSetImpl implements MarkerSet {
}
@Override
public Marker createMarker(String id, String label, String world, int x, int y, int z, MarkerIcon icon, boolean is_persistent) {
public Marker createMarker(String id, String label, String world, double x, double y, double z, MarkerIcon icon, boolean is_persistent) {
if(id == null) { /* If not defined, generate unique one */
int i = 0;
do {

View File

@ -43,6 +43,8 @@ components:
# 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
# If set, shows labels all the time (default is only on hover)
#showlabel: true
- class: org.dynmap.ClientComponent
type: chat

View File

@ -26,7 +26,13 @@ commands:
dmarker:
description: Manipulate map markers
usage: |
/<command> add <label> - add new marker at current location (use double-quotes if spaces needed)
/<command> add <label> - add new marker with generated ID at current location (use double-quotes if spaces needed)
/<command> add id=<id> <label> - add new marker with given ID at current location (use double-quotes if spaces needed)
/<command> movehere id=<id> - move marker with given ID to current location
/<command> update id=<id> <label> icon=<icon> - update marker with given ID with new label and/or icon
/<command> delete id=<id> - delete marker with given ID
/<command> list - list details of all markers
/<command> icons - list details of all icons
permissions:
dynmap.*:
@ -45,6 +51,11 @@ permissions:
dynmap.stats: true
dynmap.resetstats: true
dynmap.marker.add: true
dynmap.marker.update: true
dynmap.marker.movehere: true
dynmap.marker.delete: true
dynmap.marker.list: true
dynmap.marker.icons: true
dynmap.render:
description: Allows /dynmap render command
default: true
@ -81,4 +92,17 @@ permissions:
dynmap.marker.add:
description: Allows /dmarker add
default: op
dynmap.marker.update:
description: Allows /dmarker update
default: op
dynmap.marker.movehere:
description: Allows /dmarker movehere
default: op
dynmap.marker.delete:
description: Allows /dmarker delete
default: op
dynmap.marker.list:
description: Allows /dmarker list
dynmap.marker.icons:
description: Allows /dmarker icons

View File

@ -760,7 +760,7 @@
position: absolute;
top: -8px;
left: 10px;
z-index: 18;
z-index: 16;
white-space: nowrap;

View File

@ -4,23 +4,31 @@ var dynmapmarkersets = {};
componentconstructors['markers'] = function(dynmap, configuration) {
var me = this;
function removeall() {
function removeAllMarkers() {
$.each(dynmapmarkersets, function(setname, set) {
$.each(set.markers, function(mname, marker) {
set.layergroup.removeLayer(marker.our_marker);
});
dynmap.layercontrol.removeLayer(set.layergroup);
});
}
function loadmarkers(world) {
removeall();
dynmapmarkersets = {};
removeAllMarkers();
$.getJSON(dynmap.options.tileUrl+'_markers_/marker_'+world+'.json', function(data) {
var ts = data.timestamp;
$.each(data.sets, function(name, markerset) {
dynmapmarkersets[name] = markerset;
createMarkerSet(markerset);
if(!dynmapmarkersets[name]) {
dynmapmarkersets[name] = markerset;
createMarkerSet(markerset);
}
else {
if(dynmapmarkersets[name].label != markerset.label) {
dynmapmarkersets[name].label = markerset.label;
dynmap.layercontrol.removeLayer(dynmapmarkersets[name].layergroup);
dynmap.layercontrol.addOverlay(dynmapmarkersets[name].layergroup, dynmapmarkersets[name].label);
}
dynmapmarkersets[name].markers = markerset.markers;
}
$.each(markerset.markers, function(name, marker) {
createMarker(markerset, marker);
});
@ -45,7 +53,7 @@ componentconstructors['markers'] = function(dynmap, configuration) {
.addClass('mapMarker')
.append($('<img/>').addClass('markerIcon16x16').attr({ src: dynmap.options.tileUrl+'_markers_/'+marker.icon+'.png' }))
.append($('<span/>')
.addClass('markerName')
.addClass(configuration.showlabel?'markerName-show':'markerName')
.text(marker.label));
return div;
}});
@ -77,6 +85,26 @@ componentconstructors['markers'] = function(dynmap, configuration) {
}
delete dynmapmarkersets[msg.set].markers[msg.id];
}
else if(msg.msg == 'setupdated') {
if(!dynmapmarkersets[msg.id]) {
dynmapmarkersets[msg.id] = { label: msg.label, markers:{} };
createMarkerSet(dynmapmarkersets[msg.id]);
}
else {
if(dynmapmarkersets[msg.id].label != msg.label) {
dynmapmarkersets[msg.id].label = msg.label;
dynmap.layercontrol.removeLayer(dynmapmarkersets[msg.id].layergroup);
dynmap.layercontrol.addOverlay(dynmapmarkersets[msg.id].layergroup, dynmapmarkersets[msg.id].label);
}
}
}
else if(msg.msg == 'setdeleted') {
if(dynmapmarkersets[msg.id]) {
dynmap.layercontrol.removeLayer(dynmapmarkersets[msg.id].layergroup);
delete dynmapmarkersets[msg.id].layergroup;
delete dynmapmarkersets[msg.id];
}
}
});
// Remove marker on start of map change