Provider
使用 Provider 安全地创建、修改和删除领地、组、成员及相关数据。
为什么要使用 Provider
DominionDTO、GroupDTO 和 MemberDTO 暴露了一些 set... 方法,但附属不应直接用这些方法绕过 Dominion 的业务流程。Provider 会在写入前执行权限、边界、经济和数据一致性检查,并触发对应事件。
所有数据操作 Provider 都返回 CompletableFuture。完成值为 null 通常表示 Dominion 拒绝或执行失败;传送 Provider 使用 Boolean 表示成功与否。请处理 null,并用 exceptionally 记录意外异常。
操作身份 operator
DominionProvider、GroupProvider、MemberProvider 和 CopyProvider 的操作方法都有 CommandSender operator 参数:
- 传入
Player:以该玩家身份执行,Dominion 会检查玩家是否有对应领地权限; - 传入
Bukkit.getConsoleSender():表示后台/控制台操作,绕过玩家权限检查,但不绕过名称、边界、数据库等基础合法性检查; - 不要把普通玩家对象替换成控制台对象来隐藏权限逻辑。附属应明确让服务器管理员决定是否允许该操作。
DominionProvider
入口:DominionAPI.getDominionProvider()。
| 方法 | 作用 |
|---|---|
createDominion(operator, name, owner, world, cuboid, parent, skipEconomy) | 创建顶级领地或子领地 |
resizeDominion(operator, dominion, type, direction, size) | 按方向扩展/收缩领地 |
deleteDominion(operator, dominion, skipEconomy, force) | 删除领地;可控制是否强制删除子领地 |
renameDominion(operator, dominion, newName) | 修改领地名称 |
transferDominion(operator, dominion, newOwner, force) | 转移顶级领地所有权 |
setDominionTpLocation(operator, dominion, location) | 修改传送点 |
setDominionMessage(operator, dominion, type, message) | 修改进入/离开消息 |
setDominionMapColor(operator, dominion, color) | 修改地图显示颜色 |
setDominionEnvFlag(operator, dominion, flag, value) | 修改领地环境 flag |
setDominionGuestFlag(operator, dominion, flag, value) | 修改访客权限 flag |
createDominion 的 parent 为 null 时创建顶级领地。skipEconomy 只表示跳过经济检查/扣费,不代表跳过所有限制。resizeDominion 使用 DominionReSizeEvent.TYPE 和 DIRECTION 枚举,方向包括 NORTH、SOUTH、EAST、WEST、UP、DOWN。
deleteDominion(operator, dominion, skipEconomy) 和 transferDominion(operator, dominion, newOwner) 是便利重载,默认 force 为 true。高风险附属功能应显式传入完整参数,避免误删或误转移。
GroupProvider
入口:DominionAPI.getGroupProvider()。
| 方法 | 作用 |
|---|---|
createGroup(operator, dominion, groupName) | 创建组 |
deleteGroup(operator, dominion, group) | 删除组;组成员会脱离该组 |
renameGroup(operator, dominion, group, newName) | 修改组名 |
setGroupFlag(operator, dominion, group, flag, value) | 修改组权限 flag |
addMember(operator, dominion, group, member) | 将成员加入组 |
removeMember(operator, dominion, group, member) | 将成员移出组 |
组权限与成员自己的权限是两个来源。移出组只会移除组提供的权限,成员直接设置的权限仍由 MemberDTO 保留。
MemberProvider
入口:DominionAPI.getMemberProvider()。
| 方法 | 作用 |
|---|---|
addMember(operator, dominion, player) | 将玩家添加为领地成员 |
removeMember(operator, dominion, member) | 移除成员及其在该领地中的组关系 |
setMemberFlag(operator, dominion, member, flag, value) | 修改成员个人权限 flag |
添加成员前先通过 api.getPlayer(UUID) 获取 PlayerDTO。在线 Bukkit Player 与 Dominion 的 PlayerDTO 不是同一个类型。
其他 Provider
| Provider | 常用方法 | 说明 |
|---|---|---|
PlayerProvider | getKnownPlayers()、getAvailableGroupTitles(UUID)、setGroupTitle(Player, GroupDTO) | 玩家资料和展示用组称号 |
TeleportProvider | teleport(Player, DominionDTO) | 支持本服/跨服的 Dominion 传送流程,返回 CompletableFuture<Boolean> |
TemplateProvider | getTemplates、createTemplate、setTemplateFlag、applyTemplate | 玩家拥有的权限模板 |
CopyProvider | copy(operator, source, target, CopyType) | 在领地间复制选定管理数据 |
CopyType 包括 ENVIRONMENT、GUEST、MEMBER 和 GROUP。复制涉及已有领地配置和成员数据,附属应在配置中提供明确开关,并在生产环境执行前提醒管理员备份。
正确处理异步结果
DominionAPI api = DominionAPI.getInstance();
DominionDTO result = null;
api.getDominionProvider()
.renameDominion(Bukkit.getConsoleSender(), dominion, "new-name")
.thenAccept(updated -> {
if (updated == null) {
getLogger().warning("Dominion rename was rejected.");
return;
}
getLogger().info("Renamed dominion to " + updated.getName());
})
.exceptionally(error -> {
getLogger().severe("Dominion operation failed: " + error.getMessage());
return null;
});
上例中的 result 不应在异步调用后立即读取;Future 尚未完成。不要在 Bukkit 主线程或 Folia 区域线程调用 future.get()/future.join()。回调中如果要操作实体、界面或世界,请切回目标服务端调度器,并按照 Paper/Folia 的线程模型执行。