Skip to content

feat: 支持 Minecraft 26.1(NeoForge / Forge / Fabric) - #71

Open
qawow wants to merge 2 commits into
CFPAOrg:mainfrom
qawow:feat/minecraft-26.1
Open

feat: 支持 Minecraft 26.1(NeoForge / Forge / Fabric)#71
qawow wants to merge 2 commits into
CFPAOrg:mainfrom
qawow:feat/minecraft-26.1

Conversation

@qawow

@qawow qawow commented Aug 11, 2026

Copy link
Copy Markdown

背景

Minecraft 26.1 带来两处不向后兼容的变化,通用 jar 需要适配后才能在该版本工作。

改动

1. NeoForge 新增 javafml 入口

NeoForge 的 FML 11 移除了 ModLauncher,现有的 ITransformationService 入口在 26.1 上不再被调用,Mod 完全不加载。因此新增 NeoForgeMod 作为 @Mod 入口。

为了不破坏「一个 jar 通吃」的前提,NeoForge API 通过 src/compat 下的编译期 shim 提供,并在打包时排除,运行时由 NeoForge 自身提供。这样构建无需引入需要 Java 25 的 NeoForge 依赖,产物仍以 VERSION_1_8 编译。

@Mod 只声明 valuedist(注解默认值不会写入 class 文件),因此该 jar 在旧版 FML 4 上依然可以加载。FMLLoader 的两种 API 形态均以反射解析:

FML 11(26.1+) FML 14(1.20.11.21.x)
游戏目录 getCurrent().getGameDir() getGamePath()
版本 getCurrent().getVersionInfo().mcVersion() versionInfo().mcVersion()

旧版 NeoForge 上 ModLauncher 入口与 @Mod 入口都可能到达 init,故加一个初始化标记,只让先到者执行。

2. pack.mcmeta 格式

pack_format 自 25w31a 起改为 min_format / max_format,且取值可以是整数或 [major, minor] 数组,因此建模为 Gson JsonElement 而非 Integer。26.1.x 对应 [84, 0]

3. Forge 26.1 的版本获取

Forge 在 26.1 上仍然经由 ModLauncher 启动(bootstrap 2.1.8 + modlauncher 10.2.6),所以该入口在 Forge 上保留。但 --fml.mcversion 启动参数已被移除(26.1 只传 --launchTarget forge_client),/forge_version.json 成为唯一版本来源。

该查找改为不触发静态初始化的 Class.forName(name, false, loader),并额外捕获 LinkageError:初始化失败抛出的是 Error,原先的 catch (Exception) 拦不住,会逸出到加载器里。

4. 版本号解析修正

原实现取 minecraftVersion.split("\\.")[1],对 26.1.2 会得到 1,落到 <= 12 分支,导致写入 options.txt 的资源包名缺少 file/ 前缀,资源包无法应用。

验证

在 All the Mods 11(26.1.2 + NeoForge,236 个 mod)实测通过:

  • 单次初始化,loader 正确识别为 NeoForge
  • 26.1 / 1.21 / 1.20 / 1.19 四包合并
  • 输出 pack.mcmeta[84, 0]
  • 资源包被游戏正常加载

另新增 11 个离线单元测试,覆盖 pack_format 两种形态、26.1 各修订版的元数据解析与回退链、转换器域过滤、以及入口的注解形状与反射调用形态(后者以字节码断言,因为构建没有 NeoForge 依赖,方法改名不会有别处报错)。

关于改动范围

第二个 commit 把改动收敛到了 26.1 支持真正需要的部分,移除了三处经实测无行为差异的顺带改动(域过滤条件重写、loader 标签改写、注入 minecraft 域)。收敛后以真实的 4 个源包与 236 个 mod jar 复跑转换,产物与线上包逐条目一致。

26.1 的 asset 条目指向 CFPA 尚未发布的 26.1 包;在其发布前,回退链会自动走 1.21 / 1.20 / 1.19。另外 gameVersions 上界为 26.1.2,26.1.3 发布时需要同步更新此处。

qawow added 2 commits August 11, 2026 01:06
将支持范围扩展到 Minecraft 26.1 / 26.1.1 / 26.1.2,覆盖三个加载器。

NeoForge 26.1(FML 11)完全移除了 ModLauncher,因此新增 NeoForgeMod 作为
@mod javafml 入口;同时用编译垫片(src/compat)让项目无需依赖 NeoForge
即可构建,垫片不进入最终 jar。

Forge 26.1 仍走 ModLauncher,但启动参数删除了 --fml.mcversion,唯一版本
来源变成 /forge_version.json。原代码用 Class.forName(name) 加载 FMLLoader
会触发静态初始化,初始化失败抛出的 Error 会逃过 catch (Exception)。改用
不初始化的加载方式,并捕获 LinkageError。

Minecraft 25w31a 起 pack_format 替换为 min_format/max_format,值可以是
[major, minor] 数组,原来的 Integer 字段存不下 26.1 的 [84,0],改为
JsonElement。

Fabric 侧无需改动,fabric-loader 0.19.3 上现有入口即可工作。
移除三处与 26.1 支持无关、经实测为无行为差异的改动:

- ResourcePackConverter 的域过滤条件还原为 main 的写法。在 26.1/1.21/
  1.20/1.19 四个真实资源包上逐条目比对,两种写法筛选结果完全一致,
  属于纯重构。
- ModLauncherService 不再按 NeoForge 改写 loader 标签。metadata 中每个
  版本的 Forge 与 NeoForge 条目都指向同一个包,该标签不影响下载选择;
  NeoForge 误判问题属于独立议题。
- 不再向域集合注入 minecraft。1.21/1.20/1.19 的包同样把 CJK 字体放在
  assets/minecraft/ 下,该域本就被保留,注入会改变所有版本的既有行为。

随之移除因此变为死代码的 isNeoForge(),以及依赖外部 NeoForge jar、
默认始终跳过的 FmlApiShapeTest 及其构建配置。

改动后以真实的 4 个源包与 236 个 mod jar 复跑转换,产物与线上包逐条目
一致,pack.mcmeta 完全相同。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant