File size: 1,850 Bytes
3ce1a40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "rollback.h"
#include "../runtime/engine.h"

namespace unify {

void RollbackBuffer::advance(Engine& engine) {
    uint64_t tick = engine.sim_clock().tick;
    if (tick % interval_ == 0) snaps_.push_back({tick, engine.save_state(false)});
    engine.tick();
    log_.push_back(engine.input().frame());
    // Bound history: drop snapshots (and the input they cover) older than the window.
    while (!snaps_.empty() && tick - snaps_.front().tick > max_ticks_ && snaps_.size() > 1) snaps_.pop_front();
    while (!log_.empty() && !snaps_.empty() && log_.front().tick < snaps_.front().tick) log_.pop_front();
}

bool RollbackBuffer::rewind_and_resimulate(Engine& engine, uint64_t tick, std::string& error) {
    uint64_t now = engine.sim_clock().tick;
    const Snap* base = nullptr;
    for (const Snap& s : snaps_) if (s.tick <= tick) base = &s;
    if (!base) { error = "tick is older than the rollback window"; return false; }
    if (!engine.load_state(base->state, error)) return false;
    for (const InputFrame& f : log_) {
        if (f.tick < base->tick) continue;
        if (f.tick >= now) break;
        if (f.tick % interval_ == 0) {  // refresh snapshots along the corrected timeline
            for (Snap& s : snaps_) if (s.tick == f.tick) s.state = engine.save_state(false);
        }
        engine.replay_tick(f);
        resimulated_++;
    }
    return engine.sim_clock().tick == now || (error = "resimulation ended at the wrong tick", false);
}

bool RollbackBuffer::correct(Engine& engine, uint64_t tick, const InputFrame& frame, std::string& error) {
    for (InputFrame& f : log_) {
        if (f.tick != tick) continue;
        f = frame;
        f.tick = tick;
        return rewind_and_resimulate(engine, tick, error);
    }
    error = "no recorded input for that tick";
    return false;
}

}  // namespace unify