Theseus 模组文档
API 参考 / 只读视图、场景、音频与文本

GameplayContext


游玩状态只读视图。宿主在事件发布与滤镜调用时构造快照,模组可在 GameStartEvent / ChartLoadEvent / NoteJudgedEvent / ComboBreakEvent / GameEndEvent / PauseEvent / ResumeEvent 的 context(),以及 FilterFrame#context()、JudgmentAdjuster#adjust(JudgeResult, GameplayContext) 中拿到它。下文示例中的 ctx 均指这样取得的 GameplayContext 快照。

方法速览

方法用途
musicTimeMs()当前音乐时间 τ(毫秒),倒带期非单调
combo()当前连击数
score()当前分数
perfects() / greats() / misses()三种内置判定计数
maxCombo()历史最大连击
paused()是否暂停
finished()是否已结束
preview()是否来自编辑器/宿主的内嵌预览会话
sessionId()游玩会话 id(实机为空串)
hostKind()宿主类型 game / editor / cli
chartTitle() / chartAuthor() / chartDifficulty()谱面元数据三项
progress()按已判音符数计算的进度 0-1
disorderActive() 等 7 个无序模式(disorder)状态与充能条数据
chartDurationMs()谱面末音符时间(毫秒)
totalNoteCount() / judgedNoteCount() / remainingNoteCount()音符总数 / 已判 / 剩余
musicPositionRatio()按音乐时间线计算的进度 0-1
accuracy()准度 0-1
judgmentWindowMs()合并后的当前判定窗口(可能为 null)
defaultJudgmentWindowMs()内置默认判定窗口 70/150/150/150/50
chartBpm()谱面 0ms 处的主 BPM
pendingNotes()3 秒预告窗口内的待判定音符
nextNote()下一个待判定音符(比列表轻量)
lanes()当前渲染中的全部轨道视图
altHudActive() / altComboCenterX() / altComboBottomY()AltHud 激活状态与 COMBO 区定位
coverImage()谱面曲绘句柄(无则 null)
currentModeId()当前激活模式 id
chartView()谱面元数据只读视图
isRewinding()是否处于暂停恢复的倒带重演窗口
hp() / maxHp()游玩期血量快照(未提供为 -1)
noteById(long)按稳定实例 id 反查音符
notesInWindow(int, long, long)时间窗批量查询音符 id
activeHitEffects()存活的活动打击特效句柄
audioDurationMs()音频真实时长
beatNumerator() / beatDenominator()拍号(当前恒 4/4)
beatIndex() / beatPhase() / beatBpm() / beatPeriodMs()节拍快照(τ 的纯函数)

musicTimeMs()

java
long musicTimeMs();

行为:当前音乐时间 τ(毫秒)。倒带重演窗口内非单调(先倒流回 T-3s 再正向重演回 T),依赖「时间只增」的模组必须先查 isRewinding()。 示例:

java
long now = ctx.musicTimeMs();

combo()

java
int combo();

行为:当前连击数,被 MISS 打断后归零;与 maxCombo() 不可互替。 示例:

java
if (ctx.combo() >= 100) { /* 百连演出 */ }

score()

java
int score();

行为:当前总分(宿主计分器实时值)。 示例:

java
int score = ctx.score();

perfects()

java
int perfects();

行为:本局 PERFECT 计数。示例:

java
int p = ctx.perfects();

greats()

java
int greats();

行为:本局 GREAT 计数。示例:

java
int g = ctx.greats();

misses()

java
int misses();

行为:本局 MISS 计数(含漏接与超窗)。示例:

java
int m = ctx.misses();

maxCombo()

java
int maxCombo();

行为:历史最大连击数(不随当前连击归零而减小)。示例:

java
int best = ctx.maxCombo();

paused()

java
boolean paused();

行为:当前是否处于暂停态。暂停菜单期间为 true;恢复倒计时期间为 false(宿主在进入倒计时前已清除暂停位,倒带窗口改由 isRewinding() 表达)。示例:

java
if (ctx.paused()) return;

finished()

java
boolean finished();

行为:本局是否已结束(结算流程启动后为 true)。示例:

java
boolean over = ctx.finished();

preview()

java
default boolean preview();

