JS 模组开发

用 JavaScript 写一个可加载、可进游戏的 TN 模组。 · UPDATED 2026-11-08

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;

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. 调试