排错与调试
排错与调试
宝石类插件最难排查的问题是静默失效:镶嵌成功了,也没报错,但装备上什么都没变。本页按「先看什么、再看什么」的顺序整理排查路径。
排查三步
Paper 26.2:NoSuchFieldException: map
如果堆栈包含 NMSItemTagLegacy,这是旧构建通过 TabooLib NMS 映射读写物品标签时失败,详见 Issue #1。绕过 disable-on-unsupported-version 不会修复字段映射。
2026-09-10 的 0.0.4 修订构建将宝石标识、镶嵌历史、属性累计值和隐藏 Lore 改为 Bukkit PDC 存储,移除了插件的 BukkitNMSItemTag 依赖。新宝石直接写入 PDC;旧物品通过 Paper 公共 serializeAsBytes() 接口读取标准 NBT,在下次写入时导入 PDC。支持旧 tag 和现代 minecraft:custom_data 格式;损坏数据会报错,不会当作空记录覆盖。
更新前备份世界与玩家数据,停服替换修订 JAR 后启动。当时修订版本号仍为 0.0.4;当前手册对应 0.0.6 修订构建,升级时请核对实际构建内容。PDC 数据不供旧构建读取,不能假定降级后仍可识别新宝石或最新拆卸记录。此修改已通过构建与数据编解码测试,尚未在 Paper 26.2 实服验证;其他 TabooLib 模块的版本兼容性仍需单独确认。
跑配置自检
/sgem reload
/sgem compat all
自检会列出所有「写错的条目」(含拼写建议)和「当前版本不支持所以跳过的条目」。大部分问题在这一步就能定位。
开对应的 debug tag
/sgem debug Reward,GemManager # 镶嵌相关
/sgem debug Skill,SkillExec # 技能相关
/sgem debug Menu,Workbench # 菜单相关
/sgem debug Buff # 常驻 BUFF
/sgem debug all 或 /sgem debug <tag>[,<tag>] 会立即开启调试;输出写入服务器控制台,游戏聊天栏只显示开启回执。开启时控制台会立即打印一条确认日志。日志会说明每一步的判定与未生效原因。
看完关掉
/sgem debug off # 关闭调试
日志量很大,排查完记得关。
debug tag 清单
/sgem debug <tag>[,<tag>] 可只看指定范围并自动开启。/sgem debug all 开启所有范围;不带参数的 /sgem debug 仍可切换开关。指令设置在本次服务器运行期间有效,执行 /sgem reload 或在游戏内保存编辑器配置不会关闭它;服务器重启后使用 config.yml 中的 Debug 与 DebugTags。
| tag | 覆盖范围 |
|---|---|
Registry | 配置文件加载(宝石/菜单/技能) |
Compat | 版本兼容层:注册表快照、物品分类、能力探测 |
Command | /sgem 各子命令 |
Menu | 工作台菜单的点击/拖拽/关闭/镶嵌 |
Workbench | 菜单的打开与图标渲染 |
Embed | 内置镶嵌台的放入/校验/镶嵌 |
GUI | /sgem view 与 /sgem inspect 面板 |
Editor | 游戏内编辑器保存与回滚 |
GemUse | 右键/食用直接使用宝石 |
Protect | 宝石防放置保护 |
GemManager | 镶嵌/拆除/给予的核心逻辑 |
Dismantle | 拆卸宝石的扣费与损坏判定 |
Rune | 符文锻造 |
ItemFactory | 宝石物品构建与 NBT 读写 |
Reward | 奖励函数执行 |
Skill | 技能触发判定 |
SkillExec | 技能函数执行 |
Buff | BUFF 定时引擎 |
Points | 点券账户 |
Money | Vault 经济 |
PlayerPoints | PlayerPoints 对接过程 |
Update | 版本更新检测与公告拉取 |
也可以在 config.yml 里持久化:
Debug: true
DebugTags: [Reward, GemManager]
Buff tag 会疯狂刷屏。插件对重复内容做了去重(同样的内容不重复输出),但换个装备或换个玩家就会再打一次。排查完立刻关掉。静默失效的常见原因
按遇到频率排序。
1. Attribute 的 limit 与累计贡献不符合预期
limit 是本插件累计贡献的上限,不是镶嵌次数,也不包含装备自带的数值。当前实现对与表达式结果方向相同的 limit 进行夹取;反方向的 limit 不会限制本次变化。减益应配负上限,避免无限累加。
# 缩小:每次减少 0.1,插件累计最低 -0.3
- Attribute{name=scale;operation=0;slot=any;var=v-0.1;limit=-0.3}
到达上限或会使现有累计贡献倒退时,此条奖励不生效。只有整颗宝石没有任何奖励生效且没有异常副作用时,才按无效操作处理;不能将某一条无效等同于整颗不消耗。
2. BUFF 宝石与 BUFF 定义的标记不一致
症状:BUFF 宝石镶嵌成功,装备 lore 上也有那行字,但没有任何效果。
宝石 LoreAdd{lore=...} 写的文本必须和 BUFF 定义的 Lore: 一致(去色后比较)。
排查:/sgem debug Buff,如果日志里从来没有「命中 BUFF 定义」,就是标记对不上。
3. 技能行漏写触发标记
症状:技能完全不触发。
# 错:没有 ~onUse,永远不会被触发
- Blink{distance=32} @Forward
# 对
- Blink{distance=32} ~onUse @Forward
排查:配置自检会直接报「这一行没有写触发标记,永远不会被触发」。
4. 技能定义没写 Lore
症状:装备拿在手里,技能不触发。
技能靠装备 lore 文本绑定。Lore 留空的定义不会被任何装备触发(只能作为 Switch 的目标形态或被 Reward{} 嵌套调用)。
5. PlayerGem 用了作用于物品的奖励
症状:右键饮用/使用后,提示发了但没效果。
PlayerGem 没有目标物品,不能用 Attribute、Enchant、LoreAdd、Unbreakable 等。只能用 MaxHealth、ExpLevel、Point、Money、ItemGive、ItemTake。
排查:/sgem debug Reward,日志会打印「本次操作没有目标物品」。
6. 用了当前版本不存在的内容
症状:某些宝石在 A 服正常,在 B 服无效。
排查:/sgem compat 对比两个服的能力清单。这属于正常行为,不是 bug。
7. $LORE: 引用的标记与自身 Lore 不一致
症状:可叠加等级的 BUFF 等级永远是 1,不涨。
抗性提升:
Lore: "&6&l[&c&lBUFF&6&l] &b&l抗性提升 "
Skills:
# $LORE: 里必须写去色后的形式,且和上面 Lore 一致
- Potion{type=resistance;level=$LORE:[BUFF] 抗性提升?1$} ~onTimer
8. 改了配置没重载
只有 lang/<语言代码>.yml 是热重载的(保存即生效)。config.yml、gems/、skills/、gui/ 都需要 /sgem reload。
9. 拆卸失败,或 BUFF 仍短暂存在
新记录的 LoreAdd / LoreReplace 已支持局部撤销。旧配置里的 $onRemove 已不执行;拆卸价格与返还成功率应在 dismantle/ 中配置。若记录缺失或外部插件改写了 Lore,无法安全撤销时会取消拆卸并尝试退款。LoreVar、Name、修复和玩家奖励不支持通用撤销。
装备处于技能隐藏状态时,先拆隐藏粉尘。成功移除 BUFF 标记后只停止续期,已经施加的药水效果需等现有持续时间结束。详见拆卸规则。
10. 玩家用不了某个命令
症状:提示没有权限。
每个子命令都有独立权限节点。先确认 snowygems.command(主命令基础权限)没被显式设为 false——它被否定后所有子命令都失效。详见权限节点。
不生效但不是 bug 的情况
这几种「没变化」是插件的有意设计,避免玩家白吃宝石:
| 场景 | 行为 |
|---|---|
属性已达 limit | 视为未生效,宝石不消耗 |
| 附魔已经是目标等级 | 视为未生效 |
level=0 但物品本来就没这个附魔 | 视为未生效 |
| 耐久已满还用修复宝石 | 视为未生效 |
| 生命已满还用治疗技能 | 返回 false |
日志里会明确写「视为未生效」,不用怀疑是坏了。
已知的不生效字段
以下配置仍有限制。Embed 已生效,见数量与互斥规则:
| 位置 | 字段 | 说明 |
|---|---|---|
| 菜单配置 | Page | 没有翻页功能 |
| 菜单配置 | Locations | 没有「在世界坐标放置工作台」的功能 |
| 宝石配置 | RemoveTip | 已移除;拆卸提示走 lang/<语言代码>.yml 的 dismantle.* |
菜单类型里的 PAGE_PREV、PAGE_NEXT、PAGE_TIP 同理——它们和 TIP 的行为完全一样(纯装饰),是为将来的翻页功能预留的名字。
报错日志怎么读
「配置自检发现 N 处写错的条目」
后面跟着 [文件.yml -> 宝石ID] 函数{参数} -> 原因。想看完整明细:
/sgem compat all- 或把
config.yml的Compat.OnMissingFeature改成warn
「配置自检发现缺失文件」
0.0.4 的文件自检会列出缺失路径。插件会自动尝试补回默认的 config.yml、lang/、gui/、gems/ 和 runes/ 文件,并且不会覆盖同名文件。若重载后仍提示缺失,先检查 plugins/SnowyGems/ 的读写权限,再确认外部同步或清理脚本没有删除文件。
config.yml 和语言文件支持新增节点迁移;菜单、宝石和技能文件的同名内容不会自动合并,避免覆盖服主配置。请从源码 src/main/resources 或 JAR 根目录的对应资源中手动合并新条目,完成后执行 /sgem reload。
「配置中有 N 处内容当前版本不支持,已跳过」
正常提示,不是错误。想看是哪些,用 /sgem compat all。
「未注册的技能函数: XXX —— 你是不是想写: YYY?」
函数名拼错了,按建议改。全部函数用 /sgem skills 查。
「Require 条目 'XXX' 既不是当前版本的物品名,也不是可用的分类关键字」
分类关键字拼错。可用分类清单在同一条日志的括号里,也可用 /sgem compat all 查看。
「附魔 XXX 不在当前版本的注册表中」
用现代命名空间 ID(小写下划线,如 unbreaking、sharpness),或确认这个附魔需要更高版本。
数据存在哪里
排查数据丢失问题时可能需要:
| 数据 | 位置 |
|---|---|
| 宝石身份标记 | 物品 PDC 载荷内字段:SnowyGemsGemId、SnowyGemsGemType |
| 装备上已镶嵌的宝石列表 | 物品 PDC 载荷内字段:SnowyGemsAppliedGems(拆卸就是从这个列表里摘除) |
| 装备原生属性已固化的标记 | 物品 PDC 载荷内字段:SnowyGemsDefaultsKept |
| 属性叠加值 | 物品 PDC 载荷内字段:SnowyGemsAttr_<属性与槽位标识> |
| LoreVar 的数值 | 物品 PDC 载荷内字段:SnowyGemsLoreVar_<哈希> |
| 附魔切换记住的等级 | 物品 PDC:snowygems:ench_<附魔键> |
| 形态切换状态 | 物品 PDC:snowygems:switch_mode |
| 属性修饰符身份 | NamespacedKey("snowygems", "attr_<属性名>") |
| 内置点券 | plugins/SnowyGems/data/points.yml |
宝石身份、镶嵌与效果数据保存在物品身上的 snowygems:item_data_v1 PDC 字节载荷中;内置点券、方块坐标和诊断日志另有文件。这意味着:物品被其他插件重建(某些「物品修复」「跨服同步」插件会丢 NBT)、放进展示框、或者被合成消耗,宝石数据就没了。
插件已经拦截了「把宝石当方块放置」和「把宝石塞进展示框」两种最常见的丢失场景(Protect tag),但无法拦住所有第三方插件的行为。
性能问题
症状:在线人数多时 TPS 下降。
BUFF 引擎每秒检查玩家最多 6 个物品槽,只扫描带 Lore 且含 onTimer 的缓存定义,同 ID 每轮最多成功施放一次。定义数量大(几百个)叠加高在线人数会有可观开销。
排查与缓解:
/sgem reload后看控制台的「已加载 N 个技能/BUFF 定义,带 Lore 标记可触发的共 M 个」——其中含 onTimer 的定义才参与定时扫描- 删掉不用的 BUFF 定义,别留着
- 一次性效果用事件触发标记(
~onUse等),不要用~onTimer - 避免
Repeat配很短的interval用在高频触发的技能上
求助时请提供
如果自己排查不出来,提供这些信息能大幅加快定位:
/sgem compat all的完整输出- 开对应 tag 后完整操作一次的日志(不要只截结尾)
- 相关宝石/技能的配置片段
- 服务端版本与实现(Paper/Leaves/Purpur + 具体版本号)
logs/latest.log 里带 Caused by: 的完整段落。新版工作台排错
| 现象 | 检查与处理 |
|---|---|
| 符文台没有铁砧确认按钮 | 已有 gui 文件不会自动覆盖;按升级步骤合并新布局,旧布局可空光标 Shift+右键装备 |
| 普通点击装备不再镶嵌 | 普通点击用于取回,请用确认按钮 |
| 新菜单导致重载失败 | 检查 1~6 行、每行 9 字符、Items 定义、Type、Amount,以及重复菜单名 |
| 符文分解按钮找不到配方 | 确认 gems/RuneGem.yml 存在并包含符文分解券和符文碎片,然后 reload |
| Shift 放入或拖拽被拒绝 | 检查槽位 Require、宝石 Gui 与 Amount;装备槽只接收单件 |
| 拆卸没返还或退款失败 | 查看当前宝石的返还成功率和聊天提示;检查身边掉落物,保留日志并核对经济余额 |
| 重载后旧浏览/拆卸页点击无反应 | 重新执行对应命令打开;投入物品的工作台会在重载时关闭并返还 |
建议在测试服依次检查:单颗和四槽镶嵌、失败概率、相同 ID 重复强化后拆一颗、开着工作台 reload、背包满关闭、主副手食用以及符文分解。自动化测试不能替代这些联机行为检查。
随机点券兑换券无效
如果固定点券券可用,但随机券日志出现 Point: 表达式 ... -> 1696.588...、Point ... -> false,随后提示“镶嵌未生效”,原因是旧构建把小数传给只接受整数的 PlayerPoints。
更新到包含随机点券修复的 0.0.7 修订构建 并正常重启。原有 100+2900*$RANDOM() 配置可继续使用,新日志会同时显示表达式结果和实际交易整数;例如 1696.588... 实际发放 1696 点券,成功后消费一张兑换券。PLAYER_HEAD 的 Lore 没有响应 onUse 的技能定义 只是技能扫描信息,不是这次点券失败的原因。
更新后仍失败时,检查 PlayerPoints 是否启用、Points.Provider 是否正确及接口交易日志;后端失败时兑换券不消耗,也不会切换 Internal。完整数额规则见宝石配置。
0.0.6 修订构建常见问题
| 现象 | 处理 |
|---|---|
| catalog 头颅显示成纸 | 更新到包含显示修复的构建并正常重启;确认该宝石的 Texture 为有效 base64。图鉴有 Texture 时使用 PLAYER_HEAD,并加载纹理 |
| history 出现 UUID、原始字段或混淆文字 | 修订构建改为每次最新 5 条摘要,去除物品名的颜色 / 混淆代码及控制字符;历史缓存重启后清空,请产生新操作后验证 |
| history 没有记录 | 只查本次启动后的全局最近 500 条摘要,不读取磁盘历史。旧记录在 logs/operations-*.log;扣费中间步骤只写磁盘 |
| 重载失败但旧配置仍有效 | 查看控制台的文件、ID 和原因;修复重复 ID、关键引用或 strict 校验错误后再重载,勿反复删配置 |
| 首次启动就停用 | 首次启动没有旧注册表可恢复。修正加载错误后正常重启;不要靠关闭 strict 掩盖文件 / 引用错误 |
| PlayerPoints 不可用后无法奖励 / 拆卸 | 当前不会自动切换 Internal。恢复外部后端及其 API,核对真实余额后再试 |
| 第三颗同类宝石不能镶嵌 | 检查 Embed;它统计同 ID 的已记录次数,不是全装备总孔数 |
| 多件装备的同一 BUFF 不再叠加 | 同 ID 每轮只成功施放一次,按主手、副手、头、胸、腿、脚顺序,且遵守 Slot 和共享冷却 |
| 重载后延迟技能没执行 | 旧任务按设计失效;离线、死亡或目标无效也会取消延迟执行 |
聊天输出、日志保留范围和各结果含义见图鉴与操作记录。