深色模式
架构、数据与安全模型
六模块结构
text
sealitems-api
↓
sealitems-core
↓
sealitems-asset
↓
sealitems-gameplay
↓
sealitems-paper
↓
sealitems-plugin准确依赖是:Core → API;Asset → Core;Gameplay → Core + Asset;Paper → Core + Asset + Gameplay;Plugin 打包全部内部模块和 API。根构建会拒绝未批准的生产模块依赖。
API
最小第三方契约,不引用 Paper 内部实现。
Core
纯业务定义、编译快照、稳定 ID、物品识别、品质/词条/孔位状态 codec。应尽量不依赖服务器运行时。
Asset
请求、expected state、迁移与提交结果契约。描述“准备做什么”和“提交时必须仍成立什么”。
Gameplay
鉴定、改造、掉落、孔位等规则的纯编译/决策层。
Paper
ItemStack/PDC、玩家背包、事件、GUI、外部插件适配器和真实事务提交。
Plugin
TabooLib 生命周期、配置发现/加载、候选编译、原子发布、命令和总装配。
快照与原子发布
配置重载先读取全部候选,严格解析、解析跨文件引用、编译业务规则,全部成功后一次替换已发布快照。失败不会发布半套品质、半套词条或一半宝石规则。
这也解释了为什么修改一个物品可能触发鉴定/改造交叉验证:旧玩法快照不能指向已删除定义。
物品身份
PDC 使用 sealitems namespace 保存:schema version、item ID、definition fingerprint、individual UUID、revision,以及编码后的装备属性、词条、品质、孔位、鉴定状态。改造保底另使用 sealitems_gameplay:modification_state。
当前 schema 5;旧 schema 1..4 可被识别并按支持路径迁移。以下情况进入 PROTECTED:
- schema 缺失/未知;
- ID 格式非法或当前定义不存在;
- 指纹缺失/非法;
- individual 缺 UUID/revision;
- stackable 带 individual 状态;
- codec 类型或内容损坏。
PROTECTED 的目的不是惩罚玩家,而是避免错误数据被重写成看似正常的新物品。
Revision、指纹与 CAS
GUI 打开时看到的物品不是提交时的真相。请求会携带 requestId、操作者/目标、目标槽位、完整 expected item state、规则/配置指纹和玩法状态摘要。提交时再次读取:
- 玩家仍在线;
- 输入槽仍是同一件物品;
- UUID、revision、品质、词条、孔位等都未变化;
- 规则与 provider 仍是同一发布快照;
- 材料槽和余额仍匹配;
- 目标背包空间足够。
任何事实变化都会冲突或阻止,不会基于旧预览强行覆盖。
本地物品与外部经济事务
背包/PDC 可以本地恢复,外部经济通常没有跨插件数据库事务。SealItems 使用预检、最终检查、可恢复本地提交、单次外部扣款和结果分类:
- 明确未扣款:回滚本地状态。
- 明确扣款成功:完成提交。
- 事实未知:保留现场、冻结 provider、输出审计,禁止自动重试。
“未知”不能假装失败,否则玩家重试可能二次扣款。
线程与性能
Paper 物品/背包/GUI 操作在服务器线程语义内完成。配置先编译为不可变快照,运行时避免重复解析 YAML。读装备与迁移按事件/预算执行,不全量扫描离线数据。高候选工作量在配置编译期设固定上限,防止一次 GUI 点击展开极端候选。
安全扩展原则
- 公共 API 保持最小。
- 新写操作必须有 expected state、明确失败状态、幂等/重试语义和审计。
- 不让客户端决定费用、概率或结果。
- 不把外部 API shade 进成品。
- 数据损坏时故障关闭,不猜测修复。
- 新配置继续使用严格字段与候选原子发布。