联动
Map 模块跨模块联动、公开 Capability、EventBus 主题与第三方插件对接
联动
Capability 注册
Map 模块注册以下公开能力,供其他模块与外部插件调用:
MapNavigable(公开)
地图导航能力接口,标注 @PublicCapability + @Stable——AXS 模块内部经 getCapability(MapNavigable.class) 获取,外部 Bukkit 插件经 AxsCapabilities.get(MapNavigable.class) 获取(插件需 depend: [ArcartXSuite] 或 softdepend)。
定位:地图是展示层与事件源。来源(QuestGPS / 外部插件)推送第三方插件注册路径点供玩家浏览;玩家点击"导航"时按优先级路由:全局委托 → useMapNavigation 地图代导航 → 来源 MapNavigationHandler 回调。
| 方法 | 参数 | 说明 |
|---|---|---|
upsertExternalTarget | Player, MapExternalTargetSpec spec, boolean select | 新增/更新单个第三方插件注册路径点;select=true 切到目标世界并选中 |
upsertExternalTargets | Player, List<MapExternalTargetSpec> | 批量推送第三方插件注册路径点,一次视图同步 |
reconcileExternalTargets | Player, String source, List<MapExternalTargetSpec> | 用给定集合原子替换该来源全部目标:单次同步、仍存在的目标选中态不闪断;空列表 = 清空该来源 |
clearExternalTargets | Player, String source, boolean syncView | 按来源清除第三方插件注册路径点(source 为空串 = 全部来源) |
setExternalNavigated | Player, String targetId, boolean navigated | 来源回推导航状态,驱动面板"导航 ↔ 取消"按钮(useMapNavigation 目标由地图自维护,无需调用) |
navigateExternalTarget | Player, String targetId | 由地图内置导航栈开始导航指定第三方插件注册路径点("地图代导航"命令式入口);已在导航返回 true,目标不存在/导航不可用返回 false |
registerNavigationSource | Plugin owner, String source, MapNavigationHandler | 注册来源导航回调;owner 插件禁用时自动注销 |
unregisterNavigationSource | String source | 注销来源导航回调 |
setNavigationDelegate | Plugin owner, MapNavigationDelegate | 注册全局导航委托(全量接管导航点击);全服仅一个,重复注册由后者覆盖;owner 插件禁用时自动注销 |
clearNavigationDelegate | Plugin owner | 注销导航委托(仅当当前委托属于该插件时生效) |
hasNavigationDelegate | — | 当前是否已注册全局导航委托 |
clearTrack | Player | 静默清除地图自身导航——来源开始自身导航时调用,实现导航互斥 |
openMenuFor | Player, String targetId | 打开地图并选中目标;依次匹配第三方插件注册路径点 → 路径点 → 标记点,未命中按世界 ID 兜底打开 |
MapExternalTargetSpec
第三方插件注册路径点规格 record,字段:targetId / source / worldId / title / description / x / y / z / iconId / navigated / sortOrder / useMapNavigation(保留省略 useMapNavigation 的兼容构造,另有省略 iconId/navigated/sortOrder/useMapNavigation 的便捷构造)。
useMapNavigation=true 时,玩家点该目标的"导航"由地图内置导航栈执行(客户端路标 + 路径标记 + 到达判定),不回调来源 handler——来源推送后零代码获得导航能力;导航样式/到达半径/命令钩子走地图 navigation.* 配置。默认 false 走来源回调/全局委托。
MapNavigationHandler
MapNavigationDelegate(全局委托)
setNavigationDelegate(owner, delegate) 注册的委托会先于一切导航处理拦截玩家在地图上的"导航"点击(锚点/路径点/第三方插件注册路径点;标记点 pin 不可导航不经此接口):
MapNavigationRequest record 携带目标完整描述:targetType(anchor/waypoint/external)、targetId、worldId、title、x/y/z、source(自有目标固定 "map")。契约要点:
- 导航执行(信标/路径标记/追踪状态)完全由委托方负责,地图不建客户端路标
- 委托接管第三方插件注册路径点时应另调
setExternalNavigated(player, targetId, true)驱动该目标行按钮切换 - 全服同一时间只有一个委托;重复注册由后者覆盖;
owner插件禁用时自动注销
导航互斥约定
互斥体现在跨来源层面(来源 ↔ 地图自身的锚点/路径点导航不共存;来源内部多目标并行不受此约束):
- 来源开始自身导航 → 调
clearTrack(player)静默清除地图导航(nav_cleared,reason=source_took_over) - 地图开始锚点/路径点导航 → 发布
axs.map.nav_started,来源应订阅并停止自身导航
调用示例(外部插件)
upsertExternalTarget/reconcile/clearExternalTargets/openMenuFor为同步主线程操作;registerNavigationSource/unregisterNavigationSource线程安全。
数据清理与迁移
/axs purge可按 UUID 或全量清理玩家地图数据(解锁记录、路径点、标记点、地图设置)/axs migrate map支持 SQLite ↔ MySQL 跨源迁移
第三方插件对接方案
获取接口:AxsCapabilities.get(MapNavigable.class)(需 depend/softdepend: [ArcartXSuite] + compileOnly axs-api)。
第三方插件注册路径点"导航"点击按优先级路由:全局委托 → useMapNavigation 地图代导航 → 来源 handler → 提示「来源未提供导航支持」。按接入用途选择:
| 用途 | 接入方式 | 导航执行方 |
|---|---|---|
| 第三方插件注册路径点由 Map 执行导航 | spec 设 useMapNavigation=true,或调用 navigateExternalTarget | Map 模块导航栈 |
| 第三方插件代理自身注册路径点导航 | registerNavigationSource 注册来源回调 | 第三方插件 |
| 第三方插件代理全部地图标记点导航(含自带锚点/路径点) | setNavigationDelegate | 第三方插件 |
| 仅展示第三方插件注册路径点,不提供导航 | 仅推送第三方插件注册路径点 | 无 |
同一
source可按目标混用:部分目标useMapNavigation=true交由 Map 导航,其余经来源 handler 自行执行。
第三方插件注册路径点由 Map 执行导航(useMapNavigation)
spec 设 useMapNavigation=true 后,点击"导航"由 Map 导航栈全程执行——客户端路标、路径标记、到达判定、finish-commands、按钮态翻转、取消、互斥、跨世界 cross_world_navigate:
- 取消路径同样由 Map 处理:来源插件不接收
onCancelRequest,亦无需调用setExternalNavigated(navigated标志由 Map 维护) upsert/reconcile推送新坐标时自动刷新路标;目标被reconcile/clear移除时其导航态一并回收- 导航样式与行为参数(
navigation.waypoint.*/finish-*等)统一采用 Map 配置,来源插件不可按目标定制 navigateExternalTarget亦可在来源 handler 内按需转交:同一source可混用"Map 执行"与"来源自执行"的目标
第三方插件代理自身注册路径点导航(来源回调)
来源插件注册 MapNavigationHandler:玩家点击"导航"/"取消"回调至来源插件,导航执行由来源插件完成:
互斥义务:来源插件开始导航前调用 map.clearTrack(player) 清除地图导航;订阅 axs.map.nav_started,在 Map 开始导航时停止自身导航。QuestGPS 模块即采用此模式。
第三方插件代理全部地图标记点导航(全局委托)
setNavigationDelegate(this, delegate) 后,锚点/路径点/第三方插件注册路径点的"导航"点击统一回调 onNavigateRequest(标记点 pin 不可导航,不经委托):
- 返回
true表示接管:Map 记录委托导航态并发布nav_started,不创建路标——路标/路径/到达判定均由委托方实现;返回false表示放行,移交下一级处理(可按targetType/source选择性接管) onCancelRequest在取消/互斥/玩家退出时触发,须保证幂等;取消逻辑应以targetType + targetId建立稳定映射——request 坐标为尽力重解(目标已删除时为 0),不可依赖坐标- 委托接管第三方插件注册路径点时需另调
setExternalNavigated更新该行按钮;全局唯一委托,重复注册覆盖,owner插件禁用时自动注销 - 边界:
cross_world_navigate的传送段(含扣费)由 Map 先行执行,成功后移交委托方;传送/解锁/路径点管理不经委托;除onCancelRequest外无其他生命周期回调(无到达事件)
其他入口
- 仅展示:仅推送目标、不注册 handler,点击"导航"提示「来源未提供导航支持」(适合位置公示,可在
description注明) - 事件订阅:经
EventBusCapability订阅下表主题——external_navigate在回调/委托之前发布,各接管路径均可观测 - 打开地图:
openMenuFor(player, targetId)依次匹配第三方插件注册路径点 → 路径点 → 标记点,未命中按世界兜底打开
AXS 模块额外选项:复用导航栈
axs-api 提供可复用的导航目标/路径标记组件(Map 与 QuestGPS 的导航均构建其上)。AXS 模块实例化后可获得多目标并行登记 + 单路标单路线、到达滞回 + 命令钩子、NPC 动态跟随、跨世界提示、标题模板等能力。
此路线需要模块上下文注入的路标/NPC 桥接,仅适用于 AXS 模块,外部 Bukkit 插件不可用。
EventBus 主题
Map 模块向 EventBus 发布以下主题,其他模块/外部插件可经 EventBusCapability 订阅:
| 主题 | 触发时机 | Payload |
|---|---|---|
axs.map.nav_started | 玩家开始导航(锚点/路径点,含委托接管与地图代导航的第三方插件注册路径点) | type(anchor/waypoint/external)、id、world_id |
axs.map.nav_cleared | 玩家停止地图导航(含委托态移除) | type(anchor/waypoint/external)、id、world_id、reason(cleared/来源接管 source_took_over) |
axs.map.external_navigate | 面板点击第三方插件注册路径点"导航"(在委托/来源回调之前发布,两种接管路径都能观测) | target_id、source、world_id |
axs.map.external_nav_cancel | 面板点击第三方插件注册路径点"取消" | target_id、source、world_id |
跨服同步
ArcartXMap.yml 中 worlds、anchors、waypoints 段支持跨服配置同步,其他配置段各服独立加载。
实际生效的世界/锚点定义位于
worlds/目录的独立文件中,多服部署需自行保持各服worlds/文件一致。
数据存储
Map 模块将玩家的锚点解锁记录、路径点、标记点与地图设置存储在数据库中(SQLite 或 MySQL,支持共享存储与自建存储模式)。客户端小地图设置改动会自动同步到服务端持久化。
与其他模块联动
QuestGPS
| 联动方式 | 说明 |
|---|---|
| 第三方插件注册路径点注入 | QuestGPS 把进行中任务原子同步为地图第三方路径点(source = questgps),任务接取/失败/完成/进服时刷新 |
| 坐标跟随 | Chemdah tracker 动态坐标变化时更新目标坐标 |
| 导航回调 | 面板"导航"→ QuestGPS 追踪,"取消"→ 停止追踪(标记保留) |
| 导航互斥 | QuestGPS 起导航清除地图导航;地图起导航时 QuestGPS 停止自身任务导航 |
| 打开地图 | QuestGPS 任务面板可打开 Map 菜单并选中目标 |
Map 模块不存在时 QuestGPS 导航功能正常运行,仅跳过地图标记同步。
Chat(点位分享)
| 联动方式 | 说明 |
|---|---|
| 分享卡片 | 路径点/标记点分享通过 Chat 模块的聊天卡片发送到聊天栏 |
| 卡片领取 | 卡片按钮领取点位(分享码即凭据) |
| 文本降级 | 卡片不可用时降级为文本广播 + 点击文本 |
ArcartX Waypoint
| 联动方式 | 说明 |
|---|---|
| 路标导航 | 通过 ArcartX Waypoint 创建/移除路标,在客户端显示方向指引 |
| 样式解析 | 路标样式 ID 优先使用 navigation.waypoint.style-id,回退到 waypoints.default-style-id |
ArcartX Waypoint 不存在时锚点/路径点导航不可用,但地图菜单、HUD 与第三方路径点转发正常使用。
Adyeshach
| 联动方式 | 说明 |
|---|---|
| 导航标记模型 | 使用 Adyeshach 私有实体 + ArcartX 模型渲染客户端导航标记 |
| 路径标记 | 沿导航路径放置标记模型,仅追踪玩家可见 |
| Debug 模式 | debug: true 时输出调试日志 |
Adyeshach 不存在时模型导航提示自动关闭(
navigation.model-marker.enabled仍可设为true,但运行时检测不可用后跳过),路标导航与贴图导航提示(navigation.texture-marker)不受影响。
Multiverse-Core
| 联动方式 | 说明 |
|---|---|
| 世界显示名 | 世界文件 display-name 留空时,用 Multiverse colourless alias 自动补齐 |
| 小地图世界名 | 小地图用 %multiverse-core_alias% PAPI 显示当前世界名 |
Vault / 货币系统
| 联动方式 | 说明 |
|---|---|
| 锚点解锁费用 | 通过宿主货币桥接扣除锚点解锁所需的货币 |
| 锚点传送费用 | 通过宿主货币桥接扣除锚点传送所需的货币 |
| 余额检查 | 解锁/传送前检查玩家货币余额是否充足 |
| 回滚机制 | 扣费失败或后续操作失败时自动回滚已扣除的货币 |
Vault 不存在时锚点解锁/传送的货币消耗不可用。配置了货币消耗但桥接不可用时,操作失败并提示「货币桥接不可用」。
物品消耗
| 联动方式 | 说明 |
|---|---|
| 锚点解锁物品 | 通过物品匹配器匹配玩家背包物品,解锁时消耗指定数量 |
| 预检机制 | 解锁前先检查背包是否有足够物品,不足时提示「缺少解锁所需物品」 |
| 回滚机制 | 物品扣除后若后续操作失败,自动恢复原始背包内容 |
物品匹配器配置参考 /docs/guide/item-sources 中的物品匹配器语法。
配置版本迁移
Map 模块自动将旧版本配置升级到当前版本:
| 迁移 | 操作 |
|---|---|
| 1 → 2 | client 节的 UI 配置字段(menu-ui-id/hud-ui-id/packet-id/register-ui-on-enable/overwrite-ui-files)整体迁移到统一 ui 节,移除 client 节 |
| 2 → 3 | storage.mode 重命名为 storage.shared,值从 sqlite/mysql 映射为 true/false;storage.shared 缺失时设为 true |
| 3 → 4 | 移除全局 default-unlocks 节,自动解锁改为 worlds/<world>.yml 锚点的 unlock.default / unlock.on-permission |
模块启动时自动检测
config-version并按序执行迁移,无需人工干预。