Skip to content

feat: 车万女仆(TouhouLittleMaid)兼容层的 Fabric 实现 - #28

Open
gege-tlph wants to merge 1 commit into
IzumiiKonata:mainfrom
gege-tlph:pr/tlm-compat
Open

feat: 车万女仆(TouhouLittleMaid)兼容层的 Fabric 实现#28
gege-tlph wants to merge 1 commit into
IzumiiKonata:mainfrom
gege-tlph:pr/tlm-compat

Conversation

@gege-tlph

Copy link
Copy Markdown

把本仓 Fabric 侧的车万女仆(TouhouLittleMaid)兼容模块从 stub 做成真的实现。

#27 文件零重叠,两者可独立合并、顺序无关。本 PR 单独基于 main 头部构建通过。

先说明:这是个较大的功能 PR(29 文件 / +2055 行)。如果不打算在本仓维护车万女仆兼容,
直接关掉即可,不必勉强——我们的 fork 会继续维护这部分。开 PR 是因为它对
同时使用两个模组的用户有实际价值,且实现是照原版 OpenYSM 的同名模块移植的,
不是新设计。

现状

TouhouLittleMaidCompatImpl.isLoaded() 恒返回 false,16 个女仆 molang 变量全部返回常量。
所以即便用户同时装了本模组与车万女仆,兼容也不会生效——女仆不会渲染成 YSM 模型。

Forge 1.20.1 的 OpenYSM 原版(OpenYSM/OpenYSM)里这个模块是完整的(22 文件 / 1366 行),
本 PR 是把它移植到 1.21.11 Fabric。

实现内容

  • 实体与物品判定、16 个女仆 molang 变量的真实绑定、坐乘交互动画
  • MaidAnimatable(对应原版 MaidCapability)与 MaidRenderStore 客户端弱键缓存
  • 骨骼定位桥:YSM 骨骼/模型 → 车万女仆的 ILocationBone / ILocationModel
  • 动画层:主选择器、13 个主状态、雕像 / 手办 / 胜负 / 乞求,以及轮盘通道
  • 20 个动画控制器的装配表,并接上 buildControllers
  • 渲染底座 MaidGeoRenderer 与客户端装配 / 钩子注入
  • 渲染态 tick 驱动、轮盘激活、molang 执行入口
  • GUI 链四个类(女仆的模型屏 / 材质屏 / 两种格子)并接上开屏事件
  • 动画轮盘:与玩家自己的轮盘分流,仅在「准星指向女仆 + 该女仆已切 YSM 模型 +
    属主是本地玩家」三条全中时接管(判宽了会抢玩家按键)

类加载隔离

TouhouLittleMaidCompatImpl / TouhouMaidCompatImpl 不 import 任何车万女仆类型
车万女仆类型只活在 rip.ysm.compat.touhoulittlemaid.fabric.tlm 子包,
且只在 isLoaded() 为真的分支被触碰。未装车万女仆时那些类不会被加载。

依赖

libs/touhoulittlemaid-fabric-0.8.4-neo1.5.3+mc1.21.11.jar 按本仓 libs/ 的既有约定加入
(该目录已 vendored 约 30 个第三方 jar)。声明为 modCompileOnly——
只参与编译,不会进入产物 jar,不构成再分发。

如果你更希望换一种依赖方式(例如换成 Maven 坐标、或干脆不入库由构建者自备),
告诉我,我来改。

工具链随之升级:arch-loom1.17.487architectury-plugin3.5-SNAPSHOT
以便与车万女仆侧的 fabric-loom 1.17.x 同代。旧版本组合会在 RunConfig 上炸
NoClassDefFound 并违反 compileClasspath 声明。

几处设计取舍(附理由,以免被"顺手优化"回去)

  • MaidGeoRenderer 不继承本仓的 GeoReplacedEntityRenderer 后者已被收窄为
    <TEntity extends Player, …, S extends AvatarRenderState> + PlayerModel
    要它吃女仆 render state 就得连模型类型参数一起泛化成四参泛型,牵动
    CustomPlayerRendererAvatarRenderer mixin。女仆是新增功能、玩家渲染是本模组主功能,
    风险不对称,故另建底座、宁可重复。
  • 控制器前缀不对称是原版语义:具名控制器用 maid.,其余全用 player.——
    女仆复用玩家模型的动画入口表,模型作者写的键就是 player.main。统一了动画全找不到入口。
  • 骨骼桥保留了原版的左右互换extraLeftHandBones()rightHandChain(),反之亦然)。
    看着像写反,但模型作者的动画是照现行行为调的,改了是破坏性变更。
  • 原版里本就是空实现的三处未"补全"handleMaidFeedbackClientDistChecker
    UpdateRemoteStructEvent(原版零消费者)。

移植期实测暴露并已修复的两处缺陷

  • 「使用 YSM 皮肤」按钮点了没反应。 车万女仆只对已是 YSM 模型的女仆触发 tick 事件,
    而那是渲染态唯一的创建时机,却拿「渲染态在场」当开屏门禁,形成鸡生蛋死锁。
  • 开发环境的映射假象导致 NoSuchMethodError Fabric 重映射 mod jar 时,
    若调用点 owner 是别的模组的类而成员继承自原版,解析不出继承链就把 intermediary 名
    原样留下。现已把凡来自车万女仆类型上的原版继承成员全部改经原版静态类型访问,
    并把两个 helper 的形参直接改成原版类型(owner 天然正确,不靠调用点自觉)。
    正式环境无此问题(两侧都是 intermediary)。

验证

实机逐项确认:模型切换与渲染 · 13 个动画状态 · 材质切换 · 名字牌 · 雕像/手办里的女仆动画 ·
轮盘键分流 · 多人与专用服务器(双向包过真实网络边界,未被踢、两侧零异常)·
与其余若干兼容模组共存 · 未安装车万女仆时完整构建与运行全绿

已知缺口

YSM 模型的女仆不渲染车万女仆的挂件(背包 / 手持物 / 背旗 / 头顶方块)。
通道两端俱在、中间断开:车万女仆的 5 个 gecko layer 移植到 1.21.11 时改用了自家的
modelStateILocationModel 在车万女仆里成了零消费者接口。
缺口在车万女仆一侧,本 PR 的骨骼定位桥已就绪,无需本仓改动。

本仓 Fabric 侧的车万女仆兼容模块目前是全 stub:TouhouLittleMaidCompatImpl.isLoaded()
恒返回 false,16 个女仆 molang 变量全部返回常量,所以即便同时装了车万女仆也不会生效。
本提交把它做成真的实现,移植自 OpenYSM 原版(OpenYSM/OpenYSM,Forge 1.20.1)的
同名模块(原版 22 文件 / 1366 行)。

实现内容:

- 实体与物品判定、16 个女仆 molang 变量的真实绑定、坐乘交互动画
- MaidAnimatable(对应原版 MaidCapability)与 MaidRenderStore 客户端弱键缓存
- 骨骼定位桥:YSM 骨骼/模型 → 车万女仆的 ILocationBone / ILocationModel
- 动画层:主选择器、13 个主状态、雕像/手办/胜负/乞求,以及轮盘通道
- 20 个动画控制器的装配表,并接上 buildControllers
- 渲染底座 MaidGeoRenderer 与客户端装配/钩子注入
- 渲染态 tick 驱动、轮盘激活、molang 执行入口
- GUI 链四个类(女仆的模型屏 / 材质屏 / 两种格子)并接上开屏事件
- 动画轮盘:与玩家自己的轮盘分流,仅在「准星指向女仆 + 该女仆已切 YSM 模型 +
  属主是本地玩家」三条全中时接管,判宽了会抢玩家按键

类加载隔离:TouhouLittleMaidCompatImpl / TouhouMaidCompatImpl 不 import 任何车万女仆类型;
车万女仆类型只活在 rip.ysm.compat.touhoulittlemaid.fabric.tlm 子包,
且只在 isLoaded() 为真的分支被触碰。未装车万女仆时那些类不会被加载。

几处设计取舍,附理由以免被"顺手优化"回去:

- MaidGeoRenderer 不继承本仓的 GeoReplacedEntityRenderer。后者已被收窄为
  <TEntity extends Player, …, S extends AvatarRenderState> + PlayerModel,
  要它吃女仆 render state 就得连模型类型参数一起泛化成四参泛型,牵动
  CustomPlayerRenderer 与 AvatarRenderer mixin。女仆是新增功能、玩家渲染是本模组主功能,
  风险不对称,故另建底座、宁可重复。
- 控制器前缀不对称是原版语义:具名控制器用 maid.,其余全用 player.——
  女仆复用玩家模型的动画入口表,模型作者写的键就是 player.main。统一了动画全找不到入口。
- 骨骼桥保留了原版的左右互换(extraLeftHandBones() 取 rightHandChain(),反之亦然)。
  看着像写反,但模型作者的动画是照现行行为调的,改了是破坏性变更。
- 原版里本就是空实现的三处未"补全":handleMaidFeedback、ClientDistChecker、
  UpdateRemoteStructEvent(原版零消费者)。

另含移植期实测暴露的两处缺陷修复:

- 「使用 YSM 皮肤」按钮点了没反应。车万女仆只对**已是** YSM 模型的女仆触发 tick 事件,
  而那是渲染态唯一的创建时机,却拿「渲染态在场」当开屏门禁,形成鸡生蛋死锁。
- 开发环境的映射假象导致 NoSuchMethodError。Fabric 重映射 mod jar 时,若调用点 owner 是
  别的模组的类而成员继承自原版,解析不出继承链就把 intermediary 名原样留下。
  现已把凡来自车万女仆类型上的原版继承成员全部改经原版静态类型访问,
  并把两个 helper 的形参直接改成原版类型(owner 天然正确,不靠调用点自觉)。
  正式环境无此问题(两侧都是 intermediary)。

依赖与工具链:

- libs/touhoulittlemaid-fabric-0.8.4-neo1.5.3+mc1.21.11.jar 按本仓 libs/ 的既有约定加入,
  声明为 **modCompileOnly**——只参与编译,**不会进入产物 jar**,不构成再分发。
- arch-loom 升级到 1.17.487、architectury-plugin 升级到 3.5-SNAPSHOT,
  以便与车万女仆侧的 fabric-loom 1.17.x 同代;旧版本组合会在 RunConfig 上炸
  NoClassDefFound 并违反 compileClasspath 声明。
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