Skip to main content

net_replication/
net_replication.rs

1//! Replication helpers on top of byte messages: snapshot interpolation,
2//! authority epochs and interest by distance. Run with
3//! `cargo run --example net_replication --no-default-features`.
4use ponko::*;
5
6fn main() {
7    // ANCHOR: snapshots
8    // One stream per remote entity: it holds the snapshots received and learns
9    // the sender's clock from their timestamps. The wire format is yours.
10    let mut car = SnapshotStream::<Pose>::new(); // shown 100 ms in the past
11    let mut newest = LatestWins::new(); // drops duplicate and late packets
12    for n in 0u16..20 {
13        // In a game this is a decoded packet from `NetMessages::events()`:
14        let (entity, stamp) = (7u64, UpdateStamp { epoch: 0, seq: n });
15        let sender_time = 5000.0 + f64::from(n) * 0.05; // on the sender's clock
16        let arrived = f64::from(n) * 0.05 + 0.03; // on yours, e.g. ctx.time()
17        let pose = Pose::at(vec3(n as f32, 0.0, 0.0)).moving(vec3(20.0, 0.0, 0.0));
18        if newest.accept(entity, stamp) {
19            car.push(sender_time, arrived, pose);
20        }
21    }
22    // Every frame: where to draw it. Between snapshots it is interpolated;
23    // when packets are late it is extrapolated for 250 ms, then held.
24    let shown = car.sample(1.0).unwrap();
25    println!("{:?} at {:?}", shown.state, shown.value.position);
26    // ANCHOR_END: snapshots
27    assert_eq!(shown.state, SnapshotState::Interpolated);
28    assert!((shown.value.position.x - 17.4).abs() < 0.05);
29    assert!(!newest.accept(7, UpdateStamp { epoch: 0, seq: 3 }));
30
31    // ANCHOR: authority
32    let (host, guest) = (PeerId::HOST, PeerId::from_bits(1));
33    let mut vehicle = Authority::new(host); // the host owns it...
34    let epoch = vehicle.handoff(guest); // ...until the guest takes the wheel.
35    // Announce (guest, epoch) on a reliable lane; every other peer calls
36    // `vehicle.adopt(guest, epoch)` when it arrives. State updates carry the
37    // epoch they were sent under, and the receiver checks it:
38    assert_eq!(vehicle.check(host, 0), AuthorityCheck::Stale); // late, from before the handoff
39    assert_eq!(vehicle.check(guest, epoch), AuthorityCheck::Accept);
40    assert!(seq_newer(2, 65535)); // sequence numbers wrap around
41    // ANCHOR_END: authority
42
43    // ANCHOR: interest
44    // Near entities every tick, mid ones every 4th, far ones never.
45    let mut interest = Interest::new(InterestConfig::default());
46    let viewers = [InterestViewer {
47        peer: PeerId::HOST,
48        position: vec3(0.0, 0.0, 0.0),
49    }];
50    let world = [
51        InterestEntity {
52            id: 1,
53            position: vec3(10.0, 0.0, 0.0),
54        },
55        InterestEntity {
56            id: 2,
57            position: vec3(500.0, 0.0, 0.0),
58        },
59    ];
60    let mut sent = 0;
61    for tick in 0..8u64 {
62        interest.update(tick, &viewers, &world);
63        for change in interest.changes() {
64            println!("{:?} {:?} for peer {:?}", change.kind, change.entity, change.peer);
65        }
66        for entry in interest.due(PeerId::HOST) {
67            sent += 1; // send entity `entry.entity` to this peer now
68            let _ = entry;
69        }
70    }
71    // ANCHOR_END: interest
72    assert_eq!(sent, 8);
73}