Map: game servers send tiles, players and overlay; BlueMap and LiveMapSync removed from the Java side

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjMbLQujBHunCCu5GpsHaT
This commit is contained in:
Claude committed 2026-10-01 00:43:11 +00:00
1 parent ead4a706c7
commit d98cc61ee6
31 files changed
+268 -596

No files matched your search

@@ -31,7 +31,6 @@ final class ClientLinkBridge implements PluginMessageListener {
private final ShopPoints shops;
private ActionPoller poller;
private MapService mapService;
private Object blueMap;
private EconomyHandler economy;
ClientLinkBridge(ScopenetPlugin plugin, Integration integration) {
@@ -64,7 +63,7 @@ final class ClientLinkBridge implements PluginMessageListener {
}
/**
* Shop points, actions from the map, and the BlueMap addon. Called once the command handlers exist; any of them may be
* Shop points, actions from the map, and the claims and pins for the SCOPENET Map. Called once the command handlers exist; any of them may be
* null when that system is switched off.
*/
void startMap(EssentialsHandler essentials, GuildHandler guilds, EconomyHandler economy) {
@@ -81,11 +80,9 @@ final class ClientLinkBridge implements PluginMessageListener {
@Override public Collection<ShopPoints.Shop> shops() { return shops.all(); }
};
mapService = new MapService(env, integration.client().claims(), source, cache, integration.settings().panel().toString(),
plugin.getConfig().getBoolean("bluemap.show-homes", false), Bukkit.getServer().getName());
plugin.getConfig().getBoolean("map.show-homes", false), Bukkit.getServer().getName());
integration.setMapOverlay(() -> net.scopenet.core.map.MapOverlay.toJson(mapService.snapshot()).toString());
Bukkit.getScheduler().runTaskTimer(plugin, () -> { poller.tick(); mapService.tick(); }, 60, 20);
if (plugin.getConfig().getBoolean("bluemap.enabled", true) && Bukkit.getPluginManager().getPlugin("BlueMap") != null) {
blueMap = BlueMapHook.start(mapService, plugin.getLogger());
}
}
/** /market point add|remove|list, on the block the player is looking at (or standing on). */
@@ -113,20 +110,7 @@ final class ClientLinkBridge implements PluginMessageListener {
}
}
/** Kept apart so BlueMap's classes are only loaded when BlueMap is installed. */
private static final class BlueMapHook {
static Object start(MapService service, Logger log) {
return net.scopenet.bluemap.MapAddon.start(new net.scopenet.bluemap.MapAddon.Feed() {
@Override public net.scopenet.core.map.MapData snapshot() { return service.snapshot(); }
@Override public com.google.gson.JsonObject playersJson() { return service.playersJson(); }
}, log);
}
static void stop(Object handle) { ((net.scopenet.bluemap.MapAddon) handle).stop(); }
}
void stop() {
if (blueMap != null) { BlueMapHook.stop(blueMap); blueMap = null; }
Bukkit.getMessenger().unregisterOutgoingPluginChannel(plugin, Wire.S2C);
Bukkit.getMessenger().unregisterIncomingPluginChannel(plugin, Wire.C2S, this);
}
@@ -51,10 +51,19 @@ public final class ScopenetPlugin extends JavaPlugin implements Listener {
// Claim protection runs from a local copy of the panel's claims, refreshed in the background.
integration.startClaimSync();
// Live positions center the in-app BlueMap claim view on the player.
if (getConfig().getBoolean("livemap.enabled", true)) {
integration.enableLiveMap();
Bukkit.getScheduler().runTaskTimer(this, this::snapshotPlayers, 40, 20);
// The SCOPENET Map: renders the world to tiles and sends them, positions, claims and pins to the panel.
// Started on the first tick so the worlds exist.
if (getConfig().getBoolean("map.enabled", getConfig().getBoolean("livemap.enabled", true))) {
Bukkit.getScheduler().runTask(this, () -> {
if (integration == null || Bukkit.getWorlds().isEmpty()) return;
integration.enableMap(Bukkit.getWorlds().get(0).getWorldFolder().toPath(), getDataFolder().toPath().resolve("map"));
Bukkit.getScheduler().runTaskTimer(this, this::snapshotPlayers, 40, 20);
});
getServer().getPluginManager().registerEvents(new org.bukkit.event.Listener() {
@org.bukkit.event.EventHandler public void onSave(org.bukkit.event.world.WorldSaveEvent event) {
if (integration != null) integration.mapSaved();
}
}, this);
}
// Developer API: other plugins use SCOPENET through ScopenetApiProvider / the services manager,
@@ -114,7 +123,7 @@ public final class ScopenetPlugin extends JavaPlugin implements Listener {
bindCommand("autoclaim", guilds);
}
// Physical shops, actions from the map, and (when BlueMap is installed) claims, pins and the player panel on it.
// Physical shops, actions from the map, and the claims and pins the SCOPENET Map draws.
clientLink.startMap(essentialsHandler, guildHandler, economy);
// Reloading an auth plugin cannot silently admit existing sessions.
@@ -160,7 +169,7 @@ public final class ScopenetPlugin extends JavaPlugin implements Listener {
private void snapshotPlayers() {
if (integration == null) return;
java.util.List<LiveMapSync.Player> list = new java.util.ArrayList<>();
java.util.List<net.scopenet.worldmap.WorldMapSync.Player> list = new java.util.ArrayList<>();
for (Player p : Bukkit.getOnlinePlayers()) {
Location at = p.getLocation();
String dim = switch (at.getWorld().getEnvironment()) {
@@ -169,11 +178,11 @@ public final class ScopenetPlugin extends JavaPlugin implements Listener {
default -> "minecraft:overworld";
};
// Rounded so an idle roster doesn't look "changed" on every tick.
list.add(new LiveMapSync.Player(p.getUniqueId().toString(), p.getName(), dim,
list.add(new net.scopenet.worldmap.WorldMapSync.Player(p.getUniqueId().toString(), p.getName(), dim,
Math.round(at.getX() * 10) / 10.0, Math.round(at.getY() * 10) / 10.0, Math.round(at.getZ() * 10) / 10.0,
Math.round(at.getYaw()), Math.round(at.getPitch())));
}
integration.liveMapPlayers(list);
integration.mapPlayers(list);
}
public static String dimension(World world) {
@@ -51,10 +51,13 @@ essentials:
# RTP search radius
rtp-radius: 2500
livemap:
# Send live player positions to the panel for the launcher BlueMap claim view.
# Configure BlueMap's public address and enable live positions in the panel.
map:
# The SCOPENET Map: this server renders its world to map tiles in the background and sends only what changed,
# with player positions, guild claims and pins, to the panel. Players see it in the launcher; admins in the panel.
# It also needs the map switched on for this server in the panel (it is by default).
enabled: true
# Show every player's homes as pins. Off by default: homes are private.
show-homes: false
economy:
# Server Economy commands (/balance, /pay, /baltop, /shop, /sell, /market, /orders, /trade, /transactions)
@@ -93,17 +96,6 @@ integrations:
enabled: true
report-interval-seconds: 30
# ==============================================================================
# BlueMap
# With BlueMap installed, SCOPENET adds guild claims (coloured, with the guild's icon and name), spawn, warps, guild
# homes, markets and shops to the 3D map, and a player panel when you click someone. Put the map's web address in the
# panel (Servers -> this server -> Map address) and players get a Live Map button in the launcher.
# ==============================================================================
bluemap:
enabled: true
# Show every player's homes as pins. Off by default: homes are private, and the map is public to anyone with the link.
show-homes: false
# ==============================================================================
# Client mod link
# Sends balance, level, guild and claim info to players who have the optional SCOPENET
@@ -4,7 +4,7 @@ main: net.scopenet.paper.ScopenetPlugin
api-version: '1.20'
description: SCOPENET private authentication, access control and activity reporting.
load: STARTUP
softdepend: [LuckPerms, PlaceholderAPI, Vault, CoreProtect, WorldGuard, WorldEdit, spark, BlueMap]
softdepend: [LuckPerms, PlaceholderAPI, Vault, CoreProtect, WorldGuard, WorldEdit, spark]
commands:
scopenet: