mcpField
M
minecraft-multiloader

minecraft-multiloader

github.com/jahrome907开发192147 次安装2 周前更新
代码仓库

关于 minecraft-multiloader

minecraft-multiloader 为 Minecraft 模组开发者提供基于 Architectury 的多加载器开发指南,帮助维护一套代码并构建 Fabric 与 NeoForge JAR。

主要功能

  1. 01common、fabric、neoforge 子项目布局
  2. 02通过 Architectury API 抽象平台差异
  3. 03使用 @ExpectPlatform 编写平台实现
  4. 04静态检查版本与配置
  5. 05构建 Fabric 和 NeoForge JAR

适用场景

  1. 01为 Fabric 和 NeoForge 共用模组代码
  2. 02划分通用逻辑与加载器专属实现
  3. 03检查 Gradle 属性中的版本设置
  4. 04构建并检查两个平台的模组产物

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jahrome907/minecraft-agent-skills --skill minecraft-multiloader

安装后在 Claude Code 中输入/minecraft-multiloader确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
architectury-reference.md
legacy-1.21.11-template.md
scripts/
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-loomGradle 插件——扩展 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 在运行时会抛出 AssertionErrorfabric/ 和 neoforge/ 都必须有匹配的同包 *Impl 类
在 fabric/ 和 neoforge/ 中重复放置资源将资源保存在 common/src/main/resources/assets/ 中
common Mixin 导入加载器 API,或以某个加载器为目标将其放在对应的平台子项目中;如果两个生成的平台配置都包含加载器无关的 Mixin,则可以将其放在 common 中
在 mod 初始化线程上访问世界/注册表使用 mod bus 事件进行设置;切勿在初始化时访问世界

参考资料

评论

支持 Markdown