@@ -79,5 +96,11 @@
3.3.3
provided
+
+ org.jetbrains
+ annotations
+ 24.0.1
+ compile
+
\ No newline at end of file
diff --git a/src/main/java/org/dynmap/factions/AreaStyle.java b/src/main/java/org/dynmap/factions/AreaStyle.java
index 080d419..95fb372 100644
--- a/src/main/java/org/dynmap/factions/AreaStyle.java
+++ b/src/main/java/org/dynmap/factions/AreaStyle.java
@@ -2,50 +2,82 @@ package org.dynmap.factions;
import org.bukkit.configuration.file.FileConfiguration;
import org.dynmap.markers.MarkerIcon;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-class AreaStyle {
+/**
+ * A style usable to mark a faction area
+ *
+ * @param strokeColor The color of the outer stroke
+ * @param strokeOpacity The opacity of the outer stroke
+ * @param strokeWeight The weight (priority) of the stroke
+ * @param fillColor The color of the filled-in area
+ * @param fillOpacity The opacity of the filled-in area
+ * @param homeMarker The name of the icon to use for marking faction homes
+ * @param homeIcon The icon to use for marking faction homes
+ * @param boost
+ */
+public record AreaStyle(String strokeColor, double strokeOpacity, int strokeWeight, String fillColor,
+ double fillOpacity, String homeMarker, MarkerIcon homeIcon, boolean boost) {
- final String strokecolor;
- final double strokeopacity;
- final int strokeweight;
- final String fillcolor;
- final double fillopacity;
- final String homemarker;
- MarkerIcon homeicon;
- final boolean boost;
-
- AreaStyle(DynmapFactionsPlugin dynmapFactionsPlugin, FileConfiguration cfg, String path, AreaStyle def) {
- strokecolor = cfg.getString(path + ".strokeColor", def.strokecolor);
- strokeopacity = cfg.getDouble(path + ".strokeOpacity", def.strokeopacity);
- strokeweight = cfg.getInt(path + ".strokeWeight", def.strokeweight);
- fillcolor = cfg.getString(path + ".fillColor", def.fillcolor);
- fillopacity = cfg.getDouble(path + ".fillOpacity", def.fillopacity);
- homemarker = cfg.getString(path + ".homeicon", def.homemarker);
- if (homemarker != null) {
- homeicon = dynmapFactionsPlugin.markerapi.getMarkerIcon(homemarker);
- if (homeicon == null) {
- DynmapFactionsPlugin.severe("Invalid homeicon: " + homemarker);
- homeicon = dynmapFactionsPlugin.markerapi.getMarkerIcon("blueicon");
- }
- }
- boost = cfg.getBoolean(path + ".boost", def.boost);
+ /**
+ * Instantiates a new area style
+ *
+ * @param dynmapFactionsPlugin An instance of the dynmap factions plugin
+ * @param cfg The configuration to read
+ * @param path The path of the area style to load from the config
+ * @param def The default area style to use for missing values
+ */
+ public AreaStyle(@NotNull DynmapFactionsPlugin dynmapFactionsPlugin, @NotNull FileConfiguration cfg,
+ @NotNull String path, @NotNull AreaStyle def) {
+ this(cfg.getString(path + ".strokeColor", def.strokeColor),
+ cfg.getDouble(path + ".strokeOpacity", def.strokeOpacity),
+ cfg.getInt(path + ".strokeWeight", def.strokeWeight),
+ cfg.getString(path + ".fillColor", def.fillColor),
+ cfg.getDouble(path + ".fillOpacity", def.fillOpacity),
+ cfg.getString(path + ".homeIcon", def.homeMarker),
+ getHomeIcon(dynmapFactionsPlugin, cfg.getString(path + ".homeIcon", def.homeMarker)),
+ cfg.getBoolean(path + ".boost", def.boost));
}
- AreaStyle(DynmapFactionsPlugin dynmapFactionsPlugin, FileConfiguration cfg, String path) {
- strokecolor = cfg.getString(path + ".strokeColor", "#FF0000");
- strokeopacity = cfg.getDouble(path + ".strokeOpacity", 0.8);
- strokeweight = cfg.getInt(path + ".strokeWeight", 3);
- fillcolor = cfg.getString(path + ".fillColor", "#FF0000");
- fillopacity = cfg.getDouble(path + ".fillOpacity", 0.35);
- homemarker = cfg.getString(path + ".homeicon", null);
- if (homemarker != null) {
- homeicon = dynmapFactionsPlugin.markerapi.getMarkerIcon(homemarker);
- if (homeicon == null) {
- DynmapFactionsPlugin.severe("Invalid homeicon: " + homemarker);
- homeicon = dynmapFactionsPlugin.markerapi.getMarkerIcon("blueicon");
+ /**
+ * Instantiates a new area style
+ *
+ * @param dynmapFactionsPlugin An instance of the dynmap factions plugin
+ * @param cfg The configuration to read
+ * @param path The path of the area style to load from the config
+ */
+ public AreaStyle(@NotNull DynmapFactionsPlugin dynmapFactionsPlugin, @NotNull FileConfiguration cfg,
+ @NotNull String path) {
+ this(cfg.getString(path + ".strokeColor", "#FF0000"),
+ cfg.getDouble(path + ".strokeOpacity", 0.8),
+ cfg.getInt(path + ".strokeWeight", 3),
+ cfg.getString(path + ".fillColor", "#FF0000"),
+ cfg.getDouble(path + ".fillOpacity", 0.35),
+ cfg.getString(path + ".homeIcon", null),
+ getHomeIcon(dynmapFactionsPlugin, cfg.getString(path + ".homeIcon", null)),
+ cfg.getBoolean(path + ".boost", false));
+ }
+
+ /**
+ * Gets the icon to use for marking a faction home
+ *
+ * @param dynmapFactionsPlugin An instance of the dynmap factions plugin
+ * @param homeMarker The name of the marker to get
+ * @return The marker, or null if it does not exist
+ */
+ @Nullable
+ private static MarkerIcon getHomeIcon(@NotNull DynmapFactionsPlugin dynmapFactionsPlugin,
+ @Nullable String homeMarker) {
+ MarkerIcon homeIcon = null;
+ if (homeMarker != null) {
+ homeIcon = dynmapFactionsPlugin.markerAPI.getMarkerIcon(homeMarker);
+ if (homeIcon == null) {
+ DynmapFactionsPlugin.severe("Invalid home icon: " + homeMarker);
+ homeIcon = dynmapFactionsPlugin.markerAPI.getMarkerIcon("blueicon");
}
}
- boost = cfg.getBoolean(path + ".boost", false);
+ return homeIcon;
}
-
+
}
diff --git a/src/main/java/org/dynmap/factions/Direction.java b/src/main/java/org/dynmap/factions/Direction.java
index 38e37f5..fa4aaa2 100644
--- a/src/main/java/org/dynmap/factions/Direction.java
+++ b/src/main/java/org/dynmap/factions/Direction.java
@@ -1,10 +1,28 @@
package org.dynmap.factions;
+/**
+ * A representation of the directions that make sense in a Dynmap context
+ */
public enum Direction {
-
- XPLUS,
- ZPLUS,
- XMINUS,
- ZMINUS
+
+ /**
+ * The positive X direction
+ */
+ POSITIVE_X,
+
+ /**
+ * The positive Z direction
+ */
+ POSITIVE_Z,
+
+ /**
+ * The negative x direction
+ */
+ NEGATIVE_X,
+
+ /**
+ * The negative z direction
+ */
+ NEGATIVE_Z
}
diff --git a/src/main/java/org/dynmap/factions/OurServerListener.java b/src/main/java/org/dynmap/factions/DynmapFactionsListener.java
similarity index 69%
rename from src/main/java/org/dynmap/factions/OurServerListener.java
rename to src/main/java/org/dynmap/factions/DynmapFactionsListener.java
index dfa5bef..02beaf3 100644
--- a/src/main/java/org/dynmap/factions/OurServerListener.java
+++ b/src/main/java/org/dynmap/factions/DynmapFactionsListener.java
@@ -14,16 +14,18 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
+
+public class DynmapFactionsListener implements Listener {
-class OurServerListener implements Listener {
private final DynmapFactionsPlugin dynmapFactionsPlugin;
- public OurServerListener(DynmapFactionsPlugin dynmapFactionsPlugin) {
+ public DynmapFactionsListener(DynmapFactionsPlugin dynmapFactionsPlugin) {
this.dynmapFactionsPlugin = dynmapFactionsPlugin;
}
@EventHandler
- public void onPluginEnable(PluginEnableEvent event) {
+ public void onPluginEnable(@NotNull PluginEnableEvent event) {
Plugin p = event.getPlugin();
String name = p.getDescription().getName();
if (name.equals("dynmap") || name.equals("Factions")) {
@@ -34,33 +36,33 @@ class OurServerListener implements Listener {
}
@EventHandler(priority = EventPriority.MONITOR)
- public void onFPlayerJoin(EventFactionsMembershipChange event) {
+ public void onFPlayerJoin(@NotNull EventFactionsMembershipChange event) {
if (event.isCancelled()) {
return;
}
- if (dynmapFactionsPlugin.playersets) {
+ if (dynmapFactionsPlugin.playerSets) {
Faction f = event.getNewFaction();
dynmapFactionsPlugin.requestUpdatePlayerSet(f.getId());
}
}
@EventHandler(priority = EventPriority.MONITOR)
- public void onFactionCreate(EventFactionsCreate event) {
+ public void onFactionCreate(@NotNull EventFactionsCreate event) {
if (event.isCancelled()) {
return;
}
- if (dynmapFactionsPlugin.playersets) {
+ if (dynmapFactionsPlugin.playerSets) {
dynmapFactionsPlugin.requestUpdatePlayerSet(event.getFactionId());
}
requestUpdateFactions();
}
@EventHandler(priority = EventPriority.MONITOR)
- public void onFactionDisband(EventFactionsDisband event) {
+ public void onFactionDisband(@NotNull EventFactionsDisband event) {
if (event.isCancelled()) {
return;
}
- if (dynmapFactionsPlugin.playersets) {
+ if (dynmapFactionsPlugin.playerSets) {
Faction f = event.getFaction();
dynmapFactionsPlugin.requestUpdatePlayerSet(f.getId());
}
@@ -68,7 +70,7 @@ class OurServerListener implements Listener {
}
@EventHandler(priority = EventPriority.MONITOR)
- public void onFactionRename(EventFactionsNameChange event) {
+ public void onFactionRename(@NotNull EventFactionsNameChange event) {
if (event.isCancelled()) {
return;
}
@@ -76,7 +78,7 @@ class OurServerListener implements Listener {
}
@EventHandler(priority = EventPriority.MONITOR)
- public void onFactionRename(EventFactionsWarpAdd event) {
+ public void onFactionRename(@NotNull EventFactionsWarpAdd event) {
if (event.isCancelled()) {
return;
}
@@ -84,7 +86,7 @@ class OurServerListener implements Listener {
}
@EventHandler(priority = EventPriority.MONITOR)
- public void onFactionRename(EventFactionsWarpRemove event) {
+ public void onFactionRename(@NotNull EventFactionsWarpRemove event) {
if (event.isCancelled()) {
return;
}
@@ -92,7 +94,7 @@ class OurServerListener implements Listener {
}
@EventHandler(priority = EventPriority.MONITOR)
- public void onFactionRename(EventFactionsChunksChange event) {
+ public void onFactionRename(@NotNull EventFactionsChunksChange event) {
if (event.isCancelled()) {
return;
}
@@ -101,10 +103,11 @@ class OurServerListener implements Listener {
private void requestUpdateFactions() {
if (DynmapFactionsPlugin.instance.pending == null) {
- FactionsUpdate upd = new FactionsUpdate(DynmapFactionsPlugin.instance);
- upd.runonce = true;
- DynmapFactionsPlugin.instance.pending = upd;
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(DynmapFactionsPlugin.instance, upd, 20);
+ FactionsUpdate factionsUpdate = new FactionsUpdate(DynmapFactionsPlugin.instance,
+ DynmapFactionsPlugin.instance.getConfig());
+ factionsUpdate.runonce = true;
+ DynmapFactionsPlugin.instance.pending = factionsUpdate;
+ Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(DynmapFactionsPlugin.instance, factionsUpdate, 20);
}
}
diff --git a/src/main/java/org/dynmap/factions/DynmapFactionsPlugin.java b/src/main/java/org/dynmap/factions/DynmapFactionsPlugin.java
index 11a96d6..466bc5f 100644
--- a/src/main/java/org/dynmap/factions/DynmapFactionsPlugin.java
+++ b/src/main/java/org/dynmap/factions/DynmapFactionsPlugin.java
@@ -1,16 +1,8 @@
package org.dynmap.factions;
-import com.massivecraft.factions.Factions;
-import com.massivecraft.factions.entity.BoardColl;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.FactionColl;
-import com.massivecraft.factions.entity.MFlag;
-import com.massivecraft.factions.entity.MFlagColl;
import com.massivecraft.factions.entity.MPlayer;
-import com.massivecraft.factions.entity.Warp;
-import com.massivecraft.massivecore.ps.PS;
-import com.massivecraft.massivecore.store.EntityInternalMap;
-import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.Plugin;
@@ -20,17 +12,12 @@ import org.dynmap.DynmapAPI;
import org.dynmap.markers.AreaMarker;
import org.dynmap.markers.Marker;
import org.dynmap.markers.MarkerAPI;
-import org.dynmap.markers.MarkerIcon;
import org.dynmap.markers.MarkerSet;
import org.dynmap.markers.PlayerSet;
+import org.jetbrains.annotations.NotNull;
-import java.io.IOException;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -40,33 +27,36 @@ import java.util.logging.Logger;
public class DynmapFactionsPlugin extends JavaPlugin {
private static Logger log;
- private static final String DEF_INFOWINDOW = "%regionname%
Flags
%flags%
";
Plugin dynmap;
DynmapAPI api;
- MarkerAPI markerapi;
+ MarkerAPI markerAPI;
Plugin factions;
- Factions factapi;
- boolean playersets;
-
- int blocksize;
-
+ boolean playerSets;
+ Map factionAreaMarkers = new HashMap<>();
+ Map factionMarkers = new HashMap<>();
+ AreaStyle defaultStyle;
+ Map customStyle;
+ int blockSize;
MarkerSet set;
- long updperiod;
- boolean use3d;
- String infowindow;
- AreaStyle defstyle;
- Map cusstyle;
+ long updatePeriod;
+
Set visible;
Set hidden;
boolean stop;
static DynmapFactionsPlugin instance;
+ private boolean reload = false;
@Override
public void onLoad() {
log = this.getLogger();
}
- public static void info(String msg) {
+ /**
+ * Logs an info message
+ *
+ * @param msg The message to log
+ */
+ public static void info(@NotNull String msg) {
log.log(Level.INFO, msg);
}
@@ -74,391 +64,47 @@ public class DynmapFactionsPlugin extends JavaPlugin {
log.log(Level.SEVERE, msg);
}
- void requestUpdatePlayerSet(String factid) {
- if (playersets) {
- getServer().getScheduler().scheduleSyncDelayedTask(this, new PlayerSetUpdate(this, factid));
+ void requestUpdatePlayerSet(String factionId) {
+ if (playerSets) {
+ getServer().getScheduler().scheduleSyncDelayedTask(this, new PlayerSetUpdate(this, factionId));
}
}
FactionsUpdate pending = null;
- void updatePlayerSet(String factid) {
+ void updatePlayerSet(String factionId) {
/* If Wilderness or other unassociated factions (guid-style ID), skip */
- if (factid.indexOf('-') >= 0) {
+ if (factionId.indexOf('-') >= 0) {
return;
}
- Set plids = new HashSet<>();
+ Set playerIds = new HashSet<>();
FactionColl fc = FactionColl.get();
- Faction f = fc.getByName(factid); /* Get faction */
+ Faction f = fc.getByName(factionId); /* Get faction */
if (f != null) {
List ps = f.getMPlayers();
for (MPlayer fp : ps) {
- plids.add(fp.getId());
+ playerIds.add(fp.getId());
}
- factid = f.getId();
+ factionId = f.getId();
}
- String setid = "factions." + factid;
- PlayerSet set = markerapi.getPlayerSet(setid); /* See if set exists */
+ String setId = "factions." + factionId;
+ PlayerSet set = markerAPI.getPlayerSet(setId); /* See if set exists */
if ((set == null) && (f != null)) {
- set = markerapi.createPlayerSet(setid, true, plids, false);
- info("Added player visibility set '" + setid + "' for faction " + factid);
+ set = markerAPI.createPlayerSet(setId, true, playerIds, false);
+ info("Added player visibility set '" + setId + "' for faction " + factionId);
}
-
+
if (f != null) {
- set.setPlayers(plids);
+ set.setPlayers(playerIds);
} else if (set != null) {
set.deleteSet();
}
}
- private Map resareas = new HashMap<>();
- private Map resmark = new HashMap<>();
-
- private String formatInfoWindow(Faction fact) {
- String v = "" + infowindow + "
";
- v = v.replace("%regionname%", ChatColor.stripColor(fact.getName()));
- v = v.replace("%description%", ChatColor.stripColor(fact.getDescription()));
- MPlayer adm = fact.getLeader();
- v = v.replace("%playerowners%", (adm != null) ? adm.getName() : "");
- StringBuilder res = new StringBuilder();
- for (MPlayer r : fact.getMPlayers()) {
- if (!res.isEmpty()) {
- res.append(", ");
- }
- res.append(r.getName());
- }
- v = v.replace("%playermembers%", res.toString());
-
- v = v.replace("%nation%", ChatColor.stripColor(fact.getName()));
- /* Build flags */
- StringBuilder flgs = new StringBuilder();
- for (MFlag ff : MFlagColl.get().getAll()) {
- flgs.append("
").append(ff.getName()).append(": ").append(fact.getFlag(ff));
- v = v.replace("%flag." + ff.getName() + "%", fact.getFlag(ff) ? "true" : "false");
- }
- v = v.replace("%flags%", flgs.toString());
- return v;
- }
-
- private boolean isVisible(String id, String worldname) {
- if ((visible != null) && (!visible.isEmpty())) {
- if ((!visible.contains(id)) && (!visible.contains("world:" + worldname))) {
- return false;
- }
- }
- if ((hidden != null) && (!hidden.isEmpty())) {
- return !hidden.contains(id) && !hidden.contains("world:" + worldname);
- }
- return true;
- }
-
- private void addStyle(String resid, AreaMarker m) {
- AreaStyle as = cusstyle.get(resid);
- if (as == null) {
- as = defstyle;
- }
- int sc = 0xFF0000;
- int fc = 0xFF0000;
- try {
- sc = Integer.parseInt(as.strokecolor.substring(1), 16);
- fc = Integer.parseInt(as.fillcolor.substring(1), 16);
- } catch (NumberFormatException ignored) {
- }
- m.setLineStyle(as.strokeweight, as.strokeopacity, sc);
- m.setFillStyle(as.fillopacity, fc);
- m.setBoostFlag(as.boost);
- }
-
- private MarkerIcon getMarkerIcon(String factname, Faction fact) {
- AreaStyle as = cusstyle.get(factname);
- if (as == null) {
- as = defstyle;
- }
- return as.homeicon;
- }
-
- /**
- * Find all contiguous blocks, set in target and clear in source
- */
- private int floodFillTarget(TileFlags src, TileFlags dest, int x, int y) {
- int cnt = 0;
- ArrayDeque stack = new ArrayDeque<>();
- stack.push(new int[]{x, y});
-
- while (!stack.isEmpty()) {
- int[] nxt = stack.pop();
- x = nxt[0];
- y = nxt[1];
- if (src.getFlag(x, y)) { /* Set in src */
- src.setFlag(x, y, false); /* Clear source */
- dest.setFlag(x, y, true); /* Set in destination */
- cnt++;
- if (src.getFlag(x + 1, y)) {
- stack.push(new int[]{x + 1, y});
- }
- if (src.getFlag(x - 1, y)) {
- stack.push(new int[]{x - 1, y});
- }
- if (src.getFlag(x, y + 1)) {
- stack.push(new int[]{x, y + 1});
- }
- if (src.getFlag(x, y - 1)) {
- stack.push(new int[]{x, y - 1});
- }
- }
- }
- return cnt;
- }
-
- /* Handle specific faction on specific world */
- private void handleFactionOnWorld(String factname, Faction fact, String world, LinkedList blocks, Map newmap, Map newmark) {
- double[] x;
- double[] z;
- int poly_index = 0; /* Index of polygon for given faction */
-
- /* Build popup */
- String desc = formatInfoWindow(fact);
-
- /* Handle areas */
- if (isVisible(factname, world)) {
- if (blocks.isEmpty()) {
- return;
- }
- LinkedList nodevals = new LinkedList<>();
- TileFlags curblks = new TileFlags();
- /* Loop through blocks: set flags on blockmaps */
- for (FactionBlock b : blocks) {
- curblks.setFlag(b.x(), b.z(), true); /* Set flag for block */
- nodevals.addLast(b);
- }
- /* Loop through until we don't find more areas */
- while (nodevals != null) {
- LinkedList ournodes = null;
- LinkedList newlist = null;
- TileFlags ourblks = null;
- int minx = Integer.MAX_VALUE;
- int minz = Integer.MAX_VALUE;
- for (FactionBlock node : nodevals) {
- int nodex = node.x();
- int nodez = node.z();
- /* If we need to start shape, and this block is not part of one yet */
- if ((ourblks == null) && curblks.getFlag(nodex, nodez)) {
- ourblks = new TileFlags(); /* Create map for shape */
- ournodes = new LinkedList<>();
- floodFillTarget(curblks, ourblks, nodex, nodez); /* Copy shape */
- ournodes.add(node); /* Add it to our node list */
- minx = nodex;
- minz = nodez;
- }
- /* If shape found, and we're in it, add to our node list */
- else if ((ourblks != null) && ourblks.getFlag(nodex, nodez)) {
- ournodes.add(node);
- if (nodex < minx) {
- minx = nodex;
- minz = nodez;
- } else if ((nodex == minx) && (nodez < minz)) {
- minz = nodez;
- }
- } else { /* Else, keep it in the list for the next polygon */
- if (newlist == null) {
- newlist = new LinkedList<>();
- }
- newlist.add(node);
- }
- }
- nodevals = newlist; /* Replace list (null if no more to process) */
- if (ourblks != null) {
- /* Trace outline of blocks - start from minx, minz going to x+ */
- int cur_x = minx;
- int cur_z = minz;
- Direction dir = Direction.XPLUS;
- ArrayList linelist = new ArrayList<>();
- linelist.add(new int[]{minx, minz}); // Add start point
- while ((cur_x != minx) || (cur_z != minz) || (dir != Direction.ZMINUS)) {
- switch (dir) {
- case XPLUS: /* Segment in X+ direction */
- if (!ourblks.getFlag(cur_x + 1, cur_z)) { /* Right turn? */
- linelist.add(new int[]{cur_x + 1, cur_z}); /* Finish line */
- dir = Direction.ZPLUS; /* Change direction */
- } else if (!ourblks.getFlag(cur_x + 1, cur_z - 1)) { /* Straight? */
- cur_x++;
- } else { /* Left turn */
- linelist.add(new int[]{cur_x + 1, cur_z}); /* Finish line */
- dir = Direction.ZMINUS;
- cur_x++;
- cur_z--;
- }
- break;
- case ZPLUS: /* Segment in Z+ direction */
- if (!ourblks.getFlag(cur_x, cur_z + 1)) { /* Right turn? */
- linelist.add(new int[]{cur_x + 1, cur_z + 1}); /* Finish line */
- dir = Direction.XMINUS; /* Change direction */
- } else if (!ourblks.getFlag(cur_x + 1, cur_z + 1)) { /* Straight? */
- cur_z++;
- } else { /* Left turn */
- linelist.add(new int[]{cur_x + 1, cur_z + 1}); /* Finish line */
- dir = Direction.XPLUS;
- cur_x++;
- cur_z++;
- }
- break;
- case XMINUS: /* Segment in X- direction */
- if (!ourblks.getFlag(cur_x - 1, cur_z)) { /* Right turn? */
- linelist.add(new int[]{cur_x, cur_z + 1}); /* Finish line */
- dir = Direction.ZMINUS; /* Change direction */
- } else if (!ourblks.getFlag(cur_x - 1, cur_z + 1)) { /* Straight? */
- cur_x--;
- } else { /* Left turn */
- linelist.add(new int[]{cur_x, cur_z + 1}); /* Finish line */
- dir = Direction.ZPLUS;
- cur_x--;
- cur_z++;
- }
- break;
- case ZMINUS: /* Segment in Z- direction */
- if (!ourblks.getFlag(cur_x, cur_z - 1)) { /* Right turn? */
- linelist.add(new int[]{cur_x, cur_z}); /* Finish line */
- dir = Direction.XPLUS; /* Change direction */
- } else if (!ourblks.getFlag(cur_x - 1, cur_z - 1)) { /* Straight? */
- cur_z--;
- } else { /* Left turn */
- linelist.add(new int[]{cur_x, cur_z}); /* Finish line */
- dir = Direction.XMINUS;
- cur_x--;
- cur_z--;
- }
- break;
- }
- }
- /* Build information for specific area */
- String polyid = factname + "__" + world + "__" + poly_index;
- int sz = linelist.size();
- x = new double[sz];
- z = new double[sz];
- for (int i = 0; i < sz; i++) {
- int[] line = linelist.get(i);
- x[i] = (double) line[0] * (double) blocksize;
- z[i] = (double) line[1] * (double) blocksize;
- }
- /* Find existing one */
- AreaMarker m = resareas.remove(polyid); /* Existing area? */
- if (m == null) {
- m = set.createAreaMarker(polyid, factname, false, world, x, z, false);
- if (m == null) {
- info("error adding area marker " + polyid);
- return;
- }
- } else {
- m.setCornerLocations(x, z); /* Replace corner locations */
- m.setLabel(factname); /* Update label */
- }
- m.setDescription(desc); /* Set popup */
-
- /* Set line and fill properties */
- addStyle(factname, m);
-
- /* Add to map */
- newmap.put(polyid, m);
- poly_index++;
- }
- }
- }
- }
-
- /* Update Factions information */
- void updateFactions() {
- Map newmap = new HashMap<>(); /* Build new map */
- Map newmark = new HashMap<>(); /* Build new map */
-
- /* Parse into faction centric mapping, split by world */
- Map blocks_by_faction = new HashMap<>();
-
- FactionColl fc = FactionColl.get();
- Collection facts = fc.getAll();
- for (Faction fact : facts) {
- Set chunks = BoardColl.get().getChunks(fact);
- String fid = fc.getUniverse() + "_" + fact.getId();
- FactionBlocks factblocks = blocks_by_faction.get(fid); /* Look up faction */
- if (factblocks == null) { /* Create faction block if first time */
- factblocks = new FactionBlocks();
- blocks_by_faction.put(fid, factblocks);
- }
-
- for (PS cc : chunks) {
- String world = cc.getWorld();
-
- /* Get block set for given world */
- LinkedList blocks = factblocks.blocks.computeIfAbsent(world, k -> new LinkedList<>());
- FactionBlock fb = new FactionBlock(cc.getChunkX(), cc.getChunkZ());
- blocks.add(fb); /* Add to list */
- }
- }
- /* Loop through factions */
- for (Faction fact : facts) {
- String factname = ChatColor.stripColor(fact.getName());
- String fid = fc.getUniverse() + "_" + fact.getId();
- FactionBlocks factblocks = blocks_by_faction.get(fid); /* Look up faction */
- if (factblocks == null) {
- continue;
- }
-
- /* Loop through each world that faction has blocks on */
- for (Map.Entry> worldblocks : factblocks.blocks.entrySet()) {
- handleFactionOnWorld(factname, fact, worldblocks.getKey(), worldblocks.getValue(), newmap, newmark);
- }
- factblocks.blocks.clear();
-
- /* Now, add marker for home location */
- EntityInternalMap warps = fact.getWarps();
- Warp home = null;
- for (String warp : warps.keySet()) {
- if (warp.equalsIgnoreCase("home")) {
- home = warps.get(warp);
- }
- }
- if (home == null) {
- continue;
- }
- PS homeloc = home.getLocation();
- if (homeloc != null) {
- String markid = fc.getUniverse() + "_" + factname + "__home";
- MarkerIcon ico = getMarkerIcon(factname, fact);
- if (ico != null) {
- Marker homeMarker = resmark.remove(markid);
- String lbl = factname + " [home]";
- if (homeMarker == null) {
- homeMarker = set.createMarker(markid, lbl, homeloc.getWorld(),
- homeloc.getLocationX(), homeloc.getLocationY(), homeloc.getLocationZ(), ico, false);
- } else {
- homeMarker.setLocation(homeloc.getWorld(), homeloc.getLocationX(), homeloc.getLocationY(), homeloc.getLocationZ());
- homeMarker.setLabel(lbl); /* Update label */
- homeMarker.setMarkerIcon(ico);
- }
- if (homeMarker != null) {
- homeMarker.setDescription(formatInfoWindow(fact)); /* Set popup */
- newmark.put(markid, homeMarker);
- }
- }
- }
- }
- blocks_by_faction.clear();
-
- /* Now, review old map - anything left is gone */
- for (AreaMarker oldm : resareas.values()) {
- oldm.deleteMarker();
- }
- for (Marker oldm : resmark.values()) {
- oldm.deleteMarker();
- }
- /* And replace with new map */
- resareas = newmap;
- resmark = newmark;
-
- }
private void updatePlayerSets() {
- if (playersets) {
+ if (playerSets) {
FactionColl fc = FactionColl.get();
for (Faction f : fc.getAll()) {
if ((f == fc.getNone()) || (f == fc.getWarzone()) || (f == fc.getSafezone())) {
@@ -492,26 +138,16 @@ public class DynmapFactionsPlugin extends JavaPlugin {
if (dynmap.isEnabled() && factions.isEnabled()) {
activate();
}
-
- try {
- MetricsLite ml = new MetricsLite(this);
- ml.start();
- } catch (IOException ignored) {
- }
}
- private boolean reload = false;
-
void activate() {
- markerapi = api.getMarkerAPI();
- if (markerapi == null) {
+ markerAPI = api.getMarkerAPI();
+ if (markerAPI == null) {
severe("Error loading dynmap marker API!");
return;
}
- /* Connect to factions API */
- factapi = Factions.get();
- blocksize = 16; /* Fixed at 16 */
+ blockSize = 16; /* Fixed at 16 */
/* Load configuration */
if (reload) {
@@ -528,9 +164,9 @@ public class DynmapFactionsPlugin extends JavaPlugin {
this.saveConfig(); /* Save updates, if needed */
/* Now, add marker set for mobs (make it transient) */
- set = markerapi.getMarkerSet("factions.markerset");
+ set = markerAPI.getMarkerSet("factions.markerSet");
if (set == null) {
- set = markerapi.createMarkerSet("factions.markerset", cfg.getString("layer.name", "Factions"), null, false);
+ set = markerAPI.createMarkerSet("factions.markerSet", cfg.getString("layer.name", "Factions"), null, false);
} else {
set.setMarkerSetLabel(cfg.getString("layer.name", "Factions"));
}
@@ -539,72 +175,72 @@ public class DynmapFactionsPlugin extends JavaPlugin {
return;
}
/* Make sure these are empty (on reload) */
- resareas.clear();
- resmark.clear();
+ factionAreaMarkers.clear();
+ factionMarkers.clear();
- int minzoom = cfg.getInt("layer.minzoom", 0);
- if (minzoom > 0) {
- set.setMinZoom(minzoom);
+ int minZoom = cfg.getInt("layer.minZoom", 0);
+ if (minZoom > 0) {
+ set.setMinZoom(minZoom);
}
- set.setLayerPriority(cfg.getInt("layer.layerprio", 10));
- set.setHideByDefault(cfg.getBoolean("layer.hidebydefault", false));
- use3d = cfg.getBoolean("use3dregions", false);
- infowindow = cfg.getString("infowindow", DEF_INFOWINDOW);
+ set.setLayerPriority(cfg.getInt("layer.layerPriority", 10));
+ set.setHideByDefault(cfg.getBoolean("layer.hideByDefault", false));
+
/* Get style information */
- defstyle = new AreaStyle(this, cfg, "regionstyle");
- cusstyle = new HashMap<>();
- ConfigurationSection sect = cfg.getConfigurationSection("custstyle");
+ defaultStyle = new AreaStyle(this, cfg, "regionStyle");
+ customStyle = new HashMap<>();
+ ConfigurationSection sect = cfg.getConfigurationSection("customStyles");
if (sect != null) {
Set ids = sect.getKeys(false);
for (String id : ids) {
- cusstyle.put(id, new AreaStyle(this, cfg, "custstyle." + id, defstyle));
+ customStyle.put(id, new AreaStyle(this, cfg, "customStyles." + id, defaultStyle));
}
}
- List vis = cfg.getStringList("visibleregions");
+ List vis = cfg.getStringList("visibleRegions");
if (vis != null) {
visible = new HashSet<>(vis);
}
- List hid = cfg.getStringList("hiddenregions");
+ List hid = cfg.getStringList("hiddenRegions");
if (hid != null) {
hidden = new HashSet<>(hid);
}
- /* Chec if player sets enabled */
- playersets = cfg.getBoolean("visibility-by-faction", false);
- if (playersets) {
+ /* Check if player sets enabled */
+ playerSets = cfg.getBoolean("visibilityByFaction", false);
+ if (playerSets) {
try {
if (!api.testIfPlayerInfoProtected()) {
- playersets = false;
+ playerSets = false;
info("Dynmap does not have player-info-protected enabled - visibility-by-faction will have no effect");
}
} catch (NoSuchMethodError x) {
- playersets = false;
+ playerSets = false;
info("Dynmap does not support function needed for 'visibility-by-faction' - need to upgrade to 0.60 or later");
}
}
updatePlayerSets();
- /* Set up update job - based on periond */
+ /* Set up update job - based on period */
int per = cfg.getInt("update.period", 300);
if (per < 15) {
per = 15;
}
- updperiod = (per * 20L);
+ updatePeriod = (per * 20L);
stop = false;
- getServer().getScheduler().scheduleSyncDelayedTask(this, new FactionsUpdate(this), 40); /* First time is 2 seconds */
- getServer().getPluginManager().registerEvents(new OurServerListener(this), this);
+ getServer().getScheduler().scheduleSyncDelayedTask(this, new FactionsUpdate(this, this.getConfig()), 40); /* First time is 2 seconds */
+ getServer().getPluginManager().registerEvents(new DynmapFactionsListener(this), this);
info("version " + this.getDescription().getVersion() + " is activated");
}
+ @Override
public void onDisable() {
if (set != null) {
set.deleteMarkerSet();
set = null;
}
- resareas.clear();
+ factionAreaMarkers.clear();
stop = true;
}
diff --git a/src/main/java/org/dynmap/factions/FactionBlocks.java b/src/main/java/org/dynmap/factions/FactionBlocks.java
index 781a0ed..f9bbbe3 100644
--- a/src/main/java/org/dynmap/factions/FactionBlocks.java
+++ b/src/main/java/org/dynmap/factions/FactionBlocks.java
@@ -1,11 +1,11 @@
package org.dynmap.factions;
import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
public class FactionBlocks {
- final Map> blocks = new HashMap<>();
+ final Map> blocks = new HashMap<>();
}
diff --git a/src/main/java/org/dynmap/factions/FactionsUpdate.java b/src/main/java/org/dynmap/factions/FactionsUpdate.java
index 80a8110..3d96fc5 100644
--- a/src/main/java/org/dynmap/factions/FactionsUpdate.java
+++ b/src/main/java/org/dynmap/factions/FactionsUpdate.java
@@ -1,26 +1,397 @@
package org.dynmap.factions;
+import com.massivecraft.factions.entity.BoardColl;
+import com.massivecraft.factions.entity.Faction;
+import com.massivecraft.factions.entity.FactionColl;
+import com.massivecraft.factions.entity.MFlag;
+import com.massivecraft.factions.entity.MFlagColl;
+import com.massivecraft.factions.entity.MPlayer;
+import com.massivecraft.factions.entity.Warp;
+import com.massivecraft.massivecore.ps.PS;
+import com.massivecraft.massivecore.store.EntityInternalMap;
+import org.bukkit.ChatColor;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.dynmap.markers.AreaMarker;
+import org.dynmap.markers.Marker;
+import org.dynmap.markers.MarkerIcon;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
public class FactionsUpdate implements Runnable {
+ private static final String DEF_INFO_WINDOW = "" +
+ "%regionName%
Flags
%flags%
";
+ private final String infoWindow;
private final DynmapFactionsPlugin dynmapFactionsPlugin;
public boolean runonce;
- public FactionsUpdate(DynmapFactionsPlugin dynmapFactionsPlugin) {
+ public FactionsUpdate(DynmapFactionsPlugin dynmapFactionsPlugin, FileConfiguration configuration) {
this.dynmapFactionsPlugin = dynmapFactionsPlugin;
+ infoWindow = configuration.getString("infoWindow", DEF_INFO_WINDOW);
}
+ @Override
public void run() {
if (dynmapFactionsPlugin.stop) {
return;
}
- dynmapFactionsPlugin.updateFactions();
+ updateFactions();
if (!runonce) {
dynmapFactionsPlugin.getServer().getScheduler().scheduleSyncDelayedTask(dynmapFactionsPlugin,
- this, dynmapFactionsPlugin.updperiod);
+ this, dynmapFactionsPlugin.updatePeriod);
} else if (dynmapFactionsPlugin.pending == this) {
dynmapFactionsPlugin.pending = null;
}
}
+
+ /* Update Factions information */
+ private void updateFactions() {
+ Map newMap = new HashMap<>();
+ Map newMarkers = new HashMap<>();
+
+ /* Parse into faction centric mapping, split by world */
+ Map blocksByFaction = new HashMap<>();
+
+ FactionColl fc = FactionColl.get();
+ Collection factions = fc.getAll();
+ for (Faction faction : factions) {
+ Set chunks = BoardColl.get().getChunks(faction);
+ String fid = fc.getUniverse() + "_" + faction.getId();
+ FactionBlocks factionBlocks = blocksByFaction.get(fid); /* Look up faction */
+ if (factionBlocks == null) { /* Create faction block if first time */
+ factionBlocks = new FactionBlocks();
+ blocksByFaction.put(fid, factionBlocks);
+ }
+
+ for (PS cc : chunks) {
+ String world = cc.getWorld();
+
+ /* Get block set for given world */
+ List blocks = factionBlocks.blocks.computeIfAbsent(world, k -> new LinkedList<>());
+ FactionBlock fb = new FactionBlock(cc.getChunkX(), cc.getChunkZ());
+ blocks.add(fb); /* Add to list */
+ }
+ }
+ /* Loop through factions */
+ for (Faction faction : factions) {
+ String factionName = ChatColor.stripColor(faction.getName());
+ String fid = fc.getUniverse() + "_" + faction.getId();
+ FactionBlocks factionBLocks = blocksByFaction.get(fid); /* Look up faction */
+ if (factionBLocks == null) {
+ continue;
+ }
+
+ /* Loop through each world that faction has blocks on */
+ for (Map.Entry> worldBlocks : factionBLocks.blocks.entrySet()) {
+ handleFactionOnWorld(factionName, faction, worldBlocks.getKey(), worldBlocks.getValue(), newMap);
+ }
+ factionBLocks.blocks.clear();
+
+ /* Now, add marker for home location */
+ EntityInternalMap warps = faction.getWarps();
+ Warp home = null;
+ for (String warp : warps.keySet()) {
+ if (warp.equalsIgnoreCase("home")) {
+ home = warps.get(warp);
+ }
+ }
+ if (home == null) {
+ continue;
+ }
+ PS homeLocation = home.getLocation();
+ if (homeLocation != null) {
+ String markId = fc.getUniverse() + "_" + factionName + "__home";
+ MarkerIcon ico = getMarkerIcon(factionName);
+ if (ico != null) {
+ Marker homeMarker = dynmapFactionsPlugin.factionMarkers.remove(markId);
+ String lbl = factionName + " [home]";
+ if (homeMarker == null) {
+ homeMarker = dynmapFactionsPlugin.set.createMarker(markId, lbl, homeLocation.getWorld(),
+ homeLocation.getLocationX(), homeLocation.getLocationY(), homeLocation.getLocationZ(), ico, false);
+ } else {
+ homeMarker.setLocation(homeLocation.getWorld(), homeLocation.getLocationX(), homeLocation.getLocationY(), homeLocation.getLocationZ());
+ homeMarker.setLabel(lbl); /* Update label */
+ homeMarker.setMarkerIcon(ico);
+ }
+ if (homeMarker != null) {
+ homeMarker.setDescription(formatInfoWindow(faction)); /* Set popup */
+ newMarkers.put(markId, homeMarker);
+ }
+ }
+ }
+ }
+ blocksByFaction.clear();
+
+ /* Now, review old map - anything left is gone */
+ for (AreaMarker oldMarker : dynmapFactionsPlugin.factionAreaMarkers.values()) {
+ oldMarker.deleteMarker();
+ }
+ for (Marker oldMarker : dynmapFactionsPlugin.factionMarkers.values()) {
+ oldMarker.deleteMarker();
+ }
+ /* And replace with new map */
+ dynmapFactionsPlugin.factionAreaMarkers = newMap;
+ dynmapFactionsPlugin.factionMarkers = newMarkers;
+
+ }
+
+ /* Handle specific faction on specific world */
+ private void handleFactionOnWorld(@NotNull String factionName, @NotNull Faction faction, @NotNull String world,
+ @NotNull List blocks, @NotNull Map newmap) {
+ double[] x;
+ double[] z;
+ int poly_index = 0; /* Index of polygon for given faction */
+
+ /* Build popup */
+ String desc = formatInfoWindow(faction);
+
+ /* Handle areas */
+ if (!isVisible(factionName, world) || blocks.isEmpty()) {
+ return;
+ }
+
+ LinkedList nodeValues = new LinkedList<>();
+ TileFlags currentBlocks = new TileFlags();
+ /* Loop through blocks: set flags on block maps */
+ for (FactionBlock b : blocks) {
+ currentBlocks.setFlag(b.x(), b.z(), true); /* Set flag for block */
+ nodeValues.addLast(b);
+ }
+ /* Loop through until we don't find more areas */
+ while (nodeValues != null) {
+ LinkedList ourNodes = null;
+ LinkedList newList = null;
+ TileFlags ourBlocks = null;
+ int minX = Integer.MAX_VALUE;
+ int minZ = Integer.MAX_VALUE;
+ for (FactionBlock node : nodeValues) {
+ int nodeX = node.x();
+ int nodeZ = node.z();
+ /* If we need to start shape, and this block is not part of one yet */
+ if ((ourBlocks == null) && currentBlocks.getFlag(nodeX, nodeZ)) {
+ ourBlocks = new TileFlags(); /* Create map for shape */
+ ourNodes = new LinkedList<>();
+ floodFillTarget(currentBlocks, ourBlocks, nodeX, nodeZ); /* Copy shape */
+ ourNodes.add(node); /* Add it to our node list */
+ minX = nodeX;
+ minZ = nodeZ;
+ }
+ /* If shape found, and we're in it, add to our node list */
+ else if ((ourBlocks != null) && ourBlocks.getFlag(nodeX, nodeZ)) {
+ ourNodes.add(node);
+ if (nodeX < minX) {
+ minX = nodeX;
+ minZ = nodeZ;
+ } else if ((nodeX == minX) && (nodeZ < minZ)) {
+ minZ = nodeZ;
+ }
+ } else { /* Else, keep it in the list for the next polygon */
+ if (newList == null) {
+ newList = new LinkedList<>();
+ }
+ newList.add(node);
+ }
+ }
+ nodeValues = newList; /* Replace list (null if no more to process) */
+ if (ourBlocks != null) {
+ /* Trace outline of blocks - start from minx, min z going to x+ */
+ int cur_x = minX;
+ int cur_z = minZ;
+ Direction dir = Direction.POSITIVE_X;
+ List lineList = new ArrayList<>();
+ lineList.add(new int[]{minX, minZ}); // Add start point
+ while ((cur_x != minX) || (cur_z != minZ) || (dir != Direction.NEGATIVE_Z)) {
+ switch (dir) {
+ case POSITIVE_X: /* Segment in X+ direction */
+ if (!ourBlocks.getFlag(cur_x + 1, cur_z)) { /* Right turn? */
+ lineList.add(new int[]{cur_x + 1, cur_z}); /* Finish line */
+ dir = Direction.POSITIVE_Z; /* Change direction */
+ } else if (!ourBlocks.getFlag(cur_x + 1, cur_z - 1)) { /* Straight? */
+ cur_x++;
+ } else { /* Left turn */
+ lineList.add(new int[]{cur_x + 1, cur_z}); /* Finish line */
+ dir = Direction.NEGATIVE_Z;
+ cur_x++;
+ cur_z--;
+ }
+ break;
+ case POSITIVE_Z: /* Segment in Z+ direction */
+ if (!ourBlocks.getFlag(cur_x, cur_z + 1)) { /* Right turn? */
+ lineList.add(new int[]{cur_x + 1, cur_z + 1}); /* Finish line */
+ dir = Direction.NEGATIVE_X; /* Change direction */
+ } else if (!ourBlocks.getFlag(cur_x + 1, cur_z + 1)) { /* Straight? */
+ cur_z++;
+ } else { /* Left turn */
+ lineList.add(new int[]{cur_x + 1, cur_z + 1}); /* Finish line */
+ dir = Direction.POSITIVE_X;
+ cur_x++;
+ cur_z++;
+ }
+ break;
+ case NEGATIVE_X: /* Segment in X- direction */
+ if (!ourBlocks.getFlag(cur_x - 1, cur_z)) { /* Right turn? */
+ lineList.add(new int[]{cur_x, cur_z + 1}); /* Finish line */
+ dir = Direction.NEGATIVE_Z; /* Change direction */
+ } else if (!ourBlocks.getFlag(cur_x - 1, cur_z + 1)) { /* Straight? */
+ cur_x--;
+ } else { /* Left turn */
+ lineList.add(new int[]{cur_x, cur_z + 1}); /* Finish line */
+ dir = Direction.POSITIVE_Z;
+ cur_x--;
+ cur_z++;
+ }
+ break;
+ case NEGATIVE_Z: /* Segment in Z- direction */
+ if (!ourBlocks.getFlag(cur_x, cur_z - 1)) { /* Right turn? */
+ lineList.add(new int[]{cur_x, cur_z}); /* Finish line */
+ dir = Direction.POSITIVE_X; /* Change direction */
+ } else if (!ourBlocks.getFlag(cur_x - 1, cur_z - 1)) { /* Straight? */
+ cur_z--;
+ } else { /* Left turn */
+ lineList.add(new int[]{cur_x, cur_z}); /* Finish line */
+ dir = Direction.NEGATIVE_X;
+ cur_x--;
+ cur_z--;
+ }
+ break;
+ }
+ }
+ /* Build information for specific area */
+ String polyId = factionName + "__" + world + "__" + poly_index;
+ int sz = lineList.size();
+ x = new double[sz];
+ z = new double[sz];
+ for (int i = 0; i < sz; i++) {
+ int[] line = lineList.get(i);
+ x[i] = (double) line[0] * (double) dynmapFactionsPlugin.blockSize;
+ z[i] = (double) line[1] * (double) dynmapFactionsPlugin.blockSize;
+ }
+ /* Find existing one */
+ AreaMarker m = dynmapFactionsPlugin.factionAreaMarkers.remove(polyId); /* Existing area? */
+ if (m == null) {
+ m = dynmapFactionsPlugin.set.createAreaMarker(polyId, factionName, false, world, x, z, false);
+ if (m == null) {
+ DynmapFactionsPlugin.info("error adding area marker " + polyId);
+ return;
+ }
+ } else {
+ m.setCornerLocations(x, z); /* Replace corner locations */
+ m.setLabel(factionName); /* Update label */
+ }
+ m.setDescription(desc); /* Set popup */
+
+ /* Set line and fill properties */
+ addStyle(factionName, m);
+
+ /* Add to map */
+ newmap.put(polyId, m);
+ poly_index++;
+ }
+ }
+ }
+
+ /**
+ * Find all contiguous blocks, set in target and clear in source
+ */
+ private void floodFillTarget(TileFlags source, TileFlags destination, int x, int y) {
+ Deque stack = new ArrayDeque<>();
+ stack.push(new int[]{x, y});
+
+ while (!stack.isEmpty()) {
+ int[] next = stack.pop();
+ x = next[0];
+ y = next[1];
+ if (source.getFlag(x, y)) { /* Set in src */
+ source.setFlag(x, y, false); /* Clear source */
+ destination.setFlag(x, y, true); /* Set in destination */
+ if (source.getFlag(x + 1, y)) {
+ stack.push(new int[]{x + 1, y});
+ }
+ if (source.getFlag(x - 1, y)) {
+ stack.push(new int[]{x - 1, y});
+ }
+ if (source.getFlag(x, y + 1)) {
+ stack.push(new int[]{x, y + 1});
+ }
+ if (source.getFlag(x, y - 1)) {
+ stack.push(new int[]{x, y - 1});
+ }
+ }
+ }
+ }
+
+ private void addStyle(String factionId, AreaMarker areaMarker) {
+ AreaStyle as = dynmapFactionsPlugin.customStyle.get(factionId);
+ if (as == null) {
+ as = dynmapFactionsPlugin.defaultStyle;
+ }
+ int sc = 0xFF0000;
+ int fc = 0xFF0000;
+ try {
+ sc = Integer.parseInt(as.strokeColor().substring(1), 16);
+ fc = Integer.parseInt(as.fillColor().substring(1), 16);
+ } catch (NumberFormatException ignored) {
+ }
+ areaMarker.setLineStyle(as.strokeWeight(), as.strokeOpacity(), sc);
+ areaMarker.setFillStyle(as.fillOpacity(), fc);
+ areaMarker.setBoostFlag(as.boost());
+ }
+
+ private MarkerIcon getMarkerIcon(String factionName) {
+ AreaStyle as = dynmapFactionsPlugin.customStyle.get(factionName);
+ if (as == null) {
+ as = dynmapFactionsPlugin.defaultStyle;
+ }
+ return as.homeIcon();
+ }
+
+ private boolean isVisible(String id, String worldName) {
+ if ((dynmapFactionsPlugin.visible != null) && (!dynmapFactionsPlugin.visible.isEmpty())) {
+ if ((!dynmapFactionsPlugin.visible.contains(id)) && (!dynmapFactionsPlugin.visible.contains("world:" + worldName))) {
+ return false;
+ }
+ }
+ if ((dynmapFactionsPlugin.hidden != null) && (!dynmapFactionsPlugin.hidden.isEmpty())) {
+ return !dynmapFactionsPlugin.hidden.contains(id) && !dynmapFactionsPlugin.hidden.contains("world:" + worldName);
+ }
+ return true;
+ }
+
+ private String formatInfoWindow(Faction fact) {
+ String v = "" + infoWindow + "
";
+ v = v.replace("%regionName%", ChatColor.stripColor(fact.getName()));
+ v = v.replace("%description%", ChatColor.stripColor(fact.getDescription()));
+ MPlayer adm = fact.getLeader();
+ v = v.replace("%playerOwners%", (adm != null) ? adm.getName() : "");
+ StringBuilder res = new StringBuilder();
+ for (MPlayer r : fact.getMPlayers()) {
+ if (!res.isEmpty()) {
+ res.append(", ");
+ }
+ res.append(r.getName());
+ }
+ v = v.replace("%playerMembers%", res.toString());
+
+ v = v.replace("%nation%", ChatColor.stripColor(fact.getName()));
+ /* Build flags */
+ StringBuilder flags = new StringBuilder();
+ for (MFlag ff : MFlagColl.get().getAll()) {
+ flags.append("
").append(ff.getName()).append(": ").append(fact.getFlag(ff));
+ v = v.replace("%flag." + ff.getName() + "%", fact.getFlag(ff) ? "true" : "false");
+ }
+ v = v.replace("%flags%", flags.toString());
+ return v;
+ }
+
}
diff --git a/src/main/java/org/dynmap/factions/MetricsLite.java b/src/main/java/org/dynmap/factions/MetricsLite.java
deleted file mode 100644
index eba1b0d..0000000
--- a/src/main/java/org/dynmap/factions/MetricsLite.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright 2011 Tyler Blair. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and contributors and should not be interpreted as representing official policies,
- * either expressed or implied, of anybody else.
- */
-
-package org.dynmap.factions;
-
-import org.bukkit.Bukkit;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.plugin.PluginDescriptionFile;
-import org.bukkit.scheduler.BukkitTask;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.UUID;
-import java.util.logging.Level;
-
-public class MetricsLite {
-
- /**
- * The current revision number
- */
- private final static int REVISION = 6;
-
- /**
- * The base url of the metrics domain
- */
- private static final String BASE_URL = "http://mcstats.org";
-
- /**
- * The url used to report a server's status
- */
- private static final String REPORT_URL = "/report/%s";
-
- /**
- * Interval of time to ping (in minutes)
- */
- private final static int PING_INTERVAL = 10;
-
- /**
- * The plugin this metrics submits for
- */
- private final Plugin plugin;
-
- /**
- * The plugin configuration file
- */
- private final YamlConfiguration configuration;
-
- /**
- * The plugin configuration file
- */
- private final File configurationFile;
-
- /**
- * Unique server id
- */
- private final String guid;
-
- /**
- * Debug mode
- */
- private final boolean debug;
-
- /**
- * Lock for synchronization
- */
- private final Object optOutLock = new Object();
-
- /**
- * Id of the scheduled task
- */
- private volatile BukkitTask task = null;
-
- public MetricsLite(Plugin plugin) throws IOException {
- if (plugin == null) {
- throw new IllegalArgumentException("Plugin cannot be null");
- }
-
- this.plugin = plugin;
-
- // load the config
- configurationFile = getConfigFile();
- configuration = YamlConfiguration.loadConfiguration(configurationFile);
-
- // add some defaults
- configuration.addDefault("opt-out", false);
- configuration.addDefault("guid", UUID.randomUUID().toString());
- configuration.addDefault("debug", false);
-
- // Do we need to create the file?
- if (configuration.get("guid", null) == null) {
- configuration.options().header("http://mcstats.org").copyDefaults(true);
- configuration.save(configurationFile);
- }
-
- // Load the guid then
- guid = configuration.getString("guid");
- debug = configuration.getBoolean("debug", false);
- }
-
- /**
- * Start measuring statistics. This will immediately create an async repeating task as the plugin and send
- * the initial data to the metrics backend, and then after that it will post in increments of
- * PING_INTERVAL * 1200 ticks.
- *
- * @return True if statistics measuring is running, otherwise false.
- */
- public boolean start() {
- synchronized (optOutLock) {
- // Did we opt out?
- if (isOptOut()) {
- return false;
- }
-
- // Is metrics already running?
- if (task != null) {
- return true;
- }
-
- // Begin hitting the server with glorious data
- task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
-
- private boolean firstPost = true;
-
- public void run() {
- try {
- // This has to be synchronized or it can collide with the disable method.
- synchronized (optOutLock) {
- // Disable Task, if it is running and the server owner decided to opt-out
- if (isOptOut() && task != null) {
- task.cancel();
- task = null;
- }
- }
-
- // We use the inverse of firstPost because if it is the first time we are posting,
- // it is not a interval ping, so it evaluates to FALSE
- // Each time thereafter it will evaluate to TRUE, i.e PING!
- postPlugin(!firstPost);
-
- // After the first post we set firstPost to false
- // Each post thereafter will be a ping
- firstPost = false;
- } catch (IOException e) {
- if (debug) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
- }
- }
- }
- }, 0, PING_INTERVAL * 1200);
-
- return true;
- }
- }
-
- /**
- * Has the server owner denied plugin metrics?
- *
- * @return true if metrics should be opted out of it
- */
- public boolean isOptOut() {
- synchronized (optOutLock) {
- try {
- // Reload the metrics file
- configuration.load(getConfigFile());
- } catch (IOException | InvalidConfigurationException ex) {
- if (debug) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
- }
- return true;
- }
- return configuration.getBoolean("opt-out", false);
- }
- }
-
- /**
- * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
- *
- * @throws java.io.IOException
- */
- public void enable() throws IOException {
- // This has to be synchronized or it can collide with the check in the task.
- synchronized (optOutLock) {
- // Check if the server owner has already set opt-out, if not, set it.
- if (isOptOut()) {
- configuration.set("opt-out", false);
- configuration.save(configurationFile);
- }
-
- // Enable Task, if it is not running
- if (task == null) {
- start();
- }
- }
- }
-
- /**
- * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
- *
- * @throws java.io.IOException
- */
- public void disable() throws IOException {
- // This has to be synchronized or it can collide with the check in the task.
- synchronized (optOutLock) {
- // Check if the server owner has already set opt-out, if not, set it.
- if (!isOptOut()) {
- configuration.set("opt-out", true);
- configuration.save(configurationFile);
- }
-
- // Disable Task, if it is running
- if (task != null) {
- task.cancel();
- task = null;
- }
- }
- }
-
- /**
- * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
- *
- * @return the File object for the config file
- */
- public File getConfigFile() {
- // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
- // is to abuse the plugin object we already have
- // plugin.getDataFolder() => base/plugins/PluginA/
- // pluginsFolder => base/plugins/
- // The base is not necessarily relative to the startup directory.
- File pluginsFolder = plugin.getDataFolder().getParentFile();
-
- // return => base/plugins/PluginMetrics/config.yml
- return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
- }
-
- /**
- * Generic method that posts a plugin to the metrics website
- */
- private void postPlugin(boolean isPing) throws IOException {
- // Server software specific section
- PluginDescriptionFile description = plugin.getDescription();
- String pluginName = description.getName();
- boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
- String pluginVersion = description.getVersion();
- String serverVersion = Bukkit.getVersion();
- int playersOnline = Bukkit.getServer().getOnlinePlayers().size();
-
- // END server software specific section -- all code below does not use any code outside of this class / Java
-
- // Construct the post data
- final StringBuilder data = new StringBuilder();
-
- // The plugin's description file containg all of the plugin data such as name, version, author, etc
- data.append(encode("guid")).append('=').append(encode(guid));
- encodeDataPair(data, "version", pluginVersion);
- encodeDataPair(data, "server", serverVersion);
- encodeDataPair(data, "players", Integer.toString(playersOnline));
- encodeDataPair(data, "revision", String.valueOf(REVISION));
-
- // New data as of R6
- String osname = System.getProperty("os.name");
- String osarch = System.getProperty("os.arch");
- String osversion = System.getProperty("os.version");
- String java_version = System.getProperty("java.version");
- int coreCount = Runtime.getRuntime().availableProcessors();
-
- // normalize os arch .. amd64 -> x86_64
- if (osarch.equals("amd64")) {
- osarch = "x86_64";
- }
-
- encodeDataPair(data, "osname", osname);
- encodeDataPair(data, "osarch", osarch);
- encodeDataPair(data, "osversion", osversion);
- encodeDataPair(data, "cores", Integer.toString(coreCount));
- encodeDataPair(data, "online-mode", Boolean.toString(onlineMode));
- encodeDataPair(data, "java_version", java_version);
-
- // If we're pinging, append it
- if (isPing) {
- encodeDataPair(data, "ping", "true");
- }
-
- // Create the url
- URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(pluginName)));
-
- // Connect to the website
- URLConnection connection;
-
- // Mineshafter creates a socks proxy, so we can safely bypass it
- // It does not reroute POST requests so we need to go around it
- if (isMineshafterPresent()) {
- connection = url.openConnection(Proxy.NO_PROXY);
- } else {
- connection = url.openConnection();
- }
-
- connection.setDoOutput(true);
-
- // Write the data
- final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
- writer.write(data.toString());
- writer.flush();
-
- // Now read the response
- final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- final String response = reader.readLine();
-
- // close resources
- writer.close();
- reader.close();
-
- if (response == null || response.startsWith("ERR")) {
- throw new IOException(response); //Throw the exception
- }
- }
-
- /**
- * Check if mineshafter is present. If it is, we need to bypass it to send POST requests
- *
- * @return true if mineshafter is installed on the server
- */
- private boolean isMineshafterPresent() {
- try {
- Class.forName("mineshafter.MineServer");
- return true;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first
- * key/value pair MUST be included manually, e.g:
- *
- * StringBuffer data = new StringBuffer();
- * data.append(encode("guid")).append('=').append(encode(guid));
- * encodeDataPair(data, "version", description.getVersion());
- *
- *
- * @param buffer the stringbuilder to append the data pair onto
- * @param key the key value
- * @param value the value
- */
- private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) {
- buffer.append('&').append(encode(key)).append('=').append(encode(value));
- }
-
- /**
- * Encode text as UTF-8
- *
- * @param text the text to encode
- * @return the encoded text, as UTF-8
- */
- private static String encode(final String text) {
- return URLEncoder.encode(text, StandardCharsets.UTF_8);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/dynmap/factions/PlayerSetUpdate.java b/src/main/java/org/dynmap/factions/PlayerSetUpdate.java
index ab68665..574115e 100644
--- a/src/main/java/org/dynmap/factions/PlayerSetUpdate.java
+++ b/src/main/java/org/dynmap/factions/PlayerSetUpdate.java
@@ -1,6 +1,7 @@
package org.dynmap.factions;
class PlayerSetUpdate implements Runnable {
+
private final DynmapFactionsPlugin dynmapFactionsPlugin;
public final String faction;
@@ -14,4 +15,5 @@ class PlayerSetUpdate implements Runnable {
dynmapFactionsPlugin.updatePlayerSet(faction);
}
}
+
}
diff --git a/src/main/java/org/dynmap/factions/TileFlags.java b/src/main/java/org/dynmap/factions/TileFlags.java
index 4b078b1..7e39b4c 100644
--- a/src/main/java/org/dynmap/factions/TileFlags.java
+++ b/src/main/java/org/dynmap/factions/TileFlags.java
@@ -4,20 +4,19 @@ import java.util.HashMap;
import java.util.Map;
/**
- * scalable flags primitive - used for keeping track of potentially huge number of tiles
- *
- * Represents a flag for each tile, with 2D coordinates based on 0,0 origin. Flags are grouped
- * 64 x 64, represented by an array of 64 longs. Each set is stored in a hashmap, keyed by a long
- * computed by ((x/64)<<32)+(y/64).
+ * Scalable flags primitive - used for keeping track of potentially huge number of tiles
+ *
Represents a flag for each tile, with 2D coordinates based on 0,0 origin. Flags are grouped 64 x 64, represented
+ * by an array of 64 longs. Each set is stored in a hashmap, keyed by a long computed by ((x/64)<<32)+(y/64).
*/
public class TileFlags {
+
private final Map chunkMap = new HashMap<>();
private long last_key = Long.MAX_VALUE;
private long[] last_row;
public TileFlags() {
}
-
+
public boolean getFlag(int x, int y) {
long k = (((long) (x >> 6)) << 32) | (0xFFFFFFFFL & (long) (y >> 6));
long[] row;
@@ -59,9 +58,4 @@ public class TileFlags {
}
}
- public void clear() {
- chunkMap.clear();
- last_row = null;
- last_key = Long.MAX_VALUE;
- }
}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index a57e67c..5e2c498 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -7,37 +7,37 @@ update:
layer:
name: "Factions"
# Make mobs layer hidden by default
- hidebydefault: false
+ hideByDefault: false
# ordering priority in layer menu (low goes before high - default is 0)
- layerprio: 2
- # (optional) set minimum zoom level before layer is visible (0 = defalt, always visible)
- minzoom: 0
+ layerPriority: 2
+ # (optional) set minimum zoom level before layer is visible (0 = default, always visible)
+ minZoom: 0
# Format for popup - substitute values for macros
-infowindow: '%regionname%
Flags
%flags%
'
+infoWindow: '%regionName%
Flags
%flags%
'
# Allow players in faction to see one another on dynmap (only relevant if dynmap has 'player-info-protected' enabled)
-visibility-by-faction: true
+visibilityByFaction: true
-regionstyle:
+regionStyle:
strokeColor: "#FF0000"
strokeOpacity: 0.8
strokeWeight: 3
fillColor: "#FF0000"
fillOpacity: 0.35
- homeicon: "redflag"
+ homeIcon: "redflag"
boost: false
# Optional setting to limit which regions to show, by name - if commented out, all regions are shown
-# To show all regions on a given world, add 'world:' to the list
-visibleregions: [ ]
+# To show all regions on a given world, add 'world:' to the list
+visibleRegions: [ ]
# Optional setting to hide specific regions, by name
-# To hide all regions on a given world, add 'world:' to the list
-hiddenregions: [ ]
+# To hide all regions on a given world, add 'world:' to the list
+hiddenRegions: [ ]
-# Optional per-region overrides for regionstyle (any defined replace those in regionstyle)
-custstyle:
+# Optional per-region overrides for regionStyle (any defined replace those in regionStyle)
+customStyles:
SafeZone:
strokeColor: "#0000FF"
fillColor: "#0000FF"
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 4905e57..6a0b8f5 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,6 +1,6 @@
name: Dynmap-Factions
main: org.dynmap.factions.DynmapFactionsPlugin
-version: "${project.version}-${BUILD_NUMBER}"
-author: mikeprimm
+version: "${project.version}-${BUILD_NUMBER}"
+authors: [ EpicKnarvik97, mikeprimm ]
depend: [ dynmap, Factions ]
-
+api-version: 1.20