关于 minecraft-multiloader
minecraft-multiloader 为 Minecraft 模组开发者提供基于 Architectury 的多加载器开发指南,帮助维护一套代码并构建 Fabric 与 NeoForge JAR。
主要功能
- 01common、fabric、neoforge 子项目布局
- 02通过 Architectury API 抽象平台差异
- 03使用 @ExpectPlatform 编写平台实现
- 04静态检查版本与配置
- 05构建 Fabric 和 NeoForge JAR
适用场景
- 01为 Fabric 和 NeoForge 共用模组代码
- 02划分通用逻辑与加载器专属实现
- 03检查 Gradle 属性中的版本设置
- 04构建并检查两个平台的模组产物
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jahrome907/ minecraft-agent-skills --skill minecraft-multiloader安装后在 Claude Code 中输入/minecraft-multiloader确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/architectury-reference.mdlegacy-1.21.11-template.mdscripts/check-version-sanity.sh详细介绍
Minecraft 多加载器技能(Architectury)
什么是 Architectury?
Architectury 是一个框架,
可让你编写一套模组代码,并将其编译为 NeoForge 和 Fabric 两种 JAR。
common 子项目提供共享 API;平台子项目则通过 @ExpectPlatform 抽象层实现
特定平台的行为。
适用范围
Use when:同一套代码库必须同时构建并发布 NeoForge 和 Fabric 工件。Do not use when:项目仅面向一种加载器(使用minecraft-modding开发 NeoForge 或 Fabric,而非同时支持两者)。Do not use when:任务是开发 Paper/Bukkit 插件(使用minecraft-plugin-dev)。
| 组件 | 用途 |
|---|---|
architectury-loom | Gradle 插件——扩展 Fabric Loom,支持多加载器 |
architectury-api | 运行时库——提供适用于两个平台的抽象 |
@ExpectPlatform | 标记具有特定平台实现的方法的注解 |
common/ | 共享代码(不使用特定加载器的 API) |
fabric/ | Fabric 特定代码和入口点 |
neoforge/ | NeoForge 特定代码和入口点 |
版本(Minecraft 1.21.11)
# gradle.properties property names used by this skill's static helper.
# Get every tool version from the exact generated or known-working project.
mod_version=1.0.0
minecraft_version=1.21.11
enabled_platforms=fabric,neoforge
architectury_version=<project pin>
fabric_loader_version=<project pin>
fabric_api_version=<project pin ending in +1.21.11>
neoforge_version=<project pin in the 21.11.x family>
loom_version=<project pin>
请从同一条已生成或已知可正常工作的项目版本线上固定 architectury_version、Architectury 插件版本和 loom_version。本技能特意不提供可直接复制的依赖版本矩阵:其静态辅助工具无法判断特定版本组合是否兼容。
对于 Minecraft 26.2 / Java 25,仅当官方 Architectury 模板生成器 提供精确的目标版本选项时,才使用它。生成包含 Fabric 和 NeoForge 的 多平台 项目,然后将生成的 Gradle 布局和版本固定值作为一套配置保留。如果生成器未提供目标版本,请从该精确版本线上已能正常工作的项目开始,并检查其已解析的构建配置;不要把 1.21.11 模板重新标注为 26.2。已发布的模板下载内容不能替代精确匹配当前版本的脚手架。
不要只对保留的示例机械地修改 minecraft_version:
26.2 未混淆,其 Loom/重新映射配置与 1.21.11 不同。
随附参考资料和辅助工具
- 版本对齐参考:
references/architectury-reference.md - 基本检查器:
./scripts/check-version-sanity.sh --root <project>
编辑 gradle.properties 后运行基本检查器。它是静态的语法和版本系列预检工具:可检查缺失的键、快照版本固定值、缺少 fabric / neoforge 平台,以及明显的版本系列偏差。它不会解析依赖、验证加载器兼容性,也不能替代项目的 Fabric 和 NeoForge 构建及冒烟测试。
根项目布局
my-mod/
├── build.gradle ← root build (shared config)
├── settings.gradle
├── gradle.properties
├── common/
│ ├── build.gradle
│ └── src/main/java/com/example/mymod/
│ ├── MyMod.java ← shared init
│ ├── registry/
│ │ └── ModItems.java ← shared registry declarations
│ └── platform/
│ └── PlatformHelper.java ← @ExpectPlatform methods
├── fabric/
│ ├── build.gradle
│ └── src/main/
│ ├── java/com/example/mymod/fabric/
│ │ ├── MyModFabric.java ← Fabric entrypoint
│ ├── java/com/example/mymod/platform/
│ │ └── PlatformHelperImpl.java ← Fabric @ExpectPlatform implementation
│ └── resources/
│ ├── fabric.mod.json
│ └── assets/...
└── neoforge/
├── build.gradle
└── src/main/
├── java/com/example/mymod/neoforge/
│ ├── MyModNeoForge.java ← NeoForge @Mod entry
├── java/com/example/mymod/platform/
│ └── PlatformHelperImpl.java ← NeoForge @ExpectPlatform implementation
└── resources/
├── META-INF/neoforge.mods.toml
└── assets/...
旧版构建模板
旧的固定 Gradle 脚本基于 1.21.11 快照,因此此处有意不将其作为当前脚手架提供。对于任一受支持的版本,在修改生成的构建文件之前,请阅读
references/legacy-1.21.11-template.md
或 references/architectury-reference.md。
这些文件保留了版本锚点和源集边界,避免鼓励将不完整的构建脚本复制到其他 Minecraft 版本线上。
共享的 Common 代码
common/.../MyMod.java
package com.example.mymod;
import dev.architectury.registry.registries.DeferredRegister;
import dev.architectury.registry.registries.RegistrySupplier;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.Item;
public class MyMod {
public static final String MOD_ID = "mymod";
// Architectury's DeferredRegister — works on both platforms
public static final DeferredRegister<Item> ITEMS =
DeferredRegister.create(MOD_ID, Registries.ITEM);
public static final RegistrySupplier<Item> MY_ITEM =
ITEMS.register("my_item", () -> new Item(new Item.Properties().setId(
ResourceKey.create(Registries.ITEM,
Identifier.fromNamespaceAndPath(MOD_ID, "my_item"))
)));
public static void init() {
ITEMS.register(); // registers with both platforms
}
}
@ExpectPlatform — 特定平台的方法
在 common/ 中定义契约:
package com.example.mymod.platform;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.world.level.material.Fluid;
public class PlatformHelper {
@ExpectPlatform
public static boolean isModLoaded(String modId) {
// This body is replaced at compile time by the platform implementation
throw new AssertionError("ExpectPlatform implementation not found");
}
@ExpectPlatform
public static boolean isClient() {
throw new AssertionError();
}
}
每个特定平台的实现都应与 common 的 @ExpectPlatform 类位于同一个 Java 包中。只有源集会在 common/、fabric/ 和 neoforge/ 之间变化。
在 fabric/.../platform/PlatformHelperImpl.java 中实现:
package com.example.mymod.platform;
import net.fabricmc.loader.api.FabricLoader;
// Class name must match: <common class name>Impl
public class PlatformHelperImpl {
public static boolean isModLoaded(String modId) {
return FabricLoader.getInstance().isModLoaded(modId);
}
public static boolean isClient() {
return FabricLoader.getInstance().getEnvironmentType() ==
net.fabricmc.api.EnvType.CLIENT;
}
}
在 neoforge/.../platform/PlatformHelperImpl.java 中实现:
package com.example.mymod.platform;
import net.neoforged.fml.ModList;
import net.neoforged.fml.loading.FMLEnvironment;
public class PlatformHelperImpl {
public static boolean isModLoaded(String modId) {
return ModList.get().isLoaded(modId);
}
public static boolean isClient() {
return FMLEnvironment.dist.isClient();
}
}
Fabric 入口点
fabric/.../MyModFabric.java
package com.example.mymod.fabric;
import com.example.mymod.MyMod;
import net.fabricmc.api.ModInitializer;
public class MyModFabric implements ModInitializer {
@Override
public void onInitialize() {
MyMod.init();
}
}
fabric/.../resources/fabric.mod.json
此保留的 1.21.11 元数据示例遵循 上游 Architectury 1.21.11 分支中的最低依赖要求。 如果生成项目使用了更严格的依赖范围,请保留原范围。
{
"schemaVersion": 1,
"id": "mymod",
"version": "${version}",
"name": "My Mod",
"description": "A multiloader example mod",
"license": "MIT",
"environment": "*",
"entrypoints": {
"main": ["com.example.mymod.fabric.MyModFabric"]
},
"depends": {
"fabricloader": ">=0.18.2",
"fabric-api": ">=0.139.4+1.21.11",
"architectury": ">=19.0",
"minecraft": "~1.21.11"
}
}
NeoForge 入口点
neoforge/.../MyModNeoForge.java
package com.example.mymod.neoforge;
import com.example.mymod.MyMod;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.common.Mod;
@Mod(MyMod.MOD_ID)
public class MyModNeoForge {
public MyModNeoForge(IEventBus modEventBus) {
MyMod.init();
}
}
neoforge/.../resources/META-INF/neoforge.mods.toml
modLoader = "javafml"
loaderVersion = "[1,)"
license = "MIT"
[[mods]]
modId = "mymod"
version = "${file.jarVersion}"
displayName = "My Mod"
description = "A multiloader example mod"
[[dependencies.mymod]]
modId = "neoforge"
type = "required"
versionRange = "[21.11,)"
ordering = "NONE"
side = "BOTH"
[[dependencies.mymod]]
modId = "minecraft"
type = "required"
versionRange = "[1.21.11,1.22)"
ordering = "NONE"
side = "BOTH"
构建命令
# Build both JARs simultaneously
./gradlew build
# Inspect the project's actual outputs. Generated templates choose their own
# archive base name and version convention:
find fabric/build/libs neoforge/build/libs -maxdepth 1 -type f -name '*.jar' \
! -name '*-sources.jar' ! -name '*-dev.jar' ! -name '*-javadoc.jar'
# Run in dev environment
./gradlew :fabric:runClient
./gradlew :neoforge:runClient
./gradlew :neoforge:runServer
# Datagen (if applicable)
./gradlew :neoforge:runData
常见问题
| 问题 | 解决方案 |
|---|---|
在 common/ 中使用 net.neoforged.* / net.fabricmc.* | 在 common 中仅使用原版 MC 和 Architectury API |
在 common 中直接访问 DeferredRegister 字段(NeoForge 风格) | 使用 Architectury 的 DeferredRegister |
| 创建 26.2 物品时未提供注册表键 | 创建其 ResourceKey<Item>,并在 new Item 之前调用 Item.Properties#setId |
忘记 @ExpectPlatform 在运行时会抛出 AssertionError | fabric/ 和 neoforge/ 都必须有匹配的同包 *Impl 类 |
| 在 fabric/ 和 neoforge/ 中重复放置资源 | 将资源保存在 common/src/main/resources/assets/ 中 |
| common Mixin 导入加载器 API,或以某个加载器为目标 | 将其放在对应的平台子项目中;如果两个生成的平台配置都包含加载器无关的 Mixin,则可以将其放在 common 中 |
| 在 mod 初始化线程上访问世界/注册表 | 使用 mod bus 事件进行设置;切勿在初始化时访问世界 |
参考资料
- Architectury API GitHub:https://github.com/architectury/architectury-api
- Architectury API 26.2 源码分支:https://github.com/architectury/architectury-api/tree/26.2
- Architectury API 1.21.11 源码分支:https://github.com/architectury/architectury-api/tree/1.21.11
- Architectury Loom:https://github.com/architectury/architectury-loom
- Architectury 模板:https://github.com/architectury/architectury-templates
- Architectury 模板生成器:https://generate.architectury.dev/
- Architectury 文档:https://docs.architectury.dev/