跳轉到

Network Sync

文件角色:implementation flow 投影;圖與步驟不得另建產品規則或參數 authority。

Implementation authority 產品 canon/流程 全域索引
network-sync.md 比賽進行 流程.md §2

Rollback 主迴圈

flowchart TD
    Start([每 frame 開始]) --> Local[寫入本地輸入]
    Local --> Broadcast[廣播 input 訊息]
    Broadcast --> Recv[接收網路訊息]
    Recv --> Process{處理訊息}
    Process -->|input| ValidateInput{loadout schema /<br/>唯一 / Event-Hold 合法?}
    ValidateInput -->|否| DropInput[丟棄並記 misbehavior]
    ValidateInput -->|是| Equivocation{同 peer+frame<br/>已有相異首值?}
    Equivocation -->|是| AbortInput[fail-closed 中止]
    Equivocation -->|否| CheckPred{該幀實際預測正確?}
    Process -->|checksum| StoreCS[鎖首票;舊輪/衝突票拒收]
    CheckPred -->|是| Continue
    CheckPred -->|否| MarkRB[標記需 rollback 至 frame N]
    StoreCS --> Continue
    MarkRB --> Continue
    Continue --> RB{需 rollback?}
    RB -->|是| Restore[restore snapshot]
    Restore --> Replay[重播至當前 frame]
    Replay --> SavePre
    RB -->|否| SavePre[saveState 當前 frame<br/>的 pre-step 快照進 buffer]
    SavePre --> StepCurrent[step 當前 frame]
    StepCurrent --> CSCheck{到達 checksum 取樣 frame?}
    CSCheck -->|是| Hash[computeStateHash]
    Hash --> SendCS[廣播 checksum]
    CSCheck -->|否| Done
    SendCS --> Done([下一 frame])

Checksum 解決流程

flowchart TD
    Start([收到 checksum]) --> Wait{全員到齊或逾等待窗?}
    Wait -->|窗內未到齊| WaitMore[等待(逾窗未到 = 該輪缺席)]
    Wait -->|到齊 / 逾窗| Count[以已到票計票]
    Count --> Tied{平手?}
    Tied -->|是| Invalid[consensus-invalid<br/>形成 RaceAbortEvidenceEvent 候選證據]
    Tied -->|否| MyMatch{我的 hash 是多數派?}
    MyMatch -->|是| Reset[清除連續 desync 計數<br/>繼續]
    MyMatch -->|否| Inc[consecutiveDesync++<br/>不 rollback(重播同 input 無法收斂)]
    Inc --> Limit{達 desync strike 門檻?}
    Limit -->|是| Invalid
    Limit -->|否| Done([繼續、待下輪 checksum])
    Reset --> Done

Input Prediction 流程

sequenceDiagram
    participant P1 as Player 1
    participant P2 as Player 2

    Note over P1,P2: frame N
    P1->>P1: localInput
    P1->>P2: input N

    Note over P2: 延遲收到另一玩家的舊 input
    P2->>P2: 延遲期間使用上一輸入作預測值
    P2->>P2: 比對 預測 vs 實際

    alt 預測正確
        Note over P2: 不需 rollback
    else 預測錯誤
        P2->>P2: rollback 至 frame N
        P2->>P2: 用實際輸入重播受影響區間
    end

8 玩家 Mesh 拓樸

graph TB
    P1[Player 1] --- P2[Player 2]
    P1 --- P3[Player 3]
    P1 --- P4[Player 4]
    P1 --- P5[Player 5]
    P1 --- P6[Player 6]
    P1 --- P7[Player 7]
    P1 --- P8[Player 8]
    P2 --- P3
    P2 --- P4
    P2 --- P5
    P2 --- P6
    P2 --- P7
    P2 --- P8
    P3 --- P4
    P3 --- P5
    P3 --- P6
    P3 --- P7
    P3 --- P8
    P4 --- P5
    P4 --- P6
    P4 --- P7
    P4 --- P8
    P5 --- P6
    P5 --- P7
    P5 --- P8
    P6 --- P7
    P6 --- P8
    P7 --- P8

    Note["玩家之間建立 full-mesh WebRTC 連線"]

Reconnect 流程

sequenceDiagram
    participant Other as 其他玩家
    participant Lost as 斷線玩家
    participant Engine as Reconnect Handler

    Other->>Other: 偵測 Lost 連線中斷
    Other->>Engine: 啟動重連窗計時器
    Other->>Other: 比賽繼續,Lost 用預測輸入

    alt 重連窗內成功
        Lost->>Other: 定向 signed sync-probe-request
        Other->>Lost: signed offer(最近兩個 aligned frame + hash,snapshot 已 pin)
        Note over Lost,Other: offer 遺失時以同 offerId 依政策重送;不重複 copy/hash
        Lost->>Other: strict-quorum 同 frame+hash 的 exact offerId/target request
        Other->>Lost: unicast sync-response(僅首選 voter 傳完整 snapshot)
        Lost->>Lost: 在回覆窗內等待;逾時先取消 pending 再換 voter
        Lost->>Lost: 驗簽成功且 enqueue 後才消耗 pending,核對來源、目標、大小與內外 frame
        Lost->>Lost: current SavedState schema+vehicle/entity/destruction/route/projectile/weather lifecycle+拓撲+數值範圍 原子 loadState
        Note over Lost,Other: 畸形或 load 失敗:記 misbehavior、不前跳、不中斷幀<br/>成功送交通道才刪 pinned offer 並進 cooldown;send 失敗保留供重試
    else 重連窗期滿仍未連
        Engine->>Other: 標記 Lost 為「異常斷線」
        Note over Other: 比賽繼續,Lost 排在最後一名
        Note over Other: 結算時 Lost 不算簽章人
    end

Snapshot Buffer 滑動視窗

flowchart LR
    Oldest[最舊可回滾快照] --> Middle[視窗內快照]
    Middle --> Newest[最新 pre-step 快照]
    Newest --> Push[推入下一份快照]
    Push --> Drop1[移除超出視窗的舊快照]

    classDef local fill:#e8f3ec,stroke:#3f8f5f,stroke-width:1.4px,color:#173525;
    classDef fail fill:#fae9e7,stroke:#b4544a,stroke-width:1.4px,color:#471d18;
    class Newest,Push local
    class Drop1 fail

Buffer 精確保留 12 個 pre-step 快照,rollback acceptance 固定為 8 frames 且不可協商; 視窗推進與接納門檻以程式參數 authority 為準。