-
-
Notifications
You must be signed in to change notification settings - Fork 146
Expand file tree
/
Copy pathDynmapHook.java
More file actions
344 lines (305 loc) · 12.9 KB
/
Copy pathDynmapHook.java
File metadata and controls
344 lines (305 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
package world.bentobox.bentobox.hooks;
import java.awt.Color;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
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.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
import world.bentobox.bentobox.api.events.island.IslandDeleteEvent;
import world.bentobox.bentobox.api.events.island.IslandNameEvent;
import world.bentobox.bentobox.api.events.island.IslandNewIslandEvent;
import world.bentobox.bentobox.api.events.island.IslandResettedEvent;
import world.bentobox.bentobox.api.hooks.MapHook;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
/**
* Hook to display island markers on Dynmap.
* @author tastybento
* @since 3.12.0
*/
public class DynmapHook extends MapHook implements Listener {
private final BentoBox plugin;
private MarkerAPI markerAPI;
/**
* One marker set per game mode; key is the marker set ID (derived from friendly name).
*/
private final Map<String, MarkerSet> markerSets = new HashMap<>();
public DynmapHook() {
super("dynmap", Material.FILLED_MAP);
this.plugin = BentoBox.getInstance();
}
@Override
public boolean hook() {
try {
DynmapAPI dynmapAPI = (DynmapAPI) getPlugin();
if (dynmapAPI == null) {
return false;
}
MarkerAPI markers = dynmapAPI.getMarkerAPI();
if (markers == null) {
return false;
}
markerAPI = markers;
} catch (Exception e) {
return false;
}
// Listen for island events and BentoBoxReadyEvent to populate island markers
// after islands are loaded (map hooks register before addons enable, so islands
// are not yet loaded at hook time)
Bukkit.getPluginManager().registerEvents(this, plugin);
return true;
}
/**
* Register all islands for a given game mode addon.
* @param addon the game mode addon
*/
public void registerGameMode(@NonNull GameModeAddon addon) {
String friendlyName = addon.getWorldSettings().getFriendlyName();
String markerSetId = friendlyName.toLowerCase(Locale.ENGLISH) + ".markers";
MarkerSet markerSet = markerSets.computeIfAbsent(friendlyName, k -> {
// Dynmap persists marker sets — check for existing one first
MarkerSet existing = markerAPI.getMarkerSet(markerSetId);
if (existing != null) {
existing.setMarkerSetLabel(friendlyName);
return existing;
}
return markerAPI.createMarkerSet(markerSetId, friendlyName, null, true);
});
// Clear stale markers from previous runs
markerSet.getMarkers().forEach(Marker::deleteMarker);
markerSet.getAreaMarkers().forEach(AreaMarker::deleteMarker);
// Create a marker for each owned island in this addon's overworld
plugin.getIslands().getIslands(addon.getOverWorld()).stream()
.filter(is -> is.getOwner() != null)
.forEach(island -> {
setMarker(markerSet, island);
});
}
private void setMarker(MarkerSet markerSet, Island island) {
String label = getIslandLabel(island);
String id = island.getUniqueId();
World w = island.getCenter().getWorld();
if (w == null) {
return;
}
String worldName = w.getName();
// Remove existing markers if present
Marker existingMarker = markerSet.findMarker(id);
if (existingMarker != null) {
existingMarker.deleteMarker();
}
AreaMarker existingArea = markerSet.findAreaMarker(id + "_area");
if (existingArea != null) {
existingArea.deleteMarker();
}
// Point marker at island center for the label/icon
if (plugin.getSettings().isDynmapIslandMarkers()) {
markerSet.createMarker(id, label, worldName,
island.getCenter().getX(), island.getCenter().getY(), island.getCenter().getZ(),
markerAPI.getMarkerIcon("default"), true);
}
// Area marker showing the protected island border
if (plugin.getSettings().isDynmapIslandAreas()) {
double[] xCorners = { island.getMinProtectedX(), island.getMaxProtectedX(),
island.getMaxProtectedX(), island.getMinProtectedX() };
double[] zCorners = { island.getMinProtectedZ(), island.getMinProtectedZ(),
island.getMaxProtectedZ(), island.getMaxProtectedZ() };
AreaMarker area = markerSet.createAreaMarker(id + "_area", label, false, worldName,
xCorners, zCorners, true);
if (area != null) {
area.setRangeY(w.getMaxHeight(), w.getMinHeight());
area.setLineStyle(2, 0.8, 0x3388FF);
area.setFillStyle(0.15, 0x3388FF);
}
}
}
private String getIslandLabel(Island island) {
if (island.getName() != null && !island.getName().isBlank()) {
return island.getName();
} else if (island.getOwner() != null) {
User owner = User.getInstance(island.getOwner());
if (owner != null) {
return owner.getName();
}
}
return island.getUniqueId();
}
@Override
public String getFailureCause() {
return "Dynmap is not loaded or its Marker API is unavailable.";
}
private void add(Island island, GameModeAddon addon) {
MarkerSet markerSet = markerSets.get(addon.getWorldSettings().getFriendlyName());
if (markerSet != null) {
setMarker(markerSet, island);
}
}
private void remove(String islandUniqueId, GameModeAddon addon) {
MarkerSet markerSet = markerSets.get(addon.getWorldSettings().getFriendlyName());
if (markerSet != null) {
Marker marker = markerSet.findMarker(islandUniqueId);
if (marker != null) {
marker.deleteMarker();
}
AreaMarker area = markerSet.findAreaMarker(islandUniqueId + "_area");
if (area != null) {
area.deleteMarker();
}
}
}
// --- Native API for direct Dynmap access ---
/**
* Returns the Dynmap MarkerAPI for addons to create custom markers directly.
* @return the MarkerAPI instance
*/
@NonNull
public MarkerAPI getMarkerAPI() {
return markerAPI;
}
/**
* Gets the native Dynmap marker set for the given game mode addon.
* @param addon the game mode addon
* @return the MarkerSet, or null if not registered
*/
public MarkerSet getNativeMarkerSet(@NonNull GameModeAddon addon) {
return markerSets.get(addon.getWorldSettings().getFriendlyName());
}
// --- MapHook abstract method implementations ---
@Override
public void createMarkerSet(@NonNull String id, @NonNull String label) {
markerSets.computeIfAbsent(id, k -> {
MarkerSet existing = markerAPI.getMarkerSet(id);
if (existing != null) {
existing.setMarkerSetLabel(label);
return existing;
}
return markerAPI.createMarkerSet(id, label, null, true);
});
}
@Override
public void removeMarkerSet(@NonNull String id) {
MarkerSet markerSet = markerSets.remove(id);
if (markerSet != null) {
markerSet.deleteMarkerSet();
}
}
@Override
public void clearMarkerSet(@NonNull String id) {
MarkerSet markerSet = markerSets.get(id);
if (markerSet != null) {
markerSet.getMarkers().forEach(Marker::deleteMarker);
markerSet.getAreaMarkers().forEach(AreaMarker::deleteMarker);
}
}
@Override
public void addPointMarker(@NonNull String markerSetId, @NonNull String markerId, @NonNull String label,
@NonNull Location location, @NonNull String iconName) {
MarkerSet markerSet = markerSets.get(markerSetId);
if (markerSet == null || location.getWorld() == null) {
return;
}
Marker existing = markerSet.findMarker(markerId);
if (existing != null) {
existing.deleteMarker();
}
MarkerIcon icon = markerAPI.getMarkerIcon(iconName);
if (icon == null) {
icon = markerAPI.getMarkerIcon("default");
}
markerSet.createMarker(markerId, label, true, location.getWorld().getName(), location.getX(),
location.getY(), location.getZ(), icon, true);
}
@Override
public void removePointMarker(@NonNull String markerSetId, @NonNull String markerId) {
MarkerSet markerSet = markerSets.get(markerSetId);
if (markerSet != null) {
Marker marker = markerSet.findMarker(markerId);
if (marker != null) {
marker.deleteMarker();
}
}
}
@Override
public void addAreaMarker(@NonNull String markerSetId, @NonNull String markerId, @NonNull String label,
@NonNull World world, double minX, double minZ, double maxX, double maxZ, @NonNull Color lineColor,
@NonNull Color fillColor, int lineWidth) {
double[] xCorners = { minX, maxX, maxX, minX };
double[] zCorners = { minZ, minZ, maxZ, maxZ };
addPolygonMarker(markerSetId, markerId, label, world, xCorners, zCorners, lineColor, fillColor, lineWidth);
}
@Override
public void addPolygonMarker(@NonNull String markerSetId, @NonNull String markerId, @NonNull String label,
@NonNull World world, @NonNull double[] xPoints, @NonNull double[] zPoints, @NonNull Color lineColor,
@NonNull Color fillColor, int lineWidth) {
MarkerSet markerSet = markerSets.get(markerSetId);
if (markerSet == null) {
return;
}
AreaMarker existing = markerSet.findAreaMarker(markerId);
if (existing != null) {
existing.deleteMarker();
}
AreaMarker area = markerSet.createAreaMarker(markerId, label, false, world.getName(), xPoints, zPoints, true);
if (area != null) {
area.setRangeY(world.getMaxHeight(), world.getMinHeight());
int lineRgb = (lineColor.getRed() << 16) | (lineColor.getGreen() << 8) | lineColor.getBlue();
int fillRgb = (fillColor.getRed() << 16) | (fillColor.getGreen() << 8) | fillColor.getBlue();
area.setLineStyle(lineWidth, lineColor.getAlpha() / 255.0, lineRgb);
area.setFillStyle(fillColor.getAlpha() / 255.0, fillRgb);
}
}
@Override
public void removeAreaMarker(@NonNull String markerSetId, @NonNull String markerId) {
MarkerSet markerSet = markerSets.get(markerSetId);
if (markerSet != null) {
AreaMarker area = markerSet.findAreaMarker(markerId);
if (area != null) {
area.deleteMarker();
}
}
}
// --- Event handlers ---
@EventHandler(priority = EventPriority.NORMAL)
public void onBentoBoxReady(BentoBoxReadyEvent e) {
// Now that islands are loaded, populate markers for all game modes
plugin.getAddonsManager().getGameModeAddons().forEach(this::registerGameMode);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onNewIsland(IslandNewIslandEvent e) {
plugin.getIWM().getAddon(e.getIsland().getWorld()).ifPresent(addon -> add(e.getIsland(), addon));
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIslandDelete(IslandDeleteEvent e) {
plugin.getIWM().getAddon(e.getIsland().getWorld())
.ifPresent(addon -> remove(e.getIsland().getUniqueId(), addon));
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIslandName(IslandNameEvent e) {
plugin.getIWM().getAddon(e.getIsland().getWorld()).ifPresent(addon -> {
remove(e.getIsland().getUniqueId(), addon);
add(e.getIsland(), addon);
});
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIslandReset(IslandResettedEvent e) {
plugin.getIWM().getAddon(e.getIsland().getWorld()).ifPresent(addon -> {
remove(e.getOldIsland().getUniqueId(), addon);
add(e.getIsland(), addon);
});
}
}