diff --git a/pom.xml b/pom.xml index 29dffe54e..a346f7662 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,13 @@ RC-37 provided + + + xyz.jpenilla + squaremap-api + 1.3.14 + provided + maven.modrinth diff --git a/src/main/java/com/bekvon/bukkit/residence/webmap/SquareWebMap.java b/src/main/java/com/bekvon/bukkit/residence/webmap/SquareWebMap.java new file mode 100644 index 000000000..1b9cf9732 --- /dev/null +++ b/src/main/java/com/bekvon/bukkit/residence/webmap/SquareWebMap.java @@ -0,0 +1,224 @@ +package com.bekvon.bukkit.residence.webmap; + +import java.awt.Color; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +import com.bekvon.bukkit.residence.containers.Flags; +import com.bekvon.bukkit.residence.containers.lm; +import com.bekvon.bukkit.residence.protection.ClaimedResidence; +import com.bekvon.bukkit.residence.protection.CuboidArea; + +import net.Zrips.CMILib.Colors.CMIChatColor; +import xyz.jpenilla.squaremap.api.BukkitAdapter; +import xyz.jpenilla.squaremap.api.Key; +import xyz.jpenilla.squaremap.api.LayerProvider; +import xyz.jpenilla.squaremap.api.MapWorld; +import xyz.jpenilla.squaremap.api.Point; +import xyz.jpenilla.squaremap.api.Registry; +import xyz.jpenilla.squaremap.api.SimpleLayerProvider; +import xyz.jpenilla.squaremap.api.Squaremap; +import xyz.jpenilla.squaremap.api.SquaremapProvider; +import xyz.jpenilla.squaremap.api.WorldIdentifier; +import xyz.jpenilla.squaremap.api.marker.Marker; +import xyz.jpenilla.squaremap.api.marker.MarkerOptions; +import xyz.jpenilla.squaremap.api.marker.Rectangle; + +public class SquareWebMap extends WebMap { + + private static final Key LAYER_KEY = Key.of("residence.residences"); + private static final String LAYER_LABEL = "Residence"; + + private final Map providers = new HashMap(); + private Squaremap api; + + @Override + protected void handleResidenceAdd(ClaimedResidence res, int depth) { + if (res == null || api == null) + return; + + String owner = res.getOwner(); + if ((owner != null && getSettings().getHiddenPlayerResidences().contains(owner.toLowerCase())) + || (res.getPermissions().has(Flags.hidden, false) && getSettings().isHideHidden()) + || !isVisible(res.getName(), res.getPermissions().getWorldName())) { + handleResidenceRemove(res.getName(), res, depth); + return; + } + + World world = Bukkit.getWorld(res.getPermissions().getWorldName()); + if (world == null) + return; + + SimpleLayerProvider provider = getProvider(world); + if (provider == null) + return; + + for (Entry oneArea : res.getAreaMap().entrySet()) { + String resName = res.getName(); + if (res.getAreaMap().size() > 1) + resName = res.getName() + " (" + oneArea.getKey() + ")"; + + Location low = oneArea.getValue().getLowLocation(); + Location high = oneArea.getValue().getHighLocation(); + + Rectangle marker = Marker.rectangle( + Point.of(low.getBlockX(), low.getBlockZ()), + Point.of(high.getBlockX() + 1D, high.getBlockZ() + 1D) + ); + + CMIChatColor border = getSettings().getBorderColor(); + CMIChatColor fill = fillColor(res); + + MarkerOptions.Builder options = MarkerOptions.builder() + .strokeColor(toColor(border)) + .strokeWeight(getSettings().getBorderWeight()) + .strokeOpacity(toOpacity(border)) + .fillColor(toColor(fill)) + .fillOpacity(toOpacity(fill)) + .clickTooltip(formatInfoWindow(res, resName)); + + marker.markerOptions(options); + provider.addMarker(markerKey(oneArea.getKey(), res.getName()), marker); + } + + if (depth <= getSettings().getLayerSubZoneDepth()) { + List subzones = res.getSubzones(); + for (ClaimedResidence subzone : subzones) { + try { + handleResidenceAdd(subzone, depth + 1); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + } + + @Override + public void handleResidenceRemove(String resid, ClaimedResidence res, int depth) { + if (resid == null || res == null || api == null) + return; + + World world = Bukkit.getWorld(res.getPermissions().getWorldName()); + if (world == null) + return; + + SimpleLayerProvider provider = getProvider(world); + if (provider == null) + return; + + for (Entry oneArea : res.getAreaMap().entrySet()) { + provider.removeMarker(markerKey(oneArea.getKey(), resid)); + } + + if (depth <= getSettings().getLayerSubZoneDepth() + 1) { + List subzones = res.getSubzones(); + for (ClaimedResidence subzone : subzones) + handleResidenceRemove(subzone.getName(), subzone, depth + 1); + } + } + + private SimpleLayerProvider getProvider(World world) { + MapWorld mapWorld = getMapWorld(world); + if (mapWorld == null) + return null; + + WorldIdentifier identifier = mapWorld.identifier(); + Registry registry = mapWorld.layerRegistry(); + ProviderRegistration registration = providers.get(identifier); + + if (registration != null) { + if (registration.registry == registry + && registry.hasEntry(LAYER_KEY) + && registry.get(LAYER_KEY) == registration.provider) + return registration.provider; + + if (registration.registry.hasEntry(LAYER_KEY) + && registration.registry.get(LAYER_KEY) == registration.provider) + registration.registry.unregister(LAYER_KEY); + + providers.remove(identifier); + } + + if (registry.hasEntry(LAYER_KEY)) + registry.unregister(LAYER_KEY); + + SimpleLayerProvider provider = SimpleLayerProvider.builder(LAYER_LABEL) + .defaultHidden(getSettings().isHideByDefault()) + .build(); + registry.register(LAYER_KEY, provider); + + providers.put(identifier, new ProviderRegistration(registry, provider)); + return provider; + } + + private MapWorld getMapWorld(World world) { + for (MapWorld mapWorld : api.mapWorlds()) { + try { + if (world.equals(BukkitAdapter.bukkitWorld(mapWorld))) + return mapWorld; + } catch (Throwable ignored) { + } + } + return null; + } + + private static Key markerKey(String areaName, String residenceName) { + String key = "residence." + areaName + "." + residenceName; + try { + return Key.of(key); + } catch (IllegalArgumentException ignored) { + String encoded = Base64.getUrlEncoder().withoutPadding().encodeToString( + (areaName + "\0" + residenceName).getBytes(StandardCharsets.UTF_8) + ); + return Key.of("residence." + encoded); + } + } + + private static Color toColor(CMIChatColor color) { + int argb = color.getARGB(); + return new Color((argb >> 16) & 0xFF, (argb >> 8) & 0xFF, argb & 0xFF); + } + + private static double toOpacity(CMIChatColor color) { + return ((color.getARGB() >>> 24) & 0xFF) / 255D; + } + + @Override + public void activate() { + api = SquaremapProvider.get(); + lm.consoleMessage("squaremap residence activated!"); + postActivated(); + } + + @Override + public void onDisable() { + if (api == null) + return; + + for (ProviderRegistration registration : providers.values()) { + if (registration.registry.hasEntry(LAYER_KEY) + && registration.registry.get(LAYER_KEY) == registration.provider) + registration.registry.unregister(LAYER_KEY); + } + providers.clear(); + api = null; + } + + private static final class ProviderRegistration { + private final Registry registry; + private final SimpleLayerProvider provider; + + private ProviderRegistration(Registry registry, SimpleLayerProvider provider) { + this.registry = registry; + this.provider = provider; + } + } +} diff --git a/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapListeners.java b/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapListeners.java index 77aae5ddb..3954d0b36 100644 --- a/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapListeners.java +++ b/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapListeners.java @@ -31,6 +31,7 @@ public void onResidenceAreaAdd(ResidenceAreaAddEvent event) { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onResidenceAreaDelete(ResidenceAreaDeleteEvent event) { plugin.getWebMapManager().fireUpdateRemove(event.getResidence()); + plugin.getWebMapManager().fireUpdateAdd(event.getResidence()); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) diff --git a/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapManager.java b/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapManager.java index 5ce072c6f..4d170879e 100644 --- a/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapManager.java +++ b/src/main/java/com/bekvon/bukkit/residence/webmap/WebMapManager.java @@ -28,7 +28,7 @@ public void loadConfig(ConfigReader c) { settings = webmap != null ? webmap.getSettings() : new MapSettings(); - c.addComment("WebMap.Use", "Enables or disable DynMap, Pl3exMap or BlueMap support"); + c.addComment("WebMap.Use", "Enables or disables DynMap, Pl3xMap, squaremap, or BlueMap support"); use = c.get("WebMap.Use", true); c.addComment("WebMap.HideByDefault", "When set to true we will hide residence areas by default on WebMap window", "Residences can still be enabled throw provided WebMap option on left top side"); @@ -63,7 +63,7 @@ public void loadConfig(ConfigReader c) { c.addComment("WebMap.HiddenRegions", "Hides region on map even if its not hidden in game"); settings.setHiddenRegions(c.get("WebMap.HiddenRegions", new ArrayList())); - c.addComment("WebMap.HiddenPlayerResidences", "List of player names whose residences should be hidden in DynMap, Pl3exMap or BlueMap independent of their settings"); + c.addComment("WebMap.HiddenPlayerResidences", "List of player names whose residences should be hidden in DynMap, Pl3xMap, squaremap, or BlueMap independent of their settings"); settings.setHiddenPlayerResidences(c.get("WebMap.HiddenPlayerResidences", new ArrayList())); } @@ -97,6 +97,19 @@ public void activate() { } } +// Try squaremap + Plugin squaremap = Bukkit.getPluginManager().getPlugin("squaremap"); + if (squaremap != null) { + try { + SquareWebMap s = new SquareWebMap(); + s.settings = settings; + s.activate(); + webmaps.add(s); + } catch (Throwable e) { + e.printStackTrace(); + } + } + // Try BlueMap Plugin bluemap = Bukkit.getPluginManager().getPlugin("BlueMap"); if (bluemap != null) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 10eb40ad9..e8c767d18 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -7,7 +7,7 @@ api-version: 1.13 folia-supported: true authors: [Zrips,bekvon] depend: [CMILib] -softdepend: [Pl3xMap,BlueMap,Vault,Essentials,RealPlugin,iConomy,bPermissions,WorldEdit,WorldGuard,CrackShot,Multiverse-Core,MultiWorld,My_Worlds,TheWorld,dynmap,LWC,Kingdoms,PlaceholderAPI,CMI,ServerControlReloaded,Slimefun,CS-CoreLib] +softdepend: [Pl3xMap,squaremap,BlueMap,Vault,Essentials,RealPlugin,iConomy,bPermissions,WorldEdit,WorldGuard,CrackShot,Multiverse-Core,MultiWorld,My_Worlds,TheWorld,dynmap,LWC,Kingdoms,PlaceholderAPI,CMI,ServerControlReloaded,Slimefun,CS-CoreLib] contributors: [lemon42,smbarbour,inorixu,Shayana_fr,Zrips] commands: res: