👆 先点右侧一个「配方格」选中它,再点这里任意方块即可放入(无需手打 ID)。数量用下方输入框控制。
选中配方格 → 点左侧方块放入。点已填入的格子可选中,再点左侧可覆盖。
支持原版方块、模组方块、材料、食物、枪械、装备。选定后自动填好类型与名称,也可再手动修改。
👆 这里列出原版 + 已加载模组 + 本工坊正在编辑的熔炼配方,方便对照。
输入/输出从「已注册」列表选择(方块/材料/食物/模组),无需手打。熔炼完成后产出对应输出物。
👆 这里列出原版 + 已加载模组 + 本工坊正在编辑的燃料,方便对照。
燃料物品从「已注册」列表选择(方块/材料/食物/模组),无需手打。放入熔炉即可作为燃料燃烧。
红石组件:填写名称 / 颜色 / 图标后,必须自己编写代码定义其行为。导出时会先自动注册一个该方块(并把它的 tileId 存入变量),然后原样插入你写的代码,可调用 ModAPI / TILE / TILE_DEF 等。
💡 可创建多个维度。群系与维度分开管理、互通:在下方添加群系时选择它生成到哪个维度,或勾选「生成到原版维度」让它同时出现在主世界/地狱/冰雪。
💡 新手用法:在左侧方块列表里**点一下**就加入群系,右侧给每个方块填个数字当「权重」(越大出现越多,留空=1)。完全不用打字。想偷懒可先选上方「方块主题」预设(演示),再手动删改;文本框与左右列表实时同步。同一维度的多个群系按噪声连续分布、互相接壤(互通)。
💡 在网格上绘制建筑外形,勾选「生成到维度」即可。世界生成时,对应维度里会按概率随机出现这座遗迹(蓝图锚定在区块左上角,尺寸无上限、可跨区块,自动读取你选的方块)。
💡 添加后可在指令下「添加子指令」实现多级(如 /warp a、/warp a b),并为每个层级配置「作用」:消息 / 传送 / 生成怪物 / 切换维度 / 设置血量 / 给予方块。
面向社区开发者:说明模组的识别机制、接口格式与语法。在右侧写代码即可开发高级功能,代码注入到工坊自动生成的模组 IIFE 内,已存在 ModAPI、__tiles、__tileVal。
加载顺序:游戏启动 → ModAPI._loadMods() 先 GET /mods/list 扫描 mods/ 顶层(.mod/.js,排除 manifest.json、server/),再去重 + 回退 manifest.json;也可在「🧩 模组」面板手动导入。
.mod 文件 = JSON 包:{ "name","version","author","description","code" }(兼容 client/source/script)。导入时自动 registerMod(meta) 登记(按 name 去重)再执行 code,无需手写 registerMod。
.js / .client.js 文件 = 纯 JavaScript,运行前已包在 IIFE 中、ModAPI 全局可用。必须自己调用 ModAPI.registerMod({name}) 才会出现在模组列表(工坊导出的 .js 已自动加)。
每个模组最终形态:
// 你的代码填写在 registerMod 之后
(function () {
if (typeof ModAPI === 'undefined') { console.warn("[模组] 未就绪"); return; }
ModAPI.registerMod({ name, version, author, description });
// ← 内容注册 / 事件订阅
})();
运行时可用辅助:__tiles(工坊方块名→tileId 映射)、__tileVal('vanilla:GRASS')(原版方块枚举名→tileId)。
// 方块 → 返回 tileId(number),注入 TILE_DEF
ModAPI.registerBlock({ name, emoji, color, hp, dmg, light,
drop, portal, walkable, slow, transparent, showEmoji });
// showEmoji:false → 世界内只渲染纯色方块,不画 emoji(默认 true)
// 怪物/Boss → 注入 ENEMY_TYPES
ModAPI.registerMob(type, { name, emoji, color, hp, atk, spd,
size, xp, score, detect, atkRange, atkCD, drops,
isBoss, isBigBoss, isFinalBoss });
// 合成配方 → 注入 CRAFT_RECIPES
ModAPI.registerRecipe({ shape:[[3x3 of {id,qty}|null]], result:{...} });
// 物品 / 食物
ModAPI.registerItem({ id, name, emoji });
ModAPI.registerFood({ id, name, emoji, sat });
// 枪械 / 装备
ModAPI.registerGun(gunId, { name, emoji, color, type, tier,
dmg, cd, speed, ammo, pierce? });
ModAPI.registerEquip(eqId, { name, emoji, color, tier, def, maxDur });
// 维度(基础注册)
ModAPI.registerDimension({ id, name, color });
// 自定义指令(玩家输入 /name ... 触发)
ModAPI.registerCommand(name, { desc, run(args, ctx) });
// ctx = { game, cmdFeedback }
// 自定义 UI 面板(自动在菜单栏注入打开按钮)
ModAPI.registerPanel({ id, title, body, autoOpen?, openButton? });
ModAPI.openPanel(id); ModAPI.closePanel(id);
// 区块生成完毕钩子(改写地形/维度)
ModAPI.on('chunk:gen', function(e){ // e={world,cx,cy,chunk}
// e.chunk.tiles[y][x] = tileId
});
// 维度切换钩子
ModAPI.on('dimension:change', function(e){ // e={id,world}
});
// 通用事件总线
ModAPI.on(evt, fn); ModAPI.once(evt, fn); ModAPI.off(evt, fn);
// 维度切换
ModAPI.setDimension(id); ModAPI.getDimensions();
ModAPI.say(text, color?) // 游戏内聊天消息(黄) ModAPI.spawnEnemy(type,x,y) // 生成怪物(坐标缺省围绕玩家) ModAPI.giveItem(item) // 给物品对象(完整结构) ModAPI.giveBlock(tileId,qty)// 给已注册方块物品 ModAPI.teleport(x,y) // 传送玩家(像素坐标) ModAPI.getGame() // 返回游戏对象(player/enemies/world)
例:ModAPI.getGame().player.hp = 100; 直接改血量。
世界生成后这些表被填充(在 chunk:gen/dimension:change 回调里一定已就绪),可直接读写扩展:
ModAPI.TILE // 原版方块枚举 (ModAPI.TILE.GRASS…) ModAPI.TILE_DEF // 方块定义表 ModAPI.ENEMY_TYPES // 怪物类型表 ModAPI.GUN_DEFS // 枪械表 ModAPI.FOOD_DEF // 食物表 ModAPI.EQUIP_TIERS // 装备表 ModAPI.CFG // 配置(CHUNK_SIZE…) ModAPI.World / Player / NPC / MISSILE_DEFS / AMMO_DEFS
下面是一份「尽量覆盖所有可添加功能」的示范,可直接整段复制到右侧编辑器(或保存为 .js 模组)。每个区块都可独立删除。
// ===== 0. 模组登记(.js 必须手写;.mod 会自动登记)=====
ModAPI.registerMod({ name:'示范模组', version:'1.0', author:'你', description:'功能全覆盖示范' });
// ===== 1. 方块(返回 tileId 数字)=====
var crystal = ModAPI.registerBlock({ name:'纯净水晶', emoji:'🔷',
color:'#66aaff', hp:350, light:8, walkable:false, transparent:false, slow:false });
var glow = ModAPI.registerBlock({ name:'辉光水晶矿', emoji:'✨',
color:'#99ccff', hp:220, light:14, walkable:false });
// ===== 2. 怪物 / Boss =====
ModAPI.registerMob('crystal_guard', { name:'水晶守卫', emoji:'👾', color:'#77bfff',
hp:220, atk:18, spd:1.3, size:30, xp:60, score:220, detect:240,
atkRange:36, atkCD:55, drops:'crystal_block', isBoss:false });
ModAPI.registerMob('crystal_lord', { name:'水晶领主', emoji:'💎', color:'#2277ff',
hp:1200, atk:35, spd:0.9, size:46, xp:550, score:1800, detect:320,
atkRange:50, atkCD:75, drops:'glow_crystal', isBoss:true, isBigBoss:true });
// ===== 3. 合成配方(3x3 形状,每格 {id,qty} 或 null)=====
ModAPI.registerRecipe({
shape:[
[{id:'crystal',qty:1}, null, {id:'crystal',qty:1}],
[null, {id:'glow',qty:1}, null],
[{id:'crystal',qty:1}, null, {id:'crystal',qty:1}]
],
result:{ type:'item', id:'crystal_core', qty:1, name:'水晶核心', emoji:'🌟' }
});
// ===== 4. 物品 / 食物 =====
ModAPI.registerItem({ id:'crystal_core', name:'水晶核心', emoji:'🌟' });
ModAPI.registerFood({ id:'crystal_food', name:'水晶果', emoji:'🍇', sat:40 });
// ===== 5. 枪械 / 装备 =====
ModAPI.registerGun('crystal_gun', { name:'水晶枪', emoji:'🔫', color:'#66aaff',
type:'rifle', tier:3, dmg:30, cd:18, speed:14, ammo:30 });
ModAPI.registerEquip('crystal_armor', { name:'水晶甲', emoji:'🛡️', color:'#66aaff',
tier:3, def:25, maxDur:600 });
// ===== 6. 维度 + 群系地形(在 chunk:gen 改写)=====
ModAPI.registerDimension({ id:'crystal_realm', name:'水晶领域', color:'#153880' });
ModAPI.on('chunk:gen', function(e){
if(e.world.dimension !== 'crystal_realm') return; // 只改本维度,别污染主世界
var CS = (ModAPI.CFG && ModAPI.CFG.CHUNK_SIZE) || 16;
for(var y=0;y
照着写基本不会出错,下面是新手最容易踩的坑:
① 所有字符串都要加引号(最最常见!)
// ❌ 错误:中文 / emoji 没加引号 → 直接 SyntaxError,模组无法加载
ModAPI.registerBlock({ name:水晶苔晶, emoji:🌀 });
// ✅ 正确:用单引号或双引号包起来
ModAPI.registerBlock({ name:'水晶苔晶', emoji:'🌀' });
② 接口必须带 ModAPI. 前缀
// ❌ 错误:裸写会被当作未定义变量
registerBlock({ name:'x' });
// ✅ 正确
ModAPI.registerBlock({ name:'x' });
③ 方块/物品用数字 id;原版用 ModAPI.TILE.*
// 自定义方块:用 registerBlock 的「返回值」
var b = ModAPI.registerBlock({ name:'我的块', emoji:'🔷', color:'#3366cc', hp:120 });
e.chunk.tiles[y][x] = b; // b 就是 tileId 数字
// 原版方块:用枚举
e.chunk.tiles[y][x] = ModAPI.TILE.GRASS;
④ 改地形先判断维度,否则污染主世界
ModAPI.on('chunk:gen', function(e){
if(e.world.dimension !== '你的维度id') return; // 务必加这行
...
});
⑤ 同名模组会被去重:第二次用相同 name 调 registerMod 会被忽略,不会重复加载。
⑥ 模组出错不会崩游戏:语法或运行出错时,游戏会弹黄色⚠「模组出错」警告窗(显示模组名与错误),关闭即可继续玩;这不是游戏 bug,按提示改代码重新导入即可。
⚠ 此代码会在游戏内直接执行;语法错误将导致该模组加载失败。建议先在「👁 预览 & 导出」查看生成的完整代码,确认无误再导出。
// 点击其他标签页添加内容后回来查看生成的代码...
mods/ 文件夹 → 开局或点「🔄 扫描」即自动识别,无需登记 manifest.json{name,version,author,description,code}。直接打开 file:// 时请用「📂 导入」手动选择。