Community编程与开发github.com

qad3n/modport

将 Minecraft Java 版模组(任何版本,jar 或源码)移植到 b1.7.3_rewrite 模组加载器,生成一个在客户端和服务端均可运行的 .b173mod 文件,必要时扩展加载器和 SDK。当用户输入 /modport、/port、“移植这个模组”或提供模组 jar 时使用。

modport 是什么?

这个技能旨在将任何版本的 Minecraft Java 版模组移植到 b1.7.3_rewrite 模组加载器上。由于 Java 模组无法直接运行,移植过程本质上是基于反编译模组作为规格说明,使用 Rust 重写为 WASM 来宾程序(使用 b173_api SDK),目标是生成一个单一的 .b173mod 文件,在 b1.7.3 版本的客户端和服务端 `mods/` 目录中同时工作,保持相同的视觉和游戏体验。 技能提供了一套完整的工具集(bash 脚本)来处理从设置、资产提取、模型转换到部署测试的整个流程。它特别强调分步工作流,包括规划(生成 PORT_STATUS.md)、按模块移植、扩展加载器(仅在必要时)和严格测试。对于加载器或 SDK 的扩展,根据用户工作模式(维护者模式或用户模式)有不同处理规则。该技能支持多个平台,包括 Claude Code 和 Cursor,包含大量关于如何处理数据形状(如块变体、物品数据组件、实体数据槽)以及如何安全扩展加载器协议和主机的详细指南。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/qad3n/b1.7.3-modport/tree/HEAD/skills/modport

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

将模组移植到 b1.7.3_rewrite 加载器

Java 模组无法运行。移植是基于反编译的模组作为规格说明,使用 Rust 重写(WASM 来宾程序,b173_api SDK)。 目标:在 b1.7.3 中保持相同的视觉、感觉和游戏玩法,从一个文件在客户端和服务端的 mods/ 目录中工作。修复源码错误,并在视觉和玩法保持不变的情况下自由优化。绝不替换原版屏幕:额外的 UI 是可切换的叠加层。

本文件是整个地图。不要阅读加载器设计或进度文档、指南或整个 SDK 文件来定位。使用工具,然后只打开步骤所需的那个范例文件。

工作区

路径相对于工作区根目录,即包含 b1.7.3_rewrite/、ports/ 和工具包仓库 b1.7.3_modport/ 的文件夹。工具包的 install.sh 将其工具链接到 tools/modport/(下文写作 T/),并将此技能链接到 .claude/skills/modport;从移植文件夹中,T/ 是 ../../tools/modport/。在 b1.7.3_modport/ 中修复或扩展工具,绝不在移植文件夹内。在新机器上,或当工具因缺少依赖而失败时,运行 T/doctor.sh:它会打印修复每个缺口的命令。所有工具都是 bash:在 Windows 上,它们在 Git Bash(Claude Code 在 Windows 上的 Bash 工具)中运行,并自行处理 .exe、py 和路径。通过 T/py.sh 调用 Python 工具,绝不直接使用 python3。

模式

每个会话检查一次:在工作区根目录执行 test -f .modport-maintainer。

  • 维护者模式(标记存在):加载器、SDK 和工具包仓库是此用户的自己的。仅当用户要求时,才按照下面的步骤提交和推送它们。
  • 用户模式(无标记,默认):加载器、SDK 和工具包仓库属于其上游作者。
    • 加载器和 SDK 的扩展保留在本地工作树中。绝不提交到这些仓库,绝不推送到它们的远程仓库,绝不运行 gh pr create、gh issue create 或任何其他针对它们的 gh 写入操作,即使被要求“分享”或“上游”一个更改。告诉用户自行完成。
    • 在 ports/<modid>/LOADER_CHANGES.md 中记录每次加载器或 SDK 的更改:添加了什么、为什么、哪些文件。
    • 告诉用户,需要本地加载器更改的移植只能在其修补后的加载器上运行,而不能在标准加载器上运行。
    • 移植文件夹是用户自己的仓库:在被要求时提交,仅推送到用户设置的远程仓库。
    • 绝不创建标记文件。