行为:本上下文是否来自编辑器/宿主的内嵌预览会话。预览与实机共用同一判定/渲染内核,但预览不访问音频设备、不写统计;模组据此决定是否把本局计入统计、是否播放真实音效。默认返回 false(既有实现者无需改动)。 示例:

java
if (ctx.preview()) { /* 预览模式:不要写持久化统计 */ }

sessionId()

java
default String sessionId();

行为:当前游玩会话 id。实机为空串;编辑器预览返回创建时指定的 id(如 "viewport-3"),用于多视口下区分同一模组的状态。默认返回 ""。 示例:

java
String key = "hud:" + ctx.sessionId();

hostKind()

java
default String hostKind();

行为:宿主类型。默认 "game";当前宿主在预览会话中返回 "editor"。"cli" 为预留取值。 示例:

java
boolean inEditor = "editor".equals(ctx.hostKind());

chartTitle()

java
String chartTitle();

行为:谱面标题;谱面元数据缺失时为空串。示例:

java
String title = ctx.chartTitle();

chartAuthor()

java
String chartAuthor();

行为:谱面作者(metadata.charter);缺失时为空串。示例:

java
String author = ctx.chartAuthor();

chartDifficulty()

java
String chartDifficulty();

行为:谱面难度名;缺失时为空串。示例:

java
String diff = ctx.chartDifficulty();

progress()

java
double progress();

行为:游玩进度 0-1,口径为「已判音符数 / 总音符数」,上限钳到 1;总音符数为 0 时返回 0。注意与 musicPositionRatio() 口径不同。 示例:

java
double byNotes = ctx.progress();

disorderActive()

java
boolean disorderActive();

行为:无序模式当前是否激活(无 disorder 引擎时为 false)。示例:

java
if (ctx.disorderActive()) { /* 绘制无序特效 */ }

disorderRemainingRatio()

java
float disorderRemainingRatio();

行为:无序剩余时间比例 1→0;未激活时为 0。示例:

java
float left = ctx.disorderRemainingRatio();

disorderChargeRatio()

java
float disorderChargeRatio();

行为:无序充能进度比例 0-1;未激活时为 0。示例:

java
float charge = ctx.disorderChargeRatio();

disorderChargeBarVisible()

java
boolean disorderChargeBarVisible();

行为:充能条当前是否可见(充能中 / 成功闪烁 / 失败闪烁)。示例:

java
boolean bar = ctx.disorderChargeBarVisible();

disorderChargeBarFlashingOn()

java
boolean disorderChargeBarFlashingOn();

行为:成功闪烁时当前是否为「亮」周期;按接口约定,非成功闪烁状态恒返回 true(宿主直接透传无序引擎的判定,无引擎时为 false)。示例:

java
boolean bright = ctx.disorderChargeBarFlashingOn();

disorderEndingSoon()

java
boolean disorderEndingSoon();

行为:无序剩余时间是否 ≤ 2000ms。示例:

java
if (ctx.disorderEndingSoon()) { /* 收尾提示 */ }

disorderRemainingTimeMs()

java
long disorderRemainingTimeMs();

行为:无序模式剩余毫秒;未激活时为 0。示例:

java
long ms = ctx.disorderRemainingTimeMs();

chartDurationMs()

java
long chartDurationMs();

行为:谱面总时长(毫秒),取末个音符的结束时间(长音符取 endTime,否则取 time),并非音频文件时长;无谱面时为 0。音频真实时长见 audioDurationMs()。 示例:

java
long chartLen = ctx.chartDurationMs();

totalNoteCount()

java
int totalNoteCount();

行为:谱面总音符数(Hold 算 1)。示例:

java
int total = ctx.totalNoteCount();

judgedNoteCount()

java
int judgedNoteCount();

行为:已判定音符数(含 MISS)。示例:

java
int judged = ctx.judgedNoteCount();

remainingNoteCount()

java
int remainingNoteCount();

行为:等于 totalNoteCount() - judgedNoteCount()。示例:

java
int rest = ctx.remainingNoteCount();

musicPositionRatio()

java
double musicPositionRatio();

