Theseus 模组文档
API 参考 / 事件系统

RewindEvent


暂停恢复时,宿主不直接从暂停点 T 续走,而是先把判定 / 渲染时间按缓动曲线倒流回 T-3s(历时约 3 秒,等于 3-2-1 倒计时),随后再正向「重演」回 T。这段区间称为倒带重演窗口 [fromMs, toMs],其中 fromMs = T-3s、toMs = T。

窗口建立时投递一次 Phase.BEGIN,窗口结束(正向重演越过 T)时投递一次 Phase.END。一次暂停-恢复周期内两者各一次;若在窗口内再次暂停并恢复,宿主先用 END 闭合旧窗口,再以新窗口投递 BEGIN(严格成对交替)。

方法速览

方法用途
phase()阶段 BEGIN / END
isBegin() / isEnd()阶段判断
fromMs()窗口左端(T-3s)
toMs()窗口右端(T)
durationMs()窗口时长(toMs - fromMs)

phase()

java
public Phase phase();

行为:返回窗口阶段。BEGIN 表示时间即将倒流,END 表示已正向重演越过 T。

isBegin()

java
public boolean isBegin();

行为:phase() == Phase.BEGIN。

isEnd()

java
public boolean isEnd();

行为:phase() == Phase.END。

fromMs()

java
public long fromMs();

行为:返回窗口左端(音乐时间毫秒,= 暂停点 T 减去回看时长),也是时间将被倒回的下界。

toMs()

java
public long toMs();

行为:返回窗口右端(音乐时间毫秒,= 暂停点 T)。

durationMs()

java
public long durationMs();

行为:返回 toMs - fromMs(毫秒)。宿主保证 fromMs <= toMs。

示例

java
ctx.eventBus().subscribe(RewindEvent.class, event -> {
    if (event.isBegin()) {
        // 宿主时间将倒流回 fromMs:重建自身动画 / 计时器等累计状态
        rebuildCumulativeState(event.fromMs());
    } else {
        // 已正向重演越过 toMs:恢复正常累加
        resumeAccumulationAt(event.toMs());
    }
});

完整签名

java
public class RewindEvent extends Event {
    public enum Phase {
        BEGIN,
        END
    }

    public RewindEvent(Phase phase, long fromMs, long toMs);
    public Phase phase();
    public boolean isBegin();
    public boolean isEnd();
    public long fromMs();
    public long toMs();
    public long durationMs();
}

行为核验:BEGIN 期间宿主时间 τ 会倒流且不再产生新的计分判定(重演的旧音符是「幽灵」,不触发 NoteJudgedEvent、不 MISS)。模组的累积型状态(state += dt 的动画、计时器、缓动)会与宿主时间脱节:应在 BEGIN 处快照 / 重建,或在窗口内改为按 τ 求值。窗口内 GameplayTickEvent.rewinding() 与 GameplayContext.isRewinding() 同为 true,可作为切换开关。

倒带跟随参考实现:测试模组 官方示例模组 的 RewindFollowHud(正向按 deltaSeconds 积分、窗口内按 musicTimeMs 求值并回滚),由 RW-follow 用例以真 GameplayModHost 全时序驱动验证(正向 → BEGIN → 倒流 → 重演 → END → 续推,零漂移)。需要倒带兼容的演出模组可照抄该实现。

稳定性: 新增,2.x 内只增不破。