Compatibility
Minecraft: Java Edition
Platforms
Supported environments
Links
Tags
Creators
Details
Sable Quota
Sable Quota 是面向 Minecraft 1.21.1、NeoForge 与 Sable 的服务端物理结构配额模组。它按玩家 UUID 记录 Sable Sub-Level 的归属和数量,限制玩家持续创建物理结构造成的性能与存储压力,并提供查询、定位和管理工具。
核心功能
- 为普通玩家和 OP 分别设置默认结构上限,
-1表示无限。 - 支持按玩家 UUID 设置个人上限,玩家离线或服务器重启后仍然保留。
- 记录结构 UUID、所有者和最后已知位置,普通卸载不会释放或误减额度。
- 覆盖 Simulated 物理装配器、旋转轴承和受支持的 Sable 单结构装配命令。
- 创建达到上限时直接取消操作,并通过 Action Bar 提示当前数量和上限。
- 在玩家破坏方块前预测结构断裂结果,避免一次断裂批量生成碎片而绕过额度。
- Sable 自动拆分出的新结构继承原结构所有者,并分别占用额度。
- 提供结构列表、坐标查询和按 UUID 强制删除功能;删除目标当前未加载时同样可处理。
- 提供第三方模组 API,用于安全地代表玩家创建单个 Sable 结构。
- 兼容修复 Create 连续 OBB 碰撞在退化情况下分离轴为
null导致的崩溃。
安装与兼容性
- Minecraft:
1.21.1 - NeoForge:
21.1.233+ - Sable:
2.0.3+(必需) - Simulated:以
1.3.0为集成目标,未安装时相关兼容代码会自动跳过。 - Create:包含针对
6.0.10的退化碰撞防崩兼容,未安装时相关兼容代码会自动跳过。
Sable Quota 服务端必装、客户端可选:
- 配额判断、所有权数据、管理指令和服务端文本均由服务器处理,只在服务端安装即可使用完整配额功能。
- Create 碰撞修复在每一端的本地游戏进程中生效。只在服务端安装只能保护服务端;如果希望客户端也避免同一碰撞崩溃,需要客户端安装相同版本的 Sable Quota。
- 客户端安装 Sable Quota 时也必须具备其必需依赖 Sable。
配置
首次启动后生成:
config/sable_quota-common.toml
默认配置:
[quota]
# 普通玩家默认结构上限;-1 为无限,0 为禁止创建。
maxStructuresPerPlayer = 3
# OP 默认结构上限;-1 为无限。
maxStructuresPerOperator = -1
[messages]
# 留空时按照玩家上报的客户端语言使用内置文本。
# 支持 {owned} 和 {limit} 占位符。
creationBlocked = ""
有效额度按以下优先级计算:
个人上限 > OP 默认上限 > 普通玩家默认上限
OP 状态不会缓存,玩家获得或失去 OP 权限后,下一次查询或创建会立即使用新的身份默认值。降低上限不会删除已有结构;已有数量超过新上限时,只会阻止继续创建和超额拆分。
指令
普通玩家可以查询自己的额度和结构。查询他人、修改额度、强制删除结构和重新加载配置需要权限等级 2,默认仅 OP 可用。
| 指令 | 权限 | 作用 |
|---|---|---|
/sablequota get |
玩家 | 查看自己的结构数量、有效上限和上限来源 |
/sablequota get <player> |
2 | 查询指定玩家,支持服务器档案中的离线玩家 |
/sablequota list |
玩家 | 查看自己的结构列表第一页 |
/sablequota list page <page> |
玩家 | 查看自己的指定页,每页最多 10 个结构 |
/sablequota list <player> [page] |
2 | 查看指定玩家的结构及位置 |
/sablequota set <player> <amount> |
2 | 设置个人上限,-1 表示无限 |
/sablequota add <player> <amount> |
2 | 在当前有效上限上增加额度,并保存为个人上限 |
/sablequota remove <player> <amount> |
2 | 减少当前有效上限,最低为 0 |
/sablequota reset <player> |
2 | 删除个人上限,恢复使用普通玩家或 OP 默认值 |
/sablequota delete <structure-uuid> |
2 | 跨维度彻底删除指定 UUID 的结构,即使结构当前未加载 |
/sablequota reload |
2 | 校验并重新读取配置;失败时继续使用旧配置 |
add 和 remove 的数量必须至少为 1。目标当前为无限额度时,需要先通过 set 设置有限上限。
delete 会通过 Sable 的结构生命周期清理实体、Plot 占用、强制加载票据、磁盘数据和配额记录。该操作不可撤销,执行前必须确认结构 UUID。
结构归属与位置
Sable 的底层分配接口不包含玩家参数,因此 Sable Quota 会在受支持的创建入口中建立一次性的玩家上下文,并让下一次 Sub-Level 分配消费该上下文。
- 已加载结构显示当前物理姿态的位置。
- 未加载结构显示持久化的最后已知位置。
- 普通列表查询不会强制加载区块或 Sub-Level。
- 安装本模组之前已经存在的结构没有可靠的创建者信息,不会被自动归属给任意玩家。
- 未接入 Sable Quota API 的第三方或系统创建会保持无归属,不计入玩家额度,也不会被强制删除。
断裂保护
玩家破坏已归属结构中的方块时,模组会按照 Sable 的 18 邻接规则预测方块移除后的连通分量。只有局部邻居可能形成多个分量且剩余额度不足时才进行图遍历;普通方块破坏不会持续扫描整个结构。
对于不是由玩家破坏直接触发的自动拆分,Sable 分配新碎片前还会执行一次额度兜底检查。成功拆分的结构会继承来源结构所有者。
第三方模组 API
第三方模组代表玩家创建单个 Sub-Level 时,可以使用:
Optional<ServerSubLevel> result = SableQuotaApi.createStructure(player, () ->
(ServerSubLevel) container.allocateNewSubLevel(pose));
一次调用最多创建一个 Sub-Level。额度不足时返回 Optional.empty() 并提示玩家;回调返回 null 或抛出异常时,临时所有权上下文仍会被清理。
数据与性能
配额数据保存在主世界 SavedData:
<world>/data/sable_quota_structures.dat
保存内容包括:
- 结构 UUID 到玩家 UUID 的所有权关系。
- 玩家个人上限覆盖值。
- 结构最后已知的维度和坐标。
运行时维护玩家到结构集合的反向索引,因此玩家结构计数为 O(1)。列表只处理当前页最多 10 个结构,不会每 Tick 轮询所有结构。强制删除未加载结构时会优先使用最后已知维度和 Sable 已有存储指针,无法直接定位时才扫描其他维度的结构存储。
构建
使用 Java 21 执行:
gradlew build
构建产物位于 build/libs/。


