mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	core, web_service: Changes to announce service
Separated registering and updating to correspond to the new announce API endpoint. Also added a verify_UID for JWT audience verification.
This commit is contained in:
		
							parent
							
								
									1a8841f96e
								
							
						
					
					
						commit
						ab335ccf1b
					
				
					 5 changed files with 135 additions and 49 deletions
				
			
		|  | @ -17,14 +17,17 @@ using MacAddress = std::array<u8, 6>; | ||||||
| 
 | 
 | ||||||
| struct Room { | struct Room { | ||||||
|     struct Member { |     struct Member { | ||||||
|         std::string name; |         std::string username; | ||||||
|  |         std::string nickname; | ||||||
|  |         std::string avatar_url; | ||||||
|         MacAddress mac_address; |         MacAddress mac_address; | ||||||
|         std::string game_name; |         std::string game_name; | ||||||
|         u64 game_id; |         u64 game_id; | ||||||
|     }; |     }; | ||||||
|  |     std::string id; | ||||||
|  |     std::string verify_UID; ///< UID used for verification
 | ||||||
|     std::string name; |     std::string name; | ||||||
|     std::string description; |     std::string description; | ||||||
|     std::string UID; |  | ||||||
|     std::string owner; |     std::string owner; | ||||||
|     std::string ip; |     std::string ip; | ||||||
|     u16 port; |     u16 port; | ||||||
|  | @ -57,9 +60,8 @@ public: | ||||||
|      * @param preferred_game The preferred game of the room |      * @param preferred_game The preferred game of the room | ||||||
|      * @param preferred_game_id The title id of the preferred game |      * @param preferred_game_id The title id of the preferred game | ||||||
|      */ |      */ | ||||||
|     virtual void SetRoomInformation(const std::string& uid, const std::string& name, |     virtual void SetRoomInformation(const std::string& name, const std::string& description, | ||||||
|                                     const std::string& description, const u16 port, |                                     const u16 port, const u32 max_player, const u32 net_version, | ||||||
|                                     const u32 max_player, const u32 net_version, |  | ||||||
|                                     const bool has_password, const std::string& preferred_game, |                                     const bool has_password, const std::string& preferred_game, | ||||||
|                                     const u64 preferred_game_id) = 0; |                                     const u64 preferred_game_id) = 0; | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -69,14 +71,21 @@ public: | ||||||
|      * @param game_id The title id of the game the player plays |      * @param game_id The title id of the game the player plays | ||||||
|      * @param game_name The name of the game the player plays |      * @param game_name The name of the game the player plays | ||||||
|      */ |      */ | ||||||
|     virtual void AddPlayer(const std::string& nickname, const MacAddress& mac_address, |     virtual void AddPlayer(const std::string& username, const std::string& nickname, | ||||||
|  |                            const std::string& avatar_url, const MacAddress& mac_address, | ||||||
|                            const u64 game_id, const std::string& game_name) = 0; |                            const u64 game_id, const std::string& game_name) = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Send the data to the announce service |      * Updates the data in the announce service. Re-register the room when required. | ||||||
|      * @result The result of the announce attempt |      * @result The result of the update attempt | ||||||
|      */ |      */ | ||||||
|     virtual Common::WebResult Announce() = 0; |     virtual Common::WebResult Update() = 0; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Registers the data in the announce service | ||||||
|  |      * @result A global Guid of the room which may be used for verification | ||||||
|  |      */ | ||||||
|  |     virtual std::string Register() = 0; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Empties the stored players |      * Empties the stored players | ||||||
|  | @ -102,16 +111,19 @@ public: | ||||||
| class NullBackend : public Backend { | class NullBackend : public Backend { | ||||||
| public: | public: | ||||||
|     ~NullBackend() = default; |     ~NullBackend() = default; | ||||||
|     void SetRoomInformation(const std::string& /*uid*/, const std::string& /*name*/, |     void SetRoomInformation(const std::string& /*name*/, const std::string& /*description*/, | ||||||
|                             const std::string& /*description*/, const u16 /*port*/, |                             const u16 /*port*/, const u32 /*max_player*/, const u32 /*net_version*/, | ||||||
|                             const u32 /*max_player*/, const u32 /*net_version*/, |  | ||||||
|                             const bool /*has_password*/, const std::string& /*preferred_game*/, |                             const bool /*has_password*/, const std::string& /*preferred_game*/, | ||||||
|                             const u64 /*preferred_game_id*/) override {} |                             const u64 /*preferred_game_id*/) override {} | ||||||
|     void AddPlayer(const std::string& /*nickname*/, const MacAddress& /*mac_address*/, |     void AddPlayer(const std::string& /*username*/, const std::string& /*nickname*/, | ||||||
|  |                    const std::string& /*avatar_url*/, const MacAddress& /*mac_address*/, | ||||||
|                    const u64 /*game_id*/, const std::string& /*game_name*/) override {} |                    const u64 /*game_id*/, const std::string& /*game_name*/) override {} | ||||||
|     Common::WebResult Announce() override { |     Common::WebResult Update() override { | ||||||
|         return Common::WebResult{Common::WebResult::Code::NoWebservice, "WebService is missing"}; |         return Common::WebResult{Common::WebResult::Code::NoWebservice, "WebService is missing"}; | ||||||
|     } |     } | ||||||
|  |     std::string Register() override { | ||||||
|  |         return ""; | ||||||
|  |     } | ||||||
|     void ClearPlayers() override {} |     void ClearPlayers() override {} | ||||||
|     RoomList GetRoomList() override { |     RoomList GetRoomList() override { | ||||||
|         return RoomList{}; |         return RoomList{}; | ||||||
|  |  | ||||||
|  | @ -29,6 +29,21 @@ AnnounceMultiplayerSession::AnnounceMultiplayerSession() { | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void AnnounceMultiplayerSession::Register() { | ||||||
|  |     std::shared_ptr<Network::Room> room = Network::GetRoom().lock(); | ||||||
|  |     if (!room) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     if (room->GetState() != Network::Room::State::Open) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     UpdateBackendData(room); | ||||||
|  |     std::string result = backend->Register(); | ||||||
|  |     LOG_INFO(WebService, "Room has been registered"); | ||||||
|  |     room->SetVerifyUID(result); | ||||||
|  |     registered = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void AnnounceMultiplayerSession::Start() { | void AnnounceMultiplayerSession::Start() { | ||||||
|     if (announce_multiplayer_thread) { |     if (announce_multiplayer_thread) { | ||||||
|         Stop(); |         Stop(); | ||||||
|  | @ -44,6 +59,7 @@ void AnnounceMultiplayerSession::Stop() { | ||||||
|         announce_multiplayer_thread->join(); |         announce_multiplayer_thread->join(); | ||||||
|         announce_multiplayer_thread.reset(); |         announce_multiplayer_thread.reset(); | ||||||
|         backend->Delete(); |         backend->Delete(); | ||||||
|  |         registered = false; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -64,7 +80,24 @@ AnnounceMultiplayerSession::~AnnounceMultiplayerSession() { | ||||||
|     Stop(); |     Stop(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void AnnounceMultiplayerSession::UpdateBackendData(std::shared_ptr<Network::Room> room) { | ||||||
|  |     Network::RoomInformation room_information = room->GetRoomInformation(); | ||||||
|  |     std::vector<Network::Room::Member> memberlist = room->GetRoomMemberList(); | ||||||
|  |     backend->SetRoomInformation( | ||||||
|  |         room_information.name, room_information.description, room_information.port, | ||||||
|  |         room_information.member_slots, Network::network_version, room->HasPassword(), | ||||||
|  |         room_information.preferred_game, room_information.preferred_game_id); | ||||||
|  |     backend->ClearPlayers(); | ||||||
|  |     for (const auto& member : memberlist) { | ||||||
|  |         backend->AddPlayer(member.username, member.nickname, member.avatar_url, member.mac_address, | ||||||
|  |                            member.game_info.id, member.game_info.name); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { | void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { | ||||||
|  |     if (!registered) { | ||||||
|  |         Register(); | ||||||
|  |     } | ||||||
|     auto update_time = std::chrono::steady_clock::now(); |     auto update_time = std::chrono::steady_clock::now(); | ||||||
|     std::future<Common::WebResult> future; |     std::future<Common::WebResult> future; | ||||||
|     while (!shutdown_event.WaitUntil(update_time)) { |     while (!shutdown_event.WaitUntil(update_time)) { | ||||||
|  | @ -76,25 +109,19 @@ void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { | ||||||
|         if (room->GetState() != Network::Room::State::Open) { |         if (room->GetState() != Network::Room::State::Open) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         Network::RoomInformation room_information = room->GetRoomInformation(); |         UpdateBackendData(room); | ||||||
|         std::vector<Network::Room::Member> memberlist = room->GetRoomMemberList(); |         Common::WebResult result = backend->Update(); | ||||||
|         backend->SetRoomInformation(room_information.uid, room_information.name, |  | ||||||
|                                     room_information.description, room_information.port, |  | ||||||
|                                     room_information.member_slots, Network::network_version, |  | ||||||
|                                     room->HasPassword(), room_information.preferred_game, |  | ||||||
|                                     room_information.preferred_game_id); |  | ||||||
|         backend->ClearPlayers(); |  | ||||||
|         for (const auto& member : memberlist) { |  | ||||||
|             backend->AddPlayer(member.nickname, member.mac_address, member.game_info.id, |  | ||||||
|                                member.game_info.name); |  | ||||||
|         } |  | ||||||
|         Common::WebResult result = backend->Announce(); |  | ||||||
|         if (result.result_code != Common::WebResult::Code::Success) { |         if (result.result_code != Common::WebResult::Code::Success) { | ||||||
|             std::lock_guard<std::mutex> lock(callback_mutex); |             std::lock_guard<std::mutex> lock(callback_mutex); | ||||||
|             for (auto callback : error_callbacks) { |             for (auto callback : error_callbacks) { | ||||||
|                 (*callback)(result); |                 (*callback)(result); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         if (result.result_string == "404") { | ||||||
|  |             registered = false; | ||||||
|  |             // Needs to register the room again
 | ||||||
|  |             Register(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <atomic> | ||||||
| #include <functional> | #include <functional> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <mutex> | #include <mutex> | ||||||
|  | @ -13,6 +14,10 @@ | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/thread.h" | #include "common/thread.h" | ||||||
| 
 | 
 | ||||||
|  | namespace Network { | ||||||
|  | class Room; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -39,6 +44,9 @@ public: | ||||||
|      */ |      */ | ||||||
|     void UnbindErrorCallback(CallbackHandle handle); |     void UnbindErrorCallback(CallbackHandle handle); | ||||||
| 
 | 
 | ||||||
|  |     /// Registers a room to web services
 | ||||||
|  |     void Register(); | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Starts the announce of a room to web services |      * Starts the announce of a room to web services | ||||||
|      */ |      */ | ||||||
|  | @ -65,6 +73,9 @@ private: | ||||||
|     /// Backend interface that logs fields
 |     /// Backend interface that logs fields
 | ||||||
|     std::unique_ptr<AnnounceMultiplayerRoom::Backend> backend; |     std::unique_ptr<AnnounceMultiplayerRoom::Backend> backend; | ||||||
| 
 | 
 | ||||||
|  |     std::atomic_bool registered = false; ///< Whether the room has been registered
 | ||||||
|  | 
 | ||||||
|  |     void UpdateBackendData(std::shared_ptr<Network::Room> room); | ||||||
|     void AnnounceMultiplayerLoop(); |     void AnnounceMultiplayerLoop(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,22 +12,36 @@ | ||||||
| namespace AnnounceMultiplayerRoom { | namespace AnnounceMultiplayerRoom { | ||||||
| 
 | 
 | ||||||
| void to_json(nlohmann::json& json, const Room::Member& member) { | void to_json(nlohmann::json& json, const Room::Member& member) { | ||||||
|     json["name"] = member.name; |     if (!member.username.empty()) { | ||||||
|  |         json["username"] = member.username; | ||||||
|  |     } | ||||||
|  |     json["nickname"] = member.nickname; | ||||||
|  |     if (!member.avatar_url.empty()) { | ||||||
|  |         json["avatarUrl"] = member.avatar_url; | ||||||
|  |     } | ||||||
|     json["gameName"] = member.game_name; |     json["gameName"] = member.game_name; | ||||||
|     json["gameId"] = member.game_id; |     json["gameId"] = member.game_id; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void from_json(const nlohmann::json& json, Room::Member& member) { | void from_json(const nlohmann::json& json, Room::Member& member) { | ||||||
|     member.name = json.at("name").get<std::string>(); |     member.nickname = json.at("nickname").get<std::string>(); | ||||||
|     member.game_name = json.at("gameName").get<std::string>(); |     member.game_name = json.at("gameName").get<std::string>(); | ||||||
|     member.game_id = json.at("gameId").get<u64>(); |     member.game_id = json.at("gameId").get<u64>(); | ||||||
|  |     try { | ||||||
|  |         member.username = json.at("username").get<std::string>(); | ||||||
|  |         member.avatar_url = json.at("avatarUrl").get<std::string>(); | ||||||
|  |     } catch (const nlohmann::detail::out_of_range& e) { | ||||||
|  |         member.username = member.avatar_url = ""; | ||||||
|  |         LOG_DEBUG(Network, "Member \'{}\' isn't authenticated", member.nickname); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void to_json(nlohmann::json& json, const Room& room) { | void to_json(nlohmann::json& json, const Room& room) { | ||||||
|     json["id"] = room.UID; |  | ||||||
|     json["port"] = room.port; |     json["port"] = room.port; | ||||||
|     json["name"] = room.name; |     json["name"] = room.name; | ||||||
|     json["description"] = room.description; |     if (!room.description.empty()) { | ||||||
|  |         json["description"] = room.description; | ||||||
|  |     } | ||||||
|     json["preferredGameName"] = room.preferred_game; |     json["preferredGameName"] = room.preferred_game; | ||||||
|     json["preferredGameId"] = room.preferred_game_id; |     json["preferredGameId"] = room.preferred_game_id; | ||||||
|     json["maxPlayers"] = room.max_player; |     json["maxPlayers"] = room.max_player; | ||||||
|  | @ -40,6 +54,7 @@ void to_json(nlohmann::json& json, const Room& room) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void from_json(const nlohmann::json& json, Room& room) { | void from_json(const nlohmann::json& json, Room& room) { | ||||||
|  |     room.verify_UID = json.at("externalGuid").get<std::string>(); | ||||||
|     room.ip = json.at("address").get<std::string>(); |     room.ip = json.at("address").get<std::string>(); | ||||||
|     room.name = json.at("name").get<std::string>(); |     room.name = json.at("name").get<std::string>(); | ||||||
|     try { |     try { | ||||||
|  | @ -66,14 +81,12 @@ void from_json(const nlohmann::json& json, Room& room) { | ||||||
| 
 | 
 | ||||||
| namespace WebService { | namespace WebService { | ||||||
| 
 | 
 | ||||||
| void RoomJson::SetRoomInformation(const std::string& uid, const std::string& name, | void RoomJson::SetRoomInformation(const std::string& name, const std::string& description, | ||||||
|                                   const std::string& description, const u16 port, |                                   const u16 port, const u32 max_player, const u32 net_version, | ||||||
|                                   const u32 max_player, const u32 net_version, |  | ||||||
|                                   const bool has_password, const std::string& preferred_game, |                                   const bool has_password, const std::string& preferred_game, | ||||||
|                                   const u64 preferred_game_id) { |                                   const u64 preferred_game_id) { | ||||||
|     room.name = name; |     room.name = name; | ||||||
|     room.description = description; |     room.description = description; | ||||||
|     room.UID = uid; |  | ||||||
|     room.port = port; |     room.port = port; | ||||||
|     room.max_player = max_player; |     room.max_player = max_player; | ||||||
|     room.net_version = net_version; |     room.net_version = net_version; | ||||||
|  | @ -81,20 +94,39 @@ void RoomJson::SetRoomInformation(const std::string& uid, const std::string& nam | ||||||
|     room.preferred_game = preferred_game; |     room.preferred_game = preferred_game; | ||||||
|     room.preferred_game_id = preferred_game_id; |     room.preferred_game_id = preferred_game_id; | ||||||
| } | } | ||||||
| void RoomJson::AddPlayer(const std::string& nickname, | void RoomJson::AddPlayer(const std::string& username, const std::string& nickname, | ||||||
|  |                          const std::string& avatar_url, | ||||||
|                          const AnnounceMultiplayerRoom::MacAddress& mac_address, const u64 game_id, |                          const AnnounceMultiplayerRoom::MacAddress& mac_address, const u64 game_id, | ||||||
|                          const std::string& game_name) { |                          const std::string& game_name) { | ||||||
|     AnnounceMultiplayerRoom::Room::Member member; |     AnnounceMultiplayerRoom::Room::Member member; | ||||||
|     member.name = nickname; |     member.username = username; | ||||||
|  |     member.nickname = nickname; | ||||||
|  |     member.avatar_url = avatar_url; | ||||||
|     member.mac_address = mac_address; |     member.mac_address = mac_address; | ||||||
|     member.game_id = game_id; |     member.game_id = game_id; | ||||||
|     member.game_name = game_name; |     member.game_name = game_name; | ||||||
|     room.members.push_back(member); |     room.members.push_back(member); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Common::WebResult RoomJson::Announce() { | Common::WebResult RoomJson::Update() { | ||||||
|  |     if (room_id.empty()) { | ||||||
|  |         LOG_ERROR(WebService, "Room must be registered to be updated"); | ||||||
|  |         return Common::WebResult{Common::WebResult::Code::LibError, "Room is not registered"}; | ||||||
|  |     } | ||||||
|  |     nlohmann::json json{{"players", room.members}}; | ||||||
|  |     return client.PostJson(fmt::format("/lobby2/{}", room_id), json.dump(), false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string RoomJson::Register() { | ||||||
|     nlohmann::json json = room; |     nlohmann::json json = room; | ||||||
|     return client.PostJson("/lobby", json.dump(), false); |     auto reply = client.PostJson("/lobby2", json.dump(), false).returned_data; | ||||||
|  |     if (reply.empty()) { | ||||||
|  |         return ""; | ||||||
|  |     } | ||||||
|  |     auto reply_json = nlohmann::json::parse(reply); | ||||||
|  |     room = reply_json.get<AnnounceMultiplayerRoom::Room>(); | ||||||
|  |     room_id = reply_json.at("id").get<std::string>(); | ||||||
|  |     return room.verify_UID; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RoomJson::ClearPlayers() { | void RoomJson::ClearPlayers() { | ||||||
|  | @ -102,7 +134,7 @@ void RoomJson::ClearPlayers() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AnnounceMultiplayerRoom::RoomList RoomJson::GetRoomList() { | AnnounceMultiplayerRoom::RoomList RoomJson::GetRoomList() { | ||||||
|     auto reply = client.GetJson("/lobby", true).returned_data; |     auto reply = client.GetJson("/lobby2", true).returned_data; | ||||||
|     if (reply.empty()) { |     if (reply.empty()) { | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
|  | @ -110,12 +142,14 @@ AnnounceMultiplayerRoom::RoomList RoomJson::GetRoomList() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RoomJson::Delete() { | void RoomJson::Delete() { | ||||||
|     nlohmann::json json; |     if (room_id.empty()) { | ||||||
|     json["id"] = room.UID; |         LOG_ERROR(WebService, "Room must be registered to be deleted"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     Common::DetachedTasks::AddTask( |     Common::DetachedTasks::AddTask( | ||||||
|         [host{this->host}, username{this->username}, token{this->token}, content{json.dump()}]() { |         [host{this->host}, username{this->username}, token{this->token}, room_id{this->room_id}]() { | ||||||
|             // create a new client here because the this->client might be destroyed.
 |             // create a new client here because the this->client might be destroyed.
 | ||||||
|             Client{host, username, token}.DeleteJson("/lobby", content, false); |             Client{host, username, token}.DeleteJson(fmt::format("/lobby2/{}", room_id), "", false); | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -20,15 +20,16 @@ public: | ||||||
|     RoomJson(const std::string& host, const std::string& username, const std::string& token) |     RoomJson(const std::string& host, const std::string& username, const std::string& token) | ||||||
|         : client(host, username, token), host(host), username(username), token(token) {} |         : client(host, username, token), host(host), username(username), token(token) {} | ||||||
|     ~RoomJson() = default; |     ~RoomJson() = default; | ||||||
|     void SetRoomInformation(const std::string& uid, const std::string& name, |     void SetRoomInformation(const std::string& name, const std::string& description, const u16 port, | ||||||
|                             const std::string& description, const u16 port, const u32 max_player, |                             const u32 max_player, const u32 net_version, const bool has_password, | ||||||
|                             const u32 net_version, const bool has_password, |  | ||||||
|                             const std::string& preferred_game, |                             const std::string& preferred_game, | ||||||
|                             const u64 preferred_game_id) override; |                             const u64 preferred_game_id) override; | ||||||
|     void AddPlayer(const std::string& nickname, |     void AddPlayer(const std::string& username, const std::string& nickname, | ||||||
|  |                    const std::string& avatar_url, | ||||||
|                    const AnnounceMultiplayerRoom::MacAddress& mac_address, const u64 game_id, |                    const AnnounceMultiplayerRoom::MacAddress& mac_address, const u64 game_id, | ||||||
|                    const std::string& game_name) override; |                    const std::string& game_name) override; | ||||||
|     Common::WebResult Announce() override; |     Common::WebResult Update() override; | ||||||
|  |     std::string Register() override; | ||||||
|     void ClearPlayers() override; |     void ClearPlayers() override; | ||||||
|     AnnounceMultiplayerRoom::RoomList GetRoomList() override; |     AnnounceMultiplayerRoom::RoomList GetRoomList() override; | ||||||
|     void Delete() override; |     void Delete() override; | ||||||
|  | @ -39,6 +40,7 @@ private: | ||||||
|     std::string host; |     std::string host; | ||||||
|     std::string username; |     std::string username; | ||||||
|     std::string token; |     std::string token; | ||||||
|  |     std::string room_id; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace WebService
 | } // namespace WebService
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue