API 参考 / judge 包:判定管线
TrackPoseAdjuster
轨道区位姿调整器:模组介入轨道位姿的高优先级层。宿主每帧先算出默认位姿(谱面动画与 setTrackOffset / setTrackTilt3D 等既有 setter 通道的合成值,既有 setter 语义零变化),再把 TrackPose 沿链可变传阅:每个调整器原地修改并传给下一个,链尾位姿交给渲染。在 onPreInit 内经 ctx.registries().trackPoseAdjusters() 注册。
方法速览
| 方法 | 用途 |
|---|---|
adjust(TrackPose, GameplayContext) | 每帧原地修改轨道位姿 |
完整签名
java
public interface TrackPoseAdjuster {
void adjust(TrackPose pose, GameplayContext ctx);
}adjust(TrackPose pose, GameplayContext ctx)
签名:
java
void adjust(TrackPose pose, GameplayContext ctx);行为:每帧每链调用一次,位于渲染入口、既有 setter 合成之后。pose 是宿主复用的可变对象,当前值 = 前一调整器的输出(链首为默认位姿);原地修改即可,链尾值由宿主读取:offsetX / offsetY 用于整轨平移,tiltDeg 交给相机位姿推导(未接管时归一为 pitch,接管时作为内容旋转合成)。
- 链式叠加:前一个调整器的输出就是后一个的输入。大幅移动(A)+ 小幅颤抖(B)天然共存——B 看到 A 改后的位姿,叠加偏移即可。
- 无注册者快速路径:注册表为空时宿主完全跳过本链,位姿等于既有通道合成值,渲染逐位不变。
- 异常隔离:单个调整器抛异常时,该帧该调整器被跳过并输出
[ModConflict]风格限频告警,链继续。 - op 追加只在回调期有效:
pose.rotateZ(...)等 op 方法依赖宿主在链执行前绑定的追加口,回调期外为空操作。 - 禁跨帧持有:
pose是宿主每帧复用的实例,不得保存引用跨帧使用;需要跨帧记忆的状态按 τ 在模组自持对象里重建。 - 纯视觉:位姿不参与判定,判定引擎零消费。
确定性契约(强制,同 JudgmentAdjuster):位姿链位于表现层可重演路径上——暂停恢复倒带会对过去的时间窗逐帧正向重演,多帧率下同一输入也必须产出同一位姿。实现必须:
- 禁随机:不使用
java.util.Random及任何非种子化随机源; - 禁墙钟:不读
System.currentTimeMillis()/System.nanoTime()(时间一律取ctx.musicTimeMs()等回调入参 τ); - 禁网络 / 禁跨帧可变共享态写入:外部世界在重演窗口内不会重放;
- 输出位姿只由入参 + 本模组按 τ 重建的纯函数状态决定。
违反契约的表现是「倒带后轨道位姿与首演不一致」;宿主无法拦截,靠实现者自律。
示例(以 τ 为唯一时间源的小幅颤抖):
java
@Override
public void onPreInit(ModContext ctx) {
ctx.registries().trackPoseAdjusters().register(
RegistryKey.of("my_mod", "tremolo", TrackPoseAdjuster.class),
(pose, gameplayCtx) -> {
double t = gameplayCtx.musicTimeMs() / 1000.0;
pose.translate(0.0, Math.sin(t * 2.0) * 8.0);
pose.tilt(Math.cos(t * 2.0) * 2.0);
});
}线程:宿主在每帧渲染前调用(游玩场景渲染线程,单线程同步)。
生命周期:onPreInit 注册,装配冻结后永久生效(重启进程才能变更)。
稳定性:2026-10-11 新增(2.0 起):2.x 内只增不破。