r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
joinRoom.cpp
Go to the documentation of this file.
1#include <cmath>
2
3#include "ECS/Component.hpp"
6#include "Utils/Common.hpp"
7#include "Utils/Logger.hpp"
8
9gme::JoinRoomScene::JoinRoomScene(const eng::id assignedId, const std::shared_ptr<eng::IRenderer> &renderer)
10 : AScene(assignedId)
11{
12 auto &registry = AScene::getRegistry();
13
14 registry.onComponentAdded(
15 [&renderer, &registry](const ecs::Entity e, const std::type_info &type)
16 {
17 const auto *colorComp = registry.getComponent<ecs::Color>(e);
18 const auto *fontComp = registry.getComponent<ecs::Font>(e);
19 const auto *textComp = registry.getComponent<ecs::Text>(e);
20 const auto *transform = registry.getComponent<ecs::Transform>(e);
21
22 if (type == typeid(ecs::Text))
23 {
24 if (textComp && transform && fontComp)
25 {
26 renderer->createFont(fontComp->id, fontComp->path);
27 renderer->createText(
28 {.font_name = fontComp->id,
29 .color = {.r = colorComp->r, .g = colorComp->g, .b = colorComp->b, .a = colorComp->a},
30 .content = textComp->content,
31 .size = textComp->font_size,
32 .x = transform->x,
33 .y = transform->y,
34 .name = textComp->id});
35 }
36 }
37 });
38
39 registry.createEntity()
40 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
41 .with<ecs::Transform>("transform_title", 100.F, 60.F, 0.F)
44 .with<ecs::Text>("title", std::string("JOIN ROOM"), 72U)
45 .build();
46
48 registry.createEntity()
49 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
50 .with<ecs::Transform>("transform_no_rooms", 100.F, 200.F, 0.F)
51 .with<ecs::Color>("color_no_rooms", utl::Config::Color::INFO_TEXT_COLOR.r,
54 .with<ecs::Text>("no_rooms_text", std::string("No rooms available"), 32U)
55 .build();
56
57 registry.createEntity()
58 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
59 .with<ecs::Transform>("transform_refresh", 100.F, 400.F, 0.F)
63 .with<ecs::Text>("refresh_text", std::string("Refresh"), 32U)
64 .build();
65
66 registry.createEntity()
67 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
68 .with<ecs::Transform>("transform_back", 100.F, 450.F, 0.F)
71 .with<ecs::Text>("back_text", std::string("Back"), 32U)
72 .build();
73
77}
78
80{
81 m_eventBus.subscribe(m_eventComponentId, utl::EventType::LOBBY_LIST_RESPONSE);
82 m_eventBus.subscribe(m_eventComponentId, utl::EventType::LOBBY_JOIN_RESPONSE);
83}
84
86{
87 try
88 {
89 rnp::Serializer serializer(event.data);
90 auto [lobbyCount, lobbies] = serializer.deserializeLobbyListResponse();
91
92 utl::Logger::log("JoinRoomScene: Received lobby list with " + std::to_string(lobbyCount) + " lobbies",
94
95 setRooms(lobbies);
96
97 for (const auto &lobby : lobbies)
98 {
99 size_t nameLen = 0;
100 for (size_t i = 0; i < lobby.lobbyName.size() && lobby.lobbyName[i] != '\0'; ++i)
101 {
102 nameLen = i + 1;
103 }
104 std::string lobbyName(lobby.lobbyName.data(), nameLen);
105 utl::Logger::log("JoinRoomScene: Found lobby '" + lobbyName + "' (ID: " + std::to_string(lobby.lobbyId) +
106 ") with " + std::to_string(lobby.currentPlayers) + "/" +
107 std::to_string(lobby.maxPlayers) + " players",
109 }
110 }
111 catch (const std::exception &e)
112 {
113 utl::Logger::log("JoinRoomScene: Failed to handle lobby list response - " + std::string(e.what()),
115 }
116}
117
119{
120 try
121 {
122 rnp::Serializer deserializer(event.data);
123 auto [lobbyId, success, errorCode, lobbyInfo] = deserializer.deserializeLobbyJoinResponse();
124
125 if (success == 1)
126 {
127 utl::Logger::log("JoinRoomScene: Successfully joined lobby " + std::to_string(lobbyId),
129 if (onJoin)
130 {
131 onJoin(static_cast<int>(lobbyId), &lobbyInfo);
132 }
133 }
134 else
135 {
136 std::string errorMsg;
137 switch (static_cast<rnp::ErrorCode>(errorCode))
138 {
140 errorMsg = "Lobby not found";
141 break;
143 errorMsg = "Lobby is full";
144 break;
146 errorMsg = "Already in a lobby";
147 break;
148 default:
149 errorMsg = "Failed to join lobby";
150 break;
151 }
152 utl::Logger::log("JoinRoomScene: " + errorMsg, utl::LogLevel::WARNING);
153 }
154 }
155 catch (const std::exception &e)
156 {
157 utl::Logger::log("JoinRoomScene: Failed to handle lobby join response - " + std::string(e.what()),
159 }
160}
161
162void gme::JoinRoomScene::update(const float dt, const eng::WindowSize & /*size*/)
163{
164 auto &reg = getRegistry();
165 auto &colors = reg.getAll<ecs::Color>();
166 auto &texts = reg.getAll<ecs::Text>();
167 auto &audios = reg.getAll<ecs::Audio>();
168
169 m_animationTime += dt;
170
171 for (auto &[entity, text] : texts)
172 {
173 if (text.id == "refresh_text")
174 {
175 auto &color = colors.at(entity);
176 if (m_selectedIndex == m_rooms.size())
177 {
178 const float glowIntensity = std::sin(m_animationTime * 2.5F);
179 color.r = 0U;
180 color.g = static_cast<unsigned char>(191U + (glowIntensity * 50));
181 color.b = 255U;
182 }
183 else
184 {
188 }
189 }
190 else if (text.id == "back_text")
191 {
192 auto &color = colors.at(entity);
193 if (m_selectedIndex == m_rooms.size() + 1)
194 {
195 const float glowIntensity = std::sin(m_animationTime * 2.5F);
196 color.r = 0U;
197 color.g = static_cast<unsigned char>(191U + (glowIntensity * 50));
198 color.b = 255U;
199 }
200 else
201 {
205 }
206 }
207 }
208
209 for (size_t i = 0; i < m_roomEntities.size(); ++i)
210 {
211 if (auto *color = reg.getComponent<ecs::Color>(m_roomEntities[i]))
212 {
213 if (i == m_selectedIndex)
214 {
215 float glowIntensity = std::sin(m_animationTime * 2.5F);
216 color->r = 0U;
217 color->g = static_cast<unsigned char>(191U + (glowIntensity * 50));
218 color->b = 255U;
219 }
220 else
221 {
225 }
226 }
227 }
228 processEventBus();
229}
230
232{
233 const size_t totalOptions = m_rooms.size() + 2;
234
235 switch (event.type)
236 {
238 if (event.key == eng::Key::Escape)
239 {
240 if (onBackToMulti)
241 {
242 onBackToMulti();
243 }
244 }
245 else if (event.key == eng::Key::Up)
246 {
247 m_playMusic = true;
248 if (totalOptions > 0)
249 {
250 m_selectedIndex = (m_selectedIndex == 0) ? totalOptions - 1 : m_selectedIndex - 1;
251 }
252 }
253 else if (event.key == eng::Key::Down)
254 {
255 m_playMusic = true;
256 if (totalOptions > 0)
257 {
258 m_selectedIndex = (m_selectedIndex == totalOptions - 1) ? 0 : m_selectedIndex + 1;
259 }
260 }
261 else if (event.key == eng::Key::Enter)
262 {
263 if (m_selectedIndex < m_rooms.size())
264 {
265 rnp::PacketLobbyJoin joinPacket{};
266 joinPacket.lobbyId = m_rooms[m_selectedIndex].lobbyId;
267
268 m_eventBus.publish(utl::EventType::LOBBY_JOIN, joinPacket, m_eventComponentId, utl::NETWORK_CLIENT);
269 }
270 else if (m_selectedIndex == m_rooms.size() && onRefreshRequest)
271 {
272 onRefreshRequest();
273 refreshRoomList();
274 }
275 else if (m_selectedIndex == m_rooms.size() + 1 && onBackToMulti)
276 {
277 onBackToMulti();
278 }
279 }
280 break;
282 break;
283 default:
284 break;
285 }
286}
287
288void gme::JoinRoomScene::setRooms(const std::vector<rnp::LobbyInfo> &rooms)
289{
290 m_rooms = rooms;
291 updateRoomDisplay();
292}
293
295{
296 m_eventBus.publish(utl::EventType::LOBBY_LIST_REQUEST, std::vector<std::uint8_t>(), m_eventComponentId,
298
299 if (onRefreshRequest)
300 {
301 onRefreshRequest();
302 }
303}
304
306{
307 auto &registry = getRegistry();
308
309 utl::Logger::log("JoinRoomScene: Updating room display with " + std::to_string(m_rooms.size()) + " rooms",
311
312 clearRoomEntities();
313
314 if (auto *noRoomsText = registry.getComponent<ecs::Text>(m_noRoomsEntity))
315 {
316 noRoomsText->content = m_rooms.empty() ? "No rooms available" : "";
317 }
318
319 for (size_t i = 0; i < m_rooms.size(); ++i)
320 {
321 const rnp::LobbyInfo &lobby = m_rooms[i];
322
323 size_t nameLen = 0;
324 for (size_t j = 0; j < lobby.lobbyName.size() && lobby.lobbyName[j] != '\0'; ++j)
325 {
326 nameLen = j + 1;
327 }
328 std::string lobbyName(lobby.lobbyName.data(), nameLen);
329
330 std::string roomText =
331 lobbyName + " " + std::to_string(lobby.currentPlayers) + "/" + std::to_string(lobby.maxPlayers);
332
333 utl::Logger::log("JoinRoomScene: Creating entity for room: " + roomText, utl::LogLevel::INFO);
334
335 ecs::Entity roomEntity =
336 registry.createEntity()
337 .with<ecs::Font>("main_font", utl::Path::Font::FONTS_RTYPE)
338 .with<ecs::Transform>("transform_room_" + std::to_string(i), 100.F, 200.F + i * 40.F, 0.F)
339 .with<ecs::Color>("color_room_" + std::to_string(i), utl::Config::Color::TEXT_VALUE_COLOR.r,
342 .with<ecs::Text>("room_" + std::to_string(i), roomText, 28U)
343 .build();
344
345 m_roomEntities.push_back(roomEntity);
346 }
347
348 if (m_selectedIndex >= m_rooms.size() + 2)
349 {
350 m_selectedIndex = 0;
351 }
352}
353
355{
356 auto &registry = getRegistry();
357
358 for (const ecs::Entity entity : m_roomEntities)
359 {
360 if (registry.getComponent<ecs::Text>(entity) != nullptr)
361 {
362 registry.removeComponent<ecs::Text>(entity);
363 }
364 if (registry.getComponent<ecs::Color>(entity) != nullptr)
365 {
366 registry.removeComponent<ecs::Color>(entity);
367 }
368 if (registry.getComponent<ecs::Transform>(entity) != nullptr)
369 {
370 registry.removeComponent<ecs::Transform>(entity);
371 }
372 if (registry.getComponent<ecs::Font>(entity) != nullptr)
373 {
374 registry.removeComponent<ecs::Font>(entity);
375 }
376 }
377
378 m_roomEntities.clear();
379}
380
382{
383 for (const std::vector<utl::Event> events = m_eventBus.consumeForTarget(m_eventComponentId);
384 const auto &event : events)
385 {
386 switch (event.type)
387 {
389 handleLobbyListResponse(event);
390 break;
392 handleLobbyJoinResponse(event);
393 break;
394 default:
395 break;
396 }
397 }
398}
This file contains the component definitions.
Lobby browser scene for joining multiplayer games.
This file contains the Logger class.
Network packet serializer for RNP protocol.
utl::EventBus & m_eventBus
Definition IScene.hpp:84
std::uint32_t m_eventComponentId
Definition IScene.hpp:85
ecs::Entity m_noRoomsEntity
Entity displaying "No rooms available" message.
Definition JoinRoom.hpp:129
void handleLobbyListResponse(const utl::Event &event)
Handle lobby list response from server.
Definition joinRoom.cpp:85
void clearRoomEntities()
Clear all lobby display entities.
Definition joinRoom.cpp:354
void event(const eng::Event &event) override
Handle input events.
Definition joinRoom.cpp:231
void setRooms(const std::vector< rnp::LobbyInfo > &rooms)
Update the displayed list of available lobbies.
Definition joinRoom.cpp:288
void update(float dt, const eng::WindowSize &size) override
Update the join room scene (called each frame)
Definition joinRoom.cpp:162
void refreshRoomList() const
Request updated lobby list from server.
Definition joinRoom.cpp:294
JoinRoomScene(eng::id assignedId, const std::shared_ptr< eng::IRenderer > &renderer)
Constructor.
Definition joinRoom.cpp:9
void setupEventSubscriptions() const
Subscribe to event bus events.
Definition joinRoom.cpp:79
void processEventBus()
Process events from event bus.
Definition joinRoom.cpp:381
void updateRoomDisplay()
Update the visual display of the lobby list.
Definition joinRoom.cpp:305
void handleLobbyJoinResponse(const utl::Event &event) const
Handle lobby join response from server.
Definition joinRoom.cpp:118
Binary serializer for RNP protocol packets.
PacketLobbyJoinResponse deserializeLobbyJoinResponse()
Deserialize LOBBY_JOIN_RESPONSE packet.
PacketLobbyListResponse deserializeLobbyListResponse()
Deserialize LOBBY_LIST_RESPONSE packet.
void registerComponent(std::uint32_t componentId, const std::string &name)
Register component name for better debugging.
Definition EventBus.hpp:423
Event structure for inter-component communication.
Definition Event.hpp:89
std::vector< std::uint8_t > data
Serialized event data.
Definition Event.hpp:96
static void log(const std::string &message, const LogLevel &logLevel)
Definition Logger.hpp:51
This file contains common definitions and constants.
std::uint32_t Entity
Definition Entity.hpp:13
unsigned int id
Definition IScene.hpp:20
ErrorCode
Error codes.
Definition Protocol.hpp:75
static constexpr eng::Color TEXT_VALUE_COLOR
Definition Common.hpp:66
static constexpr eng::Color GRAY_BLUE_SUBTLE
Definition Common.hpp:57
static constexpr eng::Color CYAN_ELECTRIC
Definition Common.hpp:56
static constexpr eng::Color INFO_TEXT_COLOR
Definition Common.hpp:63
constexpr auto FONTS_RTYPE
Definition Common.hpp:97
static constexpr std::uint32_t NETWORK_CLIENT
Definition Event.hpp:17
std::string id
Definition Component.hpp:15
unsigned char r
Definition IRenderer.hpp:17
unsigned char a
Definition IRenderer.hpp:20
unsigned char g
Definition IRenderer.hpp:18
unsigned char b
Definition IRenderer.hpp:19
EventType type
Lobby information structure.
Definition Protocol.hpp:237
std::array< char, 32 > lobbyName
Definition Protocol.hpp:239
std::uint8_t currentPlayers
Definition Protocol.hpp:240
std::uint8_t maxPlayers
Definition Protocol.hpp:241
LOBBY_JOIN packet payload.
Definition Protocol.hpp:282
std::uint32_t lobbyId
Definition Protocol.hpp:283