|
group2 0.1.0
CSE 125 Group 2
|
Top-level server game loop. More...
#include <ServerGame.hpp>
Classes | |
| struct | ShotIntentKey |
| struct | ShotIntentKeyHash |
Public Member Functions | |
| bool | init (Server &server, int tickRateHz=128, int snapshotHz=32, bool skipLobby=false) |
| Attach to an already-bound Server and initialise game state. | |
| void | run () |
| Block on the game loop until shutdown() is called. | |
| void | shutdown () |
| Signal the loop to stop and release all resources. | |
| bool | isHost (ClientId clientId) const |
| True if the given client currently owns host-only lobby/server controls. | |
| void | onMatchConfigUpdated (std::function< void(const MatchConfig &)> fn) |
| Register a callback fired after the host updates match settings. | |
| void | onDiscoverySettingsUpdated (std::function< void(const DiscoverySettings &)> fn) |
| Register a callback fired after the host updates discovery visibility. | |
| bool | setMatchConfig (const MatchConfig &config) |
| Apply a complete match config to the authoritative match controller. | |
| bool | setKillsToWin (int kills) |
| Update only the kill threshold in the authoritative match config. | |
| bool | setMaxPlayers (int maxPlayers) |
| Update only the maximum accepted player count in the authoritative match config. | |
| bool | setIdleShutdownMinutes (int minutes) |
| Configure idle shutdown timeout in minutes; non-positive values disable it. | |
Private Member Functions | |
| void | eventHandler (const Event &event) |
| Apply a single event to the ECS registry. | |
| void | applyInputEvent (ClientId clientId, const InputSnapshot &inputSnapshot) |
| void | tick (float dt, Uint64 nextTick) |
| Advance one physics tick: drain events, run ECS systems, broadcast state. | |
| void | initNewPlayerEntity (ClientId clientId) |
| Create a new player entity and map it to the given client ID. | |
| void | deletePlayerEntity (ClientId clientId) |
| Remove player entity from ECS. | |
| void | initAnimation () |
| Initialise the server-side animation subsystem (skeleton, clips, hitboxes). | |
| void | attachServerAnimator (entt::entity player) |
| Create and store a server-side animator for the given player entity. | |
| void | detachServerAnimator (entt::entity player) |
| Remove the server-side animator for the given entity. | |
| void | updateAnimationAndHitboxes (float dt) |
| Update all server-side animators and recompute hitbox capsules. | |
| void | updateLagCompTargets () |
| Phase 6: write LagCompTarget onto each connected player's entity from their connection's last-reported RTT. | |
| void | selectMatchAbilityPool () |
| Select the subset of abilities for new match. | |
| void | applyMatchAbilityChoices (AbilityState &state) const |
| void | openGroundTruthLog () |
| Open the ground-truth CSV from env var if set. | |
| void | writeGroundTruthLogIfDue () |
| Write one row per replicated player entity if the current tickCount aligns with truthHzDivider_. | |
| void | closeGroundTruthLog () noexcept |
| Flush + close the CSV if open. Safe to call from dtor. | |
| void | resetPlayersForCountdown () |
| Reset live players to spawn points for countdown. | |
| bool | isGameplayInputAllowed (MatchPhase phase) const |
| Determine if server should allow input based on phase. | |
| bool | isLobbyPhase (MatchPhase phase) const |
| Return true when roster changes should use lobby updates instead of in-match popups. | |
Private Attributes | |
| physics::MapCollisionData | mapCollision_ |
| Map collision data — owns vectors backing activeWorld(). | |
| Server * | server = nullptr |
| Non-owning pointer; main() owns and shuts down the socket. | |
| Registry | registry |
| ECS entity/component store. | |
| AbilityRegistry | abilityRegistry |
| Registry of abilities via type idx. | |
| std::vector< AbilityType > | matchPrimaryAbilities |
| list of abilities available during the match | |
| std::vector< AbilityType > | matchSecondaryAbilities |
| LobbyManager | lobbyManager |
| Owns lobby roster and validates host-initiated match starts. | |
| MatchController | matchController |
| Manages match flow and state. | |
| std::function< void(const MatchConfig &)> | matchConfigUpdatedFn_ |
| Mirrors match updates to networking/discovery. | |
| std::function< void(const DiscoverySettings &)> | discoverySettingsUpdatedFn_ |
| Mirrors discovery visibility changes. | |
| bool | lobbyStartCountdownActive = false |
| True while lobby is counting down before entering match countdown. | |
| float | lobbyStartCountdownTimer = 0.0f |
| Seconds remaining in the lobby staging countdown. | |
| ClientId | lobbyStartRequester {-1} |
| Host that requested the active lobby staging countdown. | |
| std::unordered_map< ClientId, entt::entity > | clientEntities |
| Maps client IDs to ECS entities. | |
| std::vector< NetKillEvent > | pendingKillEvents |
| Accumulates kill events waiting for network broadcast. | |
| std::array< int, player_colors::k_paletteSize > | colorSlotUseCounts_ {} |
| Use-count per palette slot for least-used color reservation. | |
| std::array< int, player_nicknames::k_nicknameCount > | nicknameSlotUseCounts_ {} |
| Use-count per nickname slot — same selection scheme as colors. | |
| bool | running = false |
| Loop continues while true. | |
| int | tickRateHz = 128 |
| Physics ticks per second. | |
| int | tickCount = 0 |
| Total ticks since start, used for periodic logging. | |
| int | snapshotEveryNTicks = 4 |
| Send a registry snapshot every Nth tick. | |
| bool | shotDebugEnabled_ = false |
| Opt-in lag-comp shot visualizer capture/send path. | |
| physics::ContactCache | contactCache_ |
| Persistent contact-manifold cache for warm-starting the PGS solver across ticks. | |
| CharacterRig | serverRig_ |
| Shared skeleton (loaded from same FBX as client). | |
| AnimationLibrary | serverAnimLibrary_ |
| Animation clips for server-side sampling. | |
| HitboxRig | hitboxRig_ |
| Shared hitbox capsule definitions. | |
| float | rigScale_ = 1.0f |
| Rig model-space → game-unit scale factor. | |
| float | rigMeshMinY_ = 0.0f |
| Minimum Y of bind-pose mesh (for vertical offset). | |
| bool | animationLoaded_ = false |
| True if rig+clips loaded successfully. | |
| 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 registry). | |
| std::FILE * | truthCsv_ = nullptr |
| int | truthHzDivider_ = 4 |
| std::unordered_map< ShotIntentKey, ShotIntentPayload, ShotIntentKeyHash > | pendingShotIntents_ |
| bool | idleShutdownEnabled_ = false |
| True if idle shutdown is enabled via env var. | |
| uint64_t | idleShutdownMs_ = 0 |
| Idle shutdown timeout in ms, from env var. 0 = no timeout. | |
| uint64_t | lastNonEmptyMs_ = 0 |
| Timestamp of the last player activity, for idle shutdown. | |
Static Private Attributes | |
| static constexpr std::size_t | k_pendingShotIntentsMax = 256 |
Top-level server game loop.
Borrows an already-bound Server from the caller (main owns the socket). Each tick it drains incoming messages, runs all ECS systems, and broadcasts state.
|
private |
|
private |
|
private |
Create and store a server-side animator for the given player entity.
|
privatenoexcept |
Flush + close the CSV if open. Safe to call from dtor.
|
private |
Remove player entity from ECS.
| clientId | Network client identifier for the player. |
|
private |
Remove the server-side animator for the given entity.
|
private |
Apply a single event to the ECS registry.
| event | The event to process. |
| bool ServerGame::init | ( | Server & | server, |
| int | tickRateHz = 128, | ||
| int | snapshotHz = 32, | ||
| bool | skipLobby = false ) |
Attach to an already-bound Server and initialise game state.
| server | Externally-owned, already-initialised Server. |
| tickRateHz | Physics tick rate in Hz (default 128). |
| snapshotHz | Registry snapshot send rate in Hz (default 32). Must be ≤ tickRateHz; clamped if not. |
| skipLobby | True to bypass lobby and enter countdown automatically. |
|
private |
Initialise the server-side animation subsystem (skeleton, clips, hitboxes).
Called once during init() after map loading.
|
private |
Create a new player entity and map it to the given client ID.
| clientId | Network client identifier for the new player. |
|
nodiscardprivate |
Determine if server should allow input based on phase.
|
nodiscard |
True if the given client currently owns host-only lobby/server controls.
|
nodiscardprivate |
Return true when roster changes should use lobby updates instead of in-match popups.
|
inline |
Register a callback fired after the host updates discovery visibility.
|
inline |
Register a callback fired after the host updates match settings.
|
private |
Open the ground-truth CSV from env var if set.
No-op when the env var is missing; load tests stay fast by default.
|
private |
Reset live players to spawn points for countdown.
| void ServerGame::run | ( | ) |
Block on the game loop until shutdown() is called.
Loop structure (each iteration = one tick at tickRateHz):
|
private |
Select the subset of abilities for new match.
| bool ServerGame::setIdleShutdownMinutes | ( | int | minutes | ) |
Configure idle shutdown timeout in minutes; non-positive values disable it.
| bool ServerGame::setKillsToWin | ( | int | kills | ) |
Update only the kill threshold in the authoritative match config.
| bool ServerGame::setMatchConfig | ( | const MatchConfig & | config | ) |
Apply a complete match config to the authoritative match controller.
| bool ServerGame::setMaxPlayers | ( | int | maxPlayers | ) |
Update only the maximum accepted player count in the authoritative match config.
| void ServerGame::shutdown | ( | ) |
Signal the loop to stop and release all resources.
|
private |
Advance one physics tick: drain events, run ECS systems, broadcast state.
Execution order each tick:
Broadcast — send updated registry snapshot, particle events, and kill events to all connected clients.
| dt | Fixed delta time in seconds (1 / tickRateHz). |
| nextTick | Performance counter deadline for the current tick. |
|
private |
Update all server-side animators and recompute hitbox capsules.
Called once per tick before weapon/damage systems.
|
private |
Phase 6: write LagCompTarget onto each connected player's entity from their connection's last-reported RTT.
Translates Connection::lastReportedRttMs (ms) into a targetServerTick = max(0, currentServerTick - rewindTicks), where rewindTicks = clamp(rttMs * tickRateHz / 2000, 0, k_maxLagCompTicks). Players with no client connection (e.g. AI bots in a future expansion) keep their previous target, which on the next pushHitboxHistory will become a valid rewind anchor — but for now, only entities bound through clientEntities get a target.
Called once per tick between pushHitboxHistory and runWeapon.
|
private |
Write one row per replicated player entity if the current tickCount aligns with truthHzDivider_.
Called at the end of each tick after the per-tick physics + broadcast settles.
|
private |
Registry of abilities via type idx.
|
private |
True if rig+clips loaded successfully.
|
private |
Maps client IDs to ECS entities.
|
private |
Use-count per palette slot for least-used color reservation.
Sized to player_colors::k_paletteSize. Incremented when a player connects (assigns the smallest-count slot, ties broken by lowest index for determinism); decremented on disconnect.
|
private |
Persistent contact-manifold cache for warm-starting the PGS solver across ticks.
Cleared on map load; trimmed each tick by runDynamics.
|
private |
Mirrors discovery visibility changes.
|
private |
Shared hitbox capsule definitions.
|
private |
True if idle shutdown is enabled via env var.
|
private |
Idle shutdown timeout in ms, from env var. 0 = no timeout.
|
staticconstexprprivate |
|
private |
Timestamp of the last player activity, for idle shutdown.
|
private |
Owns lobby roster and validates host-initiated match starts.
|
private |
True while lobby is counting down before entering match countdown.
|
private |
Seconds remaining in the lobby staging countdown.
|
private |
Host that requested the active lobby staging countdown.
|
private |
Map collision data — owns vectors backing activeWorld().
|
private |
Mirrors match updates to networking/discovery.
|
private |
Manages match flow and state.
|
private |
list of abilities available during the match
|
private |
|
private |
Use-count per nickname slot — same selection scheme as colors.
Decrements when an auto-assigned nickname is released; custom nicknames don't touch the count, since they don't reserve a slot.
|
private |
Accumulates kill events waiting for network broadcast.
|
private |
|
private |
ECS entity/component store.
|
private |
Minimum Y of bind-pose mesh (for vertical offset).
|
private |
Rig model-space → game-unit scale factor.
|
private |
Loop continues while true.
|
private |
Non-owning pointer; main() owns and shuts down the socket.
|
private |
Per-entity server animators (not ECS components to avoid pulling animation headers into the component registry).
|
private |
Animation clips for server-side sampling.
|
private |
Shared skeleton (loaded from same FBX as client).
|
private |
Opt-in lag-comp shot visualizer capture/send path.
|
private |
Send a registry snapshot every Nth tick.
Computed in init() as max(1, tickRateHz / snapshotHz) so the snapshot rate is roughly tickRateHz / snapshotEveryNTicks Hz. With the default 128 / 32 = 4 the server snapshots every 4th tick — 4× less serialization + broadcast work than pre-Phase-4.
|
private |
Total ticks since start, used for periodic logging.
|
private |
Physics ticks per second.
|
private |
|
private |