14#include <unordered_map>
23 : _networkManager(networkManager)
60 _levelSystem->registerLevelPath(1,
"config/levels/level_01.json");
61 _levelSystem->registerLevelPath(2,
"config/levels/level_02.json");
62 _levelSystem->registerLevelPath(3,
"config/levels/level_03.json");
63 _levelSystem->registerLevelPath(4,
"config/levels/level_04.json");
66 [
this](uint32_t roomId) {
69 log::error(
"Room ID {} not found for start event", roomId);
73 _levelSystem->startLevelForRoom(roomId, room->getLevelId());
75 const auto players = room->getPlayers();
76 std::vector<uint32_t> sessions;
77 sessions.reserve(players.size());
78 for (
const auto& player : players) {
79 sessions.push_back(player->getId());
83 const Vec2f spawnPos = level
85 :
Vec2f{100.f, 100.f};
87 for (
auto& player : players) {
91 scorePacket << scorePayload;
94 auto entity =
_entitySystem->createPlayerEntity(player, spawnPos);
95 uint32_t entityId =
static_cast<uint32_t
>(entity.index());
96 player->setEntityId(entityId);
97 log::info(
"Spawned Entity {} for Player {}", entity.index(), player->getId());
102 auto &healths = healthRes->get();
103 if (healths.has(entity)) {
106 healths[entity].currentHealth,
107 healths[entity].maxHealth
129 const float dt = 1.0f / 60.0f;
132 auto start = std::chrono::high_resolution_clock::now();
151 std::this_thread::sleep_for(std::chrono::milliseconds(16));
168 auto&
event = optionalEvent.value();
169 switch (event.packet.header.opCode) {
183 case RegisterRequest:
204 case UpdateSelectedWeapon: {
223 log::info(
"Client with Session ID {} connected, not logged yet", sessionId);
228 uint32_t entityId = 0;
231 std::lock_guard lock(
_mutex);
242 auto &nets = netsRes->get();
243 for (
auto e : nets.entities()) {
244 if (nets[e].
id == entityId) {
251 if (!entity.isNull()) {
256 if (transformsRes && typesRes && netsRes && roomsRes) {
257 auto &transforms = transformsRes->get();
258 auto &types = typesRes->get();
259 auto &nets = netsRes->get();
260 auto &rooms = roomsRes->get();
261 if (transforms.has(entity) && types.has(entity) && nets.has(entity) && rooms.has(entity)) {
262 auto room =
_roomSystem->getRoom(rooms[entity].
id);
264 const auto players = room->getPlayers();
265 if (!players.empty()) {
268 payload.
netId = nets[entity].id;
269 payload.type =
static_cast<uint8_t
>(types[entity].type);
270 payload.position = transforms[entity].position;
273 for (
const auto& player : players) {
285 disconnectPlayer << entityId;
289 log::info(
"Player with Session ID {} disconnected", sessionId);
294 log::info(
"Handling authentication for Session ID {}", sessionId);
295 auto [success, username, weaponKind] =
_authSystem->handleLoginRequest(sessionId, packet);
296 if (!success)
return;
300 std::lock_guard lock(
_mutex);
304 log::info(
"Player {} weapon set to {}", sessionId,
static_cast<int>(weaponKind));
311 log::error(
"Failed to join Lobby for Session ID {}", sessionId);
317 log::info(
"Handling registration for Session ID {}", sessionId);
318 auto res =
_authSystem->handleRegisterRequest(sessionId, packet);
319 if (!res.first)
return;
323 std::lock_guard lock(
_mutex);
330 log::error(
"Failed to join Lobby for Session ID {}", sessionId);
349 std::lock_guard lock(
_mutex);
353 response << static_cast<uint8_t>(0);
368 success = (newId != 0) ? 1 : 0;
371 success =
_roomSystem->joinRoom(player, newId,
false) ? 1 : 0;
375 player->setReady(
true);
376 log::info(
"Auto-ready player {} for solo game", sessionId);
390 tempPacket >> payload;
394 std::lock_guard lock(
_mutex);
420 std::lock_guard lock(
_mutex);
424 log::info(
"Handle Leave Room request from Session ID {}", sessionId);
431 std::lock_guard lock(
_mutex);
435 tempPacket >> payload;
436 log::info(
"Handle Set Ready request from Session ID {}: isReady={}",
448 log::warning(
"Failed to parse UpdateSelectedWeapon packet from session {}", sessionId);
452 std::lock_guard lock(
_mutex);
455 log::warning(
"UpdateSelectedWeapon: player for session {} not found", sessionId);
460 log::info(
"Player {} updated weapon to {}", sessionId,
static_cast<int>(kind));
462 uint32_t entityId = player->getEntityId();
473 tempPacket >> payload;
477 std::lock_guard lock(
_mutex);
483 const uint32_t roomId = player->getRoomId();
491 const std::string message(payload.
message);
495 if (player->isMuted()) {
501 const std::string username = player->getUsername();
502 std::strncpy(chatPayload.username, username.c_str(),
sizeof(chatPayload.username) - 1);
503 chatPayload.username[
sizeof(chatPayload.username) - 1] =
'\0';
504 std::strncpy(chatPayload.message, payload.
message,
sizeof(chatPayload.message) - 1);
505 chatPayload.message[
sizeof(chatPayload.message) - 1] =
'\0';
508 chatPacket << chatPayload;
510 const auto players = room->getPlayers();
511 for (
const auto& p : players) {
518 std::lock_guard lock(
_mutex);
527 tempPacket >> payload;
536 if (message.empty() || message[0] !=
'/')
539 const uint32_t roomId = player->getRoomId();
547 auto toLower = [](std::string s) {
548 for (
char &c : s) c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
552 const std::string msg = message;
553 const std::string cmd = toLower(msg.substr(0, msg.find(
' ')));
554 const std::string arg = msg.find(
' ') == std::string::npos
556 : msg.substr(msg.find(
' ') + 1);
558 if (cmd ==
"/help") {
559 sendChatToSession(player->getId(),
"Commands: /help, /kick <name>, /ban <name>, /mute <name>,");
560 sendChatToSession(player->getId(),
"/stop, /run, /speed <float>, /debug <true|false>");
561 sendChatToSession(player->getId(),
"/debug enables invincibility + hitbox display");
562 sendChatToSession(player->getId(),
"Examples: /speed 0.5 | /debug true | /kick player1");
566 if (cmd ==
"/stop") {
576 if (cmd ==
"/speed") {
582 float v = std::stof(arg);
583 if (v < 0.1f) v = 0.1f;
584 if (v > 4.0f) v = 4.0f;
592 if (cmd ==
"/debug") {
593 const std::string v = toLower(arg);
594 if (v !=
"true" && v !=
"false") {
598 const bool enabled = (v ==
"true");
606 const auto players = room->getPlayers();
607 for (
const auto& p : players) {
610 sendSystemMessageToRoom(roomId, std::string(
"Debug mode ") + (enabled ?
"enabled (invincibility ON)" :
"disabled (invincibility OFF)"));
614 if (cmd ==
"/kick" || cmd ==
"/mute" || cmd ==
"/ban") {
620 if (!target || target->getRoomId() != roomId) {
624 if (cmd ==
"/kick") {
627 response << static_cast<uint8_t>(1);
638 response << static_cast<uint8_t>(1);
645 if (cmd ==
"/mute") {
646 const bool newMuted = !target->isMuted();
647 target->setMuted(newMuted);
649 target->getUsername() + (newMuted ?
" has been muted" :
" has been unmuted"));
662 payload.username[0] =
'\0';
663 std::strncpy(payload.message, message.c_str(),
sizeof(payload.message) - 1);
664 payload.message[
sizeof(payload.message) - 1] =
'\0';
676 const auto players = room->getPlayers();
680 payload.username[0] =
'\0';
681 std::strncpy(payload.message, message.c_str(),
sizeof(payload.message) - 1);
682 payload.message[
sizeof(payload.message) - 1] =
'\0';
687 for (
const auto& p : players) {
693 const std::vector<uint32_t>& sessions)
695 if (sessions.empty())
702 if (!transformRes || !typeRes || !netRes) {
703 log::error(
"Missing component array for EntitySpawn");
707 auto &transforms = transformRes->get();
708 auto &types = typeRes->get();
709 auto &nets = netRes->get();
710 auto *boxes = boxRes ? &boxRes->get() :
nullptr;
711 if (!transforms.has(entity) || !types.has(entity) || !nets.has(entity)) {
712 log::error(
"Entity {} missing Transform/EntityType/NetworkId", entity.
index());
716 const auto &transform = transforms[entity];
717 const auto &type = types[entity];
718 const auto &
net = nets[entity];
721 if (boxes && boxes->has(entity)) {
722 const auto &box = (*boxes)[entity];
726 uint8_t weaponKind = 0;
728 auto &weapons = weaponRes->get();
729 if (weapons.has(entity)) {
730 weaponKind =
static_cast<uint8_t
>(weapons[entity].kind);
737 static_cast<uint8_t
>(type.type),
738 transform.position.x,
739 transform.position.y,
757 auto *boxes = boxRes ? &boxRes->get() :
nullptr;
758 std::unordered_map<uint32_t, ecs::Entity> netToEntity;
762 auto &nets = netRes->get();
763 for (
auto e : nets.entities()) {
764 netToEntity[nets[e].id] = e;
769 for (
auto&& [tf,
net, type, room] : view) {
770 if (room.id != roomId)
776 auto it = netToEntity.find(
net.id);
777 if (it != netToEntity.end() && boxes->has(it->second)) {
778 const auto &box = (*boxes)[it->second];
784 uint8_t weaponKind = 0;
786 auto &weapons = weaponRes->get();
787 auto it2 = netToEntity.find(
net.id);
788 if (it2 != netToEntity.end() && weapons.has(it2->second)) {
789 weaponKind =
static_cast<uint8_t
>(weapons[it2->second].kind);
796 static_cast<uint8_t
>(type.type),
Represents an entity in the ECS (Entity-Component-System) architecture.
constexpr std::uint32_t index(void) const
auto subscribe(this Self &self) -> std::expected< std::reference_wrapper< ConstLike< Self, SparseArray< T > > >, rtp::Error >
auto get(this const Self &self) -> std::expected< std::reference_wrapper< ConstLike< Self, SparseArray< T > > >, rtp::Error >
auto zipView(this Self &self)
Network packet with header and serializable body.
Header header
Packet header.
void handlePing(uint32_t sessionId, const net::Packet &packet)
std::unique_ptr< RoomSystem > _roomSystem
Room system for handling room management.
std::unique_ptr< MovementSystem > _movementSystem
Movement system for updating entity positions.
void handlePlayerDisconnect(uint32_t sessionId)
Handle a player disconnection.
void handleJoinRoom(uint32_t sessionId, const net::Packet &packet)
Handle a generic incoming packet from a player.
std::unique_ptr< PlayerMouvementSystem > _playerMouvementSystem
Player movement system for handling player-specific movement logic.
std::unique_ptr< NetworkSyncSystem > _networkSyncSystem
Server network system for handling network-related ECS operations.
std::unique_ptr< EnemyAISystem > _enemyAISystem
Enemy AI system for movement patterns.
std::unique_ptr< BoomerangSystem > _boomerangSystem
Boomerang system for boomerang projectiles.
uint32_t _serverTick
Current server tick for synchronization.
std::mutex _mutex
Mutex for thread-safe operations.
void handleRoomChatSended(uint32_t sessionId, const net::Packet &packet)
Handle a generic incoming packet from a player.
void handleListRooms(uint32_t sessionId)
Handle a request to list available rooms.
void gameLoop(void)
Main game loop.
std::unique_ptr< EnemyShootSystem > _enemyShootSystem
Enemy shooting system.
void handleLeaveRoom(uint32_t sessionId, const net::Packet &packet)
Handle a generic incoming packet from a player.
void handleCreateRoom(uint32_t sessionId, const net::Packet &packet)
Handle a generic incoming packet from a player.
void sendRoomEntitySpawnsToSession(uint32_t roomId, uint32_t sessionId)
bool handleChatCommand(PlayerPtr player, const std::string &message)
void processNetworkEvents(void)
Process incoming network events with OpCode handling.
~GameManager()
Destructor for GameManager.
std::unique_ptr< LevelSystem > _levelSystem
Level system for timed spawns.
std::unique_ptr< CollisionSystem > _collisionSystem
Collision system for pickups/obstacles.
float _gameSpeed
Global game speed multiplier.
std::unique_ptr< HomingSystem > _homingSystem
Homing system for tracker bullets.
ServerNetwork & _networkManager
Reference to the ServerNetwork instance.
std::unique_ptr< PlayerSystem > _playerSystem
Player system for handling player-related operations.
GameManager(ServerNetwork &networkManager)
Constructor for GameManager.
void sendSystemMessageToRoom(uint32_t roomId, const std::string &message)
void handlePacket(uint32_t sessionId, const net::Packet &packet)
Handle an incoming packet from a player.
bool _gamePaused
Global game pause flag.
void handlePlayerLoginAuth(uint32_t sessionId, const net::Packet &packet)
Handle player login with provided username if successful then join the lobby.
void handleUpdateSelectedWeapon(uint32_t sessionId, const net::Packet &packet)
Handle an update to the selected weapon sent by client.
ecs::Registry _registry
ECS Registry for managing entities and components.
void handleSetReady(uint32_t sessionId, const net::Packet &packet)
Handle a generic incoming packet from a player.
void handlePlayerRegisterAuth(uint32_t sessionId, const net::Packet &packet)
Handle player registration with provided username.
void sendChatToSession(uint32_t sessionId, const std::string &message)
std::unique_ptr< PlayerShootSystem > _playerShootSystem
Player shooting system for handling bullets.
std::unique_ptr< BulletCleanupSystem > _bulletCleanupSystem
Bullet cleanup system.
std::unique_ptr< EntitySystem > _entitySystem
Entity system for handling entity-related operations.
void handlePlayerConnect(uint32_t sessionId)
Handle a new player connection.
void sendEntitySpawnToSessions(const ecs::Entity &entity, const std::vector< uint32_t > &sessions)
std::unique_ptr< AuthSystem > _authSystem
Authentication system for handling player logins.
Represents a game room in the server.
uint32_t getId(void) const
Get the unique identifier of the room.
@ InGame
Game in progress.
Implementation ASIO du serveur réseau (TCP + UDP)
void sendPacket(uint32_t sessionId, const net::Packet &packet, net::NetworkMode mode)
Send a packet to a specific session.
std::optional< net::NetworkEvent > pollEvent(void) override
Poll for a network event.
void broadcastPacket(const net::Packet &packet, net::NetworkMode mode)
Broadcast a packet to all connected sessions.
File : Network.hpp License: MIT Author : Elias Josué HAJJAR LLAUQUEN elias-josue.hajjar-llauquen@epit...
WeaponKind
Types of player weapons.
constexpr Entity NullEntity
void error(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log an error message.
void warning(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log a warning message.
void info(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log an informational message.
void debug(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log a debug message.
@ DebugModeUpdate
Debug mode toggle.
@ LoginRequest
Client login request.
@ Disconnect
Disconnect notification.
@ RoomChatReceived
Chat message received in room.
@ LeaveRoom
Request to leave a room.
@ StartGame
Notification to start the game.
@ CreateRoom
Request to create a room.
@ HealthUpdate
Player health update.
@ EntitySpawn
Entity spawn notification.
@ ScoreUpdate
Player score update.
@ Kicked
Player kicked notification.
@ EntityDeath
Entity death notification.
File : GameManager.hpp License: MIT Author : Elias Josué HAJJAR LLAUQUEN elias-josue....
void startGame(Room &room)
std::shared_ptr< Player > PlayerPtr
Shared pointer type for Player.
Ammo tracking for weapons.
Marks a projectile as a boomerang and stores state for return logic.
Component representing damage value.
Component for double fire powerup.
Component representing an entity's health.
Marks an entity as homing and provides tuning parameters.
Component representing a movement pattern.
Component representing movement speed with temporary boosts.
Component representing a network identifier for an entity.
Component representing a powerup pickup.
Component representing a network identifier for an entity.
Component representing a shield that absorbs damage.
Component representing a weapon configuration.
Component representing a 2D velocity.
Data for creating a new room Client OpCode.
uint32_t seed
Seed for random generation.
uint32_t duration
Duration of the game session.
float difficulty
Difficulty level.
uint32_t maxPlayers
Maximum number of players.
uint8_t roomType
Room type (public/private)
char roomName[64]
Desired room name.
float speed
Speed multiplier.
uint32_t levelId
Level identifier.
Debug mode toggle data Server OpCode.
Entity death notification data.
uint32_t netId
Network entity identifier.
Entity spawn notification data.
Player health update data.
Data for joining an existing room Client OpCode.
uint8_t isSpectator
1 if joining as spectator
uint32_t roomId
Room identifier to join.
Ping request/response payload Client/Server /Pong OpCodes.
Data for sending chat messages in a room Client OpCode.
char message[256]
Chat message content.
Data for receiving chat messages in a room Server OpCode.
uint32_t sessionId
Sender's session identifier.
Player score update notification data.
Data for setting player readiness status Client OpCode.
uint8_t isReady
Player readiness status.