group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
ReconciliationSystem.hpp
Go to the documentation of this file.
1
28
29#pragma once
30
31#include "InputRingBuffer.hpp"
39
40#include <SDL3/SDL_log.h>
41
42#include <cstdint>
43#include <entt/entt.hpp>
44
45namespace systems
46{
47
66inline void runReconciliation(Registry& registry,
67 const InputRingBuffer& ring,
68 uint32_t ackedTick,
69 uint32_t currentTick,
70 float dt,
71 const physics::WorldGeometry& world)
72{
73 if (currentTick <= ackedTick)
74 return; // already up to date — server state is the latest predicted state.
75
76 // Find the local player. Reconciliation is meaningless without one.
77 auto localView = registry.view<LocalPlayer, InputSnapshot>();
78 auto it = localView.begin();
79 if (it == localView.end())
80 return;
81 const entt::entity local = *it;
82
83 // Replay forward, one physics tick per stored input.
84 int replayed = 0;
85 int missing = 0;
86 for (uint32_t t = ackedTick + 1; t <= currentTick; ++t) {
87 const InputSnapshot* stored = ring.find(t);
88 if (!stored) {
89 // Ring overflow or we never sent for this tick — skip. The
90 // gap means our prediction for this tick is lost, but
91 // continuity is preserved (next stored input still applies).
92 ++missing;
93 continue;
94 }
95 registry.replace<InputSnapshot>(local, *stored);
96 // runMovement+runCollision for the local player only. The
97 // PlayerSimState filter (server-only component, only present on
98 // the local player on the client) narrows the iteration
99 // automatically — no per-entity filter needed.
100 runMovement(registry, dt, world);
101 runCollision(registry, dt, world);
102 ++replayed;
103 }
104
105 if (missing > 0) {
106 // Diagnostic: a non-trivial gap in the ring is unusual at sane
107 // RTTs (256-tick capacity covers ~2 s of replay). Log so we can
108 // notice if RTT or stalls drive the buffer beyond capacity.
109 SDL_Log("[reconcile] %d ticks missing from input ring (replayed %d, range [%u..%u])",
110 missing,
111 replayed,
112 ackedTick + 1,
113 currentTick);
114 }
115}
116
117} // namespace systems
Shared collision system for swept-AABB physics resolution.
Per-tick history of stamped input snapshots, keyed by clientPredictTick.
Per-tick player input snapshot for networking and prediction.
Marker component identifying the locally controlled player entity.
Shared movement system implementing the Titanfall-inspired state machine.
Client-side prediction: run movement+collision locally each tick.
Shared ECS registry type alias for the game engine.
entt::registry Registry
Shared ECS registry type alias.
Definition Registry.hpp:11
Swept AABB and sphere collision queries against world geometry.
Definition InputRingBuffer.hpp:27
const InputSnapshot * find(uint32_t tick) const
Find the input stamped with exactly tick.
Definition InputRingBuffer.hpp:52
Client-only input sampling system — split into two halves so mouse look can run every iterate() (smoo...
Definition DebugUI.hpp:15
void runCollision(Registry &registry, float dt, const physics::WorldGeometry &world)
Run one tick of swept-AABB collision for all physics entities.
Definition CollisionSystem.cpp:324
void runMovement(Registry &registry, float dt, const physics::WorldGeometry &world)
Apply one tick of player movement physics to all eligible entities.
Definition MovementSystem.cpp:1256
void runReconciliation(Registry &registry, const InputRingBuffer &ring, uint32_t ackedTick, uint32_t currentTick, float dt, const physics::WorldGeometry &world)
Replay stored inputs from ackedTick + 1 through currentTick on the local player, restoring its predic...
Definition ReconciliationSystem.hpp:66
One tick of player input, stamped with the tick it was sampled on.
Definition InputSnapshot.hpp:17
Marker component that tags exactly one entity per client as the locally controlled player.
Definition LocalPlayer.hpp:12
All world collision geometry for one tick.
Definition SweptCollision.hpp:100