Theseus 模组文档
API 参考 / spi 包:游戏模式、谱面扩展与内容

ExtraContentApi


谱面特效表演原语通道(接缝 ):宿主游玩上下文经 ChartRuntimeContext.extraContent() 注入,模组可在 parser 的 apply 阶段或游玩期,触发与谱面 extraContent 段同一执行体的轨道/假轨/假音符表演效果(执行体为宿主 TrackRenderer 的每轨状态与假实体实例),因此表现与谱面写法逐像素同管线。方法按「意图」命名,不映射谱面 JSON 类型名。相关类型:ChartRuntimeContext、SkinProvider。

通道的共享契约:

方法速览

方法用途
setLaneAlpha(int, float)真轨背景与分隔线透明度
setKeyIndicatorAlpha(int, float)真轨快捷键框透明度
setTrackOffset(float, float)轨道区整体 X/Y 偏移
setLaneOffset(int, float, float, float)单轨 3D 偏移(含 z 深度)
setLaneRotation(int, float)单轨纯视觉旋转(弧度,圆心固定判定线中点)
setLaneSpeedFactor(int, float)单轨流速倍率(可为负)
setLaneHeight(int, float)单轨手动高度延伸
setLaneHeightAuto(int)启用单轨自动高度
setLaneScale(int, float, float)单轨渲染缩放(pivot = 几何中心)
setLaneScaleAuto(int)复位单轨缩放到 (1,1)
setLaneSkew(int, float, float)单轨线性斜切
setLaneSkewAuto(int)复位单轨斜切到 0
setLaneArc(int, float, float, float)单轨圆弧形变
setLaneArcAuto(int)复位单轨弧线到 0
setTrackTilt3D(double)轨道区 3D 透视倾斜(度)
setTrackTilt3DAuto()复位 3D 倾斜到正交
setNoteAlpha(int, float)单轨全部音符透明度
setUiAlpha(float)非轨道 HUD 透明度
createFakeTrack(int, int, float)创建/覆盖假轨道
setFakeTrackTransform(int, float, float, float, float, float, float)假轨位置/透明度/缩放/旋转一次写入
setFakeTrackAlpha(int, float)假轨背景与键框透明度
setFakeTrackRotation(int, float)假轨旋转(保留圆心)
setFakeTrackRotation(int, float, String)假轨旋转 + 圆心模式
setFakeTrackSkew(int, float, float)假轨斜切
setFakeTrackArc(int, float, float, float)假轨弧线
setFakeTrackHeight(int, float)假轨高度延伸
setFakeTrackKeyIndicatorAlpha(int, float)假轨快捷键框透明度
createFakeNote(int, int, String, Long, float)创建/覆盖假音符
setFakeNoteAlpha(int, float)假音符透明度
setNoteTransform(long, float, float, float, float, float, float, float)真音符自身 3D 变换
clearNoteTransform(long)清除音符自身变换

获取通道

java
@Override
public void apply(Object parsed, ChartRuntimeContext ctx) {
    ExtraContentApi api = ctx.extraContent();   // 非游玩上下文返回 null
    if (api == null) {
        return;
    }
    this.api = api;          // 保存到本局状态,供 GameplayTickEvent.Post 使用
    api.setLaneAlpha(0, 0.3f);
}

以下各方法的示例都假定 api 是已经判空取得的非空通道,并可用在 apply 或游玩期回调中。

真轨道原语

setLaneAlpha(int lane, float alpha)

签名:

java
void setLaneAlpha(int lane, float alpha);

行为:设置 lane(0 起)的轨道背景与分隔线透明度,alpha 由宿主钳制到 0..1。不影响该轨音符与快捷键框(后者见 setKeyIndicatorAlpha)。越界 lane 静默忽略。立即生效、纯视觉。

示例:

java
api.setLaneAlpha(0, 0.5f);

setKeyIndicatorAlpha(int lane, float alpha)