行为:按音乐时间线计算的进度,musicTimeMs / chartDurationMs 并 clamp 到 [0,1];音乐未启动(τ ≤ 0)或谱面时长 ≤ 0 时返回 0。与按音符数计算的 progress() 不同,倒带期会随 τ 回退。 示例:

java
double byMusic = ctx.musicPositionRatio();

accuracy()

java
double accuracy();

行为:准度 0-1,口径为 PERFECT=1.0 / GREAT=0.5 / MISS=0,按已判音符加权平均(分母 = perfect+great+miss);无已判音符时为 0。注意与 ResultSnapshot.accuracy() 的 0-100 百分比口径不同。 示例:

java
double acc = ctx.accuracy();

judgmentWindowMs()

java
JudgmentPolicy judgmentWindowMs();

行为:合并后的当前判定窗口快照(含 perfect/great/miss/holdEnd/lateCutoff 5 个方法),实例不可变。宿主的模组系统未就绪时返回 null,调用前必须判空。 示例:

java
JudgmentPolicy w = ctx.judgmentWindowMs();
long perfectMs = w != null ? w.perfectWindowMs() : 70L;

defaultJudgmentWindowMs()

java
JudgmentPolicy defaultJudgmentWindowMs();

行为:游戏内置默认判定窗口(70/150/150/150/50),供对比当前窗口与默认窗口的差异;宿主恒返回同一不可变实例。示例:

java
long base = ctx.defaultJudgmentWindowMs().perfectWindowMs();

chartBpm()

java
int chartBpm();

行为:谱面主 BPM,取 0ms 处的 BPM 段并四舍五入为 int;无 BPM 信息时为 0。与 beatBpm()(τ 所在段)不同。 示例:

java
int bpm = ctx.chartBpm();

pendingNotes()

java
List<NoteView> pendingNotes();

行为:3 秒预告窗口内的待判定音符视图,按时间升序。窗口为 time ∈ [τ - missWindow, τ + 3000](missWindow 取当前合并判定窗口的 miss 值,默认 150ms),且只保留尚未判定的音符(Hold 以其起始时间入窗)。返回不可变列表(同一次快照内多次调用返回同一实例;宿主的每帧上下文快照本身是新的)。不要在每帧路径上反复取用或长期持有——建议在 ChartLoadEvent 缓存或用 nextNote() 代替。 示例:

java
List<NoteView> upcoming = ctx.pendingNotes();
for (NoteView n : upcoming) {
    if (n.isHold()) { /* 预告长条 */ }
}

nextNote()

java
NoteView nextNote();

行为:预告列表的首个元素(时间最早、未判定),无则返回 null;比 pendingNotes() 轻量,逐帧场景优先用它。 示例:

java
NoteView next = ctx.nextNote();
long leadMs = next != null ? next.time() - ctx.musicTimeMs() : -1L;

lanes()

java
List<LaneView> lanes();

行为:当前渲染中的全部轨道视图(真轨在前、假轨在后,按渲染顺序),不可变列表。整份列表在上下文快照构造期生成,不要每帧调用后长期持有。几何语义见 LaneView。 示例:

java
List<LaneView> lanes = ctx.lanes();
double x = lanes.isEmpty() ? 0 : lanes.get(0).x();

altHudActive()

java
boolean altHudActive();

行为:AltHud(备用简单 HUD 取代普通 HUD)是否激活,等价于 altUiAlpha > 0.01。提示类 HUD 模组应仅在激活时绘制,避免与普通 HUD 重叠。 示例:

java
if (!ctx.altHudActive()) return;

altComboCenterX()

java
double altComboCenterX();

行为:AltHud 顶部中央 COMBO 矩形的水平中心(画布坐标,1280×720 逻辑空间);仅在 altHudActive() 为 true 时有意义,否则为上次记录的陈旧值。 示例:

java
double cx = ctx.altComboCenterX();

altComboBottomY()

java
double altComboBottomY();

行为:AltHud 顶部中央 COMBO 矩形的底边 y(画布坐标);提示 HUD 以此向下排布,同样仅在 altHudActive() 时有意义。 示例:

java
double baseline = ctx.altComboBottomY() + 8;

coverImage()

java
com.seecmd.mod.api.render.RenderImage coverImage();

行为:当前谱面曲绘(谱面选择界面展示的封面图,约定存放于 data/charts/chaets_ill/,文件名与谱面同名,支持 .png / .jpg);无曲绘返回 null。返回的句柄在整局游玩中复用(宿主懒加载一次并缓存),不是每次调用的新快照;像素处理结果请自行缓存,避免重复计算。 示例:

java
RenderImage cover = ctx.coverImage();
int[] pixels = cover != null ? cover.getPixelsARGB() : null;

currentModeId()

java
String currentModeId();

行为:当前激活的游戏模式 id(如 seecmd:normal / seecmd:disorder);模式未就绪时宿主回退为 seecmd:normal。 示例:

java
boolean normal = "seecmd:normal".equals(ctx.currentModeId());

chartView()

java
ChartView chartView();

行为:当前谱面元数据只读视图(含 JSON extensions 解析结果);当前宿主每次快照都构造新视图,字段来自 chartData,谱面未加载时为空串 / 0、chartPath() 可能为 null,调用不抛异常。详见 ChartView。 示例:

java
ChartView chart = ctx.chartView();
int lanes = chart.laneCount();

isRewinding()

java
default boolean isRewinding();

行为:是否处于暂停恢复的倒带重演窗口(含倒流段与正向重演段,与 GameplayTickEvent.rewinding() 同源同值)。窗口内 τ 非单调且不产生新判定;累积型状态应改为按 τ 求值或在窗口开始处重建。默认返回 false。 示例:

java
if (ctx.isRewinding()) { rebuildFromMusicTime(ctx.musicTimeMs()); }

hp()

java
default int hp();

行为:游玩期血量只读快照,与宿主结算页同源(0 = 死亡判定线);上下文未提供时为 -1。默认返回 -1。 示例:

java
int hp = ctx.hp();
if (hp >= 0 && hp < 200) { /* 低血量提示 */ }

maxHp()

java
default int maxHp();

行为:血量上限,与 hp() 同源;未提供时为 -1。默认返回 -1。 示例:

java
double hpRatio = ctx.maxHp() > 0 ? ctx.hp() / (double) ctx.maxHp() : 0.0;

noteById(long)

java
default NoteView noteById(long noteId);

行为:按稳定实例 id 反查音符,覆盖本局全部音符(已判定 / MISS / Payload 均在册);线性扫描全谱,id 不在册或上下文未提供查询时返回 null;id 为负直接返回 null。不应每帧调用。默认返回 null。 示例:

java
NoteView n = ctx.noteById(noteId);
if (n != null) { long t = n.time(); }

notesInWindow(int, long, long)

java
default long[] notesInWindow(int lane, long fromMs, long toMs);

行为:时间窗批量查询音符稳定 id。lane 为负 = 全轨,lane ≥ 0 仅该轨;时间窗按音符 time ∈ [fromMs, toMs] 双端含边界,fromMs > toMs 返回空数组;结果按谱面顺序(noteId 升序 = 解析期分配序)排列,无随机、无墙钟——同一谱面同一窗口恒得同一序列。覆盖本局全部音符(与 noteById 同一数据源)。这是只读查询,不是批量写原语;线性扫描全谱并构造新数组,不应每帧调用。默认返回空数组。 示例:

java
long[] ids = ctx.notesInWindow(-1, 10000L, 12000L);
for (long id : ids) { /* 逐个处理,例如读 NoteView 或写音符级变换 */ }

activeHitEffects()

java
default List<ActiveHitEffect> activeHitEffects();

行为:当前存活的活动打击特效句柄列表(只读、可能为空、不为 null)。特效以 τ 计活——倒带期 τ 回退到产生点之前时不在列表、正向重播期重演。句柄支持属性修改与销毁,见 ActiveHitEffect。宿主在每次上下文快照构造时收集并新建句柄,不应每帧调用。默认返回空列表。 示例:

java
for (ActiveHitEffect fx : ctx.activeHitEffects()) {
    if (fx.durationMs() < 80L) fx.setDurationMs(80L);
}

audioDurationMs()

java
default long audioDurationMs();

行为:音频真实时长(毫秒)——实机取宿主音频引擎缓存的 chart_music 时长,预览会话取谱面末音符时长(不访问音频设备),未起播/未知为 0。与 chartDurationMs() 区分。默认返回 0。 示例:

java
long audio = ctx.audioDurationMs();

beatNumerator()

java
default int beatNumerator();

行为:拍号分子。谱面 JSON 不携带拍号,宿主当前恒返回 4;变拍号属未来扩展,不要假设它随谱面变化。默认返回 4。 示例:

java
int num = ctx.beatNumerator();

beatDenominator()

java
default int beatDenominator();

行为:拍号分母,与 beatNumerator() 同口径,当前恒为 4。默认返回 4。 示例:

java
int den = ctx.beatDenominator();

beatIndex()

java
default long beatIndex();

行为:当前拍序号——自 τ 所在 BPM 段起点的整拍数(floorDiv),可为负 = count-in。正常推进 / 倒带重演 / 暂停冻结三态下同一 τ 恒得同一值(与 BeatGrid 同一实现)。首帧前的快照为 -1。默认返回 -1。 示例:

java
long beat = ctx.beatIndex();
if (beat >= 0 && beat % 4 == 0) { /* 小节线 */ }

beatPhase()

java
default double beatPhase();

行为:当前拍相位 [0,1),0 = 正落在拍点上;与 beatIndex() 同源。不可用时为 -1。默认返回 -1。 示例:

java
double phase = ctx.beatPhase();

beatBpm()

java
default double beatBpm();

行为:τ 所在 BPM 段的 BPM(变 BPM 谱面在段切换处随之变化),区别于 chartBpm() 的「0ms 处主 BPM」;不可用为 0。默认返回 0。 示例:

java
double bpm = ctx.beatBpm();

beatPeriodMs()

java
default long beatPeriodMs();

行为:当前拍长(毫秒),= round(60000 / beatBpm);不可用为 0。默认返回 0。 示例:

java
long halfBeat = ctx.beatPeriodMs() / 2;

完整签名

java
public interface GameplayContext {
    long musicTimeMs();
    int combo();
    int score();
    int perfects();
    int greats();
    int misses();
    int maxCombo();
    boolean paused();
    boolean finished();
    default boolean preview();
    default String sessionId();
    default String hostKind();
    String chartTitle();
    String chartAuthor();
    String chartDifficulty();
    double progress();
    boolean disorderActive();
    float disorderRemainingRatio();
    float disorderChargeRatio();
    boolean disorderChargeBarVisible();
    boolean disorderChargeBarFlashingOn();
    boolean disorderEndingSoon();
    long disorderRemainingTimeMs();
    long chartDurationMs();
    int totalNoteCount();
    int judgedNoteCount();
    int remainingNoteCount();
    double musicPositionRatio();
    double accuracy();
    JudgmentPolicy judgmentWindowMs();
    JudgmentPolicy defaultJudgmentWindowMs();
    int chartBpm();
    List<NoteView> pendingNotes();
    NoteView nextNote();
    List<LaneView> lanes();
    boolean altHudActive();
    double altComboCenterX();
    double altComboBottomY();
    com.seecmd.mod.api.render.RenderImage coverImage();
    String currentModeId();
    ChartView chartView();
    default boolean isRewinding();
    default int hp();
    default int maxHp();
    default NoteView noteById(long noteId);
    default long[] notesInWindow(int lane, long fromMs, long toMs);
    default long audioDurationMs();
    default int beatNumerator();
    default int beatDenominator();
    default long beatIndex();
    default double beatPhase();
    default double beatBpm();
    default long beatPeriodMs();
    default List<ActiveHitEffect> activeHitEffects();
}

线程:源码未声明额外线程约束。宿主均在渲染线程构造快照并同步投递给模组回调(单线程语义)。

性能:pendingNotes() / lanes() / activeHitEffects() 的列表在快照构造期一次性生成、以不可变包装复用;noteById() / notesInWindow() 每次线性扫描全谱;coverImage() 句柄整局复用。这些都不要放进每帧路径。

稳定性:2.0 起冻结:2.x 内只增不破。preview() / sessionId() / hostKind() 为 3.2 新增、isRewinding() 为 2026-10 特性、 系列方法(hp / noteById / notesInWindow / beat* / activeHitEffects)均为 default,既有实现者零改动。