Fabric Java · Beginner course

用 Java 开发你的第一个 Fabric 模组

从零搭好 JDK、IntelliJ、Gradle 与 Fabric 开发环境,真正读懂一个模组怎样被加载,再亲手做出 /hello_fabric 命令。运行以后,游戏会回应你,并送给玩家一颗绿宝石。

Minecraft Java 1.21.1 JDK 21 IntelliJ IDEA 约 90–120 分钟

Mission 01 · 学完能做什么

不是“照着敲完”,而是建立一张能继续成长的开发地图。

很多初学教程一上来就复制几十行注册代码,学生虽然看见游戏里多了东西,却不知道 JDK、Gradle、Fabric Loader 和 Fabric API 各自负责什么。一旦版本不同、包名改了或依赖下载失败,就完全不知道从哪里检查。本课先建立模型,再完成一个小而完整的作品。你会知道每个文件为何存在、每条命令在哪一层运行,以及错误信息应该从哪一行开始读。

01 · ENVIRONMENT

独立搭建环境

确认 Java 版本,设置 IntelliJ 的 Project SDK 和 Gradle JVM,并判断“系统 Java”与“项目 Java”是否一致。

02 · ARCHITECTURE

说清四个组件

区分 JDK、Gradle/Loom、Fabric Loader 与 Fabric API,理解它们怎样把普通 Java 代码送进游戏。

03 · FIRST FEATURE

做出可见功能

注册 /hello_fabric 命令,让服务端给玩家发送消息并添加一颗绿宝石,而不是只输出一句日志。

04 · DELIVERY

导出可安装 JAR

用 Gradle 构建模组,找到正确 JAR,安装到普通 Fabric 客户端,并理解版本必须成套匹配。

完成标准:你能在 IntelliJ 中启动独立开发客户端,进入世界后输入 /hello_fabric,看到中文消息、获得绿宝石,并能在 build/libs 找到构建产物。

Version strategy · 先把版本固定住

模组开发最怕的不是代码难,而是把不同年代的教程拼在一起。

Fabric、Minecraft、Java、Loader、Loom 和 Fabric API 都有自己的版本。网络上 1.20.1、1.21.1、1.21.11 与 26.x 的类名和资源格式可能不同。看见“最新版本”就全部升级,往往会让一份本来正确的示例无法编译。为了让学生稳定复现,本课锁定 Minecraft Java 1.21.1 与 JDK 21,并使用 Fabric 官方示例工程当前为 1.21.1 分支给出的依赖组合。

组件本课版本负责什么检查位置
Minecraft Java1.21.1目标游戏版本gradle.properties
JDK21编译和运行 Javajava -version
Fabric Loader0.19.3发现并加载模组loader_version
Fabric API0.116.15+1.21.1事件、命令等开发接口fabric_api_version
Fabric Loom由模板给出Gradle 开发、映射、运行与打包插件loom_version
IntelliJ IDEACommunity 2025.x编辑、导航、Gradle 与调试Help → About
关于最新版:Fabric 官方文档当前主线已经面向 Minecraft 26.x,并要求 JDK 25。本课不把主线文档里的代码生搬到 1.21.1。以后升级时,最可靠的做法是重新用官方 Template Mod Generator 选择目标游戏版本,再把自己的业务代码逐步迁移。

开始之前请准备

  • 一台可以运行 Minecraft Java Edition 的 Windows 电脑,以及你有权使用的正版游戏账号。
  • 至少 8 GB 内存;第一次 Gradle 同步需要联网下载依赖,速度取决于网络。
  • JDK 21。注意 JRE 只能“运行”,JDK 才包含 javac 等开发工具。
  • IntelliJ IDEA Community Edition。它足够完成 Fabric Java 开发,不需要购买 Ultimate。
  • 一个纯英文、无空格、非 OneDrive 的工程路径,例如 C:\Projects\teacherma-fabric-intro。

Mental model · Fabric 到底是什么

它不是一个“做模组按钮”,而是一条可组合的 Java 工具链。

Fabric Loader 是加载器:启动游戏时读取每个模组的 fabric.mod.json,检查 ID、依赖和入口类,再调用你的代码。Fabric API 是常用开发接口集合:提供命令注册、事件、物品组、网络通信等更稳定的接入点。Fabric Loom 是 Gradle 插件:帮你下载游戏与映射、生成运行配置、启动开发客户端、重映射并构建 JAR。IntelliJ IDEA 则是你写代码和调试的工作台。

Fabric 开发工具链:JDK、IntelliJ、Gradle Loom、Fabric Loader 与 Fabric API 共同把 Java 代码运行进游戏
工具链不是一堆互相替代的软件:每一层都有独立职责。知道错误属于哪一层,排错就会快很多。

模组不是修改原版 JAR

现代开发不会直接把文件塞进 Minecraft 的原始 JAR。你的模组是独立产物,由 Loader 在启动阶段发现和加载,升级、移除和定位冲突都更清楚。

注册是“把对象交给游戏”

写出一个 Java 对象还不代表游戏认识它。物品、方块、实体、命令等都需要在正确阶段注册,游戏才能通过唯一 ID 找到它们。

客户端与服务端是两套职责

渲染、按键和画面属于客户端;世界规则、物品发放和实体状态应由逻辑服务端决定。即使单人游戏,内部也有客户端与集成服务器。

Gradle 是可重复构建说明书

它记录依赖和任务,让老师与学生在不同电脑上执行同样的 runClient 和 build,而不是手工复制一堆不明来源的 JAR。

Setup · 安装与创建工程

先验证工具,再生成模板;不要在空文件夹里凭记忆手写 Gradle 配置。

1

确认 JDK 21,而不是只确认“装过 Java”

打开 PowerShell,分别运行下面两条命令。第一条检查运行环境,第二条检查编译器。两者都应该显示 21。如果 javac 不存在,通常说明只装了 JRE,或系统 PATH 没有指向 JDK。

PowerShell
java -version
javac -version
2

让 IntelliJ 的 Project SDK 与 Gradle JVM 都使用 JDK 21

进入 File → Project Structure → Project,把 SDK 设为 21;再进入 Settings → Build, Execution, Deployment → Build Tools → Gradle,把 Gradle JVM 也设为同一个 JDK 21。只改其中一处,仍可能出现“编辑器看起来正常,但构建失败”的情况。

IntelliJ IDEA Project Structure 对话框,Project SDK 已选择 JDK 21,Language level 也是 21
第一处:File → Project Structure → Project。SDK 显示 21,Language level 同样保持 21。
IntelliJ IDEA Gradle 设置页面,Gradle JVM 已选择 Project SDK 21
第二处:Settings → Build, Execution, Deployment → Build Tools → Gradle。页面底部的 Gradle JVM 显示 Project SDK 21。
3

从 Fabric Template Mod Generator 生成工程

打开官方生成器,填写:Mod Name 为 TeacherMa Fabric Intro,Mod ID 为 teacherma_fabric_intro,Package Name 为 dev.teacherma.fabricintro,Minecraft Version 选择 1.21.1,语言保持 Java。本课建议保留“拆分 client 与 main 源集”,它能更早发现把客户端类写到服务端代码里的错误。

4

解压到简单路径,并在 IntelliJ 中打开“工程根目录”

推荐路径是 C:\Projects\teacherma-fabric-intro。选择 File → Open 后,应打开包含 build.gradle、gradlew.bat 和 src 的那一层文件夹,不要只打开 src。看到 Gradle 构建脚本提示时选择导入,并等待索引和依赖下载结束。

IntelliJ IDEA 已打开 teacherma-fabric-intro 工程根目录,左侧同时可见 build.gradle、gradlew.bat、src 和 JDK 21
正确打开后的样子:窗口左侧顶层同时看得到 src、build.gradle、gradlew.bat 和 settings.gradle;External Libraries 中显示 JDK 21。
5

用课程 Starter 工程快速对照

如果你想先跑通再逐项比较,可以下载本课已经验证过的工程。它保留官方 Gradle Wrapper 和版本组合,并加入最终的命令代码。把它放在独立文件夹中打开,不要覆盖你自己的练习工程。

TeacherMa Fabric Intro Starter

包含完整源码、Gradle Wrapper、版本配置和中文 README。下载接口受课程权限保护。

Project map · 看懂工程结构

能说出这些文件的职责,才算真正“打开了项目”。

IntelliJ 中 Fabric 工程的文件树、入口类、fabric.mod.json 与 Gradle 任务示意图
左边是项目结构,右边是入口类。初学阶段最常修改的是 Java 入口、fabric.mod.json 与 gradle.properties。
项目目录
teacherma-fabric-intro/
├─ gradle/                         # Gradle Wrapper 运行文件
├─ src/
│  ├─ main/
│  │  ├─ java/
│  │  │  └─ dev/teacherma/fabricintro/
│  │  │     └─ FabricIntroMod.java # 通用/服务端入口逻辑
│  │  └─ resources/
│  │     └─ fabric.mod.json         # 模组说明书
│  └─ client/                       # 仅客户端代码与资源
├─ build.gradle                     # 插件、依赖与构建规则
├─ gradle.properties                # Minecraft/Fabric 版本
├─ settings.gradle                  # 工程名称与插件仓库
└─ gradlew.bat                      # Windows 下执行 Gradle

fabric.mod.json:Loader 先读的模组说明书

这里的 id 是整个模组的命名空间,必须使用小写字母、数字和下划线等安全字符;它也会出现在物品 ID、资源路径和日志中。entrypoints.main 必须与 Java 类的完整包名完全一致,任何一个字母不一致都会导致入口类找不到。depends 则声明最低 Loader 版本、目标 Minecraft、Java 和 Fabric API。

src/main/resources/fabric.mod.json(核心片段)
{
  "schemaVersion": 1,
  "id": "teacherma_fabric_intro",
  "name": "TeacherMa Fabric Intro",
  "environment": "*",
  "entrypoints": {
    "main": ["dev.teacherma.fabricintro.FabricIntroMod"]
  },
  "depends": {
    "fabricloader": ">=0.19.3",
    "minecraft": "~1.21.1",
    "java": ">=21",
    "fabric-api": "*"
  }
}

gradle.properties:版本要成套出现

版本不是越新越好,而是要彼此兼容。Minecraft 版本决定你面对哪一套游戏代码;Loader 负责加载;Fabric API 必须带有适配目标游戏的后缀。Loom 版本由同一模板生成器给出。升级时不要只把 minecraft_version 改成新数字,然后期待所有依赖自动兼容。

Code · 编写第一个可见功能

注册一个命令,让 Java 代码在服务端真正改变玩家状态。

我们选择命令作为第一项功能,因为它同时展示入口生命周期、Fabric API 事件、命令树、执行上下文、服务端玩家对象和游戏物品对象,又不需要先处理贴图、模型与语言文件。输入 /hello_fabric 后,命令在逻辑服务端执行,向当前玩家物品栏加入一颗绿宝石,并发送一条成功消息。

src/main/java/dev/teacherma/fabricintro/FabricIntroMod.java
package dev.teacherma.fabricintro;

import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FabricIntroMod implements ModInitializer {
    public static final String MOD_ID = "teacherma_fabric_intro";
    public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);

    @Override
    public void onInitialize() {
        CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) ->
                dispatcher.register(Commands.literal("hello_fabric")
                        .executes(context -> {
                            var player = context.getSource().getPlayerOrException();
                            player.addItem(new ItemStack(Items.EMERALD));
                            context.getSource().sendSuccess(
                                    () -> Component.literal("Hello Fabric! Java 已经改变了游戏世界。"),
                                    false
                            );
                            return 1;
                        }))
        );

        LOGGER.info("TeacherMa Fabric Intro loaded successfully.");
    }
}

1. implements ModInitializer

这个接口说明该类是通用入口。Loader 准备好模组初始化阶段后,会调用 onInitialize()。这里适合注册命令、物品、方块和事件。

2. 注册回调,而不是立即执行

CommandRegistrationCallback.EVENT.register 的意思是“命令系统准备注册时,请调用这段逻辑”。页面加载时不会立刻给玩家绿宝石。

3. context 提供执行现场

命令可能由玩家、服务器控制台或命令方块执行。getPlayerOrException() 明确要求这次执行者必须是玩家,随后拿到服务端玩家对象。

4. 返回值 1 表示成功

Minecraft 命令系统使用整数结果表示执行状态。这里返回 1,便于命令方块、函数和后续自动化判断该命令已经成功完成。

映射名称提醒:本课 Starter 使用当前 Fabric 官方 1.21.1 示例分支采用的 Mojang 官方映射,因此你会看到 net.minecraft.commands.Commands 和 Component。旧教程使用 Yarn 映射时可能写成 CommandManager 和 Text。概念相同,但类名不能混用。
从 runClient、fabric.mod.json、onInitialize、注册命令到玩家执行的 Fabric 模组生命周期
从启动到执行的完整链路。遇到问题时,沿这五个阶段逐项检查,比随机改代码有效。

Run & verify · 运行与验收

第一次启动慢是正常的;“能进游戏”之后还要做四项验证。

在 IntelliJ 右侧打开 Gradle 工具窗口,找到 Fabric 相关运行任务并执行 runClient。也可以在工程根目录打开 PowerShell,使用 Wrapper 启动。Wrapper 会确保项目使用规定的 Gradle 版本,不要求学生全局安装 Gradle。

IntelliJ IDEA 右侧 Gradle 工具窗口已展开 Tasks 和 fabric 分组,其中可以看到 runClient 任务
右侧 Gradle 工具窗口中依次展开 teacherma-fabric-intro → Tasks → fabric,双击 runClient。第一次启动需要下载并准备游戏资源,等待控制台完成即可。
Windows · 工程根目录
./gradlew.bat runClient

检查 1:日志

控制台中搜索 TeacherMa Fabric Intro loaded successfully。出现它说明 Loader 找到了入口并执行了初始化。

检查 2:Mods 列表

开发客户端启动后,确认模组名称与版本存在。若完全找不到,优先检查 fabric.mod.json 的 ID 与 entrypoint。

检查 3:命令建议

进入世界,在聊天框输入 /hello。自动补全应出现 /hello_fabric,这说明命令已经进入调度树。

检查 4:游戏结果

执行命令,看到中文消息,并确认物品栏增加一颗绿宝石。多执行几次,应该每次都增加一颗。

检查 5:只改一处

把绿宝石改成 Items.DIAMOND,重新启动并验证。一次只改一个变量,能建立代码与结果的对应关系。

检查 6:读日志首错

如果失败,从日志中第一条包含 ERROR 或 Caused by 的位置开始,不要只截最后一屏重复堆栈。

开发客户端与日常游戏分开:runClient 使用工程下的开发运行目录,不会自动把模组安装到你平时启动器的 .minecraft。这样测试更安全,也不会污染常用世界。

Debug clinic · 常见错误

先判断错误发生在哪一层,再决定该改设置、依赖还是 Java。

错误:Unsupported class file major version / invalid source release

原因:Gradle JVM、Project SDK 或系统 Java 不是项目要求的 JDK 21。处理:重新运行 java -version 和 javac -version,再检查 IntelliJ 的 Project SDK 与 Gradle JVM。改完后重新加载 Gradle 项目。

错误:Could not resolve / Read timed out / 下载依赖失败

原因:第一次构建需要访问 Fabric Maven、Maven Central 与游戏依赖服务器,网络中断或代理设置可能导致失败。处理:先确认浏览器能访问 Fabric 官网;不要反复删除源码。网络恢复后,在 Gradle 工具窗口重新加载,或执行 ./gradlew.bat --refresh-dependencies build。

错误:Could not find or load main class / entrypoint 找不到

原因:fabric.mod.json 中的完整类名与 Java 文件顶部的 package 不一致。处理:核对 dev.teacherma.fabricintro.FabricIntroMod 的每一段,并确认文件位于对应目录。包名使用全小写,类名保持大小写。

错误:Mod resolution encountered an incompatible mod set

原因:Minecraft、Loader、Fabric API 或 Java 版本不满足 depends。处理:阅读错误中列出的“requires”与当前版本,不要随便删除依赖声明。回到生成器为同一个 Minecraft 版本重新生成,通常比猜版本更可靠。

可以进游戏,但没有 /hello_fabric

先在日志里找入口成功信息。如果没有,检查 fabric.mod.json;如果有,确认代码保存且 Gradle 重新编译。还要确认你启动的是这个工程的 runClient,不是桌面上的普通 Minecraft Launcher。

代码中的类名与网上教程不同

这通常不是“Fabric 坏了”,而是映射体系或游戏版本不同。旧 Yarn 教程和当前 Mojang 官方映射会给同一概念不同名字。选择一套模板与文档后保持一致,不要从多个版本各复制一半。

用 IntelliJ 断点观察命令执行

点击 var player = ... 左侧行号添加红色断点,然后以 Debug 模式启动客户端。进入世界执行命令时,程序会暂停。此时在 Variables 窗口查看 context、player 与玩家物品栏。按 F8 单步执行,你会亲眼看到“取得玩家 → 添加物品 → 发送消息 → 返回 1”的顺序。这比背 API 更能建立程序执行模型。

IntelliJ IDEA 中在 var player 代码行左侧设置了红色断点
红点就是行断点。请把断点放在 var player = ... 这一行,再用顶部的 Debug 按钮启动;命令真正执行到这里时程序才会暂停。

Build & install · 构建并安装

开发环境里能运行,最后还要变成普通启动器可以加载的 JAR。

关闭开发客户端,在工程根目录执行构建。Gradle 会编译 Java、处理资源、重映射名称并生成可发布文件。构建成功后打开 build/libs,选择文件名最短、且不包含 sources 的 JAR;sources 包是给开发者阅读源码用的,不是普通玩家安装包。

PowerShell · 构建发布文件
./gradlew.bat clean build
IntelliJ IDEA Project 工具窗口展开 build 和 libs,显示普通 JAR 与 sources JAR
构建成功后展开 build → libs。安装 teacherma-fabric-intro-1.0.0.jar;带 -sources 的文件只用于阅读源码。
1

备份世界

安装任何新模组前都先备份重要世界。开发版模组可能写入实体、物品或存档数据,移除后未必能恢复。

2

安装匹配版本的 Fabric Loader

从 Fabric 官方 Installer 页面下载工具,选择 Minecraft 1.21.1、对应 Loader 与正确游戏目录,创建 Fabric 启动配置。不要使用第三方转载的未知安装器。

3

准备 mods 文件夹

Windows 默认目录通常是 %appdata%\.minecraft\mods。把 Fabric API 的 1.21.1 JAR 与你构建的模组 JAR 一起放进去;同一模组只保留一个版本。

4

从 Fabric 配置启动

在官方启动器选择刚创建的 Fabric 1.21.1 配置。进入游戏后检查 Mods 信息和日志,再用测试世界执行命令。不要直接在唯一的生存主世界上做首次验证。

给别人发布时:同时写清 Minecraft 版本、Fabric Loader 最低版本、Fabric API 是否必需、Java 版本以及安装步骤。一个没有版本说明的 JAR,不是合格的课程交付物。

Practice · 练习与自测

把“看懂”变成“能独立改动”:完成三个难度递增的小任务。

LEVEL 1

换奖励

把 Items.EMERALD 改成 Items.DIAMOND,把消息改成自己的课程口号。预测结果后再运行。

LEVEL 2

增加数量

研究 new ItemStack(Items.EMERALD, 3) 的第二个参数,让一次命令给予三颗绿宝石,并解释构造函数参数。

LEVEL 3

增加第二个命令

复制注册结构,创建 /fabric_level,只发送“我已经完成第一课”,但不发放物品。避免把两个命令嵌套在一起。

五分钟自测

1. Fabric Loader 与 Fabric API 的区别是什么?

Loader 负责发现模组、检查依赖并调用入口;Fabric API 是模组可选或必需依赖的接口集合,提供事件、命令、注册辅助等功能。只有 API 而没有 Loader,模组不会被正常加载。

2. 为什么本课同时检查 Project SDK 和 Gradle JVM?

编辑器分析代码使用 Project SDK,而 Gradle 构建可能使用另一套 JVM。两者不一致时会出现编辑器无红线、构建却报 Java 版本错误的情况。

3. fabric.mod.json 的 entrypoint 写错会发生什么?

Loader 能读到模组描述,但无法找到并实例化指定入口类,onInitialize() 不会执行,命令也不会注册。日志通常会明确指出入口加载失败。

4. 为什么发放物品的代码应该在逻辑服务端执行?

物品栏和世界状态由服务端作为权威来源。只在客户端修改会造成画面暂时变化、随后被服务端纠正,甚至引发不同步。单人游戏内部同样存在集成服务器。

5. 怎样找到正确的发布 JAR?

执行 build 后查看 build/libs,通常选择文件名最短且不含 sources 的 JAR。安装前还要确认目标 Minecraft、Loader、Fabric API 和 Java 版本匹配。

术语卡

术语一句话解释
Mod ID模组在代码和资源中的唯一命名空间,例如 teacherma_fabric_intro。
EntrypointLoader 在指定生命周期阶段调用的 Java 类。
Registry游戏保存可识别对象与唯一 ID 对应关系的注册系统。
Mapping把混淆后的游戏成员映射成开发者可阅读类名和方法名的命名体系。
Dependency当前项目编译或运行所依赖的外部组件,例如 Fabric API。
Logical Server负责世界规则和权威状态的一侧,单人游戏里也存在。

Official references · 官方资料

课程内容以官方模板与文档为基线。

Fabric 发展很快。课程讲清的是稳定原理;具体版本号与类名应在升级时重新核对。建议收藏以下官方入口:

Lesson complete

你已经跨过最关键的一步:让自己的 Java 逻辑进入了游戏。

下一阶段可以开始学习注册第一个自定义物品:建立唯一 ID、物品类、创造模式分组、语言文本、模型 JSON 和 16×16 贴图。请先保存本课工程的可运行版本,再复制出新分支做实验;一个始终能运行的基线,是专业开发习惯的一部分。