工具

工具何时使用输出
T/new_port.sh <modid> <jar> [name]开始移植。写入清单,git init,反编译到 reference/src(Vineflower,首次使用下载并验证),运行清单ports/<modid>/
T/inventory.sh <src>列出模组注册的内容:块、物品和实体及其类、方块实体、模型、渲染器、GUI、世界生成、事件对于大型模组约 15 KB,保存在 reference/inventory.txt 中
T/api.sh在编写针对 SDK 的代码之前。sdk <file>(world, register, screen, behavior, events, terrain, config, services),spec <Struct>,enum <Name>(HostCall, EntityField, ModelOp),templates,events,console,hooks每行一个签名,带有 SDK 行号
T/py.sh extract_assets.py <jar> <modid>一次,从移植文件夹。纹理、声音和语言文件到 assets/<modid>,语言键映射到 tile.<modid>.x.name,item.<modid>.x.name,<modid>.<key>永不提交
T/py.sh convert_models.py --out src/models/generated.rs <Model.java>... [--arg Model.scale=0.5]模型。ModelBase 构造函数(SRG 或 MCP 名称)转换为部件和盒子。将调用包装在移植的 tools/convert_models.sh 中生成的 Rust,绝不要手动编辑
T/test.sh deploy ports/<modid> [--game]每次测试周期。构建,停止测试服务器,单独安装模组,启动服务器。--game 首先重新构建游戏和 cargo-b173(在加载器或 SDK 更改后)。当测试服务器运行时拒绝:另一个会话可能拥有它,询问后再 --force服务器控制台尾部
T/test.sh errors [n]任何失败后首先执行两个日志的 panic、trap 和错误行
T/modtest.sh cmd <console line> / log server 80驱动和检查服务器仅回复行
T/modtest.sh client / shot <png>仅视觉检查。在启动客户端前询问用户:它会在其桌面上打开一个窗口游戏窗口 PNG

控制台(T/modtest.sh cmd loader ...,语法来自 T/api.sh console):gen、map(俯视图 PNG)、slice(垂直切片 PNG)、column(在 tp 前检查:传送至地形内的玩家会窒息)、fill、tp、use、interact、close、entities、summon、slot、tile。使用读取工具读取 PNG。将重复的检查链放入 ports/<modid>/tools/ 中的小脚本,而不是重新输入。

工作流程

  1. 设置。 选择最接近 beta 版本的源码版本(1.7.10 优于 1.12 优于 1.21):其模型、纹理和数据形状几乎一一对应。1.7.10 的 jar 使用 SRG 名称(func_、field_):从使用中理解含义,不要查找映射。运行 new_port.sh,然后运行 extract_assets.py。将模组模型扩展的原版模型类复制到 reference/vanilla/ 以供转换器使用。特定资产的额外内容(来自 3D 渲染器的精灵图)放在移植自己的 tools/ 脚本中。
  2. 规划。 将 reference/inventory.txt 转换为 PORT_STATUS.md 中的待办事项行,按依赖顺序排列:块和物品、合成配方、世界生成和维度、实体、机器和 GUI、结构、Boss、玩家系统、额外槽位、物品行为、声音和粒子、配置。里程碑以部署和控制台检查结束。
  3. 逐个模块移植。 读取模组的类,使用 api.sh 检查 SDK,从范例中复制模式。在 PORT_STATUS.md 中引用源类,而不是在代码注释中。
  4. 仅当 api.sh 显示没有方法时扩展加载器(见下面的检查清单)。
  5. 测试 每个模块后使用 deploy、cmd、errors。在 PORT_STATUS.md 中维护一个错误列表,而不是在一个问题上循环;在最后修复列表。
  6. 完成。 更新 PORT_STATUS.md。在移植文件夹中运行 cargo +nightly fmt,在 b1.7.3_rewrite 中运行 cargo clippy。仅在被要求时提交:移植文件夹包含 Rust 源代码、工具和清单,绝不包含资产、reference/ 或 AI 文件。ports/ 要么是每个移植一个 git 仓库,要么是一个包含每个模组一个文件夹的单仓;new_port.sh 会检测是哪种情况。在用户模式下,在最终报告中列出移植所需的本地加载器更改,来自 LOADER_CHANGES.md。

