Bomberman Multiplayer
Authoritative multiplayer networking layer for Bomberman.
Loading...
Searching...
No Matches
ClientPrediction.h
Go to the documentation of this file.
1
25#ifndef BOMBERMAN_NET_CLIENTPREDICTION_H
26#define BOMBERMAN_NET_CLIENTPREDICTION_H
27
28#include <array>
29#include <cstddef>
30#include <cstdint>
31
32#include "Net/NetCommon.h"
33#include "Sim/Movement.h"
34
35namespace bomberman::net
36{
37 // ----- Constants and Types -----
38
40 constexpr std::size_t kClientPredictionHistorySize = 128;
41
43 "kClientPredictionHistorySize must be a power of two");
44
47 {
48 sim::TilePos posQ{};
49 uint8_t buttons = 0;
50 uint8_t playerFlags = 0;
51 };
52
53 // ----- Diagnostics and Telemetry -----
54
62 {
66 bool recoveryTriggered = false;
67 bool recoveryRestarted = false;
68 bool recoveryResolved = false;
69 bool recoveryStillActive = false;
70
71 uint32_t replayedInputs = 0;
72 uint32_t missingInputHistory = 0;
74 uint32_t recoveryCatchUpSeq = 0;
75 int32_t deltaXQ = 0;
76 int32_t deltaYQ = 0;
77 uint32_t deltaManhattanQ = 0;
78 };
79
87 {
88 uint32_t localInputsApplied = 0;
89 uint32_t localInputsDeferred = 0;
90 uint32_t rejectedLocalInputs = 0;
91
92 uint32_t correctionsApplied = 0;
94 uint32_t correctionsMismatched = 0;
95
96 uint32_t totalCorrectionDeltaQ = 0;
97 uint32_t maxCorrectionDeltaQ = 0;
98
99 uint32_t totalReplayedInputs = 0;
100 uint32_t maxReplayedInputs = 0;
101
102 uint32_t replayTruncations = 0;
105 uint32_t recoveryActivations = 0;
106 uint32_t recoveryResolutions = 0;
107 };
108
109 // ----- Client Prediction Helper -----
110
113 {
114 private:
115 enum class PredictionPhase : uint8_t
116 {
117 AwaitingBaseline,
118 Active,
119 Recovering
120 };
121
122 public:
123 ClientPrediction() = default;
124
125 // ----- Public API -----
126
128 void reset() noexcept;
130 void suspend() noexcept;
131
133 [[nodiscard]]
134 bool isInitialized() const noexcept { return phase_ != PredictionPhase::AwaitingBaseline; }
135
137 [[nodiscard]]
138 const LocalPlayerState& currentState() const noexcept { return currentState_; }
139
141 [[nodiscard]]
142 const PredictionStats& stats() const noexcept { return stats_; }
143
145 [[nodiscard]]
146 uint32_t lastRecordedInputSeq() const noexcept { return lastRecordedInputSeq_; }
147
149 bool applyLocalInput(uint32_t inputSeq, uint8_t buttons, const sim::TileMap& map) noexcept;
150
152 [[nodiscard]]
153 CorrectionReplayResult reconcileAndReplay(const MsgCorrection& correction, const sim::TileMap& map) noexcept;
154
155 private:
156 // ----- History entries -----
157
158 struct InputHistoryEntry
159 {
160 uint32_t seq = 0;
161 uint8_t buttons = 0;
162 bool valid = false;
163 };
164
165 struct StateHistoryEntry
166 {
167 uint32_t seq = 0;
168 LocalPlayerState state{};
169 bool valid = false;
170 };
171
172 [[nodiscard]]
173 static constexpr std::size_t historySlot(uint32_t seq) noexcept
174 {
175 return seq & (kClientPredictionHistorySize - 1u);
176 }
177
178 // ----- Correction helpers -----
179
181 void setCurrentAuthoritativeState(sim::TilePos posQ,
182 uint8_t buttons = 0,
183 uint8_t playerFlags = 0) noexcept;
185 void enterRecoveryFromReplayFailure(sim::TilePos authoritativePosQ,
186 uint32_t lastProcessedInputSeq,
187 uint8_t authoritativePlayerFlags,
188 CorrectionReplayResult& result,
189 bool wasRecovering) noexcept;
191 [[nodiscard]]
192 bool replayFromAuthoritativeBaseline(uint32_t lastProcessedInputSeq,
193 sim::TilePos authoritativePosQ,
194 uint8_t authoritativeButtons,
195 uint8_t authoritativePlayerFlags,
196 const sim::TileMap& map,
197 CorrectionReplayResult& result) noexcept;
199 void handleAwaitingBaselineCorrection(uint32_t lastProcessedInputSeq,
200 sim::TilePos authoritativePosQ,
201 uint8_t authoritativePlayerFlags,
202 const sim::TileMap& map,
203 CorrectionReplayResult& result) noexcept;
205 void handleRecoveringCorrection(uint32_t lastProcessedInputSeq,
206 sim::TilePos authoritativePosQ,
207 uint8_t authoritativePlayerFlags,
208 const sim::TileMap& map,
209 CorrectionReplayResult& result) noexcept;
211 void handleActiveCorrection(uint32_t lastProcessedInputSeq,
212 sim::TilePos authoritativePosQ,
213 uint8_t authoritativeButtons,
214 uint8_t authoritativePlayerFlags,
215 const sim::TileMap& map,
216 CorrectionReplayResult& result) noexcept;
218 void measureCorrectionAtAck(uint32_t lastProcessedInputSeq,
219 sim::TilePos authoritativePosQ,
220 uint8_t& predictedButtonsAtAck,
221 CorrectionReplayResult& result) noexcept;
223 [[nodiscard]]
224 bool tryGetPredictedStateAtSeq(uint32_t inputSeq, LocalPlayerState& outState) const noexcept;
225
226 // ----- History storage -----
227
229 void clearHistory() noexcept;
231 void storeInputHistory(uint32_t seq, uint8_t buttons) noexcept;
233 void storeStateHistory(uint32_t seq, const LocalPlayerState& state) noexcept;
235 void invalidateStateHistoryRange(uint32_t firstSeq, uint32_t lastSeq) noexcept;
237 void discardAcknowledgedHistory(uint32_t lastProcessedInputSeq) noexcept;
239 [[nodiscard]]
240 uint32_t countRetainedInputSuffixAfter(uint32_t inputSeq) const noexcept;
242 [[nodiscard]]
243 bool replayRetainedInputSuffixAfter(uint32_t lastProcessedInputSeq,
244 const sim::TileMap& map,
245 CorrectionReplayResult& result) noexcept;
246
247 // ----- Ring lookups and simulation -----
248
250 [[nodiscard]]
251 const InputHistoryEntry* findInputHistory(uint32_t seq) const noexcept;
252
254 [[nodiscard]]
255 const StateHistoryEntry* findStateHistory(uint32_t seq) const noexcept;
256
258 [[nodiscard]]
259 LocalPlayerState simulateNextStateFromInput(const LocalPlayerState& baseState,
260 uint8_t buttons,
261 const sim::TileMap& map) const noexcept;
262
263 // ----- State -----
264
265 std::array<InputHistoryEntry, kClientPredictionHistorySize> inputHistory_{};
266 std::array<StateHistoryEntry, kClientPredictionHistorySize> stateHistory_{};
267
268 LocalPlayerState currentState_{};
269 PredictionStats stats_{};
270 uint32_t lastRecordedInputSeq_ = 0;
271 uint32_t lastAuthoritativeInputSeq_ = 0;
272 uint32_t recoveryCatchUpSeq_ = 0;
273 PredictionPhase phase_ = PredictionPhase::AwaitingBaseline;
274 };
275
276} // namespace bomberman::net
277
278#endif // BOMBERMAN_NET_CLIENTPREDICTION_H
Shared authoritative movement simulation primitives.
Shared client/server wire contract for the multiplayer protocol.
Client-side local input prediction and reconciliation.
Definition ClientPrediction.h:113
void reset() noexcept
Clears all prediction state and history.
Definition ClientPrediction.cpp:18
void suspend() noexcept
Suspends prediction, drops retained local history, and waits for a later correction baseline to re-ar...
Definition ClientPrediction.cpp:31
CorrectionReplayResult reconcileAndReplay(const MsgCorrection &correction, const sim::TileMap &map) noexcept
Applies an authoritative correction and replays retained local inputs after it.
Definition ClientPrediction.cpp:109
bool isInitialized() const noexcept
Returns true once the first authoritative baseline has been accepted.
Definition ClientPrediction.h:134
const LocalPlayerState & currentState() const noexcept
Returns the local state currently being presented for the owning player.
Definition ClientPrediction.h:138
bool applyLocalInput(uint32_t inputSeq, uint8_t buttons, const sim::TileMap &map) noexcept
Records one new local input and simulates it immediately only while prediction is active.
Definition ClientPrediction.cpp:45
const PredictionStats & stats() const noexcept
Returns aggregate prediction diagnostics for the current session.
Definition ClientPrediction.h:142
uint32_t lastRecordedInputSeq() const noexcept
Returns the highest contiguous local input seq seen so far.
Definition ClientPrediction.h:146
Shared multiplayer protocol types and transport-facing wire helpers.
Definition ClientPrediction.cpp:13
constexpr std::size_t kClientPredictionHistorySize
Power-of-two ring size used for local prediction history and bitmask slot indexing.
Definition ClientPrediction.h:40
Tile[tileArrayHeight][tileArrayWidth] TileMap
Read-only view of a runtime tile map (same layout as LevelScene::tiles).
Definition Movement.h:36
Summary of one correction/replay attempt.
Definition ClientPrediction.h:62
uint32_t replayedInputs
Retained local inputs replayed after the acked input seq.
Definition ClientPrediction.h:71
uint32_t deltaManhattanQ
Manhattan size of that correction delta, in tile-Q8.
Definition ClientPrediction.h:77
bool recoveryResolved
Recovery finished and normal local prediction resumed.
Definition ClientPrediction.h:68
bool hadRetainedPredictedStateAtAck
Predicted state was still retained at the acked input seq.
Definition ClientPrediction.h:64
bool recoveryRestarted
Recovery was already active and restarted from a newer unresolved suffix.
Definition ClientPrediction.h:67
bool ignoredStaleCorrection
Correction was not newer than the last accepted authoritative input seq.
Definition ClientPrediction.h:63
uint32_t remainingDeferredInputs
Retained local inputs still waiting behind the authoritative cursor.
Definition ClientPrediction.h:73
uint32_t recoveryCatchUpSeq
Highest local input seq authority must catch up to before replay may resume.
Definition ClientPrediction.h:74
uint32_t missingInputHistory
Length of the first missing retained suffix that blocked replay.
Definition ClientPrediction.h:72
bool recoveryTriggered
Replay failed and presentation fell back to authority.
Definition ClientPrediction.h:66
bool correctionMatchedRetainedPrediction
That retained state matched the authoritative ack state.
Definition ClientPrediction.h:65
int32_t deltaYQ
Authoritative minus predicted Y delta at the acked input seq, in tile-Q8.
Definition ClientPrediction.h:76
int32_t deltaXQ
Authoritative minus predicted X delta at the acked input seq, in tile-Q8.
Definition ClientPrediction.h:75
bool recoveryStillActive
Presented local state is still authoritative after this correction.
Definition ClientPrediction.h:69
Local state currently presented for the owning player.
Definition ClientPrediction.h:47
uint8_t playerFlags
Owner-local replicated flags that affect prediction, such as speed boost.
Definition ClientPrediction.h:50
uint8_t buttons
Latest local buttons, used for local facing/animation context.
Definition ClientPrediction.h:49
Owner-only correction payload sent by the server.
Definition NetCommon.h:738
Aggregate prediction stats for diagnostics.
Definition ClientPrediction.h:87
uint32_t recoveryResolutions
Times recovery replay succeeded and prediction resumed.
Definition ClientPrediction.h:106
uint32_t totalMissingInputHistory
Sum of missing retained suffix sizes that caused replay truncation.
Definition ClientPrediction.h:103
uint32_t totalCorrectionDeltaQ
Sum of correction Manhattan deltas over corrections with retained predicted state.
Definition ClientPrediction.h:96
uint32_t localInputsDeferred
Inputs retained but not simulated yet.
Definition ClientPrediction.h:89
uint32_t rejectedLocalInputs
Inputs rejected for invalid or non-contiguous sequence progression.
Definition ClientPrediction.h:90
uint32_t correctionsWithRetainedPredictedState
Corrections whose acked sequence still had retained predicted state.
Definition ClientPrediction.h:93
uint32_t maxMissingInputHistory
Largest missing retained suffix observed during replay.
Definition ClientPrediction.h:104
uint32_t recoveryActivations
Transitions from active prediction into authoritative recovery mode.
Definition ClientPrediction.h:105
uint32_t correctionsMismatched
Corrections whose authoritative ack state differed from retained prediction.
Definition ClientPrediction.h:94
uint32_t localInputsApplied
Inputs simulated immediately.
Definition ClientPrediction.h:88
uint32_t maxCorrectionDeltaQ
Largest correction Manhattan delta seen so far.
Definition ClientPrediction.h:97
uint32_t replayTruncations
Replay attempts that fell back to recovery because retained input history was incomplete.
Definition ClientPrediction.h:102
uint32_t correctionsApplied
Newer authoritative corrections consumed by the helper.
Definition ClientPrediction.h:92
uint32_t maxReplayedInputs
Largest replay suffix rebuilt from one correction.
Definition ClientPrediction.h:100
uint32_t totalReplayedInputs
Sum of replayed retained inputs across all correction applications.
Definition ClientPrediction.h:99
Tile-space Q8 position representing the CENTER of the entity.
Definition Movement.h:30