签名:

java
void setKeyIndicatorAlpha(int lane, float alpha);

行为:只设置该轨快捷键框的透明度(0..1 钳制),背景与分隔线不变。谱面 lane_alpha 的 affectKeyIndicator 会同时写两者,本原语用于分别控制。

示例:

java
api.setKeyIndicatorAlpha(0, 0.0f);   // 隐藏快捷键提示,保留轨道背景

setTrackOffset(float x, float y)

签名:

java
void setTrackOffset(float x, float y);

行为:整个轨道区域相对默认布局的 X/Y 偏移(画布像素)。绝对写:每次调用同时写 x 与 y 两个分量,只想改一维时要传入另一维的当前值。跟随区域一起移动的是轨道区内容(背景、分隔线、判定线与其中的音符);HUD 不受影响。

示例:

java
api.setTrackOffset(32.0f, 0.0f);

setLaneOffset(int lane, float x, float y, float z)

签名:

java
void setLaneOffset(int lane, float x, float y, float z);

行为:单条真轨的 3D 偏移(lane_pose.x/y/z),以轨道区域为坐标系,叠加在 setTrackOffset 的区域偏移之上。x / y / z 单位均为画布像素;z 沿 +z(屏幕内)为深度,0 = 内容平面。3.0 起包含 z,旧两参调用补 0 即与旧输出逐字节一致。越界 lane 静默忽略。

示例:

java
api.setLaneOffset(1, 12.0f, -8.0f, 40.0f);

setLaneRotation(int lane, float rotationRad)

签名:

java
void setLaneRotation(int lane, float rotationRad);

行为:把整条真轨(背景、分隔线、判定线、快捷键框与音符)作纯视觉旋转,rotationRad 为弧度、顺时针为正(屏幕坐标系)。3.0 起删除 pivot 参数:圆心固定为该轨判定线中点,与 GameStateAccess.setLaneRotation 同口径;需要自定义圆心时改用 EntityPose.rotateZ(deg, pivotX, pivotY) 自绘。判定与输入不受影响。

示例:

java
api.setLaneRotation(2, (float) Math.toRadians(12.0));

setLaneSpeedFactor(int lane, float factor)

签名:

java
void setLaneSpeedFactor(int lane, float factor);

行为:该轨的流速倍率,实际下落速度 = 全局 scrollSpeed × factor;任意 float,负值表示反向下落,宿主不钳制。只改变音符的屏幕运动,判定仍按音符时间进行(纯视觉)。

示例:

java
api.setLaneSpeedFactor(3, -1.0f);

setLaneHeight(int lane, float height)

签名:

java
void setLaneHeight(int lane, float height);

行为:手动设置该轨向判定线反方向(轨道顶端)延伸的高度,单位画布像素,负值按 0 处理,并关闭该轨的自动高度。延伸影响轨道图形与音符出现高度。

示例:

java
api.setLaneHeight(0, 240.0f);

setLaneHeightAuto(int lane)

签名:

java
void setLaneHeightAuto(int lane);

行为:启用该轨自动高度:宿主每帧按轨道旋转与画布尺寸计算,保证旋转后轨道顶端不越出画布;此前手动设置的高度值被忽略(内部写 0 并置 auto)。

示例:

java
api.setLaneHeightAuto(0);

setLaneScale(int lane, float sx, float sy)

签名:

java
void setLaneScale(int lane, float sx, float sy);

行为:单条真轨的渲染缩放(lane_scale 对应物),pivot = 该轨几何中心;sx / sy 各自钳制 ≥ 0.01。全套跟随:背景、分隔线(线宽按 1/sx 补偿保持约 1px)、判定线/键框、按键指示器与音符在同一仿射变换内缩放。(1,1) 为原大小。纯视觉,判定引擎零消费。

示例:

java
api.setLaneScale(1, 1.5f, 0.8f);

setLaneScaleAuto(int lane)

签名:

java
void setLaneScaleAuto(int lane);

行为:把该轨缩放复位到 (1,1)。

示例:

java
api.setLaneScaleAuto(1);

setLaneSkew(int lane, float skew, float anchorY)

签名:

java
void setLaneSkew(int lane, float skew, float anchorY);

行为:单条真轨的线性斜切(lane_skew 对应物)。合成横移 offsetX(y) = skew × (y − anchorY) + 弧线项(y),skew 钳 |skew| ≤ 1,anchorY 为该画布 y 处零偏移的锚点。与 setLaneArc 共享同一条 per-lane 形变通道、坐标叠加;偏移是纯 y 函数,每帧 O(1) 求值,无状态/无随机/无墙钟(确定性契约)。全套跟随:背景与分隔线逐段弯曲、按键框整体横移、音符中心 x 跟随其所在 y,判定线保持水平直线,音符自身不旋转不变形(口径)。skew == 0 时回到既有直轨路径(默认零变化)。纯视觉,判定零消费。

示例:

java
api.setLaneSkew(0, 0.4f, 300.0f);

setLaneSkewAuto(int lane)

签名:

java
void setLaneSkewAuto(int lane);

行为:把该轨斜切系数归零(锚点保留;幅度为 0 时不参与偏移)。

示例:

java
api.setLaneSkewAuto(0);

setLaneArc(int lane, float bendDir, float bendAmp, float arcCenterY)

签名:

java
void setLaneArc(int lane, float bendDir, float bendAmp, float arcCenterY);

行为:单条真轨的圆弧形变(lane_arc 对应物),与 setLaneSkew 共享同一通道。弧线横移为纯 y 函数:offsetX(y) = sign(bend) × (R − √(R² − d²)),d = y − arcCenterY(钳 |d| ≤ R),R = (S² + A²) / (2A),S = 600px(弧线参考跨度),A = |bendDir × bendAmp|。bendDir 先钳 ±1(-1 左凸 / +1 右凸),bendAmp 取绝对值并钳 ≤ 300;距弧心竖直 600px 处的弧偏移恰好为 bendAmp。全套跟随与判定线水平口径同 setLaneSkew;纯视觉。

示例:

java
api.setLaneArc(0, -1.0f, 150.0f, 300.0f);

setLaneArcAuto(int lane)

签名:

java
void setLaneArcAuto(int lane);

行为:把该轨弧线归零(弧心保留;幅度为 0 时不参与偏移)。

示例:

java
api.setLaneArcAuto(0);

setTrackTilt3D(double tiltDeg)

签名:

java
void setTrackTilt3D(double tiltDeg);

行为:轨道区域的真 3D 透视倾斜(track_tilt 的会话级对应物)。tiltDeg 单位是度,正值 = 顶部远离相机向后倒(Arcaea 式),宿主钳 ±89°;0 = 正交(恒等,默认零变化)。宿主以 d = 内容高 × 0.5、锚点 = 判定线驱动透视相机:世界层(BACKGROUND / WORLD / NOTES / JUDGE_FX)随相机透视变形,HUD / OVERLAY 恒正交不受影响。与 GameStateAccess.setTrackTilt3D 写同一执行体(后写生效);倒带或加载新谱面时声明面与相机重建。纯视觉,判定零消费。

示例:

java
api.setTrackTilt3D(20.0);

setTrackTilt3DAuto()

签名:

java
void setTrackTilt3DAuto();

行为:把轨道 3D 倾斜复位到 0(正交)。

示例:

java
api.setTrackTilt3DAuto();

setNoteAlpha(int lane, float alpha)

签名:

java
void setNoteAlpha(int lane, float alpha);

行为:设置该轨全部音符的透明度,alpha 钳制到 0..1;不影响轨道背景、分隔线与快捷键框。宿主对该方法先检查 lane 范围,越界时打印 lane_note_alpha: lane N out of range 后忽略(非限频)。

