Fabric 1.21.1 移植(对齐 1.10.1-beta.1) - #2
Open
E33EPUS wants to merge 11 commits into
Open
Conversation
Convert the NeoForge mod to a Fabric 1.21.1 Loom project using official Mojang mappings. Port registry, networking, config, attachments, key bindings, custom audio stream, and optional deps (Waystones/Balm/MCEF/ NetMusic/Patchouli). Omit Curios and Integrated Dynamics (no Fabric 1.21.1 build). Carry the pure animation classes and SettingsList hover fade. Keep server/client dist isolation by moving all client networking into /client packages.
Vanilla @reDIrect on SoundEngine crashed game init with MixinExtras 0.5.0 (bundled in Fabric Loader 0.17.x): FactoryRedirectWrapperMixinTransformer casts the @reDIrect at value to a single AnnotationNode while javac stores it as a single-element array, causing ClassCastException. Switch to @WrapOperation which avoids that transformer and is conflict-friendly.
GuideME and Immersive Engineering have no Fabric 1.21.1 build, so listing them as missing integrations in the About page is misleading. Remove them from ReaderApp companion mods, BookSources, and the external book whitelist; delete the two reflection adapters that can never activate on Fabric.
…cker 1. NetMusic CD playback did nothing on 1.2.x: that release keeps its client playback classes in netmusic.audio, while 1.5.x moved them to netmusic.client.audio. Compiling against 1.5.2 hardcoded the new package, so on 1.2.x MusicPlayManager threw NoClassDefFoundError and the only trace was a log line. NetMusicPlayback now resolves both package layouts by reflection (both generations share the same signatures) and logs which one it found; failure still degrades to "this CD will not play" instead of breaking the packet handler. ItemMusicCD (the server-side read) never moved, which is why the CD was recognised but silent. 2. "Open folder" did nothing on Windows. Util.getPlatform().openPath runs rundll32 url.dll,FileProtocolHandler, which is built for files and URLs and fails silently on directories (measured: 0 Explorer windows opened, while explorer.exe opens 1). Upstream has the same code, so this was not introduced by the port. New FolderOpener uses explorer.exe on Windows, keeps openPath elsewhere, and falls back to AWT Desktop; all three call sites (wallpapers, gallery, stickers) go through it. 3. New feature: image picker ported from AtomChat (JFileChooser in our own always-on-top JFrame with FlatLaf, inline thumbnails, live preview). System native dialogs cannot be raised above Minecraft's fullscreen window. Wired into the wallpaper page as "Pick image"; WallpaperStore.importFile copies the choice into the wallpaper folder without overwriting same-named files. FlatLaf is jar-in-jar. docs/ImagePickerTest.java (19 checks) pins the accepted extensions and the no-upscaling rule, both of which fail silently otherwise. Build green: 12 assertion tests, dist isolation, remapJar.
render() computes the header and button hit-tests, then the empty-folder branch overwrote hoveredIdx with -1 before returning. With no wallpapers on disk that wiped the hit result, so "Open folder" and the new "Pick image" button did nothing at all - no window, no log line. An empty folder is exactly when a player wants those buttons: they are there to put the first image in. Only the wallpaper page had this shape. ChatMediaPicker clears hoveredIdx but leaves openFolderHovered alone, and Gallery computes the hit before its empty branch, so both were already fine. Verified explorer.exe really opens a window from a Java process (Explorer window count 2 -> 3), so FolderOpener itself was sound; the click just never reached it.
The image picker bundles FlatLaf jar-in-jar; Apache-2.0 requires the notice to travel with the binary. Also fixes the JavaMP3 path in the same file (Fabric puts jar-in-jar under META-INF/jars/, not jarjar).
Owner
|
LGTM |
Collaborator
|
不大行,暂时不大能合 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fabric 1.21.1 移植(1.10.1-beta.1 同步版)
把
main这一支(NeoForge 1.21.1)移植到 Fabric 1.21.1,功能对齐到上游v1.10.1-beta.1(0f9e0a8)。已验证:
./gradlew build全绿(compileJava、dist 隔离校验、12 份断言测试、remapJar),专用服务器
runServer冒烟加载正常,实机跑过完整流程(见下)为什么是独立 fork 而不是 Architectury
上游是单加载器工程,拆 common/neoforge/fabric 的工程量是数倍于移植本身。独立分支能最快
出可跑版本,也可以直接当作平行分支参考——每个 MC 版本/加载器各占一个分支,和
1.20.1-forge的现状一致
映射用 officialMojangMappings(Loom 在 remapJar 时自动映射到 intermediary)。这是刻意的:
上游源码是 Mojang 映射写的,换 Yarn 等于整棵树重写类名与方法名,后续每次同步上游都会在
每个文件上冲突
修掉的上游 bug(两个都是 Windows 上的静默失败)
1. 「打开文件夹」在 Windows 上点了没反应
Util.getPlatform().openPath()在 Windows 上执行rundll32 url.dll,FileProtocolHandler <uri>,这条命令是给文件与 URL 设计的,对目录静默失败:进程正常退出、返回码 0、什么都不弹。实测(数资源管理器窗口):
rundll32 url.dll,FileProtocolHandler …explorer.exe …受影响的不止壁纸页——相册与表情页的「打开文件夹」是同一行代码,同样失效
新增
core/client/FolderOpener:Windows 走explorer.exe,其他平台保留原版openPath,兜底 AWT
Desktop.open,并把相对路径转成绝对路径。三处调用点统一走它2. 壁纸目录为空时,「打开文件夹」与按钮全都点不动
WallpaperPicker.render()先算好标题行与按钮的命中(局部hovered),随后"目录为空"分支在
return前写了this.hoveredIdx = -1,把本帧刚算出的命中结果覆盖掉了。壁纸目录为空时(玩家还没放图),那个键的点击判定永远不成立——不弹窗、不打日志。
而"目录是空的"恰恰是玩家最想点它的时刻:他就是来放第一张图的。已改为
this.hoveredIdx = hovered。(同类排查:
ChatMediaPicker的空分支只清hoveredIdx、不动openFolderHovered;Gallery在空分支之前就完成了 hover 判定——两者都没有这个问题。)3. NetMusic 1.2.x 上网络 CD 放不出声
NetMusic 改过包名:1.2.x 的客户端播放类在
netmusic.audio,1.5.x 挪到了netmusic.client.audio。上游按 1.5.x 编译写死了新包名,于是 1.2.x 上MusicPlayManager抛NoClassDefFoundError,只在日志里留一行,玩家看到的是"唱片放进槽位、点了播放没反应"。
NetMusicPlayback改为反射依次探测两代包名(两代的方法签名与构造器一致,一次查找两边通用)服务端的
ItemMusicCD两代同路径——这正是"CD 认得出、只是不响"的原因新增功能:图片选择器
上游让玩家自己把图放进
config/mcphone/wallpapers/;这里补一个游戏内入口移植自我们自己的另一个项目(AtomChat,MIT),在壁纸页加了「选择图片」按钮
为什么不用系统原生选择器:Windows 的
GetOpenFileName既不继承WS_EX_TOPMOST,也不理会我们设的任何提示,永远待在 z 序最底下——玩家点"选一张图"什么都看不见
所以窗口必须是我们自己的
JFrame(always-on-top)+JFileChooser+ FlatLaf 换皮肤,带行内缩略图与右侧实时预览。选完复制进壁纸目录,重名挂序号不覆盖
与上游联动 mod 的差异
上游的联动里有一部分在 Fabric 1.21.1 上没有构建,所以这边只能这样:
需要作者注意的三件事
1. 第三方许可证:FlatLaf(Apache-2.0)
图片选择器的界面外观用了 FlatLaf(
com.formdev:flatlaf:3.7.2,Apache-2.0),以未修改的二进制形式 jar-in-jar 打包。Apache-2.0 要求许可证声明随二进制一起分发,
所以我把它写进了
src/main/resources/THIRD-PARTY.txt(该文件上游已有,原本只列 JavaMP3)如果这个 PR 里只合并移植部分、不合并选择器,那这一条不适用——FlatLaf 与选择器可以整体摘掉,
移植其余部分不依赖它
(说明:选择器代码本身移植自 AtomChat,那是 MIT,版权人就是我们;FlatLaf 是它依赖的
第三方库,是 Apache-2.0)
2. 版本号与 CI 的
guard-versionbuild.yml里那道闸会拦下任何非 bot 手改mod_version的提交。移植分支需要自己的版本号(
1.10.1-beta.1-fabric.N),和1.20.1-forge分支自带0.12.0-beta.1是同一个道理,所以这个 PR 必然触发它。
如果作者决定合并,建议像
1.20.1-forge那样先建1.21.1-Fabric分支,再让 CI 接管该分支的版本号;PR 里的版本号改动不必保留。
3. 分支命名
合并后建新分支
1.21.1-Fabric(我这边已经用这个名字推了)工程上的几处 Fabric 特有处理(供评审参考)
MCphoneNetwork门面在 Fabric 侧用"候车室"实现——共享阶段只登记编解码并挂起 S2C 接收器,
core/client/ClientNetworking在客户端启动时领走注册。这样上游1.10.1 那套
registerToServer/registerToClient的调用面可以逐字保留,S2C 处理函数继续住在共享的
*Networking类里sync()(1.4.0+/MC1.21.5 才有),PHONE_TERMINAL的客户端同步用SyncPhoneTerminalPacket手工补(写入时发 + JOIN 推初值)。KeyboardHandlerMixin转发 GLFW 键盘事件;新增可取消的MouseHandlerMixin补上 NeoForge
InputEvent.MouseButton.Pre的取消语义(绑在侧键上的 App 打开时不会顺带挥手/放方块)
config/mcphone-client.json、<世界>/serverconfig/mcphone-server.json),键名与语义不变,服务端配置靠SyncServerConfigPacket在 JOIN 时推送verifyDistIsolation思路并接进check,全部客户端类型关在client/包内docs/下 12 份带main()的测试已挂进check(含上游 1.10.1 新加的两份编解码测试与移植带来的动画测试)
测试情况
./gradlew build:compileJava 0 错误、dist 隔离校验过、12 份断言测试全过、remapJar 出包NoClassDefFoundError商店购买、聊天收发图、音乐本地/网络播放、终端 App(RS/TOMS)、副手 HUD、快捷键
(键盘 + 鼠标侧键 + 组合键)、界面缩放 —— 均通过
后续
如果这个方向有价值,我可以按同样的方式继续跟上游的每次发版(这次同步 1.9.3→1.10.1-beta.1
解了 58 个冲突)。也欢迎指出哪里不符合仓库惯例