Theseus 模组文档
API 参考 / capability 包:服务、状态与游玩访问

GameStateAccess


游玩状态机与游玩访问能力:读 / 改音乐时间与暂停结束状态、控制每轨视觉几何(流速、旋转、缩放、斜切、弧线、3D 偏移)、读写相机位姿与投影查询、查询轨道区布局、读写游戏内光标、强制 altHUD,以及查询面形态的模组实体层级。经 ctx.capabilities().get(GameStateAccess.class) 取用,只在游玩中注册(其它场景返回 null,且取到的是携带调用方模组 id 的包装视图,用于实体所有权校验)。

除 setLaneSpeedFactor(改变音符下落外观与收集窗口)外,轨道几何与相机类入口都是纯视觉:判定引擎零消费,画面写得再激进也不影响判定结果与成绩。

方法速览

方法用途
musicTimeMs()当前音乐时间(毫秒)
isPaused()是否暂停
isFinished()是否已结束
play()开始游玩(进入播放)
pause()暂停(与 ESC 同路径,可被 PauseEvent 否决)
resume()恢复(含恢复倒计时与倒带,可被 ResumeEvent 否决)
seek(long)跳转到指定音乐时间
setSpeed(double)设置播放速度倍率
requestMode(String)程序化激活已注册玩法模式
endGame()结束当前游玩(进入结算)
setLaneSpeedFactor(int, double)设置单轨流速倍率
getLaneSpeedFactor(int)读取单轨流速倍率
setLaneRotation(int, double)设置单轨旋转(弧度)
getLaneRotation(int)读取单轨旋转(弧度)
setLaneScale(int, double, double)设置单轨渲染缩放
getLaneScaleX(int) / getLaneScaleY(int)读取单轨缩放
setLaneSkew(int, double, double)设置单轨斜切形变
getLaneSkew(int)读取单轨斜切系数
setLaneArc(int, double, double, double)设置单轨弧线形变
getLaneArcBend(int)读取单轨有符号弧幅
setLaneOffset(int, double, double, double)设置单轨 3D 偏移
flashLane(int, long)触发单轨原生按压高亮
project(double, double, double)内容坐标 → 屏幕坐标
unproject(double, double, double)屏幕坐标 → 内容坐标(指定深度平面)
cameraPose()当前生效相机位姿
setTrackTilt3D(double)轨道区 3D 倾斜(度)
setTrackTilt3DAuto()复位 3D 倾斜
setCameraPose(double, double, double, double, double, double)直接写相机位姿(接管视角)
setCameraPoseAuto()复位相机位姿接管
setAltHudForced(boolean)强制 / 恢复备用 HUD
cursorPosition() / setCursorPosition(int, int)读写游戏内光标(画布逻辑坐标)
laneRotationPivot(int)单轨旋转圆心(世界坐标)
trackAreaGeometry()轨道区布局快照
setTrackOffset(double, double)整区 X/Y 平移
createEntity(String)创建本模组实体(未挂载)
mountToTrackArea(SceneEntity)挂到轨道区节点
mountToTrack(SceneEntity, int)挂到指定轨道节点
mountToEntity(SceneEntity, SceneEntity)挂到自有实体之下
entityPose(SceneEntity)本 tick 本地位姿写入面
entityWorldMatrix(SceneEntity)世界矩阵(列主序 double[16])
entityVisible(SceneEntity)有效可见性(父 ∧ 本)
setEntityVisible(SceneEntity, boolean)写本节点自身可见性
entityAlpha(SceneEntity)有效 alpha(父链连乘)
setEntityAlpha(SceneEntity, double)写本节点自身 alpha
destroyEntity(SceneEntity)显式销毁(级联子树)

完整签名

java
public interface GameStateAccess {

    long musicTimeMs();

    boolean isPaused();

    boolean isFinished();

    void play();

    void pause();

    void resume();

    void seek(long musicTimeMs);