示例:

java
api.setNoteAlpha(2, 0.25f);

setUiAlpha(float alpha)

签名:

java
void setUiAlpha(float alpha);

行为:设置非轨道 UI(分数、连击等 HUD)的整体透明度,期望 0..1。注意宿主此通道直写 HUD 透明度、不额外钳制,越界值会原样进入渲染,请自行限制。宿主未注入 UI 通道时静默无操作。

示例:

java
api.setUiAlpha(0.2f);

假轨道原语

createFakeTrack(int id, int originLane, float alpha)

签名:

java
void createFakeTrack(int id, int originLane, float alpha);

行为:创建一条表演用假轨道。id 是后续 setFakeTrackXxx 的寻址键,已存在时用新实例覆盖(位置、透明度、缩放、旋转、形变全部重置)。originLane 指定参考真轨,以其判定线中心为坐标原点;-1 = 画布原点模式(不绑定真轨,快捷键框显示 ?)。alpha 为初始透明度(0..1)。3.0 起没有 z 参数(画家算法层级已移除,前后关系由真 3D 深度决定)。假轨不参与判定/输入。

示例:

java
api.createFakeTrack(1, 0, 0.8f);

setFakeTrackTransform(int id, float x, float y, float alpha, float scaleX, float scaleY, float rotationRad)

签名:

java
void setFakeTrackTransform(int id, float x, float y, float alpha, float scaleX, float scaleY, float rotationRad);

行为:一次写入假轨的位置、透明度、缩放与旋转(fake_track_move 非动画分支)。rotationRad 为弧度、顺时针为正;alpha 同时写背景/分隔线与快捷键框(宿主内部 setAlpha);scaleX / scaleY 各钳 ≥ 0.01。id 不存在时限频告警并忽略。

示例:

java
api.setFakeTrackTransform(1, 20.0f, -40.0f, 0.8f, 1.2f, 0.9f, 0.0f);

setFakeTrackAlpha(int id, float alpha)

签名:

java
void setFakeTrackAlpha(int id, float alpha);

行为:只改假轨透明度(0..1 钳制);不影响位置/缩放/旋转。宿主实现中该写入会同时设置背景/分隔线与快捷键框两者,只想改键框请用 setFakeTrackKeyIndicatorAlpha。

示例:

java
api.setFakeTrackAlpha(1, 0.4f);

setFakeTrackRotation(int id, float rotationRad)

签名:

java
void setFakeTrackRotation(int id, float rotationRad);

行为:只改假轨旋转角(弧度,顺时针正),圆心保持当前设置(默认判定线中点)。

示例:

java
api.setFakeTrackRotation(1, (float) Math.toRadians(8.0));

setFakeTrackRotation(int id, float rotationRad, String pivot)

签名:

java
void setFakeTrackRotation(int id, float rotationRad, String pivot);

行为:设置旋转角并同时指定圆心。pivot 取 "judge_line"(该假轨判定线中点,默认)或 "track_center"(背景几何中心);null 与未知值都回退 "judge_line",未知的非 null 值额外打印告警。等价于先调用两参版本再设定圆心。

示例:

java
api.setFakeTrackRotation(1, (float) Math.toRadians(8.0), "track_center");

setFakeTrackSkew(int id, float skew, float anchorY)

签名:

java
void setFakeTrackSkew(int id, float skew, float anchorY);

行为:假轨斜切,口径与 setLaneSkew 一致——钳制算式与真轨共用宿主 TrackGeometry.normalizeSkew(|skew| ≤ 1)。anchorY 为该 y 处零偏移的锚点。假轨本不参与判定,零判定副作用。

示例:

java
api.setFakeTrackSkew(1, 0.3f, 300.0f);

setFakeTrackArc(int id, float bendDir, float bendAmp, float arcCenterY)

签名:

