数据写入
使用 Provider 修改 Dominion 数据,并正确处理权限、失败结果和异步回调。
修改领地名称
api.getDominionProvider()
.renameDominion(Bukkit.getConsoleSender(), dominion, newName)
.thenAccept(updated -> {
if (updated == null) {
getLogger().warning("Rename rejected: " + newName);
return;
}
getLogger().info("Dominion renamed to " + updated.getName());
});
不需要模拟玩家权限的后台任务可以使用控制台作为 operator。如果操作应该受领地主人或成员权限约束,传入真实的 Player,不要使用控制台替代权限判断。
添加成员并设置权限
PlayerDTO target = api.getPlayer(targetUuid);
if (target == null) {
return;
}
api.getMemberProvider()
.addMember(operator, dominion, target)
.thenAccept(member -> {
if (member == null) return;
api.getMemberProvider()
.setMemberFlag(operator, dominion, member, Flags.CONTAINER, true)
.thenAccept(updated -> {
if (updated == null) {
getLogger().warning("Member flag update failed.");
}
});
});
如果想为一组玩家设置相同权限,创建 GroupDTO 后使用 GroupProvider.setGroupFlag,再用 GroupProvider.addMember 把成员加入组。不要在多个 DTO 上直接复制 flag Map。
创建领地
CuboidDTO cuboid = new CuboidDTO(
minX, minY, minZ,
maxX, maxY, maxZ
);
api.getDominionProvider()
.createDominion(
Bukkit.getConsoleSender(),
"addon-created",
ownerUuid,
world,
cuboid,
null, // null 表示顶级领地
true // 示例中跳过经济检查;生产功能应由管理员配置
)
.thenAccept(created -> {
if (created == null) {
getLogger().warning("Dominion creation failed.");
return;
}
getLogger().info("Created dominion " + created.getName());
});
skipEconomy 不应被当成“跳过所有限制”。Dominion 仍会检查名称、数量、边界、重叠、父子关系和其他合法性。
调整边界
使用 DominionReSizeEvent.TYPE.EXPAND/CONTRACT 和 DIRECTION 指定方向:
api.getDominionProvider().resizeDominion(
operator,
dominion,
DominionReSizeEvent.TYPE.EXPAND,
DominionReSizeEvent.DIRECTION.EAST,
8
).thenAccept(updated -> {
if (updated == null) {
getLogger().warning("Resize rejected.");
}
});
在生产服开放边界修改前,先检查目标领地的父领地、子领地、相邻领地和管理员权限;Provider 会执行这些检查,但附属仍应给用户清晰的失败提示。
异步调用的注意事项
- 不要连续调用
future.get()或join()等待结果; - 链式操作使用
thenCompose,避免嵌套回调; - 回调中不要假设仍处于 Bukkit 主线程或同一个 Folia region;
- 需要访问在线实体、打开菜单或发送依赖线程模型的操作时,使用对应服务端调度器;
- 领地已被删除、玩家已离线或操作员权限已变化时,仍可能得到
null/false。