    void setSpeed(double speed);

    boolean requestMode(String modeId);

    void setLaneSpeedFactor(int lane, double factor);

    double getLaneSpeedFactor(int lane);

    void setLaneRotation(int lane, double rotationRad);

    double getLaneRotation(int lane);

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

    double getLaneScaleX(int lane);

    double getLaneScaleY(int lane);

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

    double getLaneSkew(int lane);

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

    double getLaneArcBend(int lane);

    void setLaneOffset(int lane, double offsetX, double offsetY, double offsetZ);

    void flashLane(int lane, long durationMs);

    default double[] project(double x, double y, double z);

    default double[] unproject(double screenX, double screenY, double z);

    default double[] cameraPose();

    void setTrackTilt3D(double tiltDeg);

    void setTrackTilt3DAuto();

    void setCameraPose(double x, double y, double z, double yawDeg, double pitchDeg, double fovDeg);

    void setCameraPoseAuto();

    void setAltHudForced(boolean forced);

    int[] cursorPosition();

    void setCursorPosition(int x, int y);

    double[] laneRotationPivot(int lane);

    double[] trackAreaGeometry();

    void setTrackOffset(double x, double y);

    default SceneEntity createEntity(String name);

    default void mountToTrackArea(SceneEntity e);

    default void mountToTrack(SceneEntity e, int lane);

    default void mountToEntity(SceneEntity child, SceneEntity parent);

    default EntityPose entityPose(SceneEntity e);

    default double[] entityWorldMatrix(SceneEntity e);

    default boolean entityVisible(SceneEntity e);

    default void setEntityVisible(SceneEntity e, boolean v);

    default double entityAlpha(SceneEntity e);

    default void setEntityAlpha(SceneEntity e, double a);

    default void destroyEntity(SceneEntity e);

    void endGame();
}

musicTimeMs()

签名:

java
long musicTimeMs();

行为:返回当前音乐时间(毫秒),即游玩时间轴——倒带期间会随倒带一起回退。暂停时返回冻结值。单位毫秒、long。

示例:

java
GameStateAccess gs = ctx.capabilities().get(GameStateAccess.class);
if (gs != null) {
    long now = gs.musicTimeMs();
}

isPaused()

签名:

java
boolean isPaused();

行为:当前是否处于暂停态(pause() 或 ESC 暂停置位;resume() 受理后立即复位为 false,恢复倒计时期间不算暂停)。

示例:

java
if (gs.isPaused()) {
    // 暂停中
}

isFinished()

签名:

java
boolean isFinished();

行为:本局是否已结束(已进入结算流程)。

示例:

java
if (!gs.isFinished()) {
    // 仍在游玩
}

play()

签名:

java
void play();

行为:开始游玩:启动谱面音频(谱面声明了音频且文件存在时)并把音乐标记为已开始,同时发布 GameplayStart。已开始或仍在加载时为空操作;本方法不解除暂停(恢复请用 resume())。

示例:

java
gs.play();

pause()

签名:

java
void pause();

行为:暂停游玩,与 ESC 暂停走同一路径:先发布可取消的 PauseEvent(DENY 时状态一律不变),随后置暂停、暂停谱面音频并播放提示音。已暂停或已结束时空操作。

示例:

java
gs.pause();

resume()

签名:

java
void resume();

行为:恢复游玩,与暂停菜单 RESUME 同一路径:先发布可取消的 ResumeEvent(DENY 时保持暂停),随后进入恢复倒计时 + 倒带——判定 / 渲染时间从暂停点按缓动回退到 max(0, T−3s),音频同步反向回放,倒带结束后从终点重新正放。倒带期按键被丢弃,不产生任何新判定;已判定音符状态与计数不变。未暂停或已结束时空操作。

示例:

java
gs.resume();

seek(long musicTimeMs)

签名:

java
void seek(long musicTimeMs);