java
void setFakeTrackArc(int id, float bendDir, float bendAmp, float arcCenterY);

行为:假轨弧线,口径与 setLaneArc 一致——TrackGeometry.normalizeArcBend 统一钳制:方向钳 ±1、幅度取绝对值并钳 ≤ 300,返回有符号幅度;arcCenterY 为弧心 y。

示例:

java
api.setFakeTrackArc(1, 1.0f, 120.0f, 300.0f);

setFakeTrackHeight(int id, float height)

签名:

java
void setFakeTrackHeight(int id, float height);

行为:假轨高度延伸(向判定线反方向),负值按 0 处理,口径同 setLaneHeight 的手动分支。

示例:

java
api.setFakeTrackHeight(1, 180.0f);

setFakeTrackKeyIndicatorAlpha(int id, float alpha)

签名:

java
void setFakeTrackKeyIndicatorAlpha(int id, float alpha);

行为:只改假轨快捷键框透明度(0..1 钳制),背景/分隔线不变。谱面 fake_track_alpha 同时写两者,本原语用于分别控制。

示例:

java
api.setFakeTrackKeyIndicatorAlpha(1, 0.0f);

假音符原语

createFakeNote(int id, int fakeTrackId, String noteType, Long lengthMs, float alpha)

签名:

java
void createFakeNote(int id, int fakeTrackId, String noteType, Long lengthMs, float alpha);

行为:创建一个绑定到假轨的假音符。id 已存在时覆盖。noteType 取 "normal" 或 "hold"(null 按 normal,大小写不敏感);只有 "hold" 且 lengthMs != null && lengthMs > 0 时按长条绘制,否则按普通音符,normal 请传 null。fakeTrackId 应先用 createFakeTrack 创建;宿主不在此处校验,绑定的假轨不存在时该音符不会被绘制。alpha 初始透明度(0..1)。

示例:

java
api.createFakeNote(10, 1, "hold", 1200L, 0.9f);

setFakeNoteAlpha(int id, float alpha)

签名:

java
void setFakeNoteAlpha(int id, float alpha);

行为:只改指定假音符的透明度(0..1 钳制),不影响假轨与其他假音符;id 不存在时打印告警并忽略。

示例:

java
api.setFakeNoteAlpha(10, 0.5f);

音符级原语

setNoteTransform(long noteId, float dx, float dy, float dz, float pitchDeg, float yawDeg, float rollDeg, float scale)

签名:

java
void setNoteTransform(long noteId, float dx, float dy, float dz, float pitchDeg, float yawDeg, float rollDeg, float scale);

行为:真谱面音符的自身 3D 变换,按 noteId 寻址,偏移 + 三轴旋转 + 等比缩放一次写入。

示例:

java
// 对固定 noteId 做「上移 18px + 顺时针 15° + 放大 1.2 倍」
api.setNoteTransform(42L, 0.0f, -18.0f, 0.0f, 0.0f, 0.0f, 15.0f, 1.2f);

clearNoteTransform(long noteId)

签名:

java
void clearNoteTransform(long noteId);

行为:清除该 noteId 的自身变换条目,回到恒等;无条目时为 no-op。与 setNoteTransform 的「常驻」语义配套,是唯一的复位入口。

示例:

java
api.clearNoteTransform(42L);

与 GameStateAccess 的双面差异(同一执行体、两套入口)

