Suite

联动

Regions 跨模块联动、Capability、数据库表与模块集成

联动

Regions 模块通过 EventBus、Capability、存储层等机制与其他模块和外部系统联动。

EventBus 事件

Regions 模块通过 EventBusCapability 发布区域进出事件,其他模块可通过 EventBus 监听这些事件实现联动。

发布的事件

事件 Topic触发时机Payload
axs.regions.region_change玩家进入或离开区域region_id(区域 ID)、typeenter / leave

事件发布机制

事件通过 EventBusCapability 延迟查找发布,由 RegionProtectionListener 在玩家移动检测到区域变化时触发:

private void publishRegionEvent(Player player, String regionId, String type) {
    if (eventBusProvider == null) return;
    EventBusCapability eventBus = eventBusProvider.get();
    if (eventBus == null) return;
    Map<String, String> payload = new HashMap<>();
    payload.put("region_id", regionId);
    payload.put("type", type);
    eventBus.publish("axs.regions.region_change", player, payload);
}

模块在 startService() 中注入 EventBus 提供者:

protectionListener = new RegionProtectionListener(regionManager, configuration);
protectionListener.setEventBusProvider(() -> getCapability(EventBusCapability.class));

EventBus 为延迟查找(getCapability),因模块加载顺序不定。若 EventBus 模块未加载,事件发布为空操作,不影响 Regions 正常运行。

已发布的 Topic 声明

Regions 模块在 publishedTopics() 中声明了发布的事件 Topic:

@Override
protected List<String> publishedTopics() {
    return List.of("axs.regions.region_change");
}

Capability 注册

Regions 模块注册了以下 Capability,供其他模块和宿主管理工具调用。

RegionQueryable(公开)

区域只读查询能力(@PublicCapability),外部插件经 AxsCapabilities.get(RegionQueryable.class) 获取;Regions 模块未启用时返回 null。请在 Bukkit 主线程调用(Region 内部成员集合非并发容器)。

方法说明
regionsAt(world, x, y, z)指定坐标命中的全部区域(按优先级排序)
regionsInWorld(world)指定世界的全部区域
allRegions()全部区域
countRegionsByOwner(uuid)玩家作为 owner 的区域数量

返回 RegionInfo record(id/world/minX..maxZ/priority/parentId/owners/members,集合为不可变拷贝),并提供 contains(world,x,y,z)hasAccess(uuid) 便捷方法。不暴露模块内部 Region 类型。

DatabaseMigratable

支持数据库迁移,供本体存储管理模块调用,可在 SQLite 与 MySQL 之间迁移区域数据。

方法返回类型说明
moduleId()String返回 regions
migrateDatabase(target, overwrite)MigrationResult迁移数据到目标存储描述符
currentDescriptor()StorageDescriptor返回当前存储描述符
registerCapability(DatabaseMigratable.class, new DatabaseMigratable() {
    @Override public String moduleId() { return "regions"; }
    @Override public MigrationResult migrateDatabase(StorageDescriptor target, boolean overwrite) {
        return repository.migrateData(target, overwrite);
    }
    @Override public StorageDescriptor currentDescriptor() {
        return repository.getDescriptor();
    }
});

PlayerDataPurgeable

支持玩家数据清理,供管理工具调用。Regions 的玩家数据为选区会话和进出追踪记录(内存态),数据库表以区域 ID + 世界为主键,无玩家 UUID 列。

方法返回类型说明
moduleId()String返回 regions
purgePlayerData(playerUuid)int删除指定玩家的选区与进出追踪数据
purgeAllPlayerData()int删除所有玩家的选区与进出追踪数据
registerCapability(PlayerDataPurgeable.class, new PlayerDataPurgeable() {
    @Override public String moduleId() { return "regions"; }
    @Override public int purgePlayerData(UUID playerUuid) {
        return repository.deletePlayerData(playerUuid);
    }
    @Override public int purgeAllPlayerData() {
        return repository.deleteAllPlayerData();
    }
});

Regions 的数据库表(regionsflagsmembers)以区域 ID + 世界为主键,不包含玩家 UUID 列。playerDataTables() 返回空列表,玩家数据清理仅针对内存中的选区会话和进出追踪记录。

存储模式

Regions 模块支持两种存储模式,通过 storage.shared 配置切换:

共享存储模式(推荐)

storage.shared: true 时,模块使用本体统一数据源,数据库连接由宿主 StorageManager 统一管控。模块仅需提供表前缀(axs_rg_),各模块共用 config.ymlstorage 节配置。

rgDesc = storageManager.getDescriptor().withTablePrefix(configuration.storage().tablePrefix());
rgDs = storageManager.resolveModuleDataSource("regions",
    configuration.storage().sqliteFileName(), dataFolder, null);

自建存储模式

storage.shared: false 时,模块自建独立 HikariCP 连接池,不复用本体连接。支持 SQLite 和 MySQL 两种方言。