行为:设置音乐时间到指定毫秒;负值钳为 0。若音乐已开始且谱面声明了音频,同时向音频引擎 seek。不改变暂停态。

示例:

java
gs.seek(30_000L);   // 跳到 30 秒

setSpeed(double speed)

签名:

java
void setSpeed(double speed);

行为:设置播放速度倍率。宿主实现把 max(0.05, speed) 作为绝对播放速率下发给音频命令通道,同时把当前滚动速度乘以该倍率——因此连续多次调用会累乘滚动速度,需要绝对设定时按当前值一次调用即可。

示例:

java
gs.setSpeed(1.5);   // 1.5 倍速

requestMode(String modeId)

签名:

java
boolean requestMode(String modeId);

行为:程序化激活一个已注册的玩法模式("<ns>:<name>"),语义与选曲面板传 modeId 参数的进场选择一致:旧模式 onExit → 切换 → 新模式 onEnter(每步异常隔离)。激活后 mapLane / 镜像 / 每帧回调立即按新模式派发;激活 seecmd:disorder 与面板显式选择同语义(整曲强制无序)。

示例:

java
if (!gs.requestMode("mymod:hardcore")) {
    ctx.getLogger().warning("模式未注册,保持当前模式");
}

endGame()

签名:

java
void endGame();

行为:结束当前游玩并进入结算;已结束时为空操作。

示例:

java
gs.endGame();

setLaneSpeedFactor(int lane, double factor)

签名:

java
void setLaneSpeedFactor(int lane, double factor);

行为:设置指定真轨道的流速倍率(乘在全局 scrollSpeed 上),瞬时生效。1.0 = 与全局一致,0 = 静止,负值 = 反向下落;不钳制,接受任意有限值。只影响音符下落外观与该轨收集窗口,判定仍按音乐时间,不改变判定时机。lane 越界时静默忽略。

示例:

java
gs.setLaneSpeedFactor(0, 1.5);    // 第 0 轨 1.5 倍速
gs.setLaneSpeedFactor(1, -1.0);   // 第 1 轨反向下落

getLaneSpeedFactor(int lane)

签名:

java
double getLaneSpeedFactor(int lane);

行为:读取该轨流速倍率;越界或无布局时返回 1.0。

示例:

java
double f = gs.getLaneSpeedFactor(0);

setLaneRotation(int lane, double rotationRad)

签名:

java
void setLaneRotation(int lane, double rotationRad);

行为:设置指定真轨道绕判定线中点的旋转角(弧度,正值顺时针),纯视觉,不影响判定与输入。宿主把弧度换算为度写入每轨 rollDeg,因此与谱面额外内容特效 lane_pose.rollDeg 写同一份每轨状态(同时使用会互相覆盖)。旋转轨道的背景、分隔线、音符(含自定义类型)与顶端剔除窗口都会跟随变换。

3.0 起无 pivot 参数:圆心固定为该轨判定线中点;旧 TRACK_CENTER 等价形态请改用 EntityPose.rotateZ(deg, pivotX, pivotY) 显式给圆心。lane 越界时静默忽略。

示例:

java
gs.setLaneRotation(0, Math.toRadians(15));   // 第 0 轨顺时针 15°

getLaneRotation(int lane)

签名:

java
double getLaneRotation(int lane);

行为:读取该轨旋转角(弧度,由存储的度值反算);越界或无布局时返回 0.0。

示例:

java
double rad = gs.getLaneRotation(0);

setLaneScale(int lane, double sx, double sy)

签名:

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

行为:设置指定真轨道的渲染缩放(纯视觉)。该轨的背景、分隔线、判定线(按键框顶边)、按键指示器与音符在同一仿射变换内缩放,pivot = 该轨几何中心。sx / sy 钳制 ≥0.01(防止 0 缩放导致绘制异常)。与谱面每轨缩放通道写同一份 LanePose 状态(后写生效)。

示例:

java
gs.setLaneScale(2, 1.2, 0.8);

