Provider

Provider

使用 Provider 安全地创建、修改和删除领地、组、成员及相关数据。

为什么要使用 Provider

DominionDTOGroupDTOMemberDTO 暴露了一些 set... 方法,但附属不应直接用这些方法绕过 Dominion 的业务流程。Provider 会在写入前执行权限、边界、经济和数据一致性检查,并触发对应事件。

所有数据操作 Provider 都返回 CompletableFuture。完成值为 null 通常表示 Dominion 拒绝或执行失败;传送 Provider 使用 Boolean 表示成功与否。请处理 null,并用 exceptionally 记录意外异常。

操作身份 operator

DominionProviderGroupProviderMemberProviderCopyProvider 的操作方法都有 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

createDominionparentnull 时创建顶级领地。skipEconomy 只表示跳过经济检查/扣费,不代表跳过所有限制。resizeDominion 使用 DominionReSizeEvent.TYPEDIRECTION 枚举,方向包括 NORTHSOUTHEASTWESTUPDOWN

deleteDominion(operator, dominion, skipEconomy)transferDominion(operator, dominion, newOwner) 是便利重载,默认 forcetrue。高风险附属功能应显式传入完整参数,避免误删或误转移。

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常用方法说明
PlayerProvidergetKnownPlayers()getAvailableGroupTitles(UUID)setGroupTitle(Player, GroupDTO)玩家资料和展示用组称号
TeleportProviderteleport(Player, DominionDTO)支持本服/跨服的 Dominion 传送流程,返回 CompletableFuture<Boolean>
TemplateProvidergetTemplatescreateTemplatesetTemplateFlagapplyTemplate玩家拥有的权限模板
CopyProvidercopy(operator, source, target, CopyType)在领地间复制选定管理数据

CopyType 包括 ENVIRONMENTGUESTMEMBERGROUP。复制涉及已有领地配置和成员数据,附属应在配置中提供明确开关,并在生产环境执行前提醒管理员备份。

正确处理异步结果

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 的线程模型执行。