
简介这份资源是面向《Mindustry》模组开发者的 JavaScript 脚本工具核心为 MultiCrafter 多合成器功能帮助玩家在自定义模组中快速注册并管理多种配方适合已掌握基础 mod 结构、希望扩展工厂玩法与合成逻辑的中阶开发者。压缩包共 2 个文件包含 1 个 js 脚本与 1 个 md 说明文档前者是可直接引入的 multi-crafter 主逻辑后者提供用法与参数说明整体仅 4KB轻量易读。已有 171 人学习下载说明该方案在 Mindustry 模组圈具备一定参考价值。通过阅读脚本与文档读者可了解如何以 require 方式加载模块、调用 newCrafter 定义配方并借助 prov 回调配置输入物品、液体与数量等参数从而把多合成器机制嵌入自己的 main.js减少重复造轮子的时间也为后续扩展配方条件与产出逻辑提供可复用的代码骨架。1. MultiCrafter 到底解决什么问题Mindustry 6.0 的 JS 模组为什么值得折腾如果你玩过 Mindustry 的模组大概率遇到过这种场景想加一种新工厂能同时产出三种资源但原版逻辑里一个工厂只能对应一种配方写 Java 又嫌重、编译又慢改一行要等半天。MultiCrafter 就是冲这个痛点来的——它让你用 JavaScript 在 Mindustry 6.0 里定义多配方工厂一个方块挂多套输入输出运行时动态切换。这不是简单的 JSON 配置而是把 JS 脚本嵌进模组逻辑里靠脚本引擎解析执行。适合谁适合已经会写一点 JS、想快速迭代模组玩法、又不想每次改逻辑都重新打包 Java 的人。热搜里常出现「Mindustry mod js」「js 函数」「js 引入」这些词说明不少人卡在脚本怎么挂进模组、函数怎么被调用这一步。这一章先把边界划清楚MultiCrafter 不是万能的它只负责配方调度和工厂行为不替你处理贴图、音效、UI 布局。你仍然需要基础的模组目录结构和 Mindustry 6.0 的 mod 加载机制。下面从实际落地角度拆开讲。2. 把 JS 挂进 Mindustry 6.0MultiCrafter 的最小可跑结构2.1 模组目录与脚本入口的对应关系Mindustry 6.0 的 mod 加载器会扫描mods/你的模组名/下的mod.json然后根据scripts字段去加载 JS 文件。MultiCrafter 本身是一个 Java 侧提供的脚本宿主它暴露了一些全局对象和函数你的 JS 文件通过mod.json里的scripts数组被引入。常见做法是建一个scripts/main.js然后在mod.json里写scripts: [scripts/main.js]。注意路径是相对于模组根目录的不要写成绝对路径。下面是一个最小mod.json示例{ name: multicrafter-demo, displayName: MultiCrafter Demo, version: 1.0, minGameVersion: 6.0, scripts: [scripts/main.js] }这段配置的作用是告诉加载器这个模组有一个脚本入口位于scripts/main.js。minGameVersion必须写6.0否则 6.0 的加载器可能拒绝加载。参数说明name是内部标识不要有空格displayName是游戏里显示的名字version随便写但建议语义化。改完mod.json后游戏启动时会在控制台输出脚本加载日志如果路径写错日志里会出现Script file not found这时候先检查大小写——Linux 和 Android 对大小写敏感Windows 不敏感但跨平台发布时容易翻车。2.2 用 JS 定义一个多配方工厂的最小函数MultiCrafter 的核心是让你注册一个工厂方块并给它绑定多个配方。JS 侧通常通过一个全局注册函数来完成比如MultiCrafter.registerFactory之类的接口具体名字取决于你用的 MultiCrafter 版本常见做法是查它暴露的全局对象。下面是一个可复现的最小脚本// scripts/main.js // 假设 MultiCrafter 暴露了 global.MultiCrafter const mc global.MultiCrafter; // 定义一个工厂输入铜和铅输出硅 mc.registerFactory({ name: multi-smelter, size: 2, health: 200, recipes: [ { input: { copper: 2, lead: 1 }, output: { silicon: 1 }, craftTime: 60 }, { input: { copper: 1, coal: 2 }, output: { silicon: 2 }, craftTime: 90 } ] });逻辑说明registerFactory接收一个配置对象recipes数组里每个元素是一套配方。input和output的键是物品内部名必须和 Mindustry 6.0 的物品注册名一致比如copper、lead、silicon、coal。craftTime单位是 tick60 tick 约等于 1 秒Mindustry 默认 60 tick 每秒。参数怎么改size决定方块占几格2 表示 2x2health是耐久如果想让工厂根据输入自动选择配方MultiCrafter 通常会在运行时遍历recipes找到第一个输入满足的配方执行。失败时看什么如果游戏里方块显示但不出货先检查物品名拼写再检查craftTime是否设得太小导致逻辑没触发。常见误用是把input写成数组但多数 MultiCrafter 版本要求对象键值对。2.3 脚本加载顺序与依赖注入的注意点JS 文件在 Mindustry 6.0 里是按scripts数组顺序加载的如果你有多个脚本后面的脚本可以访问前面脚本定义的全局变量。但 MultiCrafter 的全局对象不一定在第一时间就绪常见做法是在脚本里用if (global.MultiCrafter) { ... }做保护或者监听一个初始化事件。有些版本要求你把注册逻辑放在Events.on(ClientLoadEvent, ...)里但服务端和客户端加载时机不同单机模式下客户端加载完就能注册。如果你在专用服务器上跑要确认 MultiCrafter 的 Java 侧已经初始化完毕。一个血泪经验不要在脚本顶层直接调用mc.registerFactory而不做存在性检查否则一旦加载顺序变了整个脚本会抛异常后续代码全不执行。建议写成if (global.MultiCrafter) { global.MultiCrafter.registerFactory({ /* ... */ }); } else { // 延迟到下一帧再试或者打印日志 Log.warn(MultiCrafter not ready, skip factory registration); }这样即使 MultiCrafter 还没挂载也不会把整个模组搞崩。3. 配方调度与运行时行为参数怎么设才不翻车3.1 craftTime、输入输出比例与生产节拍craftTime是 MultiCrafter 里最容易被忽视的参数。设得太小工厂会疯狂消耗输入但输出速度受限于物品传输速率导致输入瞬间被抽干工厂频繁空转设得太大玩家觉得慢。常见做法是参考原版工厂原版硅冶炼厂craftTime大约是 40 tick输入 1 铜 1 煤 1 沙输出 1 硅。如果你做多配方每个配方的craftTime应该和它的输入复杂度成正比。比如输入 2 铜 1 铅产出 1 硅craftTime设 60 比较合理输入 1 铜 2 煤产出 2 硅craftTime设 90 到 100。参数调整时可以用一个简单公式craftTime ≈ 基础时间 × 输入物品总数 / 输出物品总数基础时间取 30 到 40 tick。另外MultiCrafter 可能支持craftTime为 0 表示瞬时但实际会每 tick 执行一次性能开销大不建议。3.2 多配方切换的判定逻辑与优先级MultiCrafter 在运行时如何决定用哪个配方常见实现是遍历recipes数组检查当前工厂内部库存是否满足某个配方的input满足就锁定该配方并开始计时。这意味着配方的顺序会影响行为如果你把“输入铜和铅”放在“输入铜和煤”前面当工厂同时有铜、铅、煤时它会优先选第一个。如果你希望某个配方优先就把它放前面。但要注意如果两个配方输入有重叠比如配方 A 需要铜 2配方 B 需要铜 1工厂有铜 2 时可能先匹配 A导致 B 永远不执行。解决办法是让输入集合尽量互斥或者用更具体的条件如果 MultiCrafter 支持priority字段。我一般会按“输入种类多的配方放前面”因为它的条件更严格不容易误匹配。如果发现工厂只产一种东西先检查配方顺序和输入重叠。3.3 物品内部名与本地化显示的对应JS 里写的copper、lead是内部名游戏里显示的是本地化后的名字。如果你写错内部名比如把silicon写成silicon2MultiCrafter 可能不会报错但工厂会一直缺输入因为那个物品不存在。排查方法在脚本里加一行Log.info(Object.keys(global.MultiCrafter.items))之类的调试输出如果暴露了物品列表或者直接查 Mindustry 6.0 的源码物品注册表。常见内部名copper、lead、coal、sand、silicon、titanium、metaglass、graphite、thorium、plastanium、phase-fabric、surge-alloy。注意phase-fabric和surge-alloy带连字符别写成下划线。另外物品名大小写敏感Copper和copper不一样。热搜里「js 忽略大小写」这个词在这里不适用因为 Mindustry 内部名是严格区分大小写的。4. 避坑与排查MultiCrafter 脚本最常见的 5 个翻车现场4.1 现象脚本加载了但工厂不出现原因mod.json里scripts路径写错或者 JS 文件有语法错误导致整个脚本被跳过。Mindustry 6.0 的脚本引擎在解析失败时可能只打一行日志不中断游戏。解决打开游戏控制台看有没有Error parsing script或Script file not found。如果有语法错误用node -c scripts/main.js在本地先检查语法前提是你本地有 Node.js。另外mod.json的minGameVersion如果写成6而不是6.0某些加载器会认为不兼容。4.2 现象工厂能放但一直不生产原因input里的物品名拼错或者craftTime设成了 0 导致逻辑异常。解决先确认物品名再检查craftTime是否大于 0。如果物品名正确看工厂库存是否真的被输入了——有时候传送带没接上或者工厂的size和实际占地不匹配导致输入口位置不对。MultiCrafter 的工厂通常有默认的输入输出口但如果你改了size口的位置可能变。建议先用size: 2测试别一上来就搞 3x3。4.3 现象多个配方只有一个生效原因配方顺序问题或者输入条件重叠导致第一个配方永远满足。解决调整recipes数组顺序把输入种类多的放前面。如果还是不行检查是否所有配方的output都写了漏写output可能导致配方被跳过。另外有些 MultiCrafter 版本要求每个配方有唯一id如果没有id内部可能用索引做键但切换时出问题。建议显式加id。4.4 现象游戏卡顿或崩溃原因craftTime太小或者配方数量太多导致每 tick 遍历开销大。解决把craftTime调到至少 30 tick配方数量控制在 5 个以内。如果崩溃日志指向 MultiCrafter 的 Java 侧可能是 JS 对象和 Java 对象转换时出了类型错误比如把字符串传给了期望数字的字段。检查所有数值字段是不是真的数字别写成60。4.5 现象多人模式下工厂行为不同步原因JS 脚本在客户端和服务端都执行但注册逻辑可能只在客户端跑导致服务端没有工厂定义。解决确认 MultiCrafter 是否要求把注册放在服务端事件里。常见做法是用Events.on(ServerLoadEvent, ...)包一层或者用if (!Vars.net.client())判断。如果只在客户端注册多人游戏里其他玩家看不到你的工厂。这个坑很隐蔽单机测试正常一联机就翻车。5. 进阶用 JS 动态生成配方与运行时热重载技巧5.1 从外部数据生成配方数组如果你有很多配方手写recipes数组很累可以用 JS 在运行时生成。比如从一个 JSON 文件读取配方定义然后 map 成 MultiCrafter 需要的格式。下面是一个示例// 假设有一个 recipes.json 在模组目录下 const fs global.MultiCrafter.fs; // 如果暴露了文件系统接口 const raw fs.readFile(recipes.json); const data JSON.parse(raw); const recipes data.map((item, index) ({ id: recipe- index, input: item.input, output: item.output, craftTime: item.craftTime || 60 })); global.MultiCrafter.registerFactory({ name: dynamic-factory, size: 2, health: 200, recipes: recipes });逻辑说明先读取外部 JSON解析成对象数组然后转换成 MultiCrafter 的配方格式。参数说明item.input和item.output必须是对象键是物品内部名。如果 MultiCrafter 没有暴露fs可以用Vars里的文件读取接口或者干脆把数据内联在 JS 里。这个技巧的好处是配方数据可以独立维护改配方不用动脚本逻辑。注意 JSON 解析失败会抛异常建议用try/catch包住。5.2 运行时热重载的可行性与限制Mindustry 6.0 本身不支持脚本热重载改完 JS 必须重启游戏或重新加载模组。但你可以做一个“伪热重载”把配方数据放在外部文件每次改完文件后在游戏里执行一个命令重新读取并重新注册工厂。不过 MultiCrafter 可能不允许重复注册同名工厂所以需要先注销再注册或者用不同的name。常见做法是开发阶段用name: factory- Date.now()生成唯一名测试完再改回固定名。这个技巧能省不少重启时间但别在发布版里用否则工厂名会乱。另外热重载时旧工厂的实例可能还在世界里需要手动拆除不然会残留。5.3 验证脚本是否生效的三种方法第一种看控制台日志在脚本关键位置加Log.info(factory registered)如果日志没出现说明脚本没执行到那行。第二种在游戏里放一个工厂看它的信息面板是否显示多个配方如果只显示一个说明recipes数组没传对。第三种用Vars.content.blocks()遍历所有方块找你的工厂名确认它真的被注册了。我一般会先跑第一种因为最快。如果日志有但工厂不出现再查mod.json的name和脚本里的name是否一致。最后记得在发布前把调试日志删掉不然控制台会刷屏。希望帮到你。本文还有配套的精品资源点击获取