getLaneScaleX(int lane)

签名:

java
double getLaneScaleX(int lane);

行为:读取该轨水平缩放因子;默认 / 越界 1.0。

示例:

java
double sx = gs.getLaneScaleX(2);

getLaneScaleY(int lane)

签名:

java
double getLaneScaleY(int lane);

行为:读取该轨垂直缩放因子;默认 / 越界 1.0。

示例:

java
double sy = gs.getLaneScaleY(2);

setLaneSkew(int lane, double skew, double anchorY)

签名:

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

行为:设置指定真轨道的斜切形变(纯视觉)。合成偏移 = skew×(y−anchorY) + 弧线项(y)(与 setLaneArc 共享同一 per-lane 形变通道,纯 y 函数、每帧 O(1) 求值——确定性契约:无状态 / 无随机 / 无墙钟)。该轨背景 / 分隔线 / 按键框 / 音符绘制的 x 统一叠加;判定线保持水平直线(按键框整体横移),音符中心 x 跟随其所在 y 的偏移、自身不旋转不变形。

skew 钳 |skew|≤1(每 px 纵移的横移系数,1 = 45° 斜切极限);anchorY 为零偏移锚点(画布 y)。与谱面额外内容特效 lane_skew 写同一份每轨形变状态(后写生效)。lane 越界时静默忽略。

示例:

java
gs.setLaneSkew(0, 0.25, gs.trackAreaGeometry()[3]);   // 以判定线高度为锚点

getLaneSkew(int lane)

签名:

java
double getLaneSkew(int lane);

行为:读取该轨斜切系数(已钳制后的值);默认 / 越界 0.0。

示例:

java
double k = gs.getLaneSkew(0);

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

签名:

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

行为:把指定真轨道整轨弯成圆弧(纯视觉)。标准圆弧:弧心处偏移 0、切线水平,距弧心 600px 竖直距离处弧偏移 = bendAmp。bendDir 钳 [-1,1](-1 = 向左弯、+1 = 向右弯);bendAmp 取绝对值后钳 ≤300px;宿主内部存的是有符号幅度 bendDir×bendAmp。arcCenterY 为弧心 y(画布坐标)。与谱面额外内容特效 lane_arc 写同一份每轨形变状态。lane 越界时静默忽略。

示例:

java
gs.setLaneArc(1, 1.0, 120.0, 360.0);

getLaneArcBend(int lane)

签名:

java
double getLaneArcBend(int lane);

行为:读取该轨有符号弧线幅度(bendDir×bendAmp,px);默认 / 越界 0.0。

示例:

java
double bend = gs.getLaneArcBend(1);

setLaneOffset(int lane, double offsetX, double offsetY, double offsetZ)

签名:

java
void setLaneOffset(int lane, double offsetX, double offsetY, double offsetZ);

行为:设置指定真轨道的 3D 偏移(世界坐标 px,纯视觉,不影响判定)。真轨本地 (0,0,0) = 世界原点,未写 lane_pose 时所有轨默认堆叠在世界原点;本方法与谱面 lane_pose.x/y/z 写同一份每轨状态(后写生效)。轨道的背景、分隔线、音符(含自定义类型)均跟随偏移。

offsetZ 为沿 +z(屏幕内) 的深度(px),在旋转之后施加,与旋转圆心无交互;只传 x/y 的旧代码补 0 即像素输出不变。lane 越界时静默忽略。

示例:

java
gs.setLaneOffset(0, 0.0, 0.0, -120.0);   // 第 0 轨向屏幕外推 120px

flashLane(int lane, long durationMs)

签名:

java
void flashLane(int lane, long durationMs);

行为:触发指定真轨道的原生按压高亮:与玩家按键时轨道指示器 / 轨道背景点亮完全同源(同一份按下状态),当帧立即点亮,持续 durationMs 毫秒后自动熄灭,期间真实按键状态照常叠加。重复调用刷新持续时间。用于模组判定命中时复用原生视觉反馈,无需自绘。lane 越界或 durationMs ≤ 0 时无操作。

