summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorAestek <thib.gilles@gmail.com>2016-02-02 16:35:27 +0100
committerAestek <thib.gilles@gmail.com>2016-07-23 20:58:51 +0200
commit6a0fc4c438dcc827b6ed4e0a22a2e54676682ea0 (patch)
treeb44ade2f80ade233a2e82965af0717b18257e4f6 /Source/Core
parentaa34e5e20e5f66cfdbace167b98c30c1fedcf522 (diff)
Improve netplay setup dialog UX
* Focus "Hash Code" / "IP address" text box by default in "Connect" * Focus game list in "Host" tab * RETURN keypress now host/join depending on selected tab * Remember last hosted game * Remove PanicAlertT: * Simply log message to netplay window * Remove them when they are useless * Show some netplay message in OSD * Chat messages * Pad buffer changes * Desync alerts * Stop the game consistently when another player disconnects / crashes * Prettify chat textbox * Log netplay ping to OSD Join scenario: * Copy netplay code * Open netplay * Paste code * Press enter Host scenario: * Open netplay * Go to host tab * Press enter
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/TraversalClient.cpp19
-rw-r--r--Source/Core/Core/NetPlayClient.cpp61
-rw-r--r--Source/Core/Core/NetPlayClient.h6
-rw-r--r--Source/Core/Core/NetPlayServer.cpp26
-rw-r--r--Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.cpp158
-rw-r--r--Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.h14
-rw-r--r--Source/Core/DolphinWX/NetPlay/NetWindow.cpp162
-rw-r--r--Source/Core/DolphinWX/NetPlay/NetWindow.h26
-rw-r--r--Source/Core/DolphinWX/VideoConfigDiag.cpp23
-rw-r--r--Source/Core/VideoCommon/OnScreenDisplay.cpp67
-rw-r--r--Source/Core/VideoCommon/OnScreenDisplay.h42
-rw-r--r--Source/Core/VideoCommon/VideoConfig.cpp4
-rw-r--r--Source/Core/VideoCommon/VideoConfig.h2
13 files changed, 430 insertions, 180 deletions
diff --git a/Source/Core/Common/TraversalClient.cpp b/Source/Core/Common/TraversalClient.cpp
index 81d592d4c3..67b4676769 100644
--- a/Source/Core/Common/TraversalClient.cpp
+++ b/Source/Core/Common/TraversalClient.cpp
@@ -208,25 +208,6 @@ void TraversalClient::OnFailure(FailureReason reason)
m_State = Failure;
m_FailureReason = reason;
- switch (reason)
- {
- case TraversalClient::BadHost:
- PanicAlertT("Couldn't look up central server %s", m_Server.c_str());
- break;
- case TraversalClient::VersionTooOld:
- PanicAlertT("Dolphin too old for traversal server");
- break;
- case TraversalClient::ServerForgotAboutUs:
- PanicAlertT("Disconnected from traversal server");
- break;
- case TraversalClient::SocketSendError:
- PanicAlertT("Socket error sending to traversal server");
- break;
- case TraversalClient::ResendTimeout:
- PanicAlertT("Timeout connecting to traversal server");
- break;
- }
-
if (m_Client)
m_Client->OnTraversalStateChanged();
}
diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp
index 9d974d3342..19c073c020 100644
--- a/Source/Core/Core/NetPlayClient.cpp
+++ b/Source/Core/Core/NetPlayClient.cpp
@@ -27,6 +27,8 @@
#include "Core/Movie.h"
#include "Core/NetPlayClient.h"
#include "InputCommon/GCAdapter.h"
+#include "VideoCommon/OnScreenDisplay.h"
+#include "VideoCommon/VideoConfig.h"
static std::mutex crit_netplay_client;
static NetPlayClient* netplay_client = nullptr;
@@ -351,6 +353,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> size;
m_target_buffer_size = size;
+ m_dialog->OnPadBufferChanged(size);
}
break;
@@ -428,17 +431,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
break;
case NP_MSG_STOP_GAME:
- {
- m_dialog->OnMsgStopGame();
- }
- break;
-
case NP_MSG_DISABLE_GAME:
{
- PanicAlertT("Other client disconnected while game is running!! NetPlay is disabled. You must "
- "manually stop the game.");
- m_is_running.store(false);
- NetPlay_Disable();
+ StopGame();
+ m_dialog->OnMsgStopGame();
}
break;
@@ -466,6 +462,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> player.ping;
}
+ DisplayPlayersPing();
m_dialog->Update();
}
break;
@@ -476,18 +473,15 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
u32 frame;
packet >> pid_to_blame;
packet >> frame;
- const char* blame_str = "";
- const char* blame_name = "";
+
+ std::string player = "??";
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
- if (pid_to_blame != -1)
{
auto it = m_players.find(pid_to_blame);
- blame_str = " from player ";
- blame_name = it != m_players.end() ? it->second.name.c_str() : "??";
+ if (it != m_players.end())
+ player = it->second.name;
}
-
- m_dialog->AppendChat(StringFromFormat("/!\\ Possible desync detected%s%s on frame %u",
- blame_str, blame_name, frame));
+ m_dialog->OnDesync(frame, player);
}
break;
@@ -571,6 +565,24 @@ void NetPlayClient::Send(sf::Packet& packet)
enet_peer_send(m_server, 0, epac);
}
+void NetPlayClient::DisplayPlayersPing()
+{
+ if (!g_ActiveConfig.bShowNetPlayPing)
+ return;
+
+ OSD::AddTypedMessage(OSD::MessageType::NetPlayPing,
+ StringFromFormat("Ping: %u", GetPlayersMaxPing()), OSD::Duration::SHORT,
+ OSD::Color::CYAN);
+}
+
+u32 NetPlayClient::GetPlayersMaxPing() const
+{
+ return std::max_element(
+ m_players.begin(), m_players.end(),
+ [](const auto& a, const auto& b) { return a.second.ping < b.second.ping; })
+ ->second.ping;
+}
+
void NetPlayClient::Disconnect()
{
ENetEvent netEvent;
@@ -636,13 +648,11 @@ void NetPlayClient::ThreadFunc()
enet_packet_destroy(netEvent.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
- m_is_running.store(false);
- NetPlay_Disable();
- m_dialog->AppendChat("< LOST CONNECTION TO SERVER >");
- PanicAlertT("Lost connection to server!");
- m_do_loop.store(false);
+ m_dialog->OnConnectionLost();
+
+ if (m_is_running.load())
+ StopGame();
- netEvent.peer->data = nullptr;
break;
default:
break;
@@ -786,8 +796,6 @@ bool NetPlayClient::StartGame(const std::string& path)
return false;
}
- m_dialog->AppendChat(" -- STARTING GAME -- ");
-
m_timebase_frame = 0;
m_is_running.store(true);
@@ -895,6 +903,7 @@ void NetPlayClient::OnTraversalStateChanged()
m_traversal_client->m_State == TraversalClient::Failure)
{
Disconnect();
+ m_dialog->OnTraversalError(m_traversal_client->m_FailureReason);
}
}
@@ -1080,8 +1089,6 @@ bool NetPlayClient::StopGame()
return false;
}
- m_dialog->AppendChat(" -- STOPPING GAME -- ");
-
m_is_running.store(false);
NetPlay_Disable();
diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h
index 196066d457..4eddc36adf 100644
--- a/Source/Core/Core/NetPlayClient.h
+++ b/Source/Core/Core/NetPlayClient.h
@@ -32,6 +32,10 @@ public:
virtual void OnMsgChangeGame(const std::string& filename) = 0;
virtual void OnMsgStartGame() = 0;
virtual void OnMsgStopGame() = 0;
+ virtual void OnPadBufferChanged(u32 buffer) = 0;
+ virtual void OnDesync(u32 frame, const std::string& player) = 0;
+ virtual void OnConnectionLost() = 0;
+ virtual void OnTraversalError(int error) = 0;
virtual bool IsRecording() = 0;
virtual std::string FindGame(const std::string& game) = 0;
virtual void ShowMD5Dialog(const std::string& file_identifier) = 0;
@@ -157,6 +161,8 @@ private:
void Disconnect();
bool Connect();
void ComputeMD5(const std::string& file_identifier);
+ void DisplayPlayersPing();
+ u32 GetPlayersMaxPing() const;
bool m_is_connected = false;
ConnectionState m_connection_state = ConnectionState::Failure;
diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp
index 3e3a6e16b4..5bc9793811 100644
--- a/Source/Core/Core/NetPlayServer.cpp
+++ b/Source/Core/Core/NetPlayServer.cpp
@@ -350,15 +350,13 @@ unsigned int NetPlayServer::OnDisconnect(Client& player)
{
if (mapping == pid && pid != 1)
{
- PanicAlertT("Client disconnect while game is running!! NetPlay is disabled. You must "
- "manually stop the game.");
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_is_running = false;
sf::Packet spac;
spac << (MessageId)NP_MSG_DISABLE_GAME;
// this thread doesn't need players lock
- SendToClients(spac, 1);
+ SendToClients(spac, -1);
break;
}
}
@@ -636,19 +634,15 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
}))
{
int pid_to_blame = -1;
- if (timebases.size() > 2)
+ for (auto pair : timebases)
{
- for (auto pair : timebases)
+ if (std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> other) {
+ return other.first == pair.first || other.second != pair.second;
+ }))
{
- if (std::all_of(timebases.begin(), timebases.end(),
- [&](std::pair<PlayerId, u64> other) {
- return other.first == pair.first || other.second != pair.second;
- }))
- {
- // we are the only outlier
- pid_to_blame = pair.first;
- break;
- }
+ // we are the only outlier
+ pid_to_blame = pair.first;
+ break;
}
}
@@ -720,8 +714,8 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
void NetPlayServer::OnTraversalStateChanged()
{
- if (m_dialog)
- m_dialog->Update();
+ if (m_dialog && m_traversal_client->m_State == TraversalClient::Failure)
+ m_dialog->OnTraversalError(m_traversal_client->m_FailureReason);
}
// called from ---GUI--- thread
diff --git a/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.cpp b/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.cpp
index 1e845d59bb..73bdb92bb2 100644
--- a/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.cpp
+++ b/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.cpp
@@ -43,10 +43,11 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
: wxFrame(parent, wxID_ANY, _("Dolphin NetPlay Setup")), m_game_list(game_list)
{
IniFile inifile;
- inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
+ inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
wxPanel* const panel = new wxPanel(this);
+ panel->Bind(wxEVT_CHAR_HOOK, &NetPlaySetupFrame::OnKeyDown, this);
// top row
wxBoxSizer* const trav_szr = new wxBoxSizer(wxHORIZONTAL);
@@ -57,7 +58,7 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
panel, wxID_ANY, _("Connection Type:"), wxDefaultPosition, wxSize(100, -1));
m_direct_traversal = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(150, -1));
- m_direct_traversal->Bind(wxEVT_CHOICE, &NetPlaySetupFrame::OnChoice, this);
+ m_direct_traversal->Bind(wxEVT_CHOICE, &NetPlaySetupFrame::OnDirectTraversalChoice, this);
m_direct_traversal->Append(_("Direct Connection"));
m_direct_traversal->Append(_("Traversal Server"));
@@ -106,19 +107,26 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
centralServer + ":" + centralPort);
}
// tabs
- wxNotebook* const notebook = new wxNotebook(panel, wxID_ANY);
- wxPanel* const connect_tab = new wxPanel(notebook, wxID_ANY);
- notebook->AddPage(connect_tab, _("Connect"));
- wxPanel* const host_tab = new wxPanel(notebook, wxID_ANY);
- notebook->AddPage(host_tab, _("Host"));
+ m_notebook = new wxNotebook(panel, wxID_ANY);
+ wxPanel* const connect_tab = new wxPanel(m_notebook, wxID_ANY);
+ m_notebook->AddPage(connect_tab, _("Connect"));
+ wxPanel* const host_tab = new wxPanel(m_notebook, wxID_ANY);
+ m_notebook->AddPage(host_tab, _("Host"));
// connect tab
{
m_ip_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Host Code :"));
- std::string address;
- netplay_section.Get("HostCode", &address, "00000000");
- m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(address));
+ std::string last_hash_code;
+ netplay_section.Get("HostCode", &last_hash_code, "00000000");
+ std::string last_ip_address;
+ netplay_section.Get("Address", &last_ip_address, "127.0.0.1");
+ m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(last_ip_address));
+ m_connect_hashcode_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(last_hash_code));
+
+ // Will be overridden by OnDirectTraversalChoice, but is necessary
+ // so that both inputs do not take up space
+ m_connect_hashcode_text->Hide();
m_client_port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"));
@@ -144,7 +152,8 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
top_szr->Add(m_ip_lbl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
top_szr->Add(m_connect_ip_text, 3);
- top_szr->Add(m_client_port_lbl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, 5);
+ top_szr->Add(m_connect_hashcode_text, 3);
+ top_szr->Add(m_client_port_lbl, 0, wxCENTER | wxRIGHT | wxLEFT, 5);
top_szr->Add(m_connect_port_text, 1);
wxBoxSizer* const con_szr = new wxBoxSizer(wxVERTICAL);
@@ -190,6 +199,10 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
NetPlayDialog::FillWithGameNames(m_game_lbox, *game_list);
+ std::string last_hosted_game;
+ if (netplay_section.Get("SelectedHostGame", &last_hosted_game, ""))
+ m_game_lbox->SetStringSelection(last_hosted_game);
+
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
top_szr->Add(m_host_port_lbl, 0, wxCENTER | wxRIGHT, 5);
top_szr->Add(m_host_port_text, 0);
@@ -221,7 +234,7 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
main_szr->Add(trav_szr, 0, wxALL | wxALIGN_LEFT, 5);
main_szr->Add(nick_szr, 0, wxALL | wxALIGN_LEFT, 5);
main_szr->Add(m_traversal_lbl, 0, wxALL | wxALIGN_LEFT, 5);
- main_szr->Add(notebook, 1, wxLEFT | wxRIGHT | wxEXPAND, 5);
+ main_szr->Add(m_notebook, 1, wxLEFT | wxRIGHT | wxEXPAND, 5);
main_szr->Add(quit_btn, 0, wxALL | wxALIGN_RIGHT, 5);
panel->SetSizerAndFit(main_szr);
@@ -237,37 +250,35 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
// Needs to be done last or it set up the spacing on the page correctly
wxCommandEvent ev;
- OnChoice(ev);
+ OnDirectTraversalChoice(ev);
}
NetPlaySetupFrame::~NetPlaySetupFrame()
{
IniFile inifile;
- const std::string dolphin_ini = File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini";
+ const std::string dolphin_ini = File::GetUserPath(F_DOLPHINCONFIG_IDX);
inifile.Load(dolphin_ini);
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
- std::string travChoice = "traversal";
- if (m_direct_traversal->GetSelection() == 1)
- {
- netplay_section.Set("TraversalChoice", travChoice);
- }
- else
+ std::string travChoice;
+ switch (m_direct_traversal->GetSelection())
{
+ case TRAVERSAL_CHOICE:
+ travChoice = "traversal";
+ break;
+ case DIRECT_CHOICE:
travChoice = "direct";
- netplay_section.Set("TraversalChoice", travChoice);
+ break;
}
+ netplay_section.Set("TraversalChoice", travChoice);
netplay_section.Set("Nickname", WxStrToStr(m_nickname_text->GetValue()));
- if (m_direct_traversal->GetCurrentSelection() == 0)
- {
+ if (m_direct_traversal->GetCurrentSelection() == DIRECT_CHOICE)
netplay_section.Set("Address", WxStrToStr(m_connect_ip_text->GetValue()));
- }
else
- {
- netplay_section.Set("HostCode", WxStrToStr(m_connect_ip_text->GetValue()));
- }
+ netplay_section.Set("HostCode", WxStrToStr(m_connect_hashcode_text->GetValue()));
+
netplay_section.Set("ConnectPort", WxStrToStr(m_connect_port_text->GetValue()));
netplay_section.Set("HostPort", WxStrToStr(m_host_port_text->GetValue()));
netplay_section.Set("ListenPort", m_traversal_listen_port_enabled->IsChecked() ?
@@ -283,21 +294,19 @@ void NetPlaySetupFrame::MakeNetPlayDiag(int port, const std::string& game, bool
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
NetPlayClient*& netplay_client = NetPlayDialog::GetNetPlayClient();
+ bool trav = !is_hosting && m_direct_traversal->GetCurrentSelection() == TRAVERSAL_CHOICE;
+
std::string ip;
npd = new NetPlayDialog(m_parent, m_game_list, game, is_hosting);
if (is_hosting)
ip = "127.0.0.1";
+ else if (trav)
+ ip = WxStrToStr(m_connect_hashcode_text->GetValue());
else
ip = WxStrToStr(m_connect_ip_text->GetValue());
- bool trav;
- if (!is_hosting && m_direct_traversal->GetCurrentSelection() == 1)
- trav = true;
- else
- trav = false;
-
IniFile inifile;
- inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
+ inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
std::string centralPortString;
@@ -323,6 +332,16 @@ void NetPlaySetupFrame::MakeNetPlayDiag(int port, const std::string& game, bool
void NetPlaySetupFrame::OnHost(wxCommandEvent&)
{
+ DoHost();
+}
+
+void NetPlaySetupFrame::DoHost()
+{
+ IniFile ini_file;
+ const std::string dolphin_ini = File::GetUserPath(F_DOLPHINCONFIG_IDX);
+ ini_file.Load(dolphin_ini);
+ IniFile::Section& netplay_section = *ini_file.GetOrCreateSection("NetPlay");
+
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
NetPlayServer*& netplay_server = NetPlayDialog::GetNetPlayServer();
@@ -354,10 +373,6 @@ void NetPlaySetupFrame::OnHost(wxCommandEvent&)
m_host_port_text->GetValue().ToULong(&listen_port);
}
- IniFile inifile;
- inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
- IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
-
std::string centralPortString;
GetTraversalPort(netplay_section, &centralPortString);
unsigned long int centralPort;
@@ -377,6 +392,9 @@ void NetPlaySetupFrame::OnHost(wxCommandEvent&)
#endif
MakeNetPlayDiag(netplay_server->GetPort(), game, true);
netplay_server->SetNetPlayUI(NetPlayDialog::GetInstance());
+
+ netplay_section.Set("SelectedHostGame", game);
+ ini_file.Save(dolphin_ini);
}
else
{
@@ -391,6 +409,11 @@ void NetPlaySetupFrame::OnHost(wxCommandEvent&)
void NetPlaySetupFrame::OnJoin(wxCommandEvent&)
{
+ DoJoin();
+}
+
+void NetPlaySetupFrame::DoJoin()
+{
NetPlayDialog*& npd = NetPlayDialog::GetInstance();
if (npd)
{
@@ -406,7 +429,7 @@ void NetPlaySetupFrame::OnJoin(wxCommandEvent&)
void NetPlaySetupFrame::OnResetTraversal(wxCommandEvent& event)
{
IniFile inifile;
- const std::string dolphin_ini = File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini";
+ const std::string dolphin_ini = File::GetUserPath(F_DOLPHINCONFIG_IDX);
inifile.Load(dolphin_ini);
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
netplay_section.Set("TraversalServer", (std::string) "stun.dolphin-emu.org");
@@ -421,26 +444,23 @@ void NetPlaySetupFrame::OnTraversalListenPortChanged(wxCommandEvent& event)
m_traversal_listen_port->Enable(m_traversal_listen_port_enabled->IsChecked());
}
-void NetPlaySetupFrame::OnChoice(wxCommandEvent& event)
+void NetPlaySetupFrame::OnDirectTraversalChoice(wxCommandEvent& event)
{
int sel = m_direct_traversal->GetSelection();
IniFile inifile;
- inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini");
+ inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
- if (sel == 1)
+ if (sel == TRAVERSAL_CHOICE)
{
m_traversal_lbl->Show();
m_trav_reset_btn->Show();
+ m_connect_hashcode_text->Show();
+ m_connect_ip_text->Hide();
// Traversal
// client tab
{
m_ip_lbl->SetLabelText("Host Code: ");
-
- std::string address;
- netplay_section.Get("HostCode", &address, "00000000");
- m_connect_ip_text->SetLabelText(address);
-
m_client_port_lbl->Hide();
m_connect_port_text->Hide();
}
@@ -460,6 +480,8 @@ void NetPlaySetupFrame::OnChoice(wxCommandEvent& event)
{
m_traversal_lbl->Hide();
m_trav_reset_btn->Hide();
+ m_connect_hashcode_text->Hide();
+ m_connect_ip_text->Show();
// Direct
// Client tab
{
@@ -482,6 +504,48 @@ void NetPlaySetupFrame::OnChoice(wxCommandEvent& event)
m_upnp_chk->Show();
#endif
}
+ m_connect_ip_text->GetParent()->Layout();
+ DispatchFocus();
+}
+
+void NetPlaySetupFrame::OnKeyDown(wxKeyEvent& event)
+{
+ // Let the event propagate
+ event.Skip();
+
+ if (event.GetKeyCode() != wxKeyCode::WXK_RETURN)
+ return;
+
+ int current_tab = m_notebook->GetSelection();
+
+ switch (current_tab)
+ {
+ case CONNECT_TAB:
+ DoJoin();
+ break;
+ case HOST_TAB:
+ DoHost();
+ break;
+ }
+}
+
+void NetPlaySetupFrame::DispatchFocus()
+{
+ int current_tab = m_notebook->GetSelection();
+
+ switch (current_tab)
+ {
+ case CONNECT_TAB:
+ if (m_direct_traversal->GetCurrentSelection() == TRAVERSAL_CHOICE)
+ m_connect_hashcode_text->SetFocus();
+ else
+ m_connect_ip_text->SetFocus();
+ break;
+
+ case HOST_TAB:
+ m_game_lbox->SetFocus();
+ break;
+ }
}
void NetPlaySetupFrame::OnQuit(wxCommandEvent&)
diff --git a/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.h b/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.h
index c2ddb569e1..24acc21b79 100644
--- a/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.h
+++ b/Source/Core/DolphinWX/NetPlay/NetPlaySetupFrame.h
@@ -23,12 +23,22 @@ public:
~NetPlaySetupFrame();
private:
+ static constexpr int CONNECT_TAB = 0;
+ static constexpr int HOST_TAB = 1;
+
+ static constexpr int DIRECT_CHOICE = 0;
+ static constexpr int TRAVERSAL_CHOICE = 1;
+
void OnJoin(wxCommandEvent& event);
void OnHost(wxCommandEvent& event);
+ void DoJoin();
+ void DoHost();
void OnQuit(wxCommandEvent& event);
- void OnChoice(wxCommandEvent& event);
+ void OnDirectTraversalChoice(wxCommandEvent& event);
void OnResetTraversal(wxCommandEvent& event);
void OnTraversalListenPortChanged(wxCommandEvent& event);
+ void OnKeyDown(wxKeyEvent& event);
+ void DispatchFocus();
void MakeNetPlayDiag(int port, const std::string& game, bool is_hosting);
@@ -39,11 +49,13 @@ private:
wxTextCtrl* m_host_port_text;
wxTextCtrl* m_connect_port_text;
wxTextCtrl* m_connect_ip_text;
+ wxTextCtrl* m_connect_hashcode_text;
wxChoice* m_direct_traversal;
wxStaticText* m_traversal_lbl;
wxButton* m_trav_reset_btn;
wxCheckBox* m_traversal_listen_port_enabled;
wxSpinCtrl* m_traversal_listen_port;
+ wxNotebook* m_notebook;
wxListBox* m_game_lbox;
#ifdef USE_UPNP
diff --git a/Source/Core/DolphinWX/NetPlay/NetWindow.cpp b/Source/Core/DolphinWX/NetPlay/NetWindow.cpp
index bbd5308e03..200597b9ca 100644
--- a/Source/Core/DolphinWX/NetPlay/NetWindow.cpp
+++ b/Source/Core/DolphinWX/NetPlay/NetWindow.cpp
@@ -12,6 +12,7 @@
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/clipbrd.h>
+#include <wx/colour.h>
#include <wx/dialog.h>
#include <wx/frame.h>
#include <wx/listbox.h>
@@ -48,29 +49,13 @@
#include "DolphinWX/WxUtils.h"
#include "MD5Dialog.h"
+#include "VideoCommon/OnScreenDisplay.h"
+#include "VideoCommon/VideoConfig.h"
+
NetPlayServer* NetPlayDialog::netplay_server = nullptr;
NetPlayClient* NetPlayDialog::netplay_client = nullptr;
NetPlayDialog* NetPlayDialog::npd = nullptr;
-static wxString FailureReasonStringForHostLabel(int reason)
-{
- switch (reason)
- {
- case TraversalClient::BadHost:
- return _("(Error: Bad host)");
- case TraversalClient::VersionTooOld:
- return _("(Error: Dolphin too old)");
- case TraversalClient::ServerForgotAboutUs:
- return _("(Error: Disconnected)");
- case TraversalClient::SocketSendError:
- return _("(Error: Socket)");
- case TraversalClient::ResendTimeout:
- return _("(Error: Timeout)");
- default:
- return _("(Error: Unknown)");
- }
-}
-
static std::string BuildGameName(const GameListItem& game)
{
// Lang needs to be consistent
@@ -280,13 +265,13 @@ NetPlayDialog::~NetPlayDialog()
void NetPlayDialog::OnChat(wxCommandEvent&)
{
- wxString text = m_chat_msg_text->GetValue();
+ std::string text = WxStrToStr(m_chat_msg_text->GetValue());
if (!text.empty())
{
- netplay_client->SendChatMessage(WxStrToStr(text));
- m_chat_text->AppendText(text.Prepend(" >> ").Append('\n'));
+ netplay_client->SendChatMessage(text);
m_chat_msg_text->Clear();
+ AddChatMessage(ChatMessageType::UserOut, text);
}
}
@@ -406,11 +391,46 @@ void NetPlayDialog::OnAdjustBuffer(wxCommandEvent& event)
{
const int val = ((wxSpinCtrl*)event.GetEventObject())->GetValue();
netplay_server->AdjustPadBufferSize(val);
+}
- std::ostringstream ss;
- ss << "< Pad Buffer: " << val << " >";
- netplay_client->SendChatMessage(ss.str());
- m_chat_text->AppendText(StrToWxStr(ss.str()).Append('\n'));
+void NetPlayDialog::OnPadBufferChanged(u32 buffer)
+{
+ m_pad_buffer = buffer;
+ wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_PAD_BUFFER_CHANGE);
+ GetEventHandler()->AddPendingEvent(evt);
+}
+
+void NetPlayDialog::OnDesync(u32 frame, const std::string& player)
+{
+ m_desync_frame = frame;
+ m_desync_player = player;
+ wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_DESYNC);
+ GetEventHandler()->AddPendingEvent(evt);
+}
+
+void NetPlayDialog::OnConnectionLost()
+{
+ wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_CONNECTION_LOST);
+ GetEventHandler()->AddPendingEvent(evt);
+}
+
+void NetPlayDialog::OnTraversalError(int error)
+{
+ switch (error)
+ {
+ case TraversalClient::BadHost:
+ PanicAlertT("Couldn't look up central server");
+ break;
+ case TraversalClient::VersionTooOld:
+ PanicAlertT("Dolphin is too old for traversal server");
+ break;
+ case TraversalClient::ServerForgotAboutUs:
+ case TraversalClient::SocketSendError:
+ case TraversalClient::ResendTimeout:
+ wxThreadEvent evt(wxEVT_THREAD, NP_GUI_EVT_TRAVERSAL_CONNECTION_ERROR);
+ GetEventHandler()->AddPendingEvent(evt);
+ break;
+ }
}
void NetPlayDialog::OnQuit(wxCommandEvent&)
@@ -477,17 +497,16 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
case NP_GUI_EVT_START_GAME:
// client start game :/
{
- std::string game = FindCurrentGame();
- if (game.empty())
- WxUtils::ShowErrorDialog(_("Game not found!"));
- else
- netplay_client->StartGame(game);
+ netplay_client->StartGame(FindCurrentGame());
+ std::string msg = "Starting game";
+ AddChatMessage(ChatMessageType::Info, msg);
}
break;
case NP_GUI_EVT_STOP_GAME:
// client stop game
{
- netplay_client->StopGame();
+ std::string msg = "Stopping game";
+ AddChatMessage(ChatMessageType::Info, msg);
}
break;
case NP_GUI_EVT_DISPLAY_MD5_DIALOG:
@@ -515,6 +534,42 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
m_MD5_dialog->SetResult(payload.first, payload.second);
}
break;
+ case NP_GUI_EVT_PAD_BUFFER_CHANGE:
+ {
+ std::string msg = StringFromFormat("Pad buffer: %d", m_pad_buffer);
+
+ if (g_ActiveConfig.bShowNetPlayMessages)
+ {
+ OSD::AddTypedMessage(OSD::MessageType::NetPlayBuffer, msg, OSD::Duration::NORMAL);
+ }
+
+ AddChatMessage(ChatMessageType::Info, msg);
+ }
+ break;
+ case NP_GUI_EVT_DESYNC:
+ {
+ std::string msg = "Possible desync detected from player " + m_desync_player + " on frame " +
+ std::to_string(m_desync_frame);
+
+ AddChatMessage(ChatMessageType::Error, msg);
+
+ if (g_ActiveConfig.bShowNetPlayMessages)
+ {
+ OSD::AddMessage(msg, OSD::Duration::VERY_LONG, OSD::Color::RED);
+ }
+ }
+ break;
+ case NP_GUI_EVT_CONNECTION_LOST:
+ {
+ std::string msg = "Lost connection to server";
+ AddChatMessage(ChatMessageType::Error, msg);
+ }
+ break;
+ case NP_GUI_EVT_TRAVERSAL_CONNECTION_ERROR:
+ {
+ std::string msg = "Traversal server connection error";
+ AddChatMessage(ChatMessageType::Error, msg);
+ }
}
// chat messages
@@ -522,8 +577,12 @@ void NetPlayDialog::OnThread(wxThreadEvent& event)
{
std::string s;
chat_msgs.Pop(s);
- // PanicAlert("message: %s", s.c_str());
- m_chat_text->AppendText(StrToWxStr(s).Append('\n'));
+ AddChatMessage(ChatMessageType::UserIn, s);
+
+ if (g_ActiveConfig.bShowNetPlayMessages)
+ {
+ OSD::AddMessage(s, OSD::Duration::NORMAL, OSD::Color::GREEN);
+ }
}
}
@@ -690,7 +749,7 @@ void NetPlayDialog::UpdateHostLabel()
break;
case TraversalClient::Failure:
m_host_label->SetForegroundColour(*wxBLACK);
- m_host_label->SetLabel(FailureReasonStringForHostLabel(g_TraversalClient->m_FailureReason));
+ m_host_label->SetLabel("...");
m_host_copy_btn->SetLabel(_("Retry"));
m_host_copy_btn->Enable();
m_host_copy_btn_is_retry = true;
@@ -724,3 +783,36 @@ void NetPlayDialog::UpdateHostLabel()
}
}
}
+
+void NetPlayDialog::AddChatMessage(ChatMessageType type, const std::string& msg)
+{
+ wxColour colour = *wxBLACK;
+ std::string printed_msg = msg;
+
+ switch (type)
+ {
+ case ChatMessageType::Info:
+ colour = wxColour(0, 150, 150); // cyan
+ break;
+
+ case ChatMessageType::Error:
+ colour = *wxRED;
+ break;
+
+ case ChatMessageType::UserIn:
+ colour = wxColour(0, 150, 0); // green
+ printed_msg = "▶ " + msg;
+ break;
+
+ case ChatMessageType::UserOut:
+ colour = wxColour(100, 100, 100); // grey
+ printed_msg = "◀ " + msg;
+ break;
+ }
+
+ if (type == ChatMessageType::Info || type == ChatMessageType::Error)
+ printed_msg = "― " + msg + " ―";
+
+ m_chat_text->SetDefaultStyle(wxTextAttr(colour));
+ m_chat_text->AppendText(StrToWxStr(printed_msg + "\n"));
+}
diff --git a/Source/Core/DolphinWX/NetPlay/NetWindow.h b/Source/Core/DolphinWX/NetPlay/NetWindow.h
index b7fb088b99..b3cb410440 100644
--- a/Source/Core/DolphinWX/NetPlay/NetWindow.h
+++ b/Source/Core/DolphinWX/NetPlay/NetWindow.h
@@ -31,6 +31,10 @@ enum
NP_GUI_EVT_DISPLAY_MD5_DIALOG,
NP_GUI_EVT_MD5_PROGRESS,
NP_GUI_EVT_MD5_RESULT,
+ NP_GUI_EVT_PAD_BUFFER_CHANGE,
+ NP_GUI_EVT_DESYNC,
+ NP_GUI_EVT_CONNECTION_LOST,
+ NP_GUI_EVT_TRAVERSAL_CONNECTION_ERROR,
};
enum
@@ -38,6 +42,18 @@ enum
INITIAL_PAD_BUFFER_SIZE = 5
};
+enum class ChatMessageType
+{
+ // Info messages logged to chat
+ Info,
+ // Error messages logged to chat
+ Error,
+ // Incoming user chat messages
+ UserIn,
+ // Outcoming user chat messages
+ UserOut,
+};
+
// IDs are UI-dependent here
enum class MD5Target
{
@@ -72,6 +88,10 @@ public:
void OnMsgChangeGame(const std::string& filename) override;
void OnMsgStartGame() override;
void OnMsgStopGame() override;
+ void OnPadBufferChanged(u32 buffer) override;
+ void OnDesync(u32 frame, const std::string& player) override;
+ void OnConnectionLost() override;
+ void OnTraversalError(int error) override;
static NetPlayDialog*& GetInstance() { return npd; }
static NetPlayClient*& GetNetPlayClient() { return netplay_client; }
@@ -92,7 +112,8 @@ private:
void OnPlayerSelect(wxCommandEvent& event);
void GetNetSettings(NetSettings& settings);
std::string FindCurrentGame();
- std::string FindGame(const std::string& game) override;
+ std::string FindGame(const std::string& game);
+ void AddChatMessage(ChatMessageType type, const std::string& msg);
void OnCopyIP(wxCommandEvent&);
void OnChoice(wxCommandEvent& event);
@@ -116,6 +137,9 @@ private:
MD5Dialog* m_MD5_dialog = nullptr;
bool m_host_copy_btn_is_retry;
bool m_is_hosting;
+ u32 m_pad_buffer;
+ u32 m_desync_frame;
+ std::string m_desync_player;
std::vector<int> m_playerids;
diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp
index 9378d6fd7d..86d37f52ed 100644
--- a/Source/Core/DolphinWX/VideoConfigDiag.cpp
+++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp
@@ -201,13 +201,20 @@ static wxString disable_fog_desc =
"detail.\nDisabling fog will break some games which rely on proper fog "
"emulation.\n\nIf unsure, leave this unchecked.");
static wxString show_fps_desc =
- wxTRANSLATE("Show the number of frames rendered per second as a measure of emulation "
- "speed.\n\nIf unsure, leave this unchecked.");
-static wxString log_render_time_to_file_desc = wxTRANSLATE(
- "Log the render time of every frame to User/Logs/render_time.txt. Use this feature when you "
- "want to measure the performance of Dolphin.\n\nIf unsure, leave this unchecked.");
+ wxTRANSLATE("Show the number of frames rendered per second as a measure of "
+ "emulation speed.\n\nIf unsure, leave this unchecked.");
+static wxString show_netplay_ping_desc =
+ wxTRANSLATE("Show the players' maximum Ping while playing on "
+ "NetPlay.\n\nIf unsure, leave this unchecked.");
+static wxString log_render_time_to_file_desc =
+ wxTRANSLATE("Log the render time of every frame to User/Logs/render_time.txt. Use this "
+ "feature when you want to measure the performance of Dolphin.\n\nIf "
+ "unsure, leave this unchecked.");
static wxString show_stats_desc =
wxTRANSLATE("Show various rendering statistics.\n\nIf unsure, leave this unchecked.");
+static wxString show_netplay_messages_desc =
+ wxTRANSLATE("When playing on NetPlay, show chat messages, buffer changes and "
+ "desync alerts.\n\nIf unsure, leave this unchecked.");
static wxString texfmt_desc =
wxTRANSLATE("Modify textures to show the format they're encoded in. Needs an emulation reset "
"in most cases.\n\nIf unsure, leave this unchecked.");
@@ -442,12 +449,18 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
{
szr_other->Add(CreateCheckBox(page_general, _("Show FPS"), wxGetTranslation(show_fps_desc),
vconfig.bShowFPS));
+ szr_other->Add(CreateCheckBox(page_general, _("Show NetPlay Ping"),
+ wxGetTranslation(show_netplay_ping_desc),
+ vconfig.bShowNetPlayPing));
szr_other->Add(CreateCheckBox(page_general, _("Log Render Time to File"),
wxGetTranslation(log_render_time_to_file_desc),
vconfig.bLogRenderTimeToFile));
szr_other->Add(CreateCheckBox(page_general, _("Auto adjust Window Size"),
wxGetTranslation(auto_window_size_desc),
SConfig::GetInstance().bRenderWindowAutoSize));
+ szr_other->Add(CreateCheckBox(page_general, _("Show NetPlay Messages"),
+ wxGetTranslation(show_netplay_messages_desc),
+ vconfig.bShowNetPlayMessages));
szr_other->Add(CreateCheckBox(page_general, _("Keep Window on Top"),
wxGetTranslation(keep_window_on_top_desc),
SConfig::GetInstance().bKeepWindowOnTop));
diff --git a/Source/Core/VideoCommon/OnScreenDisplay.cpp b/Source/Core/VideoCommon/OnScreenDisplay.cpp
index 3cc2e823d8..62997cd150 100644
--- a/Source/Core/VideoCommon/OnScreenDisplay.cpp
+++ b/Source/Core/VideoCommon/OnScreenDisplay.cpp
@@ -17,21 +17,30 @@
namespace OSD
{
-struct Message
+static std::multimap<CallbackType, Callback> s_callbacks;
+static std::multimap<MessageType, Message> s_messages;
+static std::mutex s_messages_mutex;
+
+void AddTypedMessage(MessageType type, const std::string& message, u32 ms, u32 rgba)
{
- Message() {}
- Message(const std::string& s, u32 ts, u32 rgba) : m_str(s), m_timestamp(ts), m_rgba(rgba) {}
- std::string m_str;
- u32 m_timestamp;
- u32 m_rgba;
-};
+ std::lock_guard<std::mutex> lock(s_messages_mutex);
+ s_messages.erase(type);
+ s_messages.emplace(type, Message(message, Common::Timer::GetTimeMs() + ms, rgba));
+}
-static std::multimap<CallbackType, Callback> s_callbacks;
-static std::list<Message> s_msgList;
+void AddMessage(const std::string& message, u32 ms, u32 rgba)
+{
+ std::lock_guard<std::mutex> lock(s_messages_mutex);
+ s_messages.emplace(MessageType::Typeless,
+ Message(message, Common::Timer::GetTimeMs() + ms, rgba));
+}
-void AddMessage(const std::string& str, u32 ms, u32 rgba)
+void DrawMessage(const Message& msg, int top, int left, int time_left)
{
- s_msgList.emplace_back(str, Common::Timer::GetTimeMs() + ms, rgba);
+ float alpha = std::min(1.0f, std::max(0.0f, time_left / 1024.0f));
+ u32 color = (msg.m_rgba & 0xFFFFFF) | ((u32)((msg.m_rgba >> 24) * alpha) << 24);
+
+ g_renderer->RenderText(msg.m_str, left, top, color);
}
void DrawMessages()
@@ -39,28 +48,32 @@ void DrawMessages()
if (!SConfig::GetInstance().bOnScreenDisplayMessages)
return;
- int left = 25, top = 15;
- auto it = s_msgList.begin();
- while (it != s_msgList.end())
{
- int time_left = (int)(it->m_timestamp - Common::Timer::GetTimeMs());
- float alpha = std::max(1.0f, std::min(0.0f, time_left / 1024.0f));
- u32 color = (it->m_rgba & 0xFFFFFF) | ((u32)((it->m_rgba >> 24) * alpha) << 24);
-
- g_renderer->RenderText(it->m_str, left, top, color);
-
- top += 15;
-
- if (time_left <= 0)
- it = s_msgList.erase(it);
- else
- ++it;
+ std::lock_guard<std::mutex> lock(s_messages_mutex);
+
+ u32 now = Common::Timer::GetTimeMs();
+ int left = 20, top = 35;
+
+ auto it = s_messages.begin();
+ while (it != s_messages.end())
+ {
+ const Message& msg = it->second;
+ int time_left = (int)(msg.m_timestamp - now);
+ DrawMessage(msg, top, left, time_left);
+
+ if (time_left <= 0)
+ it = s_messages.erase(it);
+ else
+ ++it;
+ top += 15;
+ }
}
}
void ClearMessages()
{
- s_msgList.clear();
+ std::lock_guard<std::mutex> lock(s_messages_mutex);
+ s_messages.clear();
}
// On-Screen Display Callbacks
diff --git a/Source/Core/VideoCommon/OnScreenDisplay.h b/Source/Core/VideoCommon/OnScreenDisplay.h
index ab74201bca..a05f4058ef 100644
--- a/Source/Core/VideoCommon/OnScreenDisplay.h
+++ b/Source/Core/VideoCommon/OnScreenDisplay.h
@@ -11,9 +11,47 @@
namespace OSD
{
+struct Message
+{
+ Message() {}
+ Message(const std::string& s, u32 ts, u32 rgba) : m_str(s), m_timestamp(ts), m_rgba(rgba) {}
+ std::string m_str;
+ u32 m_timestamp;
+ u32 m_rgba;
+};
+
+enum class MessageType
+{
+ NetPlayPing,
+ NetPlayBuffer,
+
+ // This entry must be kept last so that persistent typed messages are
+ // displayed before other messages
+ Typeless,
+};
+
+namespace Color
+{
+constexpr u32 CYAN = 0xFF00FFFF;
+constexpr u32 GREEN = 0xFF00FF00;
+constexpr u32 RED = 0xFFFF0000;
+constexpr u32 YELLOW = 0xFFFFFF30;
+};
+
+namespace Duration
+{
+constexpr u32 SHORT = 2000;
+constexpr u32 NORMAL = 5000;
+constexpr u32 VERY_LONG = 10000;
+};
+
// On-screen message display (colored yellow by default)
-void AddMessage(const std::string& str, u32 ms = 2000, u32 rgba = 0xFFFFFF30);
-void DrawMessages(); // draw the current messages on the screen. Only call once per frame.
+void AddMessage(const std::string& message, u32 ms = Duration::SHORT, u32 rgba = Color::YELLOW);
+void AddTypedMessage(MessageType type, const std::string& message, u32 ms = Duration::SHORT,
+ u32 rgba = Color::YELLOW);
+void DrawMessage(const Message& msg, int top, int left, int time_left); // draw one message
+void DrawMessages(); // draw the current messages on the screen. Only call once
+ // per frame.
void ClearMessages();
// On-screen callbacks
diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp
index c19528d7d9..7f8def5450 100644
--- a/Source/Core/VideoCommon/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/VideoConfig.cpp
@@ -60,6 +60,8 @@ void VideoConfig::Load(const std::string& ini_file)
settings->Get("UseRealXFB", &bUseRealXFB, 0);
settings->Get("SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples, 128);
settings->Get("ShowFPS", &bShowFPS, false);
+ settings->Get("ShowNetPlayPing", &bShowNetPlayPing, false);
+ settings->Get("ShowNetPlayMessages", &bShowNetPlayMessages, false);
settings->Get("LogRenderTimeToFile", &bLogRenderTimeToFile, false);
settings->Get("OverlayStats", &bOverlayStats, false);
settings->Get("OverlayProjStats", &bOverlayProjStats, false);
@@ -267,6 +269,8 @@ void VideoConfig::Save(const std::string& ini_file)
settings->Set("UseRealXFB", bUseRealXFB);
settings->Set("SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples);
settings->Set("ShowFPS", bShowFPS);
+ settings->Set("ShowNetPlayPing", bShowNetPlayPing);
+ settings->Set("ShowNetPlayMessages", bShowNetPlayMessages);
settings->Set("LogRenderTimeToFile", bLogRenderTimeToFile);
settings->Set("OverlayStats", bOverlayStats);
settings->Set("OverlayProjStats", bOverlayProjStats);
diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h
index d78c63ba90..9df952a18d 100644
--- a/Source/Core/VideoCommon/VideoConfig.h
+++ b/Source/Core/VideoCommon/VideoConfig.h
@@ -82,6 +82,8 @@ struct VideoConfig final
// Information
bool bShowFPS;
+ bool bShowNetPlayPing;
+ bool bShowNetPlayMessages;
bool bOverlayStats;
bool bOverlayProjStats;
bool bTexFmtOverlayEnable;