Skip to content

Commit ee72db0

Browse files
authored
Merge pull request #2885 from BentoBoxWorld/feature/map-api
Add generic Map API for addon web-map integration
2 parents 04ce68d + e85d642 commit ee72db0

File tree

8 files changed

+716
-49
lines changed

8 files changed

+716
-49
lines changed

src/main/java/world/bentobox/bentobox/BentoBox.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import world.bentobox.bentobox.managers.IslandWorldManager;
3636
import world.bentobox.bentobox.managers.IslandsManager;
3737
import world.bentobox.bentobox.managers.LocalesManager;
38+
import world.bentobox.bentobox.managers.MapManager;
3839
import world.bentobox.bentobox.managers.PlaceholdersManager;
3940
import world.bentobox.bentobox.managers.PlayersManager;
4041
import world.bentobox.bentobox.managers.RanksManager;
@@ -67,6 +68,7 @@ public class BentoBox extends JavaPlugin implements Listener {
6768
private BlueprintsManager blueprintsManager;
6869
private HooksManager hooksManager;
6970
private PlaceholdersManager placeholdersManager;
71+
private MapManager mapManager;
7072
private IslandDeletionManager islandDeletionManager;
7173
private WebManager webManager;
7274

@@ -219,6 +221,7 @@ private void completeSetup(long loadTime) {
219221
islandWorldManager.registerWorldsToMultiverse(true);
220222

221223
hookRegistrar.registerLateHooks();
224+
mapManager = new MapManager(this);
222225

223226
// TODO: re-enable after implementation
224227
// TODO: re-enable after rework
@@ -529,6 +532,16 @@ public PlaceholdersManager getPlaceholdersManager() {
529532
return placeholdersManager;
530533
}
531534

535+
/**
536+
* Returns the MapManager facade for web-map integrations.
537+
* Calls silently no-op when no map plugin is installed.
538+
* @return the MapManager
539+
* @since 3.12.0
540+
*/
541+
public MapManager getMapManager() {
542+
return mapManager;
543+
}
544+
532545
/**
533546
* @return the islandDeletionManager
534547
* @since 1.1
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package world.bentobox.bentobox.api.hooks;
2+
3+
import java.awt.Color;
4+
5+
import org.bukkit.Location;
6+
import org.bukkit.Material;
7+
import org.bukkit.World;
8+
import org.eclipse.jdt.annotation.NonNull;
9+
10+
/**
11+
* Abstract hook for web-map plugins (BlueMap, Dynmap, etc.).
12+
* Concrete implementations translate these calls into the native map API.
13+
* <p>
14+
* Addons should not use this class directly. Instead, use
15+
* {@link world.bentobox.bentobox.managers.MapManager} which fans out calls
16+
* to all active map hooks and silently no-ops when none are installed.
17+
*
18+
* @author tastybento
19+
* @since 3.12.0
20+
*/
21+
public abstract class MapHook extends Hook {
22+
23+
protected MapHook(@NonNull String pluginName, @NonNull Material icon) {
24+
super(pluginName, icon);
25+
}
26+
27+
// --- Marker Set operations ---
28+
29+
/**
30+
* Creates a marker set with the given ID and label. If a marker set with the
31+
* same ID already exists, it is returned unchanged.
32+
*
33+
* @param id unique identifier for the marker set
34+
* @param label display label for the marker set
35+
*/
36+
public abstract void createMarkerSet(@NonNull String id, @NonNull String label);
37+
38+
/**
39+
* Removes a marker set and all its markers.
40+
*
41+
* @param id the marker set ID
42+
*/
43+
public abstract void removeMarkerSet(@NonNull String id);
44+
45+
/**
46+
* Removes all markers from a marker set without removing the set itself.
47+
*
48+
* @param id the marker set ID
49+
*/
50+
public abstract void clearMarkerSet(@NonNull String id);
51+
52+
// --- Point Marker operations ---
53+
54+
/**
55+
* Adds or updates a point marker (icon + label) at a location.
56+
*
57+
* @param markerSetId the marker set ID
58+
* @param markerId unique ID for this marker within the set
59+
* @param label display label
60+
* @param location the location in the world
61+
*/
62+
public abstract void addPointMarker(@NonNull String markerSetId, @NonNull String markerId,
63+
@NonNull String label, @NonNull Location location);
64+
65+
/**
66+
* Removes a point marker.
67+
*
68+
* @param markerSetId the marker set ID
69+
* @param markerId the marker ID
70+
*/
71+
public abstract void removePointMarker(@NonNull String markerSetId, @NonNull String markerId);
72+
73+
// --- Area Marker operations ---
74+
75+
/**
76+
* Adds or updates a rectangular area marker with border and fill styling.
77+
*
78+
* @param markerSetId the marker set ID
79+
* @param markerId unique ID for this marker
80+
* @param label display label
81+
* @param world the world
82+
* @param minX minimum X coordinate
83+
* @param minZ minimum Z coordinate
84+
* @param maxX maximum X coordinate
85+
* @param maxZ maximum Z coordinate
86+
* @param lineColor line/border color (alpha channel is used for opacity)
87+
* @param fillColor fill color (alpha channel is used for opacity)
88+
* @param lineWidth line width in pixels
89+
*/
90+
public abstract void addAreaMarker(@NonNull String markerSetId, @NonNull String markerId,
91+
@NonNull String label, @NonNull World world, double minX, double minZ, double maxX, double maxZ,
92+
@NonNull Color lineColor, @NonNull Color fillColor, int lineWidth);
93+
94+
/**
95+
* Adds or updates a polygonal area marker with border and fill styling.
96+
*
97+
* @param markerSetId the marker set ID
98+
* @param markerId unique ID for this marker
99+
* @param label display label
100+
* @param world the world
101+
* @param xPoints X coordinates of polygon vertices
102+
* @param zPoints Z coordinates of polygon vertices
103+
* @param lineColor line/border color (alpha channel is used for opacity)
104+
* @param fillColor fill color (alpha channel is used for opacity)
105+
* @param lineWidth line width in pixels
106+
*/
107+
public abstract void addPolygonMarker(@NonNull String markerSetId, @NonNull String markerId,
108+
@NonNull String label, @NonNull World world, @NonNull double[] xPoints, @NonNull double[] zPoints,
109+
@NonNull Color lineColor, @NonNull Color fillColor, int lineWidth);
110+
111+
/**
112+
* Removes an area or polygon marker.
113+
*
114+
* @param markerSetId the marker set ID
115+
* @param markerId the marker ID
116+
*/
117+
public abstract void removeAreaMarker(@NonNull String markerSetId, @NonNull String markerId);
118+
}

src/main/java/world/bentobox/bentobox/hooks/BlueMapHook.java

Lines changed: 92 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Map;
55

66
import org.bukkit.Bukkit;
7+
import org.bukkit.Location;
78
import org.bukkit.Material;
89
import org.bukkit.World;
910
import org.bukkit.event.EventHandler;
@@ -16,15 +17,14 @@
1617
import de.bluecolored.bluemap.api.markers.MarkerSet;
1718
import de.bluecolored.bluemap.api.markers.POIMarker;
1819
import de.bluecolored.bluemap.api.markers.ShapeMarker;
19-
import de.bluecolored.bluemap.api.math.Color;
2020
import de.bluecolored.bluemap.api.math.Shape;
2121
import world.bentobox.bentobox.BentoBox;
2222
import world.bentobox.bentobox.api.addons.GameModeAddon;
2323
import world.bentobox.bentobox.api.events.island.IslandDeleteEvent;
2424
import world.bentobox.bentobox.api.events.island.IslandNameEvent;
2525
import world.bentobox.bentobox.api.events.island.IslandNewIslandEvent;
2626
import world.bentobox.bentobox.api.events.island.IslandResettedEvent;
27-
import world.bentobox.bentobox.api.hooks.Hook;
27+
import world.bentobox.bentobox.api.hooks.MapHook;
2828
import world.bentobox.bentobox.api.user.User;
2929
import world.bentobox.bentobox.database.objects.Island;
3030

@@ -33,7 +33,7 @@
3333
* @author tastybento
3434
* @since 2.1.0
3535
*/
36-
public class BlueMapHook extends Hook implements Listener {
36+
public class BlueMapHook extends MapHook implements Listener {
3737

3838
private final BentoBox plugin;
3939
private BlueMapAPI api;
@@ -118,8 +118,8 @@ private void setMarker(MarkerSet markerSet, Island island) {
118118
.shape(Shape.createRect(island.getMinProtectedX(), island.getMinProtectedZ(),
119119
island.getMaxProtectedX(), island.getMaxProtectedZ()),
120120
(float) island.getCenter().getY())
121-
.lineColor(new Color(51, 136, 255))
122-
.fillColor(new Color(51, 136, 255, 0.15f))
121+
.lineColor(new de.bluecolored.bluemap.api.math.Color(51, 136, 255))
122+
.fillColor(new de.bluecolored.bluemap.api.math.Color(51, 136, 255, 0.15f))
123123
.lineWidth(2)
124124
.build();
125125
markerSet.put(id + "_area", area);
@@ -156,10 +156,10 @@ private void remove(String islandUniqueId, GameModeAddon addon) {
156156
}
157157
}
158158

159-
// --- Public addon API ---
159+
// --- Native API for direct BlueMap access ---
160160

161161
/**
162-
* Returns the BlueMapAPI instance for addons to create custom markers.
162+
* Returns the BlueMapAPI instance for addons to create custom markers directly.
163163
* @return the BlueMapAPI instance
164164
*/
165165
@NonNull
@@ -168,27 +168,99 @@ public BlueMapAPI getBlueMapAPI() {
168168
}
169169

170170
/**
171-
* Gets the marker set for the given game mode addon, if one has been registered.
171+
* Gets the native BlueMap marker set for the given game mode addon.
172172
* @param addon the game mode addon
173173
* @return the MarkerSet, or null if not registered
174174
*/
175175
public MarkerSet getMarkerSet(@NonNull GameModeAddon addon) {
176176
return markerSets.get(addon.getWorldSettings().getFriendlyName());
177177
}
178178

179-
/**
180-
* Creates or retrieves a custom marker set and attaches it to all BlueMap maps.
181-
* Useful for addons like Warps that want to display their own markers.
182-
* @param id unique identifier for the marker set
183-
* @param label display label for the marker set
184-
* @return the MarkerSet
185-
*/
186-
@NonNull
187-
public MarkerSet createMarkerSet(@NonNull String id, @NonNull String label) {
188-
MarkerSet markerSet = MarkerSet.builder().label(label).toggleable(true).defaultHidden(false).build();
189-
// Attach to all known BlueMap maps
179+
// --- MapHook abstract method implementations ---
180+
181+
@Override
182+
public void createMarkerSet(@NonNull String id, @NonNull String label) {
183+
MarkerSet markerSet = markerSets.computeIfAbsent(id,
184+
k -> MarkerSet.builder().label(label).toggleable(true).defaultHidden(false).build());
190185
api.getMaps().forEach(map -> map.getMarkerSets().put(id, markerSet));
191-
return markerSet;
186+
}
187+
188+
@Override
189+
public void removeMarkerSet(@NonNull String id) {
190+
markerSets.remove(id);
191+
api.getMaps().forEach(map -> map.getMarkerSets().remove(id));
192+
}
193+
194+
@Override
195+
public void clearMarkerSet(@NonNull String id) {
196+
MarkerSet markerSet = markerSets.get(id);
197+
if (markerSet != null) {
198+
markerSet.getMarkers().clear();
199+
}
200+
}
201+
202+
@Override
203+
public void addPointMarker(@NonNull String markerSetId, @NonNull String markerId, @NonNull String label,
204+
@NonNull Location location) {
205+
MarkerSet markerSet = markerSets.get(markerSetId);
206+
if (markerSet != null) {
207+
POIMarker marker = POIMarker.builder().label(label).listed(true).defaultIcon()
208+
.position(location.getX(), location.getY(), location.getZ()).build();
209+
markerSet.put(markerId, marker);
210+
}
211+
}
212+
213+
@Override
214+
public void removePointMarker(@NonNull String markerSetId, @NonNull String markerId) {
215+
MarkerSet markerSet = markerSets.get(markerSetId);
216+
if (markerSet != null) {
217+
markerSet.remove(markerId);
218+
}
219+
}
220+
221+
@Override
222+
public void addAreaMarker(@NonNull String markerSetId, @NonNull String markerId, @NonNull String label,
223+
@NonNull World world, double minX, double minZ, double maxX, double maxZ,
224+
java.awt.Color lineColor, java.awt.Color fillColor, int lineWidth) {
225+
MarkerSet markerSet = markerSets.get(markerSetId);
226+
if (markerSet != null) {
227+
ShapeMarker area = ShapeMarker.builder().label(label)
228+
.shape(Shape.createRect(minX, minZ, maxX, maxZ), 64)
229+
.lineColor(toBlueMapColor(lineColor)).fillColor(toBlueMapColor(fillColor)).lineWidth(lineWidth)
230+
.build();
231+
markerSet.put(markerId, area);
232+
}
233+
}
234+
235+
@Override
236+
public void addPolygonMarker(@NonNull String markerSetId, @NonNull String markerId, @NonNull String label,
237+
@NonNull World world, @NonNull double[] xPoints, @NonNull double[] zPoints,
238+
java.awt.Color lineColor, java.awt.Color fillColor, int lineWidth) {
239+
MarkerSet markerSet = markerSets.get(markerSetId);
240+
if (markerSet != null && xPoints.length == zPoints.length && xPoints.length >= 3) {
241+
com.flowpowered.math.vector.Vector2d[] points = new com.flowpowered.math.vector.Vector2d[xPoints.length];
242+
for (int i = 0; i < xPoints.length; i++) {
243+
points[i] = new com.flowpowered.math.vector.Vector2d(xPoints[i], zPoints[i]);
244+
}
245+
Shape shape = new Shape(points);
246+
ShapeMarker area = ShapeMarker.builder().label(label).shape(shape, 64)
247+
.lineColor(toBlueMapColor(lineColor)).fillColor(toBlueMapColor(fillColor)).lineWidth(lineWidth)
248+
.build();
249+
markerSet.put(markerId, area);
250+
}
251+
}
252+
253+
@Override
254+
public void removeAreaMarker(@NonNull String markerSetId, @NonNull String markerId) {
255+
MarkerSet markerSet = markerSets.get(markerSetId);
256+
if (markerSet != null) {
257+
markerSet.remove(markerId);
258+
}
259+
}
260+
261+
private static de.bluecolored.bluemap.api.math.Color toBlueMapColor(java.awt.Color c) {
262+
return new de.bluecolored.bluemap.api.math.Color(c.getRed(), c.getGreen(), c.getBlue(),
263+
c.getAlpha() / 255.0f);
192264
}
193265

194266
// --- Event handlers ---

0 commit comments

Comments
 (0)