R-Type  2
Doom but in better
Loading...
Searching...
No Matches
game_manager.cpp
Go to the documentation of this file.
1#include "game_manager.hpp"
2#include <algorithm>
3#include <iostream>
4
5const size_t GameManager::MAX_PLAYERS_PER_GAME;
6
8 : broadcastFunc_(std::move(broadcastFunc))
9{ }
10
11std::forward_list<std::string> GameManager::syncClientToGame(uint32_t clientId) {
12 // If already assigned, return syncing with existing game
13 auto it = clientToGame_.find(clientId);
14 if (it != clientToGame_.end()) {
15 auto &gInst = games_.at(it->second);
16 return gInst.game->getCurrentGameState();
17 }
18
19 // Otherwise find/create
20 uint32_t gid = findOrCreateGame();
21 auto &gInst = games_.at(gid);
22
23 gInst.clients.push_back(clientId);
24 clientToGame_[clientId] = gid;
25
26 std::cout << "[GameManager] Added client " << clientId
27 << " to game " << gid << "\n";
28
29 // getting current game status before entering
30 auto gameState = gInst.game->getCurrentGameState();
31
32 std::string evt = "\x01" + std::to_string(clientId);
33 gInst.game->onServerEventReceived(evt);
34 return gameState;
35}
36
37uint32_t GameManager::assignClientToGame(uint32_t clientId) {
38
39
40 // Otherwise find/create
41 uint32_t gid = findOrCreateGame();
42 auto &gInst = games_.at(gid);
43
44 gInst.clients.push_back(clientId);
45 clientToGame_[clientId] = gid;
46
47 std::cout << "[GameManager] Added client " << clientId
48 << " to game " << gid << "\n";
49
50 return gid;
51}
52
53void GameManager::removeClientFromGame(uint32_t clientId) {
54 auto it = clientToGame_.find(clientId);
55 if (it == clientToGame_.end()) {
56 return;
57 }
58
59 uint32_t gid = it->second;
60 auto &gInst = games_.at(gid);
61
62 // remove from vector
63 auto &cList = gInst.clients;
64 cList.erase(std::remove(cList.begin(), cList.end(), clientId), cList.end());
65
66 // Possibly inform the game of a disconnect
67 std::string evt = "\x02" + std::to_string(clientId);
68 gInst.game->onServerEventReceived(evt);
69
70 clientToGame_.erase(clientId);
71
72 std::cout << "[GameManager] Removed client " << clientId
73 << " from game " << gid << "\n";
74
75 if (cList.empty()) {
76 games_.erase(gid);
77 std::cout << "[GameManager] Destroyed game " << gid
78 << " (no players left)\n";
79 }
80}
81
82uint32_t GameManager::getGameIdForClient(uint32_t clientId) const {
83 auto it = clientToGame_.find(clientId);
84 if (it != clientToGame_.end()) {
85 return it->second;
86 }
87 return 0;
88}
89
91 for (auto &pair : games_) {
92 auto &gInst = pair.second;
93
94 // 1) Update the game logic
95 gInst.game->update(dt);
96
97 // 2) Suppose getGameEvents() returns a list of strings
98 auto events = gInst.game->getGameEvents();
99
100 // 3) For each event, broadcast to each client in gInst.clients
101 for (const auto &evt : events) {
102 // Let's build a small Message to send
103 Message outMsg;
104 outMsg.type = evt[0]; // some code meaning "GameEvent"
105
106 // Put the string in outMsg.payload
107 outMsg.payload.assign(evt.begin() + 1, evt.end());
108
109 // Send to each client
110 for (auto cid : gInst.clients) {
111 broadcastFunc_(cid, outMsg);
112 }
113 }
114 }
115}
116
117void GameManager::handleGameMessage(uint32_t gameId, uint32_t clientId, const Message& msg) {
118 auto it = games_.find(gameId);
119 if (it == games_.end()) return;
120
121 auto &gInst = it->second;
122
123 // For demonstration, let's say we interpret the payload as a string
124 if (!msg.payload.empty()) {
125 std::string eventString(
126 reinterpret_cast<const char*>(msg.payload.data()),
127 msg.payload.size()
128 );
129 // Then feed that into the game as an event
130 gInst.game->onServerEventReceived(eventString);
131 } else {
132 // or do something if no payload
133 }
134}
135
136uint32_t GameManager::findOrCreateGame() {
137 // Look for an existing not-full game
138 for (auto &pair : games_) {
139 if (pair.second.clients.size() < MAX_PLAYERS_PER_GAME) {
140 return pair.first;
141 }
142 }
143 // Otherwise create new
144 uint32_t gid = nextGameId_++;
145 GameInstance gInst;
146 gInst.gameId = gid;
147 gInst.game = std::make_unique<Game>(); // your actual game constructor
148 games_[gid] = std::move(gInst);
149
150 std::cout << "[GameManager] Created new game " << gid << "\n";
151 return gid;
152}
uint32_t assignClientToGame(uint32_t clientId)
Assign a client to a new or existing game.
uint32_t getGameIdForClient(uint32_t clientId) const
Get the game ID for a client, or 0 if none.
void updateAllGames(float dt)
Update all games with the given deltaTime and broadcast events to clients.
std::forward_list< std::string > syncClientToGame(uint32_t clientId)
Gets the current game state for syncing.
void removeClientFromGame(uint32_t clientId)
Remove a client from whichever game they are in.
GameManager(BroadcastFunc broadcastFunc)
Constructor that takes a broadcast function (to send packets to clients).
std::function< void(uint32_t, const Message &)> BroadcastFunc
void handleGameMessage(uint32_t gameId, uint32_t clientId, const Message &msg)
Handle a message from a client in a specific game.
A single game session: a Game object plus the connected clients.
uint32_t gameId
std::unique_ptr< Game > game
Minimal network message with a 4-byte header (type + length) and a payload.
Definition message.hpp:9
uint8_t type
Could map to messageType in GameMessage.hpp (CONNECT, DISCONNECT, etc.)
Definition message.hpp:10
std::vector< uint8_t > payload
Arbitrary payload bytes.
Definition message.hpp:11