22 : m_ioContext(std::make_unique<asio::io_context>()),
23 m_socket(std::make_unique<asio::ip::udp::socket>(*m_ioContext)), m_port(0), m_tickRate(60), m_serverCaps(0),
24 m_running(false), m_started(false), m_nextSessionId(1), m_nextLobbyId(1),
25 m_packetHandler(std::make_unique<
rnp::HandlerPacket>()), m_pingInterval(std::chrono::seconds(5)),
26 m_clientTimeout(std::chrono::seconds(30)), m_componentId(
utl::NETWORK_SERVER),
27 m_eventBus(
utl::EventBus::getInstance())
76 asio::ip::udp::endpoint endpoint(asio::ip::make_address(
m_host),
m_port);
83 m_socket->set_option(asio::ip::udp::socket::reuse_address(
true));
101 catch (
const std::exception &e)
123 for (
auto &[sessionId, client] :
m_clients)
125 if (client.isConnected)
131 header.sessionId = sessionId;
153 auto joinStart = std::chrono::steady_clock::now();
158 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - joinStart).count() <
168 std::this_thread::sleep_for(std::chrono::milliseconds(10));
188 catch (
const std::exception &e)
226 if (it ==
m_clients.end() || !it->second.isConnected)
234 m_sendQueue.emplace(data, it->second.endpoint, reliable);
242 for (
const auto &client :
m_clients | std::views::values)
244 if (client.isConnected)
246 m_sendQueue.emplace(data, client.endpoint, reliable);
253 std::uint32_t lobbyId = 0;
271 std::vector<std::uint8_t> packet;
282 if (it->second.currentLobbyId != 0)
284 lobbyId = it->second.currentLobbyId;
311 return std::ranges::count_if(
m_clients, [](
const auto &pair) {
return pair.second.isConnected; });
317 std::vector<std::uint32_t> sessions;
318 for (
const auto &[sessionId, client] :
m_clients)
320 if (client.isConnected)
322 sessions.push_back(sessionId);
362 [
this](
const std::vector<rnp::EventRecord> &events,
const rnp::PacketContext &context)
393 utl::Logger::log(
"AsioServer: Cannot start receive - server not running or socket closed",
400 [
this](
const std::error_code ec,
const std::size_t bytesReceived)
404 utl::Logger::log(
"AsioServer: Received " + std::to_string(bytesReceived) +
" bytes from " +
405 m_senderEndpoint.address().to_string() +
":" +
406 std::to_string(m_senderEndpoint.port()),
407 utl::LogLevel::INFO);
408 handleReceive(bytesReceived);
411 else if (
m_running.load() && ec != asio::error::operation_aborted)
413 utl::Logger::log(
"AsioServer: Receive error - " + ec.message(), utl::LogLevel::WARNING);
414 std::this_thread::sleep_for(std::chrono::milliseconds(100));
419 utl::Logger::log(
"AsioServer: Server stopped or operation aborted, ending receive loop",
420 utl::LogLevel::INFO);
427 utl::Logger::log(
"AsioServer: Processing received packet of " + std::to_string(bytesReceived) +
" bytes",
431 constexpr std::size_t PACKET_HEADER_SIZE = 7;
432 if (bytesReceived < PACKET_HEADER_SIZE)
434 utl::Logger::log(
"AsioServer: Received packet too small (need " + std::to_string(PACKET_HEADER_SIZE) +
435 " bytes, got " + std::to_string(bytesReceived) +
")",
442 context.
receiveTime = std::chrono::steady_clock::now();
451 if (data.size() >= PACKET_HEADER_SIZE)
457 ", Session ID: " + std::to_string(header.
sessionId),
467 std::to_string(
static_cast<int>(result)),
491 if (handlersRun == 0)
494 std::this_thread::sleep_for(std::chrono::milliseconds(1));
497 catch (
const std::exception &e)
503 std::this_thread::sleep_for(std::chrono::milliseconds(100));
513 std::random_device rd;
514 std::mt19937 gen(rd());
515 std::uniform_int_distribution<std::uint32_t> dis(1, UINT32_MAX);
517 std::uint32_t sessionId = 0;
518 while (sessionId == 0 ||
m_clients.contains(sessionId))
520 sessionId = dis(gen);
528 return endpoint.address().to_string() +
":" + std::to_string(endpoint.port());
532 const asio::ip::udp::endpoint &destination)
534 utl::Logger::log(
"AsioServer: Sending " + std::to_string(data.size()) +
" bytes to " +
535 destination.address().to_string() +
":" + std::to_string(destination.port()),
549 size_t bytesSent =
m_socket->send_to(asio::buffer(data), destination);
550 utl::Logger::log(
"AsioServer: Successfully sent " + std::to_string(bytesSent) +
" bytes",
553 catch (
const std::exception &e)
557 utl::Logger::log(
"AsioServer: Failed to send packet - " + std::string(e.what()),
571 const size_t currentClientCount =
572 std::ranges::count_if(
m_clients, [](
const auto &pair) {
return pair.second.isConnected; });
707 auto now = std::chrono::steady_clock::now();
708 auto pingTime = std::chrono::milliseconds(packet.
sendTimeMs);
709 auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
710 it->second.latency =
static_cast<std::uint32_t
>((currentTime - pingTime).count());
717 void AsioServer::sendPong(std::uint32_t nonce,
const asio::ip::udp::endpoint &destination, std::uint32_t sessionId)
723 header.sessionId = sessionId;
727 pong.sendTimeMs =
static_cast<std::uint32_t
>(
728 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
747 header.sessionId = sessionId;
766 const asio::ip::udp::endpoint &destination, std::uint32_t sessionId)
771 header.length =
static_cast<std::uint16_t
>(
sizeof(
rnp::PacketError) + description.length());
772 header.sessionId = sessionId;
775 error.
errorCode =
static_cast<std::uint16_t
>(errorCode);
776 error.msgLen =
static_cast<std::uint16_t
>(description.length());
777 error.description = description;
787 const auto now = std::chrono::steady_clock::now();
793 for (
auto &[sessionId, client] :
m_clients)
795 if (client.isConnected)
802 header.sessionId = sessionId;
805 ping.
nonce = ++client.lastPingSent;
806 ping.sendTimeMs =
static_cast<std::uint32_t
>(
807 std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count());
820 std::vector<std::uint32_t> timedOutClients;
823 for (
const auto &[sessionId, client] :
m_clients)
827 timedOutClients.push_back(sessionId);
833 for (std::uint32_t sessionId : timedOutClients)
856 for (
const auto &event : events)
887 if (event.
data.size() >=
sizeof(uint32_t))
889 uint32_t sessionId = 0;
890 std::memcpy(&sessionId, event.
data.data(),
sizeof(uint32_t));
892 std::vector<uint8_t> messageData(event.
data.begin() +
sizeof(uint32_t), event.
data.end());
926 utl::Logger::log(
"AsioServer: Received " + std::to_string(events.size()) +
" entity events from session " +
931 for (
const auto &eventRecord : events)
936 std::to_string(eventRecord.data.size()),
941 event.data = eventRecord.data;
973 if (clientIt ==
m_clients.end() || !clientIt->second.isConnected)
990 std::uint32_t lobbyId = 0;
991 bool success =
false;
997 if (clientIt ==
m_clients.end() || !clientIt->second.isConnected)
1004 std::to_string(clientIt->second.currentLobbyId),
1007 if (clientIt->second.currentLobbyId != 0)
1014 std::string lobbyName;
1028 clientIt->second.currentLobbyId = lobbyId;
1039 if (success && lobbyId > 0)
1051 " for lobby " + std::to_string(packet.
lobbyId),
1054 bool joinSuccess =
false;
1062 if (clientIt ==
m_clients.end() || !clientIt->second.isConnected)
1071 if (clientIt->second.currentLobbyId != 0)
1074 " already in lobby " + std::to_string(clientIt->second.currentLobbyId),
1082 utl::Logger::log(
"AsioServer: joinLobby returned status: " + std::to_string(
static_cast<int>(joinStatus)),
1087 clientIt->second.currentLobbyId = packet.
lobbyId;
1089 " successfully joined lobby " + std::to_string(packet.
lobbyId),
1096 std::to_string(packet.
lobbyId) +
1097 " - status: " + std::to_string(
static_cast<int>(joinStatus)),
1115 std::to_string(
static_cast<int>(lobbyInfo.
currentPlayers)) +
"/" +
1116 std::to_string(
static_cast<int>(lobbyInfo.
maxPlayers)),
1138 std::uint32_t lobbyId = 0;
1144 if (clientIt ==
m_clients.end() || !clientIt->second.isConnected)
1151 if (clientIt->second.currentLobbyId == 0)
1157 lobbyId = clientIt->second.currentLobbyId;
1158 clientIt->second.currentLobbyId = 0;
1183 for (
const auto &lobby :
m_lobbies | std::views::values)
1187 std::to_string(
static_cast<int>(lobbyInfo.
currentPlayers)) +
"/" +
1188 std::to_string(
static_cast<int>(lobbyInfo.
maxPlayers)) +
" players",
1190 response.
lobbies.push_back(lobbyInfo);
1195 std::vector<std::uint8_t> packet;
1207 " lobbies, packet size: " + std::to_string(packetSerializer.
getData().size()),
1214 std::uint8_t gameMode)
1219 Lobby lobby(lobbyId, name, hostSession, maxPlayers, gameMode);
1224 utl::Logger::log(
"AsioServer: Created lobby " + std::to_string(lobbyId) +
" '" + name +
"' hosted by " +
1225 std::to_string(hostSession),
1240 utl::Logger::log(
"AsioServer: joinLobby - Lobby " + std::to_string(lobbyId) +
" not found",
1245 Lobby &lobby = lobbyIt->second;
1247 "AsioServer: joinLobby - Lobby found, current players: " + std::to_string(lobby.
playerSessions.size()) +
1248 "/" + std::to_string(lobby.
maxPlayers) +
", status: " + std::to_string(
static_cast<int>(lobby.
status)),
1270 utl::Logger::log(
"AsioServer: Player " + std::to_string(sessionId) +
" joined lobby " +
1271 std::to_string(lobbyId) +
" (now " + std::to_string(lobby.
playerSessions.size()) +
"/" +
1272 std::to_string(
static_cast<int>(lobby.
maxPlayers)) +
" players)",
1281 for (
auto &[lobbyId, lobby] :
m_lobbies)
1283 if (
auto playerIt = std::ranges::find(lobby.playerSessions, sessionId);
1284 playerIt != lobby.playerSessions.end())
1286 lobby.playerSessions.erase(playerIt);
1288 utl::Logger::log(
"AsioServer: Player " + std::to_string(sessionId) +
" left lobby " +
1289 std::to_string(lobbyId),
1295 auto clientIt =
m_clients.find(sessionId);
1298 clientIt->second.currentLobbyId = 0;
1300 std::to_string(sessionId),
1306 if (lobby.hostSessionId == sessionId)
1308 if (!lobby.playerSessions.empty())
1310 lobby.hostSessionId = lobby.playerSessions[0];
1311 utl::Logger::log(
"AsioServer: New host for lobby " + std::to_string(lobbyId) +
" is " +
1312 std::to_string(lobby.hostSessionId),
1318 utl::Logger::log(
"AsioServer: Lobby " + std::to_string(lobbyId) +
" is now empty",
1334 std::vector<std::uint32_t> lobbyIds;
1337 for (
const auto &[lobbyId, lobby] :
m_lobbies)
1339 lobbyIds.push_back(lobbyId);
1344 for (std::uint32_t lobbyId : lobbyIds)
1354 for (
auto &[sessionId, client] :
m_clients)
1356 if (client.currentLobbyId != 0)
1358 utl::Logger::log(
"AsioServer: Clearing lobby association for session " + std::to_string(sessionId),
1360 client.currentLobbyId = 0;
1372 std::vector<std::uint32_t> playerSessions;
1381 playerSessions = lobbyIt->second.playerSessions;
1387 header.
length =
static_cast<std::uint16_t
>(gameOverData.size());
1392 std::vector<std::uint8_t> packetData = serializer.
getData();
1393 packetData.insert(packetData.end(), gameOverData.begin(), gameOverData.end());
1397 for (std::uint32_t sessionId : playerSessions)
1399 auto clientIt =
m_clients.find(sessionId);
1400 if (clientIt !=
m_clients.end() && clientIt->second.isConnected)
1402 utl::Logger::log(
"AsioServer: Sending GAME_OVER to session " + std::to_string(sessionId),
1422 std::vector<std::uint8_t> data;
1427 const std::vector<std::uint8_t> &lobbyUpdateData = serializer.
getData();
1430 for (std::uint32_t sessionId : lobbyIt->second.playerSessions)
1434 header.
length =
static_cast<std::uint16_t
>(lobbyUpdateData.size());
1437 std::vector<std::uint8_t> playerPacket;
1444 auto clientIt =
m_clients.find(sessionId);
1451 utl::Logger::log(
"AsioServer: Broadcasted lobby update for lobby " + std::to_string(lobbyId),
1466 std::size_t nameLen = std::min(lobby.
lobbyName.size(),
static_cast<std::size_t
>(31));
1472 for (std::size_t i = 0; i < lobby.
playerSessions.size() && i < 8; ++i)
1477 std::size_t playerNameLen = std::min(clientIt->second.playerName.size(),
static_cast<std::size_t
>(31));
1478 std::memcpy(info.
playerNames[i].data(), clientIt->second.playerName.c_str(), playerNameLen);
1491 response.
success = success ? 1 : 0;
1492 response.
errorCode =
static_cast<std::uint16_t
>(errorCode);
1499 std::vector<std::uint8_t> packet;
1506 utl::Logger::log(
"AsioServer: Sent lobby create response to session " + std::to_string(sessionId) +
1507 " (success: " + (success ?
"true" :
"false") +
")",
1516 response.
success = success ? 1 : 0;
1517 response.
errorCode =
static_cast<std::uint16_t
>(errorCode);
1518 if (success && lobbyInfo)
1528 std::vector<std::uint8_t> packet;
1535 utl::Logger::log(
"AsioServer: Sent lobby join response to session " + std::to_string(sessionId) +
1536 " (success: " + (success ?
"true" :
"false") +
")",
1546 if (it->second.playerSessions.empty())
1548 utl::Logger::log(
"AsioServer: Cleaning up empty lobby " + std::to_string(it->first),
1563 " for lobby " + std::to_string(packet.
lobbyId),
1570 if (clientIt ==
m_clients.end() || !clientIt->second.isConnected)
1576 if (clientIt->second.currentLobbyId != packet.
lobbyId)
1594 if (lobbyIt->second.hostSessionId != context.
sessionId)
1608 std::vector<std::uint32_t> playerSessions;
1614 playerSessions = lobbyIt->second.playerSessions;
1615 utl::Logger::log(
"AsioServer: Player sessions in lobby: " + std::to_string(playerSessions.size()),
1622 std::vector<std::uint8_t> sessionsData;
1623 sessionsData.resize(
sizeof(std::uint32_t) * playerSessions.size());
1624 for (
size_t i = 0; i < playerSessions.size(); ++i)
1626 std::memcpy(sessionsData.data() + i *
sizeof(std::uint32_t), &playerSessions[i],
sizeof(std::uint32_t));
1628 startEvent.
data = sessionsData;
1631 utl::Logger::log(
"AsioServer: Sent SERVER_START to RTypeServer with " + std::to_string(playerSessions.size()) +
1654 std::vector<std::uint8_t> data;
1658 const std::vector<std::uint8_t> &gameStartData = serializer.
getData();
1661 for (std::uint32_t sessionId : lobbyIt->second.playerSessions)
1665 header.
length =
static_cast<std::uint16_t
>(gameStartData.size());
1668 std::vector<std::uint8_t> playerPacket;
1675 auto clientIt =
m_clients.find(sessionId);
1682 utl::Logger::log(
"AsioServer: Broadcasted game start for lobby " + std::to_string(lobbyId),
Asio-based UDP server implementation for R-Type multiplayer game networking.
Thread-safe event bus implementation for inter-component communication.
Event structures and types for event-driven communication.
This file contains the Logger class.
This file contains the network protocol.
void onPing(PingHandler handler)
Register PING packet handler.
void onPong(PongHandler handler)
Register PONG packet handler.
void onLobbyJoin(LobbyJoinHandler handler)
Register LOBBY_JOIN packet handler.
void onLobbyLeave(LobbyLeaveHandler handler)
Register LOBBY_LEAVE packet handler.
HandlerResult processPacket(const std::vector< std::uint8_t > &data, const PacketContext &context)
Process a received packet.
void onLobbyListRequest(LobbyListRequestHandler handler)
Register LOBBY_LIST_REQUEST packet handler.
void onConnect(ConnectHandler handler)
Register CONNECT packet handler.
void onStartGameRequest(StartGameRequestHandler handler)
Register START_GAME_REQUEST packet handler.
void onLobbyCreate(LobbyCreateHandler handler)
Register LOBBY_CREATE packet handler.
void onEntityEvent(EntityEventHandler handler)
Register ENTITY_EVENT packet handler.
void onDisconnect(DisconnectHandler handler)
Register DISCONNECT packet handler.
void clearSession(std::uint32_t sessionId)
Clear rate limiting data for a session.
Binary serializer for RNP protocol packets.
void serializePingPong(const PacketPingPong &packet)
Serialize PING/PONG packet.
void serializeLobbyCreateResponse(const PacketLobbyCreateResponse &packet)
Serialize LOBBY_CREATE_RESPONSE packet.
PacketHeader deserializeHeader()
Deserialize packet header.
void serializeLobbyListResponse(const PacketLobbyListResponse &packet)
Serialize LOBBY_LIST_RESPONSE packet.
void serializeHeader(const PacketHeader &header)
Serialize packet header.
void serializeConnectAccept(const PacketConnectAccept &packet)
Serialize CONNECT_ACCEPT packet.
void serializeGameStart(const PacketGameStart &packet)
Serialize GAME_START packet.
void serializeDisconnect(const PacketDisconnect &packet)
Serialize DISCONNECT packet.
void serializeLobbyJoinResponse(const PacketLobbyJoinResponse &packet)
Serialize LOBBY_JOIN_RESPONSE packet.
const std::vector< std::uint8_t > & getData() const
Get the serialized data.
void serializeError(const PacketError &packet)
Serialize ERROR packet.
void serializeLobbyUpdate(const PacketLobbyUpdate &packet)
Serialize LOBBY_UPDATE packet.
std::uint16_t m_tickRate
Server tick rate in Hz.
rnp::HandlerResult handlePing(const rnp::PacketPingPong &packet, const rnp::PacketContext &context)
Handle PING packet.
std::unique_ptr< asio::io_context > m_ioContext
ASIO I/O context for async operations.
rnp::HandlerResult handleLobbyJoin(const rnp::PacketLobbyJoin &packet, const rnp::PacketContext &context)
Handle LOBBY_JOIN packet.
void init(const std::string &host, std::uint16_t port) override
void disconnectClient(std::uint32_t sessionId) override
void setupPacketHandlers()
Initialize packet handlers.
void sendToClient(std::uint32_t sessionId, const std::vector< std::uint8_t > &data, bool reliable=false) override
rnp::HandlerResult handleEntityEvent(const std::vector< rnp::EventRecord > &events, const rnp::PacketContext &context) const
Handle entity event packet (including player inputs)
void cleanupEmptyLobbies()
Clean up empty lobbies.
std::uint32_t m_nextLobbyId
Next available lobby ID.
rnp::HandlerResult handleConnect(const rnp::PacketConnect &packet, const rnp::PacketContext &context)
Handle CONNECT packet.
~AsioServer() override
Destructor.
void sendConnectAccept(std::uint32_t sessionId, const asio::ip::udp::endpoint &destination)
Send CONNECT_ACCEPT response.
std::string m_host
Server bind address (e.g., "0.0.0.0")
void handleReceive(std::size_t bytesReceived)
Handle received packet.
rnp::LobbyInfo lobbyToLobbyInfo(const Lobby &lobby)
Convert Lobby to LobbyInfo for network transmission.
void setServerCapabilities(std::uint32_t caps) override
void setTickRate(std::uint16_t tickRate) override
std::string endpointToString(const asio::ip::udp::endpoint &endpoint)
Get endpoint string representation.
std::vector< std::uint32_t > getConnectedSessions() const override
rnp::HandlerResult handlePong(const rnp::PacketPingPong &packet, const rnp::PacketContext &context)
Handle PONG packet.
bool isRunning() const override
std::unique_ptr< std::thread > m_networkThread
Dedicated network thread.
std::atomic< bool > m_started
Server started state.
void startReceive()
Start receiving packets asynchronously.
void handleGameOverEvent(const utl::Event &event)
Handle GAME_OVER event from game server.
asio::ip::udp::endpoint m_senderEndpoint
Endpoint of last packet sender.
void sendError(rnp::ErrorCode errorCode, const std::string &description, const asio::ip::udp::endpoint &destination, std::uint32_t sessionId)
Send ERROR packet.
LobbyStatus joinLobby(std::uint32_t lobbyId, std::uint32_t sessionId)
Join player to lobby.
void sendPong(std::uint32_t nonce, const asio::ip::udp::endpoint &destination, std::uint32_t sessionId)
Send PONG response.
std::unordered_map< std::uint32_t, ClientSession > m_clients
Map of session ID to client session.
void networkThreadLoop() const
Network thread main loop.
std::chrono::milliseconds m_clientTimeout
Client timeout duration (15000ms)
std::uint16_t m_port
Server listening port (default: 4567)
std::mutex m_sendQueueMutex
Mutex for send queue access.
std::uint32_t m_serverCaps
Server capability flags.
void sendPacketImmediate(const std::vector< std::uint8_t > &data, const asio::ip::udp::endpoint &destination)
Send packet immediately.
std::uint32_t createLobby(const std::string &lobbyName, std::uint32_t hostSessionId, std::uint8_t maxPlayers, std::uint8_t gameMode)
Create new lobby.
std::mutex m_lobbiesMutex
Mutex for thread-safe lobby access.
void broadcastGameStart(std::uint32_t lobbyId)
Broadcast game start notification to all lobby members.
void sendLobbyCreateResponse(std::uint32_t sessionId, std::uint32_t lobbyId, bool success, rnp::ErrorCode errorCode=rnp::ErrorCode::INTERNAL_ERROR)
Send lobby create response.
std::mutex m_socketMutex
Mutex for socket operations.
void handleBroadcastEvent(const utl::Event &event)
Handle broadcast event from EventBus.
std::mutex m_clientsMutex
Mutex for thread-safe client access.
std::unordered_map< std::uint32_t, Lobby > m_lobbies
Map of lobby ID to lobby data.
std::queue< QueuedPacket > m_sendQueue
Queue of packets waiting to be sent.
rnp::HandlerResult handleLobbyCreate(const rnp::PacketLobbyCreate &packet, const rnp::PacketContext &context)
Handle LOBBY_CREATE packet.
rnp::HandlerResult handleLobbyListRequest(const rnp::PacketContext &context)
Handle LOBBY_LIST_REQUEST packet.
std::atomic< bool > m_running
Server running state (atomic for thread safety)
std::array< std::uint8_t, MAX_LEN_RECV_BUFFER > m_recvBuffer
Buffer for receiving UDP packets.
void sendToAllClients(const std::vector< std::uint8_t > &data, bool reliable=false) override
std::uint32_t m_componentId
Component ID for event bus registration.
void broadcastLobbyUpdate(std::uint32_t lobbyId)
Broadcast lobby update to all lobby members.
void processSendQueue()
Process send queue.
std::unordered_map< std::string, std::uint32_t > m_endpointToSession
Map of endpoint string to session ID.
rnp::HandlerResult handleLobbyLeave(const rnp::PacketContext &context)
Handle LOBBY_LEAVE packet.
void updateClientManagement()
Update client timeouts and send pings.
rnp::HandlerResult handleDisconnect(const rnp::PacketDisconnect &packet, const rnp::PacketContext &context)
Handle DISCONNECT packet.
std::unique_ptr< asio::ip::udp::socket > m_socket
UDP socket for network communication.
std::chrono::milliseconds m_pingInterval
Interval between ping sweeps (5000ms)
void leaveLobby(std::uint32_t sessionId)
Remove player from lobby.
void sendLobbyJoinResponse(std::uint32_t sessionId, std::uint32_t lobbyId, bool success, rnp::ErrorCode errorCode, const rnp::LobbyInfo *lobbyInfo=nullptr)
Send lobby join response.
std::chrono::steady_clock::time_point m_lastPingTime
Timestamp of last ping sweep.
std::size_t getClientCount() const override
rnp::HandlerResult handleStartGameRequest(const rnp::PacketStartGameRequest &packet, const rnp::PacketContext &context)
Handle START_GAME_REQUEST packet.
void broadcastGameOverToLobby(std::uint32_t lobbyId)
Broadcast game start to all players in lobby.
void handleSendToClientEvent(const utl::Event &event)
Handle send to client event from EventBus.
std::unique_ptr< rnp::HandlerPacket > m_packetHandler
RNP packet handler instance.
void sendLobbyList(std::uint32_t sessionId)
Send lobby list to client.
void processEventBusEvents()
Process EventBus events for network operations.
void handleSendEntityEventToClients(const utl::Event &event)
Handle send entity event to clients from EventBus.
utl::EventBus & m_eventBus
std::uint32_t generateSessionId() const
Generate unique session ID.
bool publish(const Event &event)
Publish an event to the bus.
std::vector< Event > consumeForTarget(std::uint32_t targetId, std::uint32_t maxEvents=100)
Consume events targeted to specific component.
void registerComponent(std::uint32_t componentId, const std::string &name)
Register component name for better debugging.
void subscribe(std::uint32_t componentId, EventType type)
Subscribe component to specific event types.
Event structure for inter-component communication.
std::vector< std::uint8_t > data
Serialized event data.
static void log(const std::string &message, const LogLevel &logLevel)
HandlerResult
Packet processing result.
constexpr std::size_t MAX_PAYLOAD
constexpr size_t MAX_CLIENTS
LobbyStatus
Status codes for lobby operations.
@ IN_GAME
Game in progress.
@ NOT_FOUND
Requested lobby does not exist.
@ FULL
Lobby has reached maximum capacity.
@ SUCCESS
Operation completed successfully.
@ ALREADY_IN_LOBBY
Client is already in a lobby.
static constexpr std::uint32_t GAME_LOGIC
static constexpr std::uint32_t NETWORK_SERVER
Lobby information structure.
std::uint32_t hostSessionId
std::array< char, 32 > lobbyName
std::array< std::array< char, 32 >, 8 > playerNames
std::uint8_t currentPlayers
CONNECT_ACCEPT packet payload.
std::array< char, 32 > playerName
Context information for packet processing.
std::chrono::steady_clock::time_point receiveTime
std::string senderAddress
DISCONNECT packet payload.
GAME_START packet payload.
LOBBY_CREATE_RESPONSE packet payload.
LOBBY_CREATE packet payload.
std::array< char, 32 > lobbyName
LOBBY_JOIN_RESPONSE packet payload.
LOBBY_JOIN packet payload.
LOBBY_LIST_RESPONSE packet payload.
std::vector< LobbyInfo > lobbies
LOBBY_UPDATE packet payload.
PING/PONG packet payload.
START_GAME_REQUEST packet payload (client requests to start game)
Represents an active client connection session.
bool isConnected
Connection state flag.
std::chrono::steady_clock::time_point lastSeen
Timestamp of last received packet.
std::uint32_t clientCaps
Client capability flags (reserved)
std::uint32_t sessionId
Unique session identifier assigned by server.
std::string playerName
Player's display name.
asio::ip::udp::endpoint endpoint
Client's network endpoint (IP:port)
Represents a game lobby (room) where players gather before starting a game.
std::uint32_t hostSessionId
Session ID of the lobby host.
rnp::LobbyStatus status
Current lobby status.
std::uint8_t maxPlayers
Maximum number of players allowed (1-8)
std::vector< std::uint32_t > playerSessions
List of player session IDs in this lobby.
std::uint32_t lobbyId
Unique lobby identifier.
std::string lobbyName
Human-readable lobby name.
std::uint8_t gameMode
Game mode identifier.
Represents a packet queued for asynchronous transmission.
asio::ip::udp::endpoint destination
Target endpoint.
std::vector< std::uint8_t > data
Serialized packet data.