Theseus 模组文档
开发指南

调试与排错


10.1 日志:ctx.getLogger()

ctx.getLogger() 返回名为 seecmd.mod.<模组id> 的 java.util.logging.Logger。宿主为该 logger 装配了单行格式的输出处理器,日志行前缀为 [<模组id>],因此:

java
@Override
public void onInit(ModContext ctx) {
    ctx.getLogger().info("初始化完成");
    ctx.getLogger().warning("贴图缺失:" + NOTE_TEXTURE);
}

10.2 排错清单

现象常见原因怎么查 / 怎么改
模组状态 LOAD_FAILED,原因写「此模组要求 API X,宿主支持 Y」manifest 的 Seecmd-Api-Version 与宿主支持的模组 API major 不匹配改用与宿主支持的模组 API 主版本一致的 API jar 重新编译;或改对 manifest 字段
LOAD_FAILED,原因含「引用了内核内部实现」代码 import 了 com.seecmd.* 下的宿主 / 内核类只依赖 com.seecmd.mod.api.*;需要宿主做某件事时走能力接口
LOAD_FAILED,找不到入口类manifest 的 Seecmd-Mod-Class 写错,或类未打进 jar核对全限定类名与 src/main/java 下的实际包名;用 jar tf 确认 class 在 jar 里
LOAD_FAILED,原因含加载时抛异常入口类无参构造 / info() / onPreInit 里抛了异常把 info() 保持为纯数据返回;onPreInit 中只做注册,不做 IO
抛 RegistryFrozenException注册写在了 onInit / onPostInit / 渲染回调等非注册窗口把全部 ctx.registries().xxx().register(...) 移到 onPreInit,不要捕获该异常来规避
抛 IllegalArgumentException:非法命名空间 / 非法路径ResourceLocation 的 namespace 只接受小写 [a-z0-9_.-](长度 1~64),path 只接受小写 [a-z0-9/._-](长度 1~255)全部改小写;命名空间约定 = 模组 id
抛 IllegalArgumentException:该 location 已注册同一 ResourceLocation 注册了两遍(重复注册是显式失败,不静默覆盖)注册前用 Registry.contains(location) 自检;不同内容用不同 path
抛 IllegalArgumentException:键 / 值 / 类型为 null,或 RegistryKey 的泛型与目标注册表不匹配把某类内容注册进了另一个注册表核对 RegistryKey.of(ns, path, XxxDefinition.class) 的第三个参数与目标注册表一致
加载图片 / 文本时抛 ResourceNotFoundException资源没放在 src/main/resources/assets/<模组id>/...,或路径写错1.0 没有裸路径回退,路径必须对应 assets/<命名空间>/<路径>;可用 ResourceManager.list("mymod:") 列出 jar 内实际条目
ctx.language().get(key) 在 onInit 里读不到自己的译文宿主在本模组 onInit 返回之后才扫描 jar 内的语言文件放到 onPostInit(或更晚)再读;也可改用 ctx.language().add(locale, entries) 主动注册
改了模组却「没生效」注册在启动期一次性完成重启游戏;模组列表里的启用 / 停用开关只在下次启动生效;改了模组 jar 同样要重启游戏
事件监听器抛异常后「什么都没发生」总线对每个监听器独立 try/catch(Throwable),异常被隔离并记日志到日志里搜该模组的 logger 名;异常不会影响其它模组、不会中断游戏,也不会重试

10.3 事件监听器抛异常的表现

事件总线对每个监听器独立 try/catch(Throwable):单个监听器抛异常只记日志,不影响同事件的其它监听器,也绝不冒泡到宿主循环 —— 一个模组崩不了游戏。需要注意的推论:

10.4 「需要重启才生效」的两件事