group2 0.1.0
CSE 125 Group 2
Loading...
Searching...
No Matches
ServerGame.hpp
Go to the documentation of this file.
1
3
4#pragma once
5
20#include "network/Server.hpp"
22#include "systems/Event.hpp" // PR-27: ShotIntentPayload
24
25#include <SDL3/SDL.h>
26
27#include <array>
28#include <entt/entity/entity.hpp>
29#include <functional>
30#include <memory>
31#include <unordered_map>
32#include <vector>
33
39{
40public:
48 bool init(Server& server, int tickRateHz = 128, int snapshotHz = 32, bool skipLobby = false);
49
59 void run();
60
62 void shutdown();
63
65 [[nodiscard]] bool isHost(ClientId clientId) const;
66
68 void onMatchConfigUpdated(std::function<void(const MatchConfig&)> fn) { matchConfigUpdatedFn_ = std::move(fn); }
69
71 void onDiscoverySettingsUpdated(std::function<void(const DiscoverySettings&)> fn)
72 {
73 discoverySettingsUpdatedFn_ = std::move(fn);
74 }
75
77 bool setMatchConfig(const MatchConfig& config);
78
80 bool setKillsToWin(int kills);
81
83 bool setMaxPlayers(int maxPlayers);
84
86 bool setIdleShutdownMinutes(int minutes);
87
88private:
91 void eventHandler(const Event& event);
92 void applyInputEvent(ClientId clientId, const InputSnapshot& inputSnapshot);
93
124 void tick(float dt, Uint64 nextTick);
125
128 void initNewPlayerEntity(ClientId clientId);
129
132 void deletePlayerEntity(ClientId clientId);
133
136 void initAnimation();
137
139 void attachServerAnimator(entt::entity player);
140
142 void detachServerAnimator(entt::entity player);
143
146 void updateAnimationAndHitboxes(float dt);
147
163
166 void applyMatchAbilityChoices(AbilityState& state) const;
167
169
170 Server* server = nullptr;
173 std::vector<AbilityType> matchPrimaryAbilities;
174 std::vector<AbilityType> matchSecondaryAbilities;
177 std::function<void(const MatchConfig&)> matchConfigUpdatedFn_;
178 std::function<void(const DiscoverySettings&)>
183 std::unordered_map<ClientId, entt::entity> clientEntities;
184 std::vector<NetKillEvent> pendingKillEvents;
185
191 std::array<int, player_colors::k_paletteSize> colorSlotUseCounts_{};
192
196 std::array<int, player_nicknames::k_nicknameCount> nicknameSlotUseCounts_{};
197 bool running = false;
198 int tickRateHz = 128;
199 int tickCount = 0;
200
207 bool shotDebugEnabled_ = false;
208
209 // ── Phase 6+ rigid-body dynamics state ──
214
215 // ── Server-side animation subsystem ──
219 float rigScale_ = 1.0f;
220 float rigMeshMinY_ = 0.0f;
221 bool animationLoaded_ = false;
222
225 std::unordered_map<entt::entity, std::unique_ptr<CharacterAnimator>> serverAnimators_;
226
227 // ── PR-18: server-side ground-truth log ──────────────────────────────
228 //
229 // Opened from `GROUP2_SERVER_TRUTH_CSV` env var if set. One global
230 // CSV file containing one row per replicated player per logged tick:
231 //
232 // wallTimeNs,serverTick,clientId,posX,posY,posZ
233 //
234 // Throttled to every Nth tick (default 4 = 32 Hz at the 128 Hz tick
235 // rate; tunable via `GROUP2_SERVER_TRUTH_HZ_DIVIDER`). Log rate is
236 // chosen to be high enough that linear interpolation between
237 // adjacent samples is a good approximation of "the server's
238 // position at any wall-clock time T", which is what the offline
239 // analyzer compares against bot-side observations. At 32 Hz × 100
240 // bots × ~50 B/row = ~160 KB/s — trivial disk I/O cost on any
241 // reasonable test rig.
242 //
243 // No mutex needed: this runs on the game thread, on the same path
244 // as the existing tick logic, after the per-tick physics + lag-comp
245 // updates have settled.
246 std::FILE* truthCsv_ = nullptr;
248
251 void openGroundTruthLog();
252
257
259 void closeGroundTruthLog() noexcept;
260
263
265 [[nodiscard]] bool isGameplayInputAllowed(MatchPhase phase) const;
266
268 [[nodiscard]] bool isLobbyPhase(MatchPhase phase) const;
269
270 // ── PR-27: pending client SHOT_INTENTs ───────────────────────────────
271 //
272 // The network thread enqueues `EventType::ShotIntent` events into
273 // `eventQueue`; the game thread's `processEvent` drains them and
274 // stashes the payload here, keyed by `(shooterClientId,
275 // shotInputTick)`. When the weapon-system path resolves a shot
276 // for the same shooter at the same input tick, it looks up the
277 // intent here, computes the anim-state delta vs the historical
278 // sample, and emits the result to `server_shots.csv`.
279 //
280 // Bounded at `k_pendingShotIntentsMax = 256` entries (~2 s of
281 // shots at the 128 Hz fire-rate ceiling). The map is single-
282 // threaded read/write on the game thread.
284 {
285 std::uint16_t shooterClientId = 0;
286 std::uint32_t shotInputTick = 0;
287 bool operator==(const ShotIntentKey& o) const noexcept
288 {
289 return shooterClientId == o.shooterClientId && shotInputTick == o.shotInputTick;
290 }
291 };
293 {
294 std::size_t operator()(const ShotIntentKey& k) const noexcept
295 {
296 // Mix shooter into the high bits so two shots from the
297 // same shooter at adjacent ticks aren't bucket-adjacent.
298 return (static_cast<std::size_t>(k.shooterClientId) << 32) ^ k.shotInputTick;
299 }
300 };
301 static constexpr std::size_t k_pendingShotIntentsMax = 256;
302 std::unordered_map<ShotIntentKey, ShotIntentPayload, ShotIntentKeyHash> pendingShotIntents_;
303
304 bool idleShutdownEnabled_ = false;
305 uint64_t idleShutdownMs_ = 0;
306 uint64_t lastNonEmptyMs_ = 0;
307};
Stores every ability available in the game and maps type to ability.
PR-27 — per-entity animation state snapshot, decoupled from CharacterAnimator.
Catalog of ozz animation clips shared across all animated entities.
Per-entity animator — state machine, sampling, blending, CPU skinning.
Shared skinned-character rig: skeleton, bind-pose mesh, skin weights.
Network client identifier component for multiplayer entities.
Per-pair contact manifold cache for warm-starting the solver.
Client Event structure to be consumed by server game loop.
Skeleton-driven hitbox types: body regions, capsule definitions, damage profiles, and per-entity runt...
Server-side lobby state machine: player join/leave, ready-up, and match-start gating.
Load collision geometry (and optionally visual data) from a map GLB file.
Controls match flow, including starting and ending matches and managing match state.
MatchPhase
Definition MatchStatus.hpp:8
Network configuration loaded from config.toml at startup.
Palette + tunables for the per-player color tint feature.
Curated animal-handle list used as default player nicknames.
Player status manager for things like life state and healing.
Shared ECS registry type alias for the game engine.
entt::registry Registry
Shared ECS registry type alias.
Definition Registry.hpp:11
TCP game server that accepts clients and dispatches incoming packets.
Definition AbilityRegistry.hpp:12
Collection of animation clips loaded on top of a shared skeleton.
Definition AnimationLibrary.hpp:75
Shared skinned rig — skeleton + bind-pose meshes + joint map.
Definition CharacterRig.hpp:45
A single gameplay event produced by network input processing.
Definition Event.hpp:47
Manages authoritative lobby state and broadcasts updates to connected clients.
Definition LobbyManager.hpp:17
Manages match flow: lobby → countdown → in-progress → finished → lobby.
Definition MatchController.hpp:15
Top-level server game loop.
Definition ServerGame.hpp:39
physics::ContactCache contactCache_
Persistent contact-manifold cache for warm-starting the PGS solver across ticks.
Definition ServerGame.hpp:213
bool idleShutdownEnabled_
True if idle shutdown is enabled via env var.
Definition ServerGame.hpp:304
void initAnimation()
Initialise the server-side animation subsystem (skeleton, clips, hitboxes).
Definition ServerGame.cpp:1143
bool init(Server &server, int tickRateHz=128, int snapshotHz=32, bool skipLobby=false)
Attach to an already-bound Server and initialise game state.
Definition ServerGame.cpp:118
int tickRateHz
Physics ticks per second.
Definition ServerGame.hpp:198
std::FILE * truthCsv_
Definition ServerGame.hpp:246
void openGroundTruthLog()
Open the ground-truth CSV from env var if set.
Definition ServerGame.cpp:316
void attachServerAnimator(entt::entity player)
Create and store a server-side animator for the given player entity.
Definition ServerGame.cpp:1219
bool setIdleShutdownMinutes(int minutes)
Configure idle shutdown timeout in minutes; non-positive values disable it.
Definition ServerGame.cpp:1479
void detachServerAnimator(entt::entity player)
Remove the server-side animator for the given entity.
Definition ServerGame.cpp:1229
float rigScale_
Rig model-space → game-unit scale factor.
Definition ServerGame.hpp:219
bool shotDebugEnabled_
Opt-in lag-comp shot visualizer capture/send path.
Definition ServerGame.hpp:207
int snapshotEveryNTicks
Send a registry snapshot every Nth tick.
Definition ServerGame.hpp:206
AnimationLibrary serverAnimLibrary_
Animation clips for server-side sampling.
Definition ServerGame.hpp:217
void onMatchConfigUpdated(std::function< void(const MatchConfig &)> fn)
Register a callback fired after the host updates match settings.
Definition ServerGame.hpp:68
bool setMaxPlayers(int maxPlayers)
Update only the maximum accepted player count in the authoritative match config.
Definition ServerGame.cpp:1454
std::unordered_map< ClientId, entt::entity > clientEntities
Maps client IDs to ECS entities.
Definition ServerGame.hpp:183
bool isHost(ClientId clientId) const
True if the given client currently owns host-only lobby/server controls.
Definition ServerGame.cpp:1444
void shutdown()
Signal the loop to stop and release all resources.
Definition ServerGame.cpp:307
void tick(float dt, Uint64 nextTick)
Advance one physics tick: drain events, run ECS systems, broadcast state.
Definition ServerGame.cpp:626
std::vector< NetKillEvent > pendingKillEvents
Accumulates kill events waiting for network broadcast.
Definition ServerGame.hpp:184
CharacterRig serverRig_
Shared skeleton (loaded from same FBX as client).
Definition ServerGame.hpp:216
void updateLagCompTargets()
Phase 6: write LagCompTarget onto each connected player's entity from their connection's last-reporte...
Definition ServerGame.cpp:1234
std::vector< AbilityType > matchPrimaryAbilities
list of abilities available during the match
Definition ServerGame.hpp:173
static constexpr std::size_t k_pendingShotIntentsMax
Definition ServerGame.hpp:301
HitboxRig hitboxRig_
Shared hitbox capsule definitions.
Definition ServerGame.hpp:218
uint64_t lastNonEmptyMs_
Timestamp of the last player activity, for idle shutdown.
Definition ServerGame.hpp:306
bool running
Loop continues while true.
Definition ServerGame.hpp:197
std::array< int, player_colors::k_paletteSize > colorSlotUseCounts_
Use-count per palette slot for least-used color reservation.
Definition ServerGame.hpp:191
void closeGroundTruthLog() noexcept
Flush + close the CSV if open. Safe to call from dtor.
Definition ServerGame.cpp:370
int tickCount
Total ticks since start, used for periodic logging.
Definition ServerGame.hpp:199
bool lobbyStartCountdownActive
True while lobby is counting down before entering match countdown.
Definition ServerGame.hpp:180
void eventHandler(const Event &event)
Apply a single event to the ECS registry.
Definition ServerGame.cpp:394
std::vector< AbilityType > matchSecondaryAbilities
Definition ServerGame.hpp:174
void writeGroundTruthLogIfDue()
Write one row per replicated player entity if the current tickCount aligns with truthHzDivider_.
Definition ServerGame.cpp:338
int truthHzDivider_
Definition ServerGame.hpp:247
Registry registry
ECS entity/component store.
Definition ServerGame.hpp:171
MatchController matchController
Manages match flow and state.
Definition ServerGame.hpp:176
float rigMeshMinY_
Minimum Y of bind-pose mesh (for vertical offset).
Definition ServerGame.hpp:220
uint64_t idleShutdownMs_
Idle shutdown timeout in ms, from env var. 0 = no timeout.
Definition ServerGame.hpp:305
bool isGameplayInputAllowed(MatchPhase phase) const
Determine if server should allow input based on phase.
Definition ServerGame.cpp:1561
void updateAnimationAndHitboxes(float dt)
Update all server-side animators and recompute hitbox capsules.
Definition ServerGame.cpp:1356
std::unordered_map< ShotIntentKey, ShotIntentPayload, ShotIntentKeyHash > pendingShotIntents_
Definition ServerGame.hpp:302
LobbyManager lobbyManager
Owns lobby roster and validates host-initiated match starts.
Definition ServerGame.hpp:175
bool setKillsToWin(int kills)
Update only the kill threshold in the authoritative match config.
Definition ServerGame.cpp:1449
void deletePlayerEntity(ClientId clientId)
Remove player entity from ECS.
Definition ServerGame.cpp:1105
bool setMatchConfig(const MatchConfig &config)
Apply a complete match config to the authoritative match controller.
Definition ServerGame.cpp:1466
ClientId lobbyStartRequester
Host that requested the active lobby staging countdown.
Definition ServerGame.hpp:182
std::function< void(const DiscoverySettings &)> discoverySettingsUpdatedFn_
Mirrors discovery visibility changes.
Definition ServerGame.hpp:179
std::array< int, player_nicknames::k_nicknameCount > nicknameSlotUseCounts_
Use-count per nickname slot — same selection scheme as colors.
Definition ServerGame.hpp:196
void run()
Block on the game loop until shutdown() is called.
Definition ServerGame.cpp:200
void resetPlayersForCountdown()
Reset live players to spawn points for countdown.
Definition ServerGame.cpp:1492
void selectMatchAbilityPool()
Select the subset of abilities for new match.
Definition ServerGame.cpp:605
void applyMatchAbilityChoices(AbilityState &state) const
Definition ServerGame.cpp:616
physics::MapCollisionData mapCollision_
Map collision data — owns vectors backing activeWorld().
Definition ServerGame.hpp:168
bool animationLoaded_
True if rig+clips loaded successfully.
Definition ServerGame.hpp:221
std::unordered_map< entt::entity, std::unique_ptr< CharacterAnimator > > serverAnimators_
Per-entity server animators (not ECS components to avoid pulling animation headers into the component...
Definition ServerGame.hpp:225
void onDiscoverySettingsUpdated(std::function< void(const DiscoverySettings &)> fn)
Register a callback fired after the host updates discovery visibility.
Definition ServerGame.hpp:71
void initNewPlayerEntity(ClientId clientId)
Create a new player entity and map it to the given client ID.
Definition ServerGame.cpp:1021
AbilityRegistry abilityRegistry
Registry of abilities via type idx.
Definition ServerGame.hpp:172
std::function< void(const MatchConfig &)> matchConfigUpdatedFn_
Mirrors match updates to networking/discovery.
Definition ServerGame.hpp:177
void applyInputEvent(ClientId clientId, const InputSnapshot &inputSnapshot)
Definition ServerGame.cpp:378
bool isLobbyPhase(MatchPhase phase) const
Return true when roster changes should use lobby updates instead of in-match popups.
Definition ServerGame.cpp:1571
float lobbyStartCountdownTimer
Seconds remaining in the lobby staging countdown.
Definition ServerGame.hpp:181
TCP stream socket — receives client packets and echoes them back.
Definition Server.hpp:42
Definition ContactCache.hpp:26
Definition LagCompMath.hpp:10
Definition AbilityState.hpp:87
Associates an entity with a connected network client.
Definition ClientId.hpp:10
Host-managed discovery visibility flags.
Definition DiscoverySettings.hpp:11
Hitbox rig (shared per character archetype).
Definition Hitbox.hpp:159
One tick of player input, stamped with the tick it was sampled on.
Definition InputSnapshot.hpp:17
Definition MatchConfig.hpp:4
Definition ServerGame.hpp:293
std::size_t operator()(const ShotIntentKey &k) const noexcept
Definition ServerGame.hpp:294
Definition ServerGame.hpp:284
std::uint32_t shotInputTick
Definition ServerGame.hpp:286
bool operator==(const ShotIntentKey &o) const noexcept
Definition ServerGame.hpp:287
std::uint16_t shooterClientId
Definition ServerGame.hpp:285
Collision data.
Definition MapLoader.hpp:36