示例:

java
gs.flashLane(2, 120);

project(double x, double y, double z)

签名:

java
double[] project(double x, double y, double z);

行为:内容坐标 → 屏幕坐标。内容坐标 = 轨道绘制使用的世界坐标(画布 px、y 向下、z 沿 +z 向屏幕内,0 = 内容平面)。使用最近一帧渲染生效的世界相机(含 setCameraPose、tilt 与位姿 adjuster 链的结果),与屏幕所见一致;在 tick 中调用时拿到的是上一帧相机状态(本帧渲染前宿主才更新)。

返回 double[]{screenX, screenY, ndcDepth}(像素,与画布逻辑坐标同空间);ndcDepth ∈ [-1,1](-1 近裁面、+1 远裁面),可直接用于排序 / 可见性。点位于相机后方(齐次 w ≤ 1e-9)或视锥退化时返回 null;超出远裁面的点仍会返回 ndcDepth > 1,调用方需自行判断裁剪。默认实现返回 null。

示例:

java
double[] p = gs.project(640, 360, 0);
if (p != null && p[2] >= -1.0 && p[2] <= 1.0) {
    // p[0], p[1] 为屏幕像素坐标
}

unproject(double screenX, double screenY, double z)

签名:

java
double[] unproject(double screenX, double screenY, double z);

行为:屏幕坐标 → 内容坐标,落在指定深度平面 z 上(project 的逆)。给定屏幕点与内容深度,求出该屏幕射线与 z 平面的交点;典型用途是 3D 内容的鼠标拾取(先把光标落到目标深度平面,再做 2D 命中判定)。返回 double[]{x, y, z}(内容坐标)。

屏幕坐标按画布逻辑像素(0..canvasWidth / 0..canvasHeight)解释;视线与该平面平行(行列式 ≈ 0)等退化情形返回 null。默认实现返回 null。

示例:

java
int[] c = gs.cursorPosition();
double[] hit = gs.unproject(c[0], c[1], 0.0);   // 光标落在内容平面上的点

cameraPose()

签名:

java
double[] cameraPose();

行为:读取当前生效的相机位姿,口径与 setCameraPose 一致(内容坐标 / 度)。返回 double[]{x, y, z, yawDeg, pitchDeg, fovDeg}(宿主实现恒 6 元素);fovDeg 为 Double.NaN 表示 AUTO(由宿主按画布推导)。仅作信息与近似计算用——精确换算请用 project / unproject(它们包含 tilt / adjuster 链等全部合成)。默认实现返回 null。

示例:

java
double[] pose = gs.cameraPose();
if (pose != null) {
    boolean autoFov = Double.isNaN(pose[5]);
}

setTrackTilt3D(double tiltDeg)

签名:

java
void setTrackTilt3D(double tiltDeg);

行为:整个轨道区绕判定线锚点的 X 轴做真 3D 透视倾斜(单位度,正值 = 顶部远离相机向后倒,Arcaea 式;宿主钳 ±89°)。轨道向消失点汇聚、顶部纵深收缩;tilt = 0 完全等价默认正交画面。作用于渲染 WORLD / BACKGROUND 层的相机矩阵,HUD 与系统 UI 恒为正交、不受影响。

与谱面特效通道 track_tilt 写同一份执行体状态(后写生效),生命周期为玩家会话级。2026-10-11 起内部归一为相机位姿 pitch 分量的语法糖,画面效果与旧 tilt 模型数学恒等。纯视觉,判定零消费;在 GameplayTickEvent.Post 内每帧重写 = 确定性最高优先级。

示例:

java
gs.setTrackTilt3D(30.0);

setTrackTilt3DAuto()

签名:

java
void setTrackTilt3DAuto();

