yuzu: Multiple room UI improvements
This commit is contained in:
parent
f5e635adda
commit
8f207bd93d
|
@ -35,7 +35,8 @@ namespace Service::HID {
|
||||||
|
|
||||||
// Updating period for each HID device.
|
// Updating period for each HID device.
|
||||||
// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
|
// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
|
||||||
constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz)
|
// Correct pad_update_ns is 4ms this is overclocked to lower input lag
|
||||||
|
constexpr auto pad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
|
||||||
constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
|
constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
|
||||||
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
|
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
|
||||||
|
|
||||||
|
|
|
@ -206,4 +206,14 @@ std::optional<NetworkInterface> GetSelectedNetworkInterface() {
|
||||||
return *res;
|
return *res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SelectFirstNetworkInterface() {
|
||||||
|
const auto network_interfaces = Network::GetAvailableNetworkInterfaces();
|
||||||
|
|
||||||
|
if (network_interfaces.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::values.network_interface.SetValue(network_interfaces[0].name);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Network
|
} // namespace Network
|
||||||
|
|
|
@ -24,5 +24,6 @@ struct NetworkInterface {
|
||||||
|
|
||||||
std::vector<NetworkInterface> GetAvailableNetworkInterfaces();
|
std::vector<NetworkInterface> GetAvailableNetworkInterfaces();
|
||||||
std::optional<NetworkInterface> GetSelectedNetworkInterface();
|
std::optional<NetworkInterface> GetSelectedNetworkInterface();
|
||||||
|
void SelectFirstNetworkInterface();
|
||||||
|
|
||||||
} // namespace Network
|
} // namespace Network
|
||||||
|
|
|
@ -1296,6 +1296,7 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
&MultiplayerState::OnDirectConnectToRoom);
|
&MultiplayerState::OnDirectConnectToRoom);
|
||||||
connect(ui->action_Show_Room, &QAction::triggered, multiplayer_state,
|
connect(ui->action_Show_Room, &QAction::triggered, multiplayer_state,
|
||||||
&MultiplayerState::OnOpenNetworkRoom);
|
&MultiplayerState::OnOpenNetworkRoom);
|
||||||
|
connect(multiplayer_state, &MultiplayerState::SaveConfig, this, &GMainWindow::OnSaveConfig);
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this,
|
connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this,
|
||||||
|
@ -1336,6 +1337,8 @@ void GMainWindow::UpdateMenuState() {
|
||||||
} else {
|
} else {
|
||||||
ui->action_Pause->setText(tr("&Pause"));
|
ui->action_Pause->setText(tr("&Pause"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multiplayer_state->UpdateNotificationStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnDisplayTitleBars(bool show) {
|
void GMainWindow::OnDisplayTitleBars(bool show) {
|
||||||
|
@ -2766,6 +2769,11 @@ void GMainWindow::OnExit() {
|
||||||
OnStopGame();
|
OnStopGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnSaveConfig() {
|
||||||
|
system->ApplySettings();
|
||||||
|
config->Save();
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
|
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
|
||||||
OverlayDialog dialog(render_window, *system, error_code, error_text, QString{}, tr("OK"),
|
OverlayDialog dialog(render_window, *system, error_code, error_text, QString{}, tr("OK"),
|
||||||
Qt::AlignLeft | Qt::AlignVCenter);
|
Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
|
|
@ -169,6 +169,7 @@ public slots:
|
||||||
void OnLoadComplete();
|
void OnLoadComplete();
|
||||||
void OnExecuteProgram(std::size_t program_index);
|
void OnExecuteProgram(std::size_t program_index);
|
||||||
void OnExit();
|
void OnExit();
|
||||||
|
void OnSaveConfig();
|
||||||
void ControllerSelectorReconfigureControllers(
|
void ControllerSelectorReconfigureControllers(
|
||||||
const Core::Frontend::ControllerParameters& parameters);
|
const Core::Frontend::ControllerParameters& parameters);
|
||||||
void SoftwareKeyboardInitialize(
|
void SoftwareKeyboardInitialize(
|
||||||
|
|
|
@ -265,7 +265,7 @@
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Browse Public Game Lobby</string>
|
<string>&Browse Public Game Lobby</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Start_Room">
|
<action name="action_Start_Room">
|
||||||
|
@ -273,7 +273,7 @@
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Create Room</string>
|
<string>&Create Room</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Leave_Room">
|
<action name="action_Leave_Room">
|
||||||
|
@ -281,12 +281,12 @@
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Leave Room</string>
|
<string>&Leave Room</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Connect_To_Room">
|
<action name="action_Connect_To_Room">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Direct Connect to Room</string>
|
<string>&Direct Connect to Room</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Show_Room">
|
<action name="action_Show_Room">
|
||||||
|
@ -294,7 +294,7 @@
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Current Room</string>
|
<string>&Show Current Room</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Fullscreen">
|
<action name="action_Fullscreen">
|
||||||
|
|
|
@ -97,8 +97,9 @@ void ClientRoomWindow::UpdateView() {
|
||||||
auto memberlist = member->GetMemberInformation();
|
auto memberlist = member->GetMemberInformation();
|
||||||
ui->chat->SetPlayerList(memberlist);
|
ui->chat->SetPlayerList(memberlist);
|
||||||
const auto information = member->GetRoomInformation();
|
const auto information = member->GetRoomInformation();
|
||||||
setWindowTitle(QString(tr("%1 (%2/%3 members) - connected"))
|
setWindowTitle(QString(tr("%1 - %2 (%3/%4 members) - connected"))
|
||||||
.arg(QString::fromStdString(information.name))
|
.arg(QString::fromStdString(information.name))
|
||||||
|
.arg(QString::fromStdString(information.preferred_game.name))
|
||||||
.arg(memberlist.size())
|
.arg(memberlist.size())
|
||||||
.arg(information.member_slots));
|
.arg(information.member_slots));
|
||||||
ui->description->setText(QString::fromStdString(information.description));
|
ui->description->setText(QString::fromStdString(information.description));
|
||||||
|
|
|
@ -106,6 +106,8 @@ void DirectConnectWindow::Connect() {
|
||||||
UISettings::values.multiplayer_port = UISettings::values.multiplayer_port.GetDefault();
|
UISettings::values.multiplayer_port = UISettings::values.multiplayer_port.GetDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit SaveConfig();
|
||||||
|
|
||||||
// attempt to connect in a different thread
|
// attempt to connect in a different thread
|
||||||
QFuture<void> f = QtConcurrent::run([&] {
|
QFuture<void> f = QtConcurrent::run([&] {
|
||||||
if (auto room_member = room_network.GetRoomMember().lock()) {
|
if (auto room_member = room_network.GetRoomMember().lock()) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ signals:
|
||||||
* connections that it might have.
|
* connections that it might have.
|
||||||
*/
|
*/
|
||||||
void Closed();
|
void Closed();
|
||||||
|
void SaveConfig();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void OnConnection();
|
void OnConnection();
|
||||||
|
|
|
@ -232,6 +232,7 @@ void HostRoomWindow::Host() {
|
||||||
}
|
}
|
||||||
UISettings::values.multiplayer_room_description = ui->room_description->toPlainText();
|
UISettings::values.multiplayer_room_description = ui->room_description->toPlainText();
|
||||||
ui->host->setEnabled(true);
|
ui->host->setEnabled(true);
|
||||||
|
emit SaveConfig();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,9 @@ public:
|
||||||
void UpdateGameList(QStandardItemModel* list);
|
void UpdateGameList(QStandardItemModel* list);
|
||||||
void RetranslateUi();
|
void RetranslateUi();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void SaveConfig();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Host();
|
void Host();
|
||||||
std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const;
|
std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/internal_network/network_interface.h"
|
#include "core/internal_network/network_interface.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
#include "ui_lobby.h"
|
#include "ui_lobby.h"
|
||||||
|
@ -26,9 +27,9 @@
|
||||||
Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_)
|
std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_)
|
||||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
||||||
ui(std::make_unique<Ui::Lobby>()),
|
ui(std::make_unique<Ui::Lobby>()), announce_multiplayer_session(session),
|
||||||
announce_multiplayer_session(session), system{system_}, room_network{
|
profile_manager(std::make_unique<Service::Account::ProfileManager>()), system{system_},
|
||||||
system.GetRoomNetwork()} {
|
room_network{system.GetRoomNetwork()} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// setup the watcher for background connections
|
// setup the watcher for background connections
|
||||||
|
@ -60,9 +61,17 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
|
|
||||||
ui->nickname->setValidator(validation.GetNickname());
|
ui->nickname->setValidator(validation.GetNickname());
|
||||||
ui->nickname->setText(UISettings::values.multiplayer_nickname.GetValue());
|
ui->nickname->setText(UISettings::values.multiplayer_nickname.GetValue());
|
||||||
if (ui->nickname->text().isEmpty() && !Settings::values.yuzu_username.GetValue().empty()) {
|
|
||||||
// Use yuzu Web Service user name as nickname by default
|
// Try find the best nickname by default
|
||||||
ui->nickname->setText(QString::fromStdString(Settings::values.yuzu_username.GetValue()));
|
if (ui->nickname->text().isEmpty() || ui->nickname->text() == QStringLiteral("yuzu")) {
|
||||||
|
if (!Settings::values.yuzu_username.GetValue().empty()) {
|
||||||
|
ui->nickname->setText(
|
||||||
|
QString::fromStdString(Settings::values.yuzu_username.GetValue()));
|
||||||
|
} else if (!GetProfileUsername().empty()) {
|
||||||
|
ui->nickname->setText(QString::fromStdString(GetProfileUsername()));
|
||||||
|
} else {
|
||||||
|
ui->nickname->setText(QStringLiteral("yuzu"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI Buttons
|
// UI Buttons
|
||||||
|
@ -76,12 +85,6 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
||||||
// Actions
|
// Actions
|
||||||
connect(&room_list_watcher, &QFutureWatcher<AnnounceMultiplayerRoom::RoomList>::finished, this,
|
connect(&room_list_watcher, &QFutureWatcher<AnnounceMultiplayerRoom::RoomList>::finished, this,
|
||||||
&Lobby::OnRefreshLobby);
|
&Lobby::OnRefreshLobby);
|
||||||
|
|
||||||
// manually start a refresh when the window is opening
|
|
||||||
// TODO(jroweboy): if this refresh is slow for people with bad internet, then don't do it as
|
|
||||||
// part of the constructor, but offload the refresh until after the window shown. perhaps emit a
|
|
||||||
// refreshroomlist signal from places that open the lobby
|
|
||||||
RefreshLobby();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Lobby::~Lobby() = default;
|
Lobby::~Lobby() = default;
|
||||||
|
@ -96,6 +99,7 @@ void Lobby::UpdateGameList(QStandardItemModel* list) {
|
||||||
}
|
}
|
||||||
if (proxy)
|
if (proxy)
|
||||||
proxy->UpdateGameList(game_list);
|
proxy->UpdateGameList(game_list);
|
||||||
|
ui->room_list->sortByColumn(Column::GAME_NAME, Qt::AscendingOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lobby::RetranslateUi() {
|
void Lobby::RetranslateUi() {
|
||||||
|
@ -116,6 +120,11 @@ void Lobby::OnExpandRoom(const QModelIndex& index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lobby::OnJoinRoom(const QModelIndex& source) {
|
void Lobby::OnJoinRoom(const QModelIndex& source) {
|
||||||
|
if (!Network::GetSelectedNetworkInterface()) {
|
||||||
|
LOG_INFO(WebService, "Automatically selected network interface for room network.");
|
||||||
|
Network::SelectFirstNetworkInterface();
|
||||||
|
}
|
||||||
|
|
||||||
if (!Network::GetSelectedNetworkInterface()) {
|
if (!Network::GetSelectedNetworkInterface()) {
|
||||||
NetworkMessage::ErrorManager::ShowError(
|
NetworkMessage::ErrorManager::ShowError(
|
||||||
NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED);
|
NetworkMessage::ErrorManager::NO_INTERFACE_SELECTED);
|
||||||
|
@ -197,16 +206,16 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
|
||||||
proxy->data(connection_index, LobbyItemHost::HostIPRole).toString();
|
proxy->data(connection_index, LobbyItemHost::HostIPRole).toString();
|
||||||
UISettings::values.multiplayer_port =
|
UISettings::values.multiplayer_port =
|
||||||
proxy->data(connection_index, LobbyItemHost::HostPortRole).toInt();
|
proxy->data(connection_index, LobbyItemHost::HostPortRole).toInt();
|
||||||
|
emit SaveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lobby::ResetModel() {
|
void Lobby::ResetModel() {
|
||||||
model->clear();
|
model->clear();
|
||||||
model->insertColumns(0, Column::TOTAL);
|
model->insertColumns(0, Column::TOTAL);
|
||||||
model->setHeaderData(Column::EXPAND, Qt::Horizontal, QString(), Qt::DisplayRole);
|
model->setHeaderData(Column::MEMBER, Qt::Horizontal, tr("Players"), Qt::DisplayRole);
|
||||||
model->setHeaderData(Column::ROOM_NAME, Qt::Horizontal, tr("Room Name"), Qt::DisplayRole);
|
model->setHeaderData(Column::ROOM_NAME, Qt::Horizontal, tr("Room Name"), Qt::DisplayRole);
|
||||||
model->setHeaderData(Column::GAME_NAME, Qt::Horizontal, tr("Preferred Game"), Qt::DisplayRole);
|
model->setHeaderData(Column::GAME_NAME, Qt::Horizontal, tr("Preferred Game"), Qt::DisplayRole);
|
||||||
model->setHeaderData(Column::HOST, Qt::Horizontal, tr("Host"), Qt::DisplayRole);
|
model->setHeaderData(Column::HOST, Qt::Horizontal, tr("Host"), Qt::DisplayRole);
|
||||||
model->setHeaderData(Column::MEMBER, Qt::Horizontal, tr("Players"), Qt::DisplayRole);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lobby::RefreshLobby() {
|
void Lobby::RefreshLobby() {
|
||||||
|
@ -229,6 +238,7 @@ void Lobby::OnRefreshLobby() {
|
||||||
for (int r = 0; r < game_list->rowCount(); ++r) {
|
for (int r = 0; r < game_list->rowCount(); ++r) {
|
||||||
auto index = game_list->index(r, 0);
|
auto index = game_list->index(r, 0);
|
||||||
auto game_id = game_list->data(index, GameListItemPath::ProgramIdRole).toULongLong();
|
auto game_id = game_list->data(index, GameListItemPath::ProgramIdRole).toULongLong();
|
||||||
|
|
||||||
if (game_id != 0 && room.information.preferred_game.id == game_id) {
|
if (game_id != 0 && room.information.preferred_game.id == game_id) {
|
||||||
smdh_icon = game_list->data(index, Qt::DecorationRole).value<QPixmap>();
|
smdh_icon = game_list->data(index, Qt::DecorationRole).value<QPixmap>();
|
||||||
}
|
}
|
||||||
|
@ -243,17 +253,16 @@ void Lobby::OnRefreshLobby() {
|
||||||
members.append(var);
|
members.append(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto first_item = new LobbyItem();
|
auto first_item = new LobbyItemGame(
|
||||||
|
room.information.preferred_game.id,
|
||||||
|
QString::fromStdString(room.information.preferred_game.name), smdh_icon);
|
||||||
auto row = QList<QStandardItem*>({
|
auto row = QList<QStandardItem*>({
|
||||||
first_item,
|
first_item,
|
||||||
new LobbyItemName(room.has_password, QString::fromStdString(room.information.name)),
|
new LobbyItemName(room.has_password, QString::fromStdString(room.information.name)),
|
||||||
new LobbyItemGame(room.information.preferred_game.id,
|
new LobbyItemMemberList(members, room.information.member_slots),
|
||||||
QString::fromStdString(room.information.preferred_game.name),
|
|
||||||
smdh_icon),
|
|
||||||
new LobbyItemHost(QString::fromStdString(room.information.host_username),
|
new LobbyItemHost(QString::fromStdString(room.information.host_username),
|
||||||
QString::fromStdString(room.ip), room.information.port,
|
QString::fromStdString(room.ip), room.information.port,
|
||||||
QString::fromStdString(room.verify_uid)),
|
QString::fromStdString(room.verify_uid)),
|
||||||
new LobbyItemMemberList(members, room.information.member_slots),
|
|
||||||
});
|
});
|
||||||
model->appendRow(row);
|
model->appendRow(row);
|
||||||
// To make the rows expandable, add the member data as a child of the first column of the
|
// To make the rows expandable, add the member data as a child of the first column of the
|
||||||
|
@ -283,6 +292,26 @@ void Lobby::OnRefreshLobby() {
|
||||||
ui->room_list->setFirstColumnSpanned(j, proxy->index(i, 0), true);
|
ui->room_list->setFirstColumnSpanned(j, proxy->index(i, 0), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->room_list->sortByColumn(Column::GAME_NAME, Qt::AscendingOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lobby::GetProfileUsername() {
|
||||||
|
const auto& current_user = profile_manager->GetUser(Settings::values.current_user.GetValue());
|
||||||
|
Service::Account::ProfileBase profile{};
|
||||||
|
|
||||||
|
if (!current_user.has_value()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!profile_manager->GetProfileBase(*current_user, profile)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto text = Common::StringFromFixedZeroTerminatedBuffer(
|
||||||
|
reinterpret_cast<const char*>(profile.username.data()), profile.username.size());
|
||||||
|
|
||||||
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
LobbyFilterProxyModel::LobbyFilterProxyModel(QWidget* parent, QStandardItemModel* list)
|
LobbyFilterProxyModel::LobbyFilterProxyModel(QWidget* parent, QStandardItemModel* list)
|
||||||
|
|
|
@ -24,6 +24,10 @@ namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Service::Account {
|
||||||
|
class ProfileManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listing of all public games pulled from services. The lobby should be simple enough for users to
|
* Listing of all public games pulled from services. The lobby should be simple enough for users to
|
||||||
* find the game they want to play, and join it.
|
* find the game they want to play, and join it.
|
||||||
|
@ -75,8 +79,11 @@ private slots:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void StateChanged(const Network::RoomMember::State&);
|
void StateChanged(const Network::RoomMember::State&);
|
||||||
|
void SaveConfig();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string GetProfileUsername();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all entries in the Lobby before refreshing.
|
* Removes all entries in the Lobby before refreshing.
|
||||||
*/
|
*/
|
||||||
|
@ -96,6 +103,7 @@ private:
|
||||||
|
|
||||||
QFutureWatcher<AnnounceMultiplayerRoom::RoomList> room_list_watcher;
|
QFutureWatcher<AnnounceMultiplayerRoom::RoomList> room_list_watcher;
|
||||||
std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
||||||
|
std::unique_ptr<Service::Account::ProfileManager> profile_manager;
|
||||||
QFutureWatcher<void>* watcher;
|
QFutureWatcher<void>* watcher;
|
||||||
Validation validation;
|
Validation validation;
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
|
@ -11,11 +11,10 @@
|
||||||
|
|
||||||
namespace Column {
|
namespace Column {
|
||||||
enum List {
|
enum List {
|
||||||
EXPAND,
|
|
||||||
ROOM_NAME,
|
|
||||||
GAME_NAME,
|
GAME_NAME,
|
||||||
HOST,
|
ROOM_NAME,
|
||||||
MEMBER,
|
MEMBER,
|
||||||
|
HOST,
|
||||||
TOTAL,
|
TOTAL,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -98,7 +97,12 @@ public:
|
||||||
if (role == Qt::DecorationRole) {
|
if (role == Qt::DecorationRole) {
|
||||||
auto val = data(GameIconRole);
|
auto val = data(GameIconRole);
|
||||||
if (val.isValid()) {
|
if (val.isValid()) {
|
||||||
val = val.value<QPixmap>().scaled(16, 16, Qt::KeepAspectRatio);
|
val = val.value<QPixmap>().scaled(32, 32, Qt::KeepAspectRatio,
|
||||||
|
Qt::TransformationMode::SmoothTransformation);
|
||||||
|
} else {
|
||||||
|
auto blank_image = QPixmap(32, 32);
|
||||||
|
blank_image.fill(Qt::black);
|
||||||
|
val = blank_image;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
} else if (role != Qt::DisplayRole) {
|
} else if (role != Qt::DisplayRole) {
|
||||||
|
@ -191,8 +195,8 @@ public:
|
||||||
return LobbyItem::data(role);
|
return LobbyItem::data(role);
|
||||||
}
|
}
|
||||||
auto members = data(MemberListRole).toList();
|
auto members = data(MemberListRole).toList();
|
||||||
return QStringLiteral("%1 / %2").arg(QString::number(members.size()),
|
return QStringLiteral("%1 / %2 ")
|
||||||
data(MaxPlayerRole).toString());
|
.arg(QString::number(members.size()), data(MaxPlayerRole).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const QStandardItem& other) const override {
|
bool operator<(const QStandardItem& other) const override {
|
||||||
|
|
|
@ -49,8 +49,8 @@ const ConnectionError ErrorManager::PERMISSION_DENIED(
|
||||||
QT_TR_NOOP("You do not have enough permission to perform this action."));
|
QT_TR_NOOP("You do not have enough permission to perform this action."));
|
||||||
const ConnectionError ErrorManager::NO_SUCH_USER(QT_TR_NOOP(
|
const ConnectionError ErrorManager::NO_SUCH_USER(QT_TR_NOOP(
|
||||||
"The user you are trying to kick/ban could not be found.\nThey may have left the room."));
|
"The user you are trying to kick/ban could not be found.\nThey may have left the room."));
|
||||||
const ConnectionError ErrorManager::NO_INTERFACE_SELECTED(
|
const ConnectionError ErrorManager::NO_INTERFACE_SELECTED(QT_TR_NOOP(
|
||||||
QT_TR_NOOP("No network interface is selected.\nPlease go to Configure -> System -> Network and "
|
"No valid network interface is selected.\nPlease go to Configure -> System -> Network and "
|
||||||
"make a selection."));
|
"make a selection."));
|
||||||
|
|
||||||
static bool WarnMessage(const std::string& title, const std::string& text) {
|
static bool WarnMessage(const std::string& title, const std::string& text) {
|
||||||
|
|
|
@ -44,9 +44,6 @@ MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_lis
|
||||||
|
|
||||||
status_text = new ClickableLabel(this);
|
status_text = new ClickableLabel(this);
|
||||||
status_icon = new ClickableLabel(this);
|
status_icon = new ClickableLabel(this);
|
||||||
status_text->setToolTip(tr("Current connection status"));
|
|
||||||
status_text->setText(tr("Not Connected. Click here to find a room!"));
|
|
||||||
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("disconnected")).pixmap(16));
|
|
||||||
|
|
||||||
connect(status_text, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom);
|
connect(status_text, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom);
|
||||||
connect(status_icon, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom);
|
connect(status_icon, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom);
|
||||||
|
@ -57,6 +54,8 @@ MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_lis
|
||||||
HideNotification();
|
HideNotification();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
retranslateUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiplayerState::~MultiplayerState() = default;
|
MultiplayerState::~MultiplayerState() = default;
|
||||||
|
@ -90,14 +89,7 @@ void MultiplayerState::Close() {
|
||||||
void MultiplayerState::retranslateUi() {
|
void MultiplayerState::retranslateUi() {
|
||||||
status_text->setToolTip(tr("Current connection status"));
|
status_text->setToolTip(tr("Current connection status"));
|
||||||
|
|
||||||
if (current_state == Network::RoomMember::State::Uninitialized) {
|
UpdateNotificationStatus();
|
||||||
status_text->setText(tr("Not Connected. Click here to find a room!"));
|
|
||||||
} else if (current_state == Network::RoomMember::State::Joined ||
|
|
||||||
current_state == Network::RoomMember::State::Moderator) {
|
|
||||||
status_text->setText(tr("Connected"));
|
|
||||||
} else {
|
|
||||||
status_text->setText(tr("Not Connected"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lobby) {
|
if (lobby) {
|
||||||
lobby->RetranslateUi();
|
lobby->RetranslateUi();
|
||||||
|
@ -113,21 +105,55 @@ void MultiplayerState::retranslateUi() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::SetNotificationStatus(NotificationStatus status) {
|
||||||
|
notification_status = status;
|
||||||
|
UpdateNotificationStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::UpdateNotificationStatus() {
|
||||||
|
switch (notification_status) {
|
||||||
|
case NotificationStatus::Unitialized:
|
||||||
|
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("disconnected")).pixmap(16));
|
||||||
|
status_text->setText(tr("Not Connected. Click here to find a room!"));
|
||||||
|
leave_room->setEnabled(false);
|
||||||
|
show_room->setEnabled(false);
|
||||||
|
break;
|
||||||
|
case NotificationStatus::Disconnected:
|
||||||
|
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("disconnected")).pixmap(16));
|
||||||
|
status_text->setText(tr("Not Connected"));
|
||||||
|
leave_room->setEnabled(false);
|
||||||
|
show_room->setEnabled(false);
|
||||||
|
break;
|
||||||
|
case NotificationStatus::Connected:
|
||||||
|
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("connected")).pixmap(16));
|
||||||
|
status_text->setText(tr("Connected"));
|
||||||
|
leave_room->setEnabled(true);
|
||||||
|
show_room->setEnabled(true);
|
||||||
|
break;
|
||||||
|
case NotificationStatus::Notification:
|
||||||
|
status_icon->setPixmap(
|
||||||
|
QIcon::fromTheme(QStringLiteral("connected_notification")).pixmap(16));
|
||||||
|
status_text->setText(tr("New Messages Received"));
|
||||||
|
leave_room->setEnabled(true);
|
||||||
|
show_room->setEnabled(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up status bar if game is running
|
||||||
|
if (system.IsPoweredOn()) {
|
||||||
|
status_text->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& state) {
|
void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& state) {
|
||||||
LOG_DEBUG(Frontend, "Network State: {}", Network::GetStateStr(state));
|
LOG_DEBUG(Frontend, "Network State: {}", Network::GetStateStr(state));
|
||||||
if (state == Network::RoomMember::State::Joined ||
|
if (state == Network::RoomMember::State::Joined ||
|
||||||
state == Network::RoomMember::State::Moderator) {
|
state == Network::RoomMember::State::Moderator) {
|
||||||
|
|
||||||
OnOpenNetworkRoom();
|
OnOpenNetworkRoom();
|
||||||
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("connected")).pixmap(16));
|
SetNotificationStatus(NotificationStatus::Connected);
|
||||||
status_text->setText(tr("Connected"));
|
|
||||||
leave_room->setEnabled(true);
|
|
||||||
show_room->setEnabled(true);
|
|
||||||
} else {
|
} else {
|
||||||
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("disconnected")).pixmap(16));
|
SetNotificationStatus(NotificationStatus::Disconnected);
|
||||||
status_text->setText(tr("Not Connected"));
|
|
||||||
leave_room->setEnabled(false);
|
|
||||||
show_room->setEnabled(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_state = state;
|
current_state = state;
|
||||||
|
@ -185,6 +211,10 @@ void MultiplayerState::OnAnnounceFailed(const WebService::WebResult& result) {
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiplayerState::OnSaveConfig() {
|
||||||
|
emit SaveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
void MultiplayerState::UpdateThemedIcons() {
|
void MultiplayerState::UpdateThemedIcons() {
|
||||||
if (show_notification) {
|
if (show_notification) {
|
||||||
status_icon->setPixmap(
|
status_icon->setPixmap(
|
||||||
|
@ -209,13 +239,16 @@ static void BringWidgetToFront(QWidget* widget) {
|
||||||
void MultiplayerState::OnViewLobby() {
|
void MultiplayerState::OnViewLobby() {
|
||||||
if (lobby == nullptr) {
|
if (lobby == nullptr) {
|
||||||
lobby = new Lobby(this, game_list_model, announce_multiplayer_session, system);
|
lobby = new Lobby(this, game_list_model, announce_multiplayer_session, system);
|
||||||
|
connect(lobby, &Lobby::SaveConfig, this, &MultiplayerState::OnSaveConfig);
|
||||||
}
|
}
|
||||||
|
lobby->RefreshLobby();
|
||||||
BringWidgetToFront(lobby);
|
BringWidgetToFront(lobby);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplayerState::OnCreateRoom() {
|
void MultiplayerState::OnCreateRoom() {
|
||||||
if (host_room == nullptr) {
|
if (host_room == nullptr) {
|
||||||
host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session, system);
|
host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session, system);
|
||||||
|
connect(host_room, &HostRoomWindow::SaveConfig, this, &MultiplayerState::OnSaveConfig);
|
||||||
}
|
}
|
||||||
BringWidgetToFront(host_room);
|
BringWidgetToFront(host_room);
|
||||||
}
|
}
|
||||||
|
@ -250,14 +283,12 @@ void MultiplayerState::ShowNotification() {
|
||||||
show_notification = true;
|
show_notification = true;
|
||||||
QApplication::alert(nullptr);
|
QApplication::alert(nullptr);
|
||||||
QApplication::beep();
|
QApplication::beep();
|
||||||
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("connected_notification")).pixmap(16));
|
SetNotificationStatus(NotificationStatus::Notification);
|
||||||
status_text->setText(tr("New Messages Received"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplayerState::HideNotification() {
|
void MultiplayerState::HideNotification() {
|
||||||
show_notification = false;
|
show_notification = false;
|
||||||
status_icon->setPixmap(QIcon::fromTheme(QStringLiteral("connected")).pixmap(16));
|
SetNotificationStatus(NotificationStatus::Connected);
|
||||||
status_text->setText(tr("Connected"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplayerState::OnOpenNetworkRoom() {
|
void MultiplayerState::OnOpenNetworkRoom() {
|
||||||
|
@ -280,6 +311,8 @@ void MultiplayerState::OnOpenNetworkRoom() {
|
||||||
void MultiplayerState::OnDirectConnectToRoom() {
|
void MultiplayerState::OnDirectConnectToRoom() {
|
||||||
if (direct_connect == nullptr) {
|
if (direct_connect == nullptr) {
|
||||||
direct_connect = new DirectConnectWindow(system, this);
|
direct_connect = new DirectConnectWindow(system, this);
|
||||||
|
connect(direct_connect, &DirectConnectWindow::SaveConfig, this,
|
||||||
|
&MultiplayerState::OnSaveConfig);
|
||||||
}
|
}
|
||||||
BringWidgetToFront(direct_connect);
|
BringWidgetToFront(direct_connect);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,13 @@ class MultiplayerState : public QWidget {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum class NotificationStatus {
|
||||||
|
Unitialized,
|
||||||
|
Disconnected,
|
||||||
|
Connected,
|
||||||
|
Notification,
|
||||||
|
};
|
||||||
|
|
||||||
explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room,
|
explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room,
|
||||||
QAction* show_room, Core::System& system_);
|
QAction* show_room, Core::System& system_);
|
||||||
~MultiplayerState();
|
~MultiplayerState();
|
||||||
|
@ -31,6 +38,10 @@ public:
|
||||||
*/
|
*/
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
void SetNotificationStatus(NotificationStatus state);
|
||||||
|
|
||||||
|
void UpdateNotificationStatus();
|
||||||
|
|
||||||
ClickableLabel* GetStatusText() const {
|
ClickableLabel* GetStatusText() const {
|
||||||
return status_text;
|
return status_text;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +75,7 @@ public slots:
|
||||||
void OnOpenNetworkRoom();
|
void OnOpenNetworkRoom();
|
||||||
void OnDirectConnectToRoom();
|
void OnDirectConnectToRoom();
|
||||||
void OnAnnounceFailed(const WebService::WebResult&);
|
void OnAnnounceFailed(const WebService::WebResult&);
|
||||||
|
void OnSaveConfig();
|
||||||
void UpdateThemedIcons();
|
void UpdateThemedIcons();
|
||||||
void ShowNotification();
|
void ShowNotification();
|
||||||
void HideNotification();
|
void HideNotification();
|
||||||
|
@ -72,6 +84,7 @@ signals:
|
||||||
void NetworkStateChanged(const Network::RoomMember::State&);
|
void NetworkStateChanged(const Network::RoomMember::State&);
|
||||||
void NetworkError(const Network::RoomMember::Error&);
|
void NetworkError(const Network::RoomMember::Error&);
|
||||||
void AnnounceFailed(const WebService::WebResult&);
|
void AnnounceFailed(const WebService::WebResult&);
|
||||||
|
void SaveConfig();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Lobby* lobby = nullptr;
|
Lobby* lobby = nullptr;
|
||||||
|
@ -85,6 +98,7 @@ private:
|
||||||
QAction* show_room;
|
QAction* show_room;
|
||||||
std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
|
||||||
Network::RoomMember::State current_state = Network::RoomMember::State::Uninitialized;
|
Network::RoomMember::State current_state = Network::RoomMember::State::Uninitialized;
|
||||||
|
NotificationStatus notification_status = NotificationStatus::Unitialized;
|
||||||
bool has_mod_perms = false;
|
bool has_mod_perms = false;
|
||||||
Network::RoomMember::CallbackHandle<Network::RoomMember::State> state_callback_handle;
|
Network::RoomMember::CallbackHandle<Network::RoomMember::State> state_callback_handle;
|
||||||
Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle;
|
Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle;
|
||||||
|
|
|
@ -102,7 +102,7 @@ struct Values {
|
||||||
Settings::Setting<uint32_t> callout_flags{0, "calloutFlags"};
|
Settings::Setting<uint32_t> callout_flags{0, "calloutFlags"};
|
||||||
|
|
||||||
// multiplayer settings
|
// multiplayer settings
|
||||||
Settings::Setting<QString> multiplayer_nickname{QStringLiteral("yuzu"), "nickname"};
|
Settings::Setting<QString> multiplayer_nickname{{}, "nickname"};
|
||||||
Settings::Setting<QString> multiplayer_ip{{}, "ip"};
|
Settings::Setting<QString> multiplayer_ip{{}, "ip"};
|
||||||
Settings::SwitchableSetting<uint, true> multiplayer_port{24872, 0, UINT16_MAX, "port"};
|
Settings::SwitchableSetting<uint, true> multiplayer_port{24872, 0, UINT16_MAX, "port"};
|
||||||
Settings::Setting<QString> multiplayer_room_nickname{{}, "room_nickname"};
|
Settings::Setting<QString> multiplayer_room_nickname{{}, "room_nickname"};
|
||||||
|
|
Reference in New Issue