JS 模组开发
JS 模组运行在 QuickJS 沙箱中,是上手成本最低的通道:一个目录 + 一个入口文件即可加载。
1. 最小目录
hello-tnmod/
tnmod.json
scripts/
main.js
Content/Items/HelloSword.js # 内容类按目录自动注册
2. tnmod.json
{
class="s">"format": class="s">"tnmod",
class="s">"formatVersion": 1,
class="s">"apiVersion": 1,
class="s">"id": class="s">"example.hello",
class="s">"name": class="s">"Hello TN",
class="s">"version": class="s">"1.0.0",
class="s">"entry": class="s">"scripts/main.js",
class="s">"targetGame": {
class="s">"package": class="s">"com.and.games505.Terraria",
class="s">"minVersionCode": 301720,
class="s">"maxVersionCode": 301729
},
class="s">"dependencies": [],
class="s">"permissions": [class="s">"content.register", class="s">"assets.read", class="s">"localization.read", class="s">"log"],
class="s">"capabilities": [class="s">"quickjs", class="s">"content.items", class="s">"assets.textures", class="s">"localization"]
}
capabilities里出现未知能力时模组会被禁用(fail-closed),不要填你不需要的能力。
3. 入口 scripts/main.js
class HelloTN extends TN.Mod {
Load() {
TN.log('[hello] loaded v' + this.version + ' id=' + this.id);
}
}
export default HelloTN;
- 加载器把
scripts/main.js作为 ES module 导入,要求export default一个继承TN.Mod的类; scripts/Content/与scripts/Common/下的文件会被一并导入,其中的内容类自动注册;- 日志统一用
TN.log(...),写入boot.log,管理器的「日志」页可检索。
4. 注册一个物品
scripts/Content/Items/HelloSword.js:
class HelloSword extends TN.ModItem {
constructor() {
super();
this.Type = 0; // 注册后由运行时回填
}
SetDefaults() {
this.Item.width = 24;
this.Item.height = 24;
this.Item.damage = 10;
this.Item.useAnimation = 20;
this.Item.useTime = 20;
this.Item.value = 100;
}
}
export default HelloSword;
物品的贴图放在 assets/Content/Items/HelloSword.png(与内容类同路径)。
5. 本地化
localization/
zh-Hans.hjson
en-US.hjson
条目按 Mods.<id>.Items.<ClassName>.DisplayName 的形式声明;缺失时回退到默认名。
6. 打包与导入
把目录内容打成 ZIP,扩展名改为 .tnmod(ZIP 内没有外层目录, tnmod.json 必须在 ZIP 根)。然后按模组安装导入。
开发期可以跳过打包:把目录直接放进
tnl_mods/<id>/,重启管理器后即可加载。
7. 调试
- 启动失败先看
boot.log中的TN mod loaded/TN mod rejected行(含原因码); - 语法错误会以
SyntaxError出现在日志中,附文件与行号; - 需要重载时,管理器内关闭再启用模组,或重启游戏进程。
TerraNova Loader