维度ExtraContentApi(谱面原语侧)GameStateAccess(会话侧)
参数类型float(与谱面 _extra.json 同口径)double(模组会话写入)
轨道旋转setLaneRotation(int, float rotationRad),无 pivot,圆心固定判定线中点setLaneRotation(int, double rotationRad),无 pivot,圆心固定判定线中点
每轨复位有命名式复位入口:setLaneHeightAuto / setLaneScaleAuto / setLaneSkewAuto / setLaneArcAuto无 per-lane auto(部分通道有读取 getter 供模组自持值)
轨道区偏移setTrackOffset(float x, float y)setTrackOffset(double x, double y)
3D 倾斜setTrackTilt3D(double) / setTrackTilt3DAuto()setTrackTilt3D(double) / setTrackTilt3DAuto()
相机通道无相机原语(track_tilt 在宿主内归一为相机 pitch 分量)独占 setCameraPose(...) / setCameraPoseAuto()
per-lane 3D 朝向无 pitch/yaw 原语:只有 setLaneOffset 的 z 深度与 setLaneRotation 的 roll;需要三轴朝向请用谱面 lane_pose 或自绘 MatrixStack同样无等价会话原语(setLaneOffset 的 z 之外无 3D 朝向)
生命周期谱面时间轴驱动(parser apply 阶段 / 游玩期一次性触发;宿主重建声明面时不包含模组写入)玩家会话级模组状态(随模组会话持有;setCameraPose 为绝对写、接管至倒带 / 新谱面复位)

两套入口写同一执行体(TrackRenderer 每轨状态 / 相机位姿),后写生效——模组与谱面特效同时使用会互相覆盖;在 GameplayTickEvent.Post 内每帧重写 = 确定性最高优先级。本接口仅在游玩上下文非 null(见 ChartRuntimeContext.extraContent()),调用方必须判空。

完整签名

java
public interface ExtraContentApi {

    void setLaneAlpha(int lane, float alpha);

    void setKeyIndicatorAlpha(int lane, float alpha);

    void setTrackOffset(float x, float y);

    void setLaneOffset(int lane, float x, float y, float z);

    void setLaneRotation(int lane, float rotationRad);

    void setLaneSpeedFactor(int lane, float factor);

    void setLaneHeight(int lane, float height);

    void setLaneHeightAuto(int lane);

    void setLaneScale(int lane, float sx, float sy);

    void setLaneScaleAuto(int lane);

    void setLaneSkew(int lane, float skew, float anchorY);

    void setLaneSkewAuto(int lane);

    void setLaneArc(int lane, float bendDir, float bendAmp, float arcCenterY);

    void setLaneArcAuto(int lane);

    void setTrackTilt3D(double tiltDeg);

    void setTrackTilt3DAuto();

    void setNoteAlpha(int lane, float alpha);

    void setUiAlpha(float alpha);

    void createFakeTrack(int id, int originLane, float alpha);

    void setFakeTrackTransform(int id, float x, float y, float alpha,
                               float scaleX, float scaleY, float rotationRad);

    void setFakeTrackAlpha(int id, float alpha);

    void setFakeTrackRotation(int id, float rotationRad);

    void setFakeTrackRotation(int id, float rotationRad, String pivot);

    void setFakeTrackSkew(int id, float skew, float anchorY);

    void setFakeTrackArc(int id, float bendDir, float bendAmp, float arcCenterY);

    void setFakeTrackHeight(int id, float height);

    void setFakeTrackKeyIndicatorAlpha(int id, float alpha);

    void createFakeNote(int id, int fakeTrackId, String noteType, Long lengthMs, float alpha);

    void setFakeNoteAlpha(int id, float alpha);

    void setNoteTransform(long noteId, float dx, float dy, float dz,
                          float pitchDeg, float yawDeg, float rollDeg, float scale);

    void clearNoteTransform(long noteId);
}

线程:GL 主线程调用(与谱面加载/游玩同线程);通道内部不做同步,跨线程调用需自行切回主线程。

生命周期阶段:谱面加载(parser apply 阶段,绑定前缓冲、绑定后重放)与游玩期;每局新实例,onExit 清除,无跨局状态。

稳定性:1.x 加性新增;2.x 内新增方法只增不破。3.0 随世界模型升级做过一次签名删减:setLaneRotation 去掉 pivot 参数、createFakeTrack 去掉 z 参数——3.x 模组需按本页签名书写。