From bb54a5db482aeab881dd1fb6888beee31b843dbf Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Tue, 14 May 2024 14:19:01 +0200 Subject: [PATCH] Fixes a bunch of warnings and typos --- pom.xml | 61 ++- .../java/org/dynmap/factions/AreaStyle.java | 110 ++-- .../java/org/dynmap/factions/Direction.java | 28 +- ...tener.java => DynmapFactionsListener.java} | 37 +- .../dynmap/factions/DynmapFactionsPlugin.java | 490 +++--------------- .../org/dynmap/factions/FactionBlocks.java | 4 +- .../org/dynmap/factions/FactionsUpdate.java | 377 +++++++++++++- .../java/org/dynmap/factions/MetricsLite.java | 394 -------------- .../org/dynmap/factions/PlayerSetUpdate.java | 2 + .../java/org/dynmap/factions/TileFlags.java | 16 +- src/main/resources/config.yml | 28 +- src/main/resources/plugin.yml | 6 +- 12 files changed, 619 insertions(+), 934 deletions(-) rename src/main/java/org/dynmap/factions/{OurServerListener.java => DynmapFactionsListener.java} (69%) delete mode 100644 src/main/java/org/dynmap/factions/MetricsLite.java diff --git a/pom.xml b/pom.xml index 93c97ee..7ac659a 100644 --- a/pom.xml +++ b/pom.xml @@ -12,25 +12,6 @@ - - - src/main/resources - true - - *.yml - *.txt - - - - src/main/resources - false - - *.yml - *.txt - - - - org.apache.maven.plugins @@ -41,7 +22,43 @@ 16 + + org.apache.maven.plugins + maven-shade-plugin + 3.3.0 + + + package + + shade + + + false + + + org.jetbrains.annotations + net.knarcraft.placeholdersigns.lib.annotations + + + + + org.jetbrains:annotations + + org/jetbrains/annotations/** + + + + + + + + + + src/main/resources + true + + @@ -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