范例

SDK 示例,始终存在:b1.7.3_rewrite/vendor/b1.7.3-modding-sdk/examples/,包含 testmod(所有 API 模块在一个文件中)、ruby(仅数据内容)、energy、energy_api、machines(模组间服务)。

一个完成的移植,当工作区中有时,是更快的地图。Aether 移植(ports/aether/src):

需求文件
块表、模板、行为blocks.rs(每种类型一个 const 行数组)
物品、工具、盔甲、食物、配方items.rs、tools.rs、gear.rs、recipes.rs
配置选项config.rs(移植每个生成率骰子,缺失会导致世界被淹没)
实体注册和辅助函数entities/mod.rs
被动生物和坐骑、敌对生物、飞行生物、弹射物entities/phyg.rs + mount.rs、cockatrice.rs、zephyr.rs、projectile.rs
客户端可见实体状态entities/swet.rs、entities/moa.rs(setSynced/synced)
模型和动画models/mod.rs(part、cuboid、Program;复制到新移植中)
Boss、Boss 血条 HUD、对话屏幕entities/bosses/mod.rs、valkyrie_queen.rs(transparent() 屏幕加服务端绑定通道)
带 GUI 和方块实体数据的机器machines.rs(ScreenBuilder、#[tile_behavior])
额外装备槽位、渲染层accessories.rs(screens().overlay("GuiInventory", ..)、playerLayer)
本地玩家移动player.rs(客户端在 TickPost 中,服务端状态在按实体 ID 索引的 thread_local 映射中)
维度、地形、装饰world/mod.rs、world/terrain.rs、world/decorate.rs
结构world/dungeons/mod.rs、writer.rs(terrain::structure::candidates,裁剪到 StructureBox::populated,将 256 高度压缩为 128)
传送门和旅行portal.rs

始终适用的形状:渲染器 GL 调用变为 Program 操作(push、translate、rotate、scale、texture、blend、lighting)放在实体的 pose 中;onLivingUpdate/updateEntityActionState 转到 onAi(替换模板 AI)或 onTick;terrain::Random 和噪声移植保持种子相同;在更改世界前检查 isAuthority()(单玩家将数据包回传,两端代码相同);验证每个服务端绑定负载;通过 translate("<modid>.gui.…") 聊天;声音为 <modid>.<path.with.dots>;纹理为 <modid>:<path>。

数据形状(加载器 API 1.1,ABI 3)。身份始终通过名称,而不是数字 ID:

  • 块变体和朝向。 源元数据或方块状态变为命名状态:ctx.blocks().states(name, BlockStatesSpec) 或 data/<modid>/states/<block>.toml。

    • 按源元数据顺序列出每个属性的值,以便 ctx.meta() 代码继续工作。
    • 拥有超过 16 个状态的块会从加载器获得额外的隐藏 ID。仅通过 world.blockState/setBlockState 或 ctx.state()/setState() 读写此类块。
    • 每个状态的纹理放在 variants 中。
  • 每堆物品数据。 物品 NBT 和 Capability 变为数据组件:stackComponent/setStackComponent 配合 StackRef。

    • 模组仅写入 <modid>:* 组件。
    • 具有不同组件的堆栈永不合并。
    • 伤害仍然是耐久度。使用每个变体一个物品,而不是伤害子类型。
  • 模组不拥有的东西上的数据。 实体、玩家、方块实体、区块和世界的 NBT 或 Capability 变为每个模组的槽位:

    • 实体:entity.setData 或 setSynced
    • 玩家:player.setData(key, ..)
    • 方块实体:world.setTileAttachment
    • 区块:world.setChunkAttachment
    • 世界:setWorldData

    每个槽位由模组 ID 键控,因此两个模组永不冲突。

  • 对原版或其他模组内容的编辑。 属性编辑(硬度、亮度、可燃性、工具)变为 ctx.blocks().modify(BlockModifySpec) 或 data/<modid>/modify/blocks/*.toml。生成列表编辑变为 modifySpawns 或 modify/spawns/*.toml。针对某种工具类别的挖掘速度来自 minecraft:mineable/<pickaxe|axe|shovel> 标签。冲突的编辑在 Mod 加载器屏幕中报告。绝不为了更改属性而替换整个原版块。

  • 世界生成和命令。

    • 每个世界生成功能唯一命名。名称为其随机数播种,因此其他模组永不移动它。
    • 命令响应 /<modid>:<name>。短 /<name> 转到第一个注册它的模组。

扩展加载器

仅限通用功能,绝不是一个模组的 hack。以下路径在 b1.7.3_rewrite/ 内。接触点,按顺序:

  1. 协议:在 vendor/b1.7.3-modding-sdk/mod_protocol/src/abi.rs 中的 HostCall、GuestCall、GuestReply 或 EntityField 末尾附加变体;在 spec.rs 中作为 Option 或 Default 类型添加新的规范字段(规范结构体是 #[serde(default)],因此旧模组仍然可以加载)。已发布的合约永远不会更改:更改后的合约会获得新版本。
  2. 主机:在 crates/modloader/src/host/world.rs(运行时调用)或 host/register.rs(注册阶段)中的 match 分支;更大的系统放在自己的 crates/modloader/src/<system>.rs 或 extensions.rs 中。新模板是 crates/modloader/src/entities.rs(ENTITY_TEMPLATES)或 content/templates.rs(BLOCK_TEMPLATES)中的行。
  3. SDK 包装器放在 b173_api/src/{world,register,screen}.rs 中其同级旁边,如果模组到处使用则放在 prelude 中。
  4. 客户端在 crates/client/src/modded/ 中。原版代码通过带 // rewrite: 注释的单行钩子调用新行为,该钩子在 crates/modloader/hooks.toml 中列出,并带有版本号。
  5. 开发者控制台工具在 crates/modloader/src/devtools.rs 中(添加到 USAGE)。
  6. cargo build 和 cargo clippy,然后 T/test.sh deploy ports/<modid> --game。记录工作区保存加载器说明的添加位置。维护者模式:SDK 更改在 SDK 子模块中提交,然后仅在用户要求时在 rewrite 中升级。用户模式:那里不提交任何内容,更改进入 LOADER_CHANGES.md。

示例链,World::lightning:HostCall::Lightning (abi.rs) 到其在 host/world.rs 中的分支,再到 b173_api/src/world.rs 中的包装器。

已知陷阱

  • HostCall、HostReply 和规范结构体是 postcard 编码的。绝不要向现有结构体添加字段:ABI 2 的来宾程序会停止解码。新数据需要新的变体或新的结构体。

  • T/modtest.sh 驱动一个共享的测试服务器和客户端(b1.7.3_rewrite/target/modtest,服务器在其 server/ 中)。绝不要在没有询问用户的情况下停止、重置或接管另一个已启动的会话。

  • cargo b173 build 已经运行了 wasm 构建;没有单独的 cargo build 步骤。

  • 加载器或 SDK 更改而不使用 deploy --game:服务器仍会运行旧的二进制文件,没有新的主机调用。

  • 测试客户端的窗口会失去焦点并打开暂停菜单;它是测试平台,而不是移植。

相关技能