Sign in

    weopqrst/moonroll/session does not have a README file

    Sim

    pub(open) trait Sim {
    fn save(Self) -> Bytes
    fn restore(Self, Bytes) -> Unit
    fn step(Self, UInt64, UInt64) -> Unit
    fn hash(Self) -> UInt64
    }

    接入协议:任何可确定性模拟的系统实现这 4 个方法即可接入回滚。

    • save:把当前状态编码成字节快照,必须完整
    • restore:从快照恢复,必须与 save 严格互逆
    • step:推进一帧,p0 / p1 是两个玩家按玩家索引排列的输入位图
    • hash:状态哈希,用于两端比对,不一致即 desync

    四个方法都必须是纯确定性的:同样的输入序列必须得到同样的状态与哈希。 这是回滚同步的唯一硬约束,库无法替你检查,但 Session 会对每帧调用 save,所以「忘了恢复某个字段」会立即表现为哈希不一致。

    Session

    pub struct Session[T] {
    sim : T
    local_id : Int
    window : Int
    frame : Int
    confirmed : Int
    rollbacks : Int
    p0 :
    InputRing

    p1 :
    InputRing

    snaps : SnapshotRing
    }

    回滚会话:持有模拟器、双玩家输入环、窗口内快照,负责预测、确认与重放。

    帧号从 1 开始,0 表示初始状态。frame 是本地已模拟到的最新帧, confirmed 是双方输入都已到达的最大帧(其之前的帧不会再回滚)。

    典型循环(每帧一次):
    1. 本地推进:advance(本地输入)
    2. 把 player_input(本地玩家, 帧) 发给对端
    3. 收到对端输入时调用 receive(帧, 输入)

    Session::advance

    fn[T : Sim] Session::advance(self : Session[T], local_input : UInt64) -> Int

    本地推进一帧,返回新的帧号。

    Session::confirmed

    fn[T] Session::confirmed(self : Session[T]) -> Int

    Session::frame

    fn[T] Session::frame(self : Session[T]) -> Int

    Session::hash

    fn[T : Sim] Session::hash(self : Session[T]) -> UInt64

    Session::local_player

    fn[T] Session::local_player(self : Session[T]) -> Int

    Session::new

    fn[T : Sim] Session::new(sim : T, local_id : Int) -> Session[T]

    Session::player_input

    fn[T] Session::player_input(self : Session[T], player : Int, frame : Int) -> UInt64?

    取某个玩家在某一帧的已知输入(未到达或已被覆盖时为 None)。

    Session::receive

    fn[T : Sim] Session::receive(self : Session[T], frame : Int, remote_input : UInt64) -> Unit

    收到对端在 frame 帧的输入。

    若该帧已模拟过(frame <= self.frame)且尚未确认,就从 frame - 1 的快照恢复并重放 frame..self.frame,即发生一次回滚。

    Session::rollbacks

    fn[T] Session::rollbacks(self : Session[T]) -> Int

    Session::with_window

    fn[T : Sim] Session::with_window(sim : T, local_id : Int, window : Int) -> Session[T]

    local_id 是本地玩家索引(0 或 1),window 是可回滚的最大帧数。

    SnapshotRing

    pub struct SnapshotRing {
    capacity : Int
    frames : Array[Int]
    items : Array[Bytes?]
    }

    帧号 -> 快照字节的环形缓冲。容量固定、按帧号取模寻址, 槽位记录真实帧号,被覆盖后旧帧查询返回 None。

    SnapshotRing::capacity

    fn SnapshotRing::capacity(self : SnapshotRing) -> Int

    SnapshotRing::get

    fn SnapshotRing::get(self : SnapshotRing, frame : Int) -> Bytes?

    SnapshotRing::new

    fn SnapshotRing::new(capacity : Int) -> SnapshotRing

    SnapshotRing::set

    fn SnapshotRing::set(self : SnapshotRing, frame : Int, bytes : Bytes) -> Unit

    DEFAULT_WINDOW

    let DEFAULT_WINDOW : Int

    默认回滚窗口(帧)。

    hash_state

    fn hash_state(parts : ArrayView[Int64]) -> UInt64

    把一组整数折叠成 FNV-1a 64 哈希,供 Sim::hash 复用。

    fn hash(self) -> UInt64 {
    hash_state([self.x.raw(), self.y.raw()])
    }