rgDesc = configuration.storage().toDescriptor();
rgDs = storageManager.resolveModuleDataSource("regions", null, dataFolder, rgDesc);

数据库表结构

Regions 模块管理三张数据库表,表名前缀默认为 axs_rg_(可通过 storage.mysql.table-prefix 配置)。

axs_rg_regions(区域表)

列名类型说明
idVARCHAR(64)区域 ID(主键之一)
worldVARCHAR(128)世界名(主键之一)
min_xINT最小 X 坐标
min_yINT最小 Y 坐标
min_zINT最小 Z 坐标
max_xINT最大 X 坐标
max_yINT最大 Y 坐标
max_zINT最大 Z 坐标
priorityINT优先级(默认 0)
parent_idVARCHAR(64)父区域 ID(可为 NULL)

主键:(id, world)

axs_rg_flags(标志表)

列名类型说明
region_idVARCHAR(64)区域 ID(主键之一)
worldVARCHAR(128)世界名(主键之一)
flagVARCHAR(32)标志 Key(主键之一)
stateVARCHAR(8)标志状态(allow / deny
dataTEXT附加数据(如 greeting/farewell 文本,可为 NULL)

主键:(region_id, world, flag)

axs_rg_members(成员表)

列名类型说明
region_idVARCHAR(64)区域 ID
worldVARCHAR(128)世界名
uuidVARCHAR(36)玩家 UUID(可为 NULL,当为权限组时)
group_nameVARCHAR(64)权限组名(可为 NULL,当为玩家时)
roleVARCHAR(8)角色(owner / member

MySQL 额外索引:idx_rg_members (region_id, world)

保存区域时使用事务,先 REPLACE INTO 区域记录,再删除并重建标志和成员记录,确保数据一致性。删除区域时级联删除三张表的关联记录。

跨服支持

存储层跨服

storage.shared: true 且本体配置使用 MySQL 作为统一存储后端时,Regions 的区域数据天然支持跨服共享——所有子服连接同一 MySQL 数据库,区域定义、标志、成员在全服范围内一致。

EventBus 跨服

axs.regions.region_change 事件通过 EventBusCapability 发布。若宿主配置了跨服传输(Redis + Proxy 双后端),事件可跨服传播,其他子服上的模块也能监听到玩家进出区域的事件。

跨服传输依赖宿主的 cross-server 配置。Redis 后端提供实时事件同步,Proxy 后端通过代理端插件转发。详见 跨服配置指南

数据库迁移跨服

通过 DatabaseMigratable 能力,可在 SQLite(单服)与 MySQL(跨服)之间迁移区域数据:

单服 SQLite → 迁移 → MySQL(跨服共享)

迁移由宿主存储管理工具发起,调用 migrateDatabase(target, overwrite) 完成数据搬迁。

模块集成

Essentials

Regions 与 Essentials 模块通过权限节点联动:

权限节点来源说明
axs.essentials.fly.bypassEssentials绕过世界规则禁飞限制
axs.essentials.interact.bypassEssentials绕过世界规则禁交互限制

Essentials 在 module.yml 中声明为 Regions 的 softdepends,加载顺序上 Essentials 先于 Regions 启动。

EventBus 消费方

其他模块可监听 axs.regions.region_change 事件实现联动场景:

场景联动模块说明
进入区域触发任务QuestGPS玩家进入指定区域时推进任务进度
进入区域播放音效Announcer进入特定区域时播放区域主题音效
进入区域显示标题Title进入区域时显示自定义标题
区域内挂机奖励AfkReward在指定区域内挂机获得额外奖励
区域内聊天频道Chat进入区域自动切换到区域聊天频道

存储管理

Regions 模块通过 AbstractModuleRepository 基类继承统一的存储管理能力:

能力说明
表结构自动初始化模块启动时自动创建 regionsflagsmembers 三张表
SQLite / MySQL 双方言通过 isMysql() 判断方言,MySQL 额外创建索引
表前缀隔离通过 tablePrefix 隔离多模块数据
数据迁移支持 migrateData(target, overwrite) 在不同存储后端间迁移
玩家数据清理支持 deletePlayerData(uuid)deleteAllPlayerData() 清理玩家数据

UI 资源导出

Regions 模块在启动时自动导出两个 UI 资源文件到 plugins/ArcartX-Suite/ui/ 目录:

UI 文件资源路径用途
ui/regions_menu.ymlarcartx/ui/regions_menu.yml玩家区域查看菜单
ui/regions_admin.ymlarcartx/ui/regions_admin.yml管理员区域管理面板

UI 文件使用 ArcartX Aria 脚本语法编写,支持通过 UI Editor 自定义修改。详见 ArcartX UI 文档条件系统

UI 文件导出后不会自动覆盖已有文件(ModuleUiSpecoverwrite 参数为 false),可安全自定义修改。如需恢复默认 UI,删除对应文件后重启模块即可。