diff --git a/src/citra_qt/configuration/configure_dialog.cpp b/src/citra_qt/configuration/configure_dialog.cpp index e1fc5abac..653f2a387 100644 --- a/src/citra_qt/configuration/configure_dialog.cpp +++ b/src/citra_qt/configuration/configure_dialog.cpp @@ -10,10 +10,11 @@ #include "core/settings.h" #include "ui_configure.h" -ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) +ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, bool enable_web_config) : QDialog(parent), registry(registry), ui(new Ui::ConfigureDialog) { ui->setupUi(this); ui->hotkeysTab->Populate(registry); + ui->webTab->SetWebServiceConfigEnabled(enable_web_config); this->PopulateSelectionList(); connect(ui->uiTab, &ConfigureUi::languageChanged, this, &ConfigureDialog::onLanguageChanged); diff --git a/src/citra_qt/configuration/configure_dialog.h b/src/citra_qt/configuration/configure_dialog.h index 91234ca0b..6fab7cff1 100644 --- a/src/citra_qt/configuration/configure_dialog.h +++ b/src/citra_qt/configuration/configure_dialog.h @@ -17,7 +17,8 @@ class ConfigureDialog : public QDialog { Q_OBJECT public: - explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); + explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, + bool enable_web_config = true); ~ConfigureDialog() override; void applyConfiguration(); diff --git a/src/citra_qt/configuration/configure_web.cpp b/src/citra_qt/configuration/configure_web.cpp index 56f876524..e8a0cc21f 100644 --- a/src/citra_qt/configuration/configure_web.cpp +++ b/src/citra_qt/configuration/configure_web.cpp @@ -118,3 +118,8 @@ void ConfigureWeb::OnLoginVerified() { void ConfigureWeb::retranslateUi() { ui->retranslateUi(this); } + +void ConfigureWeb::SetWebServiceConfigEnabled(bool enabled) { + ui->label_disable_info->setVisible(!enabled); + ui->groupBoxWebConfig->setEnabled(enabled); +} diff --git a/src/citra_qt/configuration/configure_web.h b/src/citra_qt/configuration/configure_web.h index d52bab7a0..2e0ab2e9b 100644 --- a/src/citra_qt/configuration/configure_web.h +++ b/src/citra_qt/configuration/configure_web.h @@ -22,6 +22,7 @@ public: void applyConfiguration(); void retranslateUi(); void setConfiguration(); + void SetWebServiceConfigEnabled(bool enabled); private: void RefreshTelemetryID(); diff --git a/src/citra_qt/configuration/configure_web.ui b/src/citra_qt/configuration/configure_web.ui index a8aeda9ad..ab3559157 100644 --- a/src/citra_qt/configuration/configure_web.ui +++ b/src/citra_qt/configuration/configure_web.ui @@ -118,6 +118,16 @@ + + + + Web Service configuration can only be changed when a public room isn't being hosted. + + + true + + + diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index 4ab491f04..dad0a3cdb 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp @@ -421,6 +421,8 @@ void GameList::DonePopulating(QStringList watch_list) { if (childrenTotal > 0) { search_field->setFocus(); } + + emit PopulatingCompleted(); } void GameList::PopupContextMenu(const QPoint& menu_location) { diff --git a/src/citra_qt/game_list.h b/src/citra_qt/game_list.h index a10d7fe15..ccf695fa5 100644 --- a/src/citra_qt/game_list.h +++ b/src/citra_qt/game_list.h @@ -76,6 +76,7 @@ signals: void OpenDirectory(QString directory); void AddDirectory(); void ShowList(bool show); + void PopulatingCompleted(); private slots: void onItemExpanded(const QModelIndex& item); diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index bcff0b9fc..055627d47 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -506,6 +506,8 @@ void GMainWindow::ConnectWidgetEvents() { connect(game_list_placeholder, &GameListPlaceholder::AddDirectory, this, &GMainWindow::OnGameListAddDirectory); connect(game_list, &GameList::ShowList, this, &GMainWindow::OnGameListShowList); + connect(game_list, &GameList::PopulatingCompleted, + [this] { multiplayer_state->UpdateGameList(game_list->GetModel()); }); connect(this, &GMainWindow::EmulationStarting, render_window, &GRenderWindow::OnEmulationStarting); @@ -1335,7 +1337,8 @@ void GMainWindow::OnCheats() { } void GMainWindow::OnConfigure() { - ConfigureDialog configureDialog(this, hotkey_registry); + ConfigureDialog configureDialog(this, hotkey_registry, + !multiplayer_state->IsHostingPublicRoom()); connect(&configureDialog, &ConfigureDialog::languageChanged, this, &GMainWindow::OnLanguageChanged); auto old_theme = UISettings::values.theme; @@ -1350,6 +1353,8 @@ void GMainWindow::OnConfigure() { UpdateUITheme(); if (UISettings::values.enable_discord_presence != old_discord_presence) SetDiscordEnabled(UISettings::values.enable_discord_presence); + if (!multiplayer_state->IsHostingPublicRoom()) + multiplayer_state->UpdateCredentials(); emit UpdateThemedIcons(); SyncMenuUISettings(); game_list->RefreshGameDirectory(); diff --git a/src/citra_qt/multiplayer/host_room.cpp b/src/citra_qt/multiplayer/host_room.cpp index 2dbc74d6c..05e696a93 100644 --- a/src/citra_qt/multiplayer/host_room.cpp +++ b/src/citra_qt/multiplayer/host_room.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -40,13 +41,7 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, // Create a proxy to the game list to display the list of preferred games game_list = new QStandardItemModel; - - for (int i = 0; i < list->rowCount(); i++) { - auto parent = list->item(i, 0); - for (int j = 0; j < parent->rowCount(); j++) { - game_list->appendRow(parent->child(j)->clone()); - } - } + UpdateGameList(list); proxy = new ComboBoxProxyModel; proxy->setSourceModel(game_list); @@ -78,6 +73,16 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, HostRoomWindow::~HostRoomWindow() = default; +void HostRoomWindow::UpdateGameList(QStandardItemModel* list) { + game_list->clear(); + for (int i = 0; i < list->rowCount(); i++) { + auto parent = list->item(i, 0); + for (int j = 0; j < parent->rowCount(); j++) { + game_list->appendRow(parent->child(j)->clone()); + } + } +} + void HostRoomWindow::RetranslateUi() { ui->retranslateUi(this); } @@ -110,6 +115,10 @@ void HostRoomWindow::Host() { NetworkMessage::ShowError(NetworkMessage::PORT_NOT_VALID); return; } + if (ui->game_list->currentIndex() == -1) { + NetworkMessage::ShowError(NetworkMessage::GAME_NOT_SELECTED); + return; + } if (auto member = Network::GetRoomMember().lock()) { if (member->GetState() == Network::RoomMember::State::Joining) { return; @@ -148,7 +157,22 @@ void HostRoomWindow::Host() { if (is_public) { if (auto session = announce_multiplayer_session.lock()) { // Register the room first to ensure verify_UID is present when we connect - session->Register(); + Common::WebResult result = session->Register(); + if (result.result_code != Common::WebResult::Code::Success) { + QMessageBox::warning( + this, tr("Error"), + tr("Failed to announce the room to the public lobby. In order to host a " + "room publicly, you must have a valid Citra account configured in " + "Emulation -> Configure -> Web. If you do not want to publish a room in " + "the public lobby, then select Unlisted instead.\nDebug Message: ") + + QString::fromStdString(result.result_string), + QMessageBox::Ok); + ui->host->setEnabled(true); + if (auto room = Network::GetRoom().lock()) { + room->Destroy(); + } + return; + } session->Start(); } else { LOG_ERROR(Network, "Starting announce session failed"); diff --git a/src/citra_qt/multiplayer/host_room.h b/src/citra_qt/multiplayer/host_room.h index 620574bd6..247028383 100644 --- a/src/citra_qt/multiplayer/host_room.h +++ b/src/citra_qt/multiplayer/host_room.h @@ -38,6 +38,11 @@ public: std::shared_ptr session); ~HostRoomWindow(); + /** + * Updates the dialog with a new game list model. + * This model should be the original model of the game list. + */ + void UpdateGameList(QStandardItemModel* list); void RetranslateUi(); private: diff --git a/src/citra_qt/multiplayer/lobby.cpp b/src/citra_qt/multiplayer/lobby.cpp index 3b48b3a95..c06738565 100644 --- a/src/citra_qt/multiplayer/lobby.cpp +++ b/src/citra_qt/multiplayer/lobby.cpp @@ -35,13 +35,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, // Create a proxy to the game list to get the list of games owned game_list = new QStandardItemModel; - - for (int i = 0; i < list->rowCount(); i++) { - auto parent = list->item(i, 0); - for (int j = 0; j < parent->rowCount(); j++) { - game_list->appendRow(parent->child(j)->clone()); - } - } + UpdateGameList(list); proxy = new LobbyFilterProxyModel(this, game_list); proxy->setSourceModel(model); @@ -88,6 +82,18 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, RefreshLobby(); } +void Lobby::UpdateGameList(QStandardItemModel* list) { + game_list->clear(); + for (int i = 0; i < list->rowCount(); i++) { + auto parent = list->item(i, 0); + for (int j = 0; j < parent->rowCount(); j++) { + game_list->appendRow(parent->child(j)->clone()); + } + } + if (proxy) + proxy->UpdateGameList(game_list); +} + void Lobby::RetranslateUi() { ui->retranslateUi(this); } @@ -260,6 +266,10 @@ void Lobby::OnRefreshLobby() { LobbyFilterProxyModel::LobbyFilterProxyModel(QWidget* parent, QStandardItemModel* list) : QSortFilterProxyModel(parent), game_list(list) {} +void LobbyFilterProxyModel::UpdateGameList(QStandardItemModel* list) { + game_list = list; +} + bool LobbyFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { // Prioritize filters by fastest to compute diff --git a/src/citra_qt/multiplayer/lobby.h b/src/citra_qt/multiplayer/lobby.h index 9d77b73b6..0b1d85b53 100644 --- a/src/citra_qt/multiplayer/lobby.h +++ b/src/citra_qt/multiplayer/lobby.h @@ -30,6 +30,11 @@ public: std::shared_ptr session); ~Lobby() = default; + /** + * Updates the lobby with a new game list model. + * This model should be the original model of the game list. + */ + void UpdateGameList(QStandardItemModel* list); void RetranslateUi(); public slots: @@ -76,9 +81,9 @@ private: */ QString PasswordPrompt(); - QStandardItemModel* model; - QStandardItemModel* game_list; - LobbyFilterProxyModel* proxy; + QStandardItemModel* model{}; + QStandardItemModel* game_list{}; + LobbyFilterProxyModel* proxy{}; QFutureWatcher room_list_watcher; std::weak_ptr announce_multiplayer_session; @@ -95,6 +100,13 @@ class LobbyFilterProxyModel : public QSortFilterProxyModel { public: explicit LobbyFilterProxyModel(QWidget* parent, QStandardItemModel* list); + + /** + * Updates the filter with a new game list model. + * This model should be the processed one created by the Lobby. + */ + void UpdateGameList(QStandardItemModel* list); + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; void sort(int column, Qt::SortOrder order) override; diff --git a/src/citra_qt/multiplayer/message.cpp b/src/citra_qt/multiplayer/message.cpp index 36e465acb..28d692c1e 100644 --- a/src/citra_qt/multiplayer/message.cpp +++ b/src/citra_qt/multiplayer/message.cpp @@ -16,6 +16,9 @@ const ConnectionError USERNAME_NOT_VALID_SERVER( QT_TR_NOOP("Username is already in use or not valid. Please choose another.")); const ConnectionError IP_ADDRESS_NOT_VALID(QT_TR_NOOP("IP is not a valid IPv4 address.")); const ConnectionError PORT_NOT_VALID(QT_TR_NOOP("Port must be a number between 0 to 65535.")); +const ConnectionError GAME_NOT_SELECTED(QT_TR_NOOP( + "You must choose a Preferred Game to host a room. If you do not have any games in your game " + "list yet, add a game folder by clicking on the plus icon in the game list.")); const ConnectionError NO_INTERNET( QT_TR_NOOP("Unable to find an internet connection. Check your internet settings.")); const ConnectionError UNABLE_TO_CONNECT( diff --git a/src/citra_qt/multiplayer/message.h b/src/citra_qt/multiplayer/message.h index 955b90847..7b1caa5fd 100644 --- a/src/citra_qt/multiplayer/message.h +++ b/src/citra_qt/multiplayer/message.h @@ -27,6 +27,7 @@ extern const ConnectionError ROOMNAME_NOT_VALID; extern const ConnectionError USERNAME_NOT_VALID_SERVER; extern const ConnectionError IP_ADDRESS_NOT_VALID; extern const ConnectionError PORT_NOT_VALID; +extern const ConnectionError GAME_NOT_SELECTED; extern const ConnectionError NO_INTERNET; extern const ConnectionError UNABLE_TO_CONNECT; extern const ConnectionError ROOM_IS_FULL; diff --git a/src/citra_qt/multiplayer/state.cpp b/src/citra_qt/multiplayer/state.cpp index 121d76b90..4daafd3a0 100644 --- a/src/citra_qt/multiplayer/state.cpp +++ b/src/citra_qt/multiplayer/state.cpp @@ -174,14 +174,11 @@ void MultiplayerState::OnNetworkError(const Network::RoomMember::Error& error) { void MultiplayerState::OnAnnounceFailed(const Common::WebResult& result) { announce_multiplayer_session->Stop(); - QMessageBox::warning( - this, tr("Error"), - tr("Failed to announce the room to the public lobby. In order to host a room publicly, you " - "must have a valid Citra account configured in Emulation -> Configure -> Web. If you do " - "not want to publish a room in the public lobby, then select Unlisted instead.\n" - "Debug Message: ") + - QString::fromStdString(result.result_string), - QMessageBox::Ok); + QMessageBox::warning(this, tr("Error"), + tr("Failed to update the room information. Please check your Internet " + "connection and try hosting the room again.\nDebug Message: ") + + QString::fromStdString(result.result_string), + QMessageBox::Ok); } void MultiplayerState::UpdateThemedIcons() { @@ -281,3 +278,21 @@ void MultiplayerState::OnDirectConnectToRoom() { } BringWidgetToFront(direct_connect); } + +bool MultiplayerState::IsHostingPublicRoom() const { + return announce_multiplayer_session->IsRunning(); +} + +void MultiplayerState::UpdateCredentials() { + announce_multiplayer_session->UpdateCredentials(); +} + +void MultiplayerState::UpdateGameList(QStandardItemModel* game_list) { + game_list_model = game_list; + if (lobby) { + lobby->UpdateGameList(game_list); + } + if (host_room) { + host_room->UpdateGameList(game_list); + } +} diff --git a/src/citra_qt/multiplayer/state.h b/src/citra_qt/multiplayer/state.h index 8061d18cf..707efd5a4 100644 --- a/src/citra_qt/multiplayer/state.h +++ b/src/citra_qt/multiplayer/state.h @@ -38,6 +38,20 @@ public: void retranslateUi(); + /** + * Whether a public room is being hosted or not. + * When this is true, Web Services configuration should be disabled. + */ + bool IsHostingPublicRoom() const; + + void UpdateCredentials(); + + /** + * Updates the multiplayer dialogs with a new game list model. + * This model should be the original model of the game list. + */ + void UpdateGameList(QStandardItemModel* game_list); + public slots: void OnNetworkStateChanged(const Network::RoomMember::State& state); void OnNetworkError(const Network::RoomMember::Error& error); diff --git a/src/common/announce_multiplayer_room.h b/src/common/announce_multiplayer_room.h index f0cf79386..b6e94b7a2 100644 --- a/src/common/announce_multiplayer_room.h +++ b/src/common/announce_multiplayer_room.h @@ -83,9 +83,10 @@ public: /** * Registers the data in the announce service - * @result A global Guid of the room which may be used for verification + * @result The result of the register attempt. When the result code is Success, A global Guid of + * the room which may be used for verification will be in the result's returned_data. */ - virtual std::string Register() = 0; + virtual Common::WebResult Register() = 0; /** * Empties the stored players @@ -121,8 +122,8 @@ public: Common::WebResult Update() override { return Common::WebResult{Common::WebResult::Code::NoWebservice, "WebService is missing"}; } - std::string Register() override { - return ""; + Common::WebResult Register() override { + return Common::WebResult{Common::WebResult::Code::NoWebservice, "WebService is missing"}; } void ClearPlayers() override {} RoomList GetRoomList() override { diff --git a/src/core/announce_multiplayer_session.cpp b/src/core/announce_multiplayer_session.cpp index afe522c25..d46c8db56 100644 --- a/src/core/announce_multiplayer_session.cpp +++ b/src/core/announce_multiplayer_session.cpp @@ -29,19 +29,23 @@ AnnounceMultiplayerSession::AnnounceMultiplayerSession() { #endif } -void AnnounceMultiplayerSession::Register() { +Common::WebResult AnnounceMultiplayerSession::Register() { std::shared_ptr room = Network::GetRoom().lock(); if (!room) { - return; + return Common::WebResult{Common::WebResult::Code::LibError, "Network is not initialized"}; } if (room->GetState() != Network::Room::State::Open) { - return; + return Common::WebResult{Common::WebResult::Code::LibError, "Room is not open"}; } UpdateBackendData(room); - std::string result = backend->Register(); + Common::WebResult result = backend->Register(); + if (result.result_code != Common::WebResult::Code::Success) { + return result; + } LOG_INFO(WebService, "Room has been registered"); - room->SetVerifyUID(result); + room->SetVerifyUID(result.returned_data); registered = true; + return Common::WebResult{Common::WebResult::Code::Success}; } void AnnounceMultiplayerSession::Start() { @@ -95,9 +99,22 @@ void AnnounceMultiplayerSession::UpdateBackendData(std::shared_ptr lock(callback_mutex); + for (auto callback : error_callbacks) { + (*callback)(result); + } + }; + if (!registered) { - Register(); + Common::WebResult result = Register(); + if (result.result_code != Common::WebResult::Code::Success) { + ErrorCallback(result); + return; + } } + auto update_time = std::chrono::steady_clock::now(); std::future future; while (!shutdown_event.WaitUntil(update_time)) { @@ -112,15 +129,15 @@ void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { UpdateBackendData(room); Common::WebResult result = backend->Update(); if (result.result_code != Common::WebResult::Code::Success) { - std::lock_guard lock(callback_mutex); - for (auto callback : error_callbacks) { - (*callback)(result); - } + ErrorCallback(result); } if (result.result_string == "404") { registered = false; // Needs to register the room again - Register(); + Common::WebResult result = Register(); + if (result.result_code != Common::WebResult::Code::Success) { + ErrorCallback(result); + } } } } @@ -129,4 +146,18 @@ AnnounceMultiplayerRoom::RoomList AnnounceMultiplayerSession::GetRoomList() { return backend->GetRoomList(); } +bool AnnounceMultiplayerSession::IsRunning() const { + return announce_multiplayer_thread != nullptr; +} + +void AnnounceMultiplayerSession::UpdateCredentials() { + ASSERT_MSG(!IsRunning(), "Credentials can only be updated when session is not running"); + +#ifdef ENABLE_WEB_SERVICE + backend = std::make_unique(Settings::values.web_api_url, + Settings::values.citra_username, + Settings::values.citra_token); +#endif +} + } // namespace Core diff --git a/src/core/announce_multiplayer_session.h b/src/core/announce_multiplayer_session.h index 79b30fb24..5647972d0 100644 --- a/src/core/announce_multiplayer_session.h +++ b/src/core/announce_multiplayer_session.h @@ -44,8 +44,11 @@ public: */ void UnbindErrorCallback(CallbackHandle handle); - /// Registers a room to web services - void Register(); + /** + * Registers a room to web services + * @return The result of the registration attempt. + */ + Common::WebResult Register(); /** * Starts the announce of a room to web services @@ -64,6 +67,17 @@ public: */ AnnounceMultiplayerRoom::RoomList GetRoomList(); + /** + * Whether the announce session is still running + */ + bool IsRunning() const; + + /** + * Recreates the backend, updating the credentials. + * This can only be used when the announce session is not running. + */ + void UpdateCredentials(); + private: Common::Event shutdown_event; std::mutex callback_mutex; diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 8f9073dde..3e287f76d 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -92,13 +92,6 @@ bool VerifyLogin(const std::string& username, const std::string& token) { } TelemetrySession::TelemetrySession() { -#ifdef ENABLE_WEB_SERVICE - backend = std::make_unique(Settings::values.web_api_url, - Settings::values.citra_username, - Settings::values.citra_token); -#else - backend = std::make_unique(); -#endif // Log one-time top-level information AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); @@ -192,9 +185,15 @@ TelemetrySession::~TelemetrySession() { .count()}; AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time); +#ifdef ENABLE_WEB_SERVICE + auto backend = std::make_unique(Settings::values.web_api_url, + Settings::values.citra_username, + Settings::values.citra_token); +#else + auto backend = std::make_unique(); +#endif + // Complete the session, submitting to web service if necessary - // This is just a placeholder to wrap up the session once the core completes and this is - // destroyed. This will be moved elsewhere once we are actually doing real I/O with the service. field_collection.Accept(*backend); if (Settings::values.enable_telemetry) backend->Complete(); @@ -203,6 +202,9 @@ TelemetrySession::~TelemetrySession() { bool TelemetrySession::SubmitTestcase() { #ifdef ENABLE_WEB_SERVICE + auto backend = std::make_unique(Settings::values.web_api_url, + Settings::values.citra_username, + Settings::values.citra_token); field_collection.Accept(*backend); return backend->SubmitTestcase(); #else diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index 12bb04c43..b3637e723 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h @@ -39,7 +39,6 @@ public: private: Telemetry::FieldCollection field_collection; ///< Tracks all added fields for the session - std::unique_ptr backend; ///< Backend interface that logs fields }; /** diff --git a/src/web_service/announce_room_json.cpp b/src/web_service/announce_room_json.cpp index 2d2601256..44d0b0578 100644 --- a/src/web_service/announce_room_json.cpp +++ b/src/web_service/announce_room_json.cpp @@ -117,16 +117,16 @@ Common::WebResult RoomJson::Update() { return client.PostJson(fmt::format("/lobby/{}", room_id), json.dump(), false); } -std::string RoomJson::Register() { +Common::WebResult RoomJson::Register() { nlohmann::json json = room; - auto reply = client.PostJson("/lobby", json.dump(), false).returned_data; - if (reply.empty()) { - return ""; + auto result = client.PostJson("/lobby", json.dump(), false); + if (result.result_code != Common::WebResult::Code::Success) { + return result; } - auto reply_json = nlohmann::json::parse(reply); + auto reply_json = nlohmann::json::parse(result.returned_data); room = reply_json.get(); room_id = reply_json.at("id").get(); - return room.verify_UID; + return Common::WebResult{Common::WebResult::Code::Success, "", room.verify_UID}; } void RoomJson::ClearPlayers() { diff --git a/src/web_service/announce_room_json.h b/src/web_service/announce_room_json.h index 16d630863..b87af60eb 100644 --- a/src/web_service/announce_room_json.h +++ b/src/web_service/announce_room_json.h @@ -29,7 +29,7 @@ public: const AnnounceMultiplayerRoom::MacAddress& mac_address, const u64 game_id, const std::string& game_name) override; Common::WebResult Update() override; - std::string Register() override; + Common::WebResult Register() override; void ClearPlayers() override; AnnounceMultiplayerRoom::RoomList GetRoomList() override; void Delete() override;