行为:把轨道 3D 倾斜复位到默认(tilt = 0,恒等正交)。模组停用 / 退出自绘效果时还原用;与谱面 track_tilt 共用同一份状态,因此也会覆盖谱面写入。

示例:

java
gs.setTrackTilt3DAuto();

setCameraPose(double x, double y, double z, double yawDeg, double pitchDeg, double fovDeg)

签名:

java
void setCameraPose(double x, double y, double z, double yawDeg, double pitchDeg, double fovDeg);

行为:直接设置相机位姿——相机无特殊设计,模组挪相机即接管视角,无需宿主开关。

示例:

java
double[] geo = gs.trackAreaGeometry();
gs.setCameraPose(geo[0] / 2.0, geo[3] - 160.0, -520.0, 0.0, -15.0,
        com.seecmd.mod.api.render.CameraPose.FOV_AUTO);

setCameraPoseAuto()

签名:

java
void setCameraPoseAuto();

行为:清除 setCameraPose 的接管标志,宿主恢复默认位姿推导(直视轨道,setTrackTilt3D / 谱面 track_tilt 通道重新作用于视图),相机位姿 adjuster 链输入回到默认推导。对未接管的相机是无害空操作。

为什么需要它:setCameraPose 是绝对写、接管持续到倒带 / 新谱面复位——只写「看起来像默认」的位姿不能恢复宿主默认推导(tilt 通道会被持续压制);这是唯一干净的还原入口。纯视觉,判定零消费。

示例:

java
gs.setCameraPoseAuto();
gs.setTrackTilt3DAuto();

setAltHudForced(boolean forced)

签名:

java
void setAltHudForced(boolean forced);

行为:强制切换游玩 HUD 至备用 UI(altHUD:顶部中央大号 COMBO + 判定等级 + 右上角准度 + 左上角 HP 条)。altHUD 原本由玩家「界面不透明度」滑杆驱动;本方法直接强制启用 / 恢复,与滑杆状态无关。

示例:

java
gs.setAltHudForced(true);

cursorPosition()

签名:

java
int[] cursorPosition();

行为:查询当前游戏内光标坐标 int[]{x, y},为画布逻辑坐标(与 NoteRenderContext 的 x() / y() 同一空间),与真实光标、自绘光标同源。返回最后已知位置(光标未进入画布时为上次位置),恒返回 2 元素数组。

示例:

java
int[] cur = gs.cursorPosition();

setCursorPosition(int x, int y)

签名:

java
void setCursorPosition(int x, int y);

行为:直接设置游戏内光标位置(画布逻辑坐标)。写入的就是 cursorPosition() 返回的那份位置;不影响系统真实光标、不做 OS 级 warp。自绘光标与场景轮询随之自然跟随;玩家移动真实鼠标后照常在其基础上累加位移(后发生者生效——模组若需与玩家共存,须自行检测真实输入并让位)。

示例:

java
double[] pivot = gs.laneRotationPivot(0);
if (pivot != null) {
    gs.setCursorPosition((int) pivot[0], (int) pivot[1] - 120);
}

laneRotationPivot(int lane)

签名:

java
double[] laneRotationPivot(int lane);

行为:查询指定真轨道当前旋转圆心的世界坐标 double[]{x, y}:含该轨 lane_pose 平移(随轨道移动),不含 setTrackOffset(整区偏移)。3.0 起圆心恒为判定线中点,不再有「模式」概念。轨道索引无效时返回 null。

示例:

java
double[] pv = gs.laneRotationPivot(0);
if (pv != null) {
    // pv[0], pv[1] 为圆心世界坐标
}

trackAreaGeometry()

签名:

java
double[] trackAreaGeometry();

行为:查询当前轨道区布局几何快照 double[]{canvasWidth, trackAreaLeft, trackAreaWidth, judgeLineY, laneCount}。轨道区 = 含两侧 padding 的完整轨道区域(padding 左右对称——区域居中即轨道组居中)。

只读布局快照:坐标为默认布局基准,不含 setTrackOffset / lane_move 等运行时视觉偏移(那些偏移渲染期才整体平移,不回写布局字段),因此可安全用于几何决策。布局未就绪(谱面未绑定)时 laneCount 为 0、几何为宿主默认,调用方按 laneCount <= 0 / trackAreaWidth <= 0 自行守卫(每帧轮询即可自愈)。恒返回 5 元素数组。

示例:

java
double[] geo = gs.trackAreaGeometry();
if (geo[4] > 0 && geo[2] > 0) {
    gs.setTrackOffset((geo[0] - geo[2]) / 2.0 - geo[1], 0.0);
}

setTrackOffset(double x, double y)

签名:

java
void setTrackOffset(double x, double y);

行为:整个轨道区的 X/Y 平移(画布 px,相对默认布局的偏移量,(0,0) = 默认布局;正值右移 / 下移)。

与谱面特效通道 ExtraContentApi.setTrackOffset 写同一执行体(后写生效),但生命周期为玩家会话级(与 setLaneRotation 同类,随模组会话持有)。纯视觉,判定零消费;在 GameplayTickEvent.Post 内每帧重写 = 确定性最高优先级。

整区深度偏移不在本方法:用轨道位姿 adjuster 的 PoseOps.translate3D(0, 0, dz);逐轨深度用 setLaneOffset。

示例:

java
gs.setTrackOffset(0.0, 0.0);   // 归位到默认布局

createEntity(String name)

签名:

java
default SceneEntity createEntity(String name);

行为:创建一个调用方模组所有的场景实体(未挂载)。实体 = 纯变换节点(组,无渲染内容):查询面形态下模组经 entityWorldMatrix 取世界矩阵后自行变换自绘内容。创建后需经 mountToTrackArea / mountToTrack / mountToEntity 挂载才进入世界层级。

name 仅用于日志,null 时宿主自动命名。返回实体句柄;世界层级未装配(布局未就绪)时返回 null 并限频告警。默认实现返回 null。生命周期:随游玩场景存续,游玩结束时宿主自动级联销毁全部模组实体。

示例:

java
SceneEntity marker = gs.createEntity("marker");

mountToTrackArea(SceneEntity e)

签名:

java
default void mountToTrackArea(SceneEntity e);

行为:把调用方模组的实体挂到轨道区节点之下(任何模组可挂,轨道区是宿主实体)。

示例:

java
gs.mountToTrackArea(marker);

mountToTrack(SceneEntity e, int lane)

签名:

java
default void mountToTrack(SceneEntity e, int lane);

行为:把实体挂到指定轨道节点之下;窗口 / 所有权 / 深度校验同 mountToTrackArea。lane 为真轨道索引(0 起),无效轨道被拒绝 + 限频告警。

示例:

java
gs.mountToTrack(marker, 1);

mountToEntity(SceneEntity child, SceneEntity parent)

签名:

java
default void mountToEntity(SceneEntity child, SceneEntity parent);

行为:把模组实体挂到另一个模组实体之下。父子都必须属于调用方模组(所有权)——挂到他人实体之下被拒绝。窗口 / 深度 / 成环校验同 mountToTrackArea。

示例:

java
SceneEntity group = gs.createEntity("group");
gs.mountToTrackArea(group);
gs.mountToEntity(marker, group);

entityPose(SceneEntity e)

签名:

java
default EntityPose entityPose(SceneEntity e);

行为:取实体的本 tick 本地位姿写入面(标量偏移可写 + op 追加面,见 SceneEntity 与 EntityPose(render 包))。

示例:

java
EntityPose pose = gs.entityPose(marker);
if (pose != null) {
    pose.setOffsetX(120);
    pose.rotateZ(30.0, 0, 0);
}

entityWorldMatrix(SceneEntity e)

签名:

java
default double[] entityWorldMatrix(SceneEntity e);

行为:查询实体世界矩阵:16 元素列主序 double[16](与 CameraState 的 V/P 同布局)= 世界(父)·本地(实体) 自顶向下累积(含轨道区偏移与位姿链、本 tick 写入的实体位姿)。返回防御性拷贝,模组可留存;查询任何时机合法(无窗口限制)。无效 / 已销毁句柄返回 null + 限频告警。默认实现返回 null。

示例:

java
double[] m = gs.entityWorldMatrix(marker);
if (m != null) {
    double wx = m[0] * 0 + m[4] * 0 + m[12];   // 本地原点 → 世界
    double wy = m[1] * 0 + m[5] * 0 + m[13];
}

entityVisible(SceneEntity e)

签名:

java
default boolean entityVisible(SceneEntity e);

行为:查询有效可见性(继承量:父 ∧ 本——任一祖先不可见或已销毁即 false)。无效句柄返回 false。默认实现返回 false。

示例:

java
if (gs.entityVisible(marker)) {
    // 整条父链都可见
}

setEntityVisible(SceneEntity e, boolean v)

签名:

java
default void setEntityVisible(SceneEntity e, boolean v);

行为:写实体自身可见性(只影响本节点,默认 true)。不提供「子强制可见」——父不可见 ⇒ 整棵子树不可见。改他人实体被拒绝 + 限频告警;无 tick 窗口限制。

示例:

java
gs.setEntityVisible(marker, false);

entityAlpha(SceneEntity e)

签名:

java
default double entityAlpha(SceneEntity e);

行为:查询有效 alpha(沿父链连乘,默认恒 1)。无效句柄返回 0。默认实现返回 0.0。

示例:

java
double a = gs.entityAlpha(marker);

setEntityAlpha(SceneEntity e, double a)

签名:

java
default void setEntityAlpha(SceneEntity e, double a);

行为:写本节点自身 alpha(乘性继承因子,默认 1)。改他人实体被拒绝 + 限频告警;无 tick 窗口限制。

示例:

java
gs.setEntityAlpha(marker, 0.5);

destroyEntity(SceneEntity e)

签名:

java
default void destroyEntity(SceneEntity e);

行为:显式销毁实体,并级联销毁其子树(挂在其下的模组实体一并销毁)。挂载窗口约束同 mountToTrackArea(tick 内拒绝);改他人实体被拒绝。游玩结束时宿主自动级联销毁全部模组实体,此后句柄失效(查询返回 null / false / 0 + 限频告警),不要跨局缓存句柄。

示例:

java
gs.destroyEntity(marker);

线程:源码未声明额外线程约束。宿主实现直接读写游玩场景与渲染器状态,且 entityPose 仅在 tick 分发期间有效——请在游戏线程(事件回调、tick、渲染回调)调用,不要在自建网络线程上操作。

稳定性:2.0 起冻结:2.x 内只增不破。其中「轨道几何」区块(setLaneRotation / getLaneRotation、setLaneScale / getLaneScaleX / getLaneScaleY、setLaneSkew / getLaneSkew、setLaneArc / getLaneArcBend、setLaneOffset、flashLane、setAltHudForced、cursorPosition / setCursorPosition、laneRotationPivot、trackAreaGeometry、setTrackOffset、setLaneSpeedFactor / getLaneSpeedFactor)标记为实验性:签名稳定,语义仍可能微调;setTrackTilt3D / setTrackTilt3DAuto、setCameraPose / setCameraPoseAuto、project / unproject / cameraPose 与「模组可见层级」区块(createEntity / mountTo* / entityPose / entityWorldMatrix / entityVisible / setEntityVisible / entityAlpha / setEntityAlpha / destroyEntity)同为实验性。3.0 已删除旧的每轨旋转圆心常量(LANE_ROTATE_PIVOT_*)与 setLaneRotation 的 pivot 参数——圆心固定为判定线中点。