D-20261030-05|越窗卡頓改走 catch-up 重同步¶
背景與驅動力¶
記號沿用 D-20261029-03:D=INPUT_DELAY_FRAMES=6、R=ROLLBACK_FRAME_BUFFER_DEFAULT=2、M=D+R=8、未來窗=2×STATE_BUFFER_MAX_FRAMES=24。
RollbackEngine 收到遠端 input 時(src/network-sync/rollback-engine.ts):
- input 幀 <
currentFrame − R即丟棄(過舊)。 - input 幀 >
currentFrame + 2×STATE_BUFFER_MAX_FRAMES時不進 InputBuffer;catch-up 進行中改入暫存,其餘丟棄(過遠)。
本機在模擬幀 c 取樣的輸入排程到 c+D 才廣播。單次卡頓(GC、分頁切換)k 幀時,固定步迴圈每 tick 最多追 MAX_SUBSTEPS 步、其餘時間丟棄,落後端恢復後比全場慢約 k 幀。設單向延遲 L 幀:
- 甲:k+L > D+R 時,落後端恢復後送出的第一批輸入到達他人時已低於受理窗,被丟棄;他人以預測模擬該車、落後端以真值模擬,雙方分歧。
- 乙:k − L+D > 2×
STATE_BUFFER_MAX_FRAMES時,他人的輸入超出落後端的未來窗而被丟棄,同樣分歧。
分歧只能由 checksum strike 處置(DESYNC_STRIKE_LIMIT=3),落後端最終被驅逐。回歸矩陣中 3 人與 8 人、k=16/24 的格都重現;約 267 ms 以上的單次卡頓就讓玩家出局(issue 001127)。D-20261029-03 的落後端快進只回收時鐘偏移,救不回已越窗的輸入;自動 catch-up 只在 lead > 2×STATE_BUFFER_MAX_FRAMES 時才觸發(程式架構/network-sync.md 第 7.2 節),中間的 (M, 24] 區段沒有對應處置。
2026-10-30 維護者裁決:落後端恢復時自行判斷待送輸入是否已超出其他 peer 的受理窗;超窗即不送舊輸入,直接轉入既有 catch-up 快照重同步。代價為卡頓者多一次重同步停頓,但不被驅逐。草稿審閱時另裁定:判定後到 catch-up 完成前不送 checksum 票,catch-up 成功即清除本機 desync strike;此自判 catch-up 不受自動 catch-up 冷卻限制;兩人場維持現行行為。
考慮過的選項¶
- 落後端自判越窗並轉入既有 catch-up(採納):不改 wire、不改受理窗,重用已有 quorum 背書的快照對齊。
- 越窗輸入補送/重放:受理窗外的幀已被他人確定,補送無法收斂,需改協定(否決)。
- 放寬受理窗 R:R 是協定常數,連動回滾深度、快照保留與效能預算(否決)。
- 以 wire 交換 frame advantage(GGPO 式時間同步):根本解,但屬協定變更,不在本決策範圍。
決定¶
1. 偵測條件¶
- 使用 D-20261029-03 的
quorumLead:各遠端最近 lead(input 幀扣 D、checksum 幀原樣,同 peer 取最大,以最近一步收訊時的幀計)的第 k 大值,k=floor(遠端數/2)+1;觀測數 < k 時視為無值。 - 每次正常 step 收訊後,若
quorumLead> D+R,判定本機待送輸入已越窗: - 甲:本機下一筆排程幀=c+D,嚴格多數遠端已至少在 c+
quorumLead;quorumLead> D+R 時 c+D < 遠端目前幀 − R,即使單向延遲為 0 也已過舊。 - 乙:遠端最近 input 幀=c+
quorumLead+D;quorumLead> 2×STATE_BUFFER_MAX_FRAMES− D(=18)時超出本機未來窗。此門檻高於 D+R,故同一條件涵蓋。 - 條件以嚴格多數計,少數 peer 自簽灌高的幀號不會單獨觸發;不新增常數。
- 只適用於三人以上的場次(遠端至少兩名);兩人場見第 5 項。
2. 處置¶
- 判定成立時,本機停止排程與廣播本機輸入(作法與 D-20261029-03 第 2 項「追趕期間不排程本機輸入」相同:event 型按鍵公告丟棄、hold 由下一次取樣重建、pending leave 延到第一個真正排程的步),並以既有自動 catch-up 發起 quorum probe(程式架構/network-sync.md 第 7.1 節)。
- 本機輸入暫停持續到 catch-up 對齊並結束分 tick 追趕;之後照常排程,排程幀=追趕結束時的幀+D。catch-up 未發起或失敗時,
quorumLead≤ D+R 才恢復排程。 - 三人以上的場次,快進的上界由 2×
STATE_BUFFER_MAX_FRAMES降為 D+R:quorumLead落在 (R, D+R] 時照常快進;> D+R 時改走本決策的 catch-up,不快進。 - catch-up 的 quorum、快照驗證、front 夾限、追趕與期限規則全部沿用 D-20261029-03 與 D-20261029-04,不新增 wire。
3. checksum 票與 strike¶
- 判定越窗後,本機狀態已知與全場不同。自判定起到 catch-up 對齊並結束分 tick 追趕為止,本機不廣播 checksum 票;這段期間記錄的暫定 hash 丟棄、不轉為正式票。他人的票照常收下,但本機沒有正式票的輪次不做本機裁定,不累積 strike。
- 由本決策觸發的 catch-up 成功(對齊並結束追趕)時,清除本機已累積的 desync strike(
consecutiveDesyncs歸零)。這是 D-20261029-03 第 3 項「consecutiveDesyncs不歸零」的例外,只適用於本機自判越窗的 catch-up:越窗期間的 strike 來自已知的輸入遺失,不是持續分歧的證據。重連或 lead > 2×STATE_BUFFER_MAX_FRAMES觸發的 catch-up 仍不歸零。 - 若 catch-up 失敗或放棄,本機恢復廣播 checksum 票,strike 規則照舊。
4. 冷卻¶
本機自判越窗而發起的 catch-up 不受自動 catch-up 冷卻(CATCH_UP_PROBE_REPLACE_AFTER_FRAMES=120 步)限制,短時間內連續卡頓時每次都可立即發起。單航班限制不變:已有 probe、快照請求或追趕進行中時不重複發起,沿用進行中的那一次。
5. 兩人場¶
兩人場維持現行行為。probe 需要 floor(全名單/2)+1 張遠端票,兩人場只有一名遠端,canon 也規定兩人場不接受唯一對手未經交叉背書的快照,所以本決策的 catch-up 無法在兩人場進行;越窗時本機不改變輸入、checksum 與快進行為(快進上界仍為 2×STATE_BUFFER_MAX_FRAMES),仍可能因 checksum 分歧而結束。這列為已知限制。
後果與影響¶
- 落後超過 D+R 但未達自動 catch-up 門檻的卡頓,由「checksum 驅逐」變為「一次重同步停頓」;三人以上的場次不因單次卡頓出局。
- 越窗期間本機不投 checksum 票,該輪的多數決只由其他 peer 的票決定;自判 catch-up 成功清除 strike,因此誠實的卡頓者不會因 catch-up 前累積的 strike 被驅逐。
- 兩人場限制:仍維持現行行為,越窗卡頓可能導致該場因 checksum 分歧而結束。
- 限制:lead 來自遠端自簽進度,比真實前緣舊約一個單程延遲 L。偵測條件不含 L,所以
quorumLead≤ D+R 但quorumLead+2L > D+R 時仍偵測不到、輸入照樣越窗(D-20261029-03 記載的 2L ≤ D+R 限制);這部分仍留在 issue 001127,根本解需以 wire 交換 frame advantage。 - 越窗到對齊期間,他人以預測模擬該車;本機輸入在這段時間不生效。
- 待實作時處理的檔案:
- main:
src/network-sync/rollback-engine.ts(偵測、暫停本機輸入與 checksum 廣播、發起不受冷卻限制的 catch-up、成功時清除 strike、快進上界)、src/network-sync/clock-sync.ts(若maxLead改由呼叫端傳 D+R 則只改呼叫端)、src/race-runtime/race-loop.ts(暫停排程期間的輸入取樣與 pending leave,沿用追趕路徑)、對應 spec 與卡頓回收矩陣(k=16、24 的格改斷言全員一致)。 - specs:程式架構/network-sync.md 第 4 節(越窗期間不投票)與第 7.1、7.2、7.3、7.5 節(第 7.5 節「限制」改寫)、程式參數/network.md 中引用快進上界的說明、流程/比賽進行.md 持續落後段。
- 與既有決策的關係:
- amends D-20261029-03:第 1 項快進的啟動區間上界由 2×
STATE_BUFFER_MAX_FRAMES改為 D+R;第 2 項「不排程本機輸入」延伸到越窗判定後、對齊前;第 3 項「consecutiveDesyncs不歸零」對本機自判越窗的 catch-up 設例外。其「已知限制與後續」中的卡頓越窗部分由本決策處理,2L 限制與 frame advantage 仍屬 issue 001127。D-20261029-03 已有一段指向 D-20261029-04 的加註,修訂關係改由本決策的 amends 欄位記錄,原文不改寫。 - 當日歷史記錄需補條目並回引本決策。
定案紀錄¶
2026-10-30 使用者審閱後同意採納:三人以上對戰中,quorumLead 超過 D+R 時落後端停送輸入與 checksum 投票並轉入 catch-up;成功後清除 desync strike,此路徑不受 120 步自動冷卻限制但仍一次一個;兩人對戰維持現行行為,列為已知限制。