From 7619b93cfe947e0f9a08225c1c38da2f271142b7 Mon Sep 17 00:00:00 2001 From: Sour Date: Sat, 16 Jun 2018 14:02:12 -0400 Subject: [PATCH] Netplay: Added password protected servers --- Core/ClientConnectionData.h | 9 +- Core/Core.vcxproj | 1 + Core/Core.vcxproj.filters | 3 + Core/GameClient.cpp | 6 +- Core/GameClient.h | 4 +- Core/GameClientConnection.cpp | 12 ++- Core/GameClientConnection.h | 7 +- Core/GameConnection.cpp | 5 +- Core/GameConnection.h | 4 +- Core/GameServer.cpp | 9 +- Core/GameServer.h | 5 +- Core/GameServerConnection.cpp | 67 +++++++++---- Core/GameServerConnection.h | 6 +- Core/HandShakeMessage.h | 25 ++++- Core/MessageType.h | 3 +- Core/ServerInformationMessage.h | 28 ++++++ GUI.NET/Config/ClientConnection.cs | 1 + GUI.NET/Config/ServerInfo.cs | 5 +- GUI.NET/Controls/MesenNumericUpDown.cs | 4 +- GUI.NET/Dependencies/resources.ca.xml | 1 + GUI.NET/Dependencies/resources.en.xml | 1 + GUI.NET/Dependencies/resources.es.xml | 1 + GUI.NET/Dependencies/resources.fr.xml | 1 + GUI.NET/Dependencies/resources.ja.xml | 1 + GUI.NET/Dependencies/resources.pt.xml | 1 + GUI.NET/Dependencies/resources.ru.xml | 1 + GUI.NET/Dependencies/resources.uk.xml | 1 + .../Forms/NetPlay/frmClientConfig.Designer.cs | 45 +++++++-- GUI.NET/Forms/NetPlay/frmClientConfig.cs | 1 + .../Forms/NetPlay/frmServerConfig.Designer.cs | 97 +++---------------- GUI.NET/Forms/NetPlay/frmServerConfig.cs | 8 +- GUI.NET/Forms/frmMain.Tools.cs | 10 +- GUI.NET/InteropEmu.cs | 4 +- InteropDLL/ConsoleWrapper.cpp | 12 +-- 34 files changed, 215 insertions(+), 174 deletions(-) create mode 100644 Core/ServerInformationMessage.h diff --git a/Core/ClientConnectionData.h b/Core/ClientConnectionData.h index 632566cd..0df67f05 100644 --- a/Core/ClientConnectionData.h +++ b/Core/ClientConnectionData.h @@ -7,13 +7,14 @@ class ClientConnectionData public: string Host; uint16_t Port; - + string Password; string PlayerName; - bool Spectator; - ClientConnectionData(string host, uint16_t port, string playerName, bool spectator) : - Host(host), Port(port), PlayerName(playerName), Spectator(spectator) + ClientConnectionData() {} + + ClientConnectionData(string host, uint16_t port, string password, string playerName, bool spectator) : + Host(host), Port(port), Password(password), PlayerName(playerName), Spectator(spectator) { } diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 94f79764..0f202033 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -531,6 +531,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 28bda578..cefa5e79 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -1372,6 +1372,9 @@ Misc + + NetPlay\Messages + diff --git a/Core/GameClient.cpp b/Core/GameClient.cpp index d41eff82..c46d96c8 100644 --- a/Core/GameClient.cpp +++ b/Core/GameClient.cpp @@ -33,7 +33,7 @@ bool GameClient::Connected() return instance ? instance->_connected : false; } -void GameClient::Connect(shared_ptr connectionData) +void GameClient::Connect(ClientConnectionData &connectionData) { _instance.reset(new GameClient()); @@ -55,11 +55,11 @@ shared_ptr GameClient::GetConnection() return instance ? instance->_connection : nullptr; } -void GameClient::PrivateConnect(shared_ptr connectionData) +void GameClient::PrivateConnect(ClientConnectionData &connectionData) { _stop = false; shared_ptr socket(new Socket()); - if(socket->Connect(connectionData->Host.c_str(), connectionData->Port)) { + if(socket->Connect(connectionData.Host.c_str(), connectionData.Port)) { _connection.reset(new GameClientConnection(socket, connectionData)); _connected = true; } else { diff --git a/Core/GameClient.h b/Core/GameClient.h index ef081149..8ef0af1d 100644 --- a/Core/GameClient.h +++ b/Core/GameClient.h @@ -19,7 +19,7 @@ private: static shared_ptr GetConnection(); - void PrivateConnect(shared_ptr connectionData); + void PrivateConnect(ClientConnectionData &connectionData); void Exec(); public: @@ -27,7 +27,7 @@ public: virtual ~GameClient(); static bool Connected(); - static void Connect(shared_ptr connectionData); + static void Connect(ClientConnectionData &connectionData); static void Disconnect(); static void SelectController(uint8_t port); diff --git a/Core/GameClientConnection.cpp b/Core/GameClientConnection.cpp index 50088de7..54015830 100644 --- a/Core/GameClientConnection.cpp +++ b/Core/GameClientConnection.cpp @@ -16,9 +16,11 @@ #include "SelectControllerMessage.h" #include "PlayerListMessage.h" #include "ForceDisconnectMessage.h" +#include "ServerInformationMessage.h" -GameClientConnection::GameClientConnection(shared_ptr socket, shared_ptr connectionData) : GameConnection(socket, connectionData) +GameClientConnection::GameClientConnection(shared_ptr socket, ClientConnectionData &connectionData) : GameConnection(socket) { + _connectionData = connectionData; _shutdown = false; _enableControllers = false; _minimumQueueSize = 3; @@ -26,7 +28,6 @@ GameClientConnection::GameClientConnection(shared_ptr socket, shared_ptr MessageManager::RegisterNotificationListener(this); MessageManager::DisplayMessage("NetPlay", "ConnectedToServer"); ControlManager::RegisterInputProvider(this); - SendHandshake(); } GameClientConnection::~GameClientConnection() @@ -50,7 +51,7 @@ void GameClientConnection::Shutdown() void GameClientConnection::SendHandshake() { - HandShakeMessage message(_connectionData->PlayerName, _connectionData->Spectator); + HandShakeMessage message(_connectionData.PlayerName, HandShakeMessage::GetPasswordHash(_connectionData.Password, _serverSalt), _connectionData.Spectator); SendNetMessage(message); } @@ -74,6 +75,11 @@ void GameClientConnection::ProcessMessage(NetMessage* message) GameInformationMessage* gameInfo; switch(message->GetType()) { + case MessageType::ServerInformation: + _serverSalt = ((ServerInformationMessage*)message)->GetHashSalt(); + SendHandshake(); + break; + case MessageType::SaveState: if(_gameLoaded) { DisableControllers(); diff --git a/Core/GameClientConnection.h b/Core/GameClientConnection.h index 3a51ab74..a8faf824 100644 --- a/Core/GameClientConnection.h +++ b/Core/GameClientConnection.h @@ -7,8 +7,7 @@ #include "BaseControlDevice.h" #include "IInputProvider.h" #include "ControlDeviceState.h" - -class ClientConnectionData; +#include "ClientConnectionData.h" class GameClientConnection : public GameConnection, public INotificationListener, public IInputProvider { @@ -28,6 +27,8 @@ private: ControlDeviceState _lastInputSent; bool _gameLoaded = false; uint8_t _controllerPort = GameConnection::SpectatorPort; + ClientConnectionData _connectionData; + string _serverSalt; private: void SendHandshake(); @@ -40,7 +41,7 @@ protected: void ProcessMessage(NetMessage* message) override; public: - GameClientConnection(shared_ptr socket, shared_ptr connectionData); + GameClientConnection(shared_ptr socket, ClientConnectionData &connectionData); virtual ~GameClientConnection(); void Shutdown(); diff --git a/Core/GameConnection.cpp b/Core/GameConnection.cpp index efa9d152..e9069c48 100644 --- a/Core/GameConnection.cpp +++ b/Core/GameConnection.cpp @@ -9,12 +9,12 @@ #include "SelectControllerMessage.h" #include "ClientConnectionData.h" #include "ForceDisconnectMessage.h" +#include "ServerInformationMessage.h" const uint32_t PlayerListMessage::PlayerNameMaxLength; -GameConnection::GameConnection(shared_ptr socket, shared_ptr connectionData) +GameConnection::GameConnection(shared_ptr socket) { - _connectionData = connectionData; _socket = socket; } @@ -64,6 +64,7 @@ NetMessage* GameConnection::ReadMessage() case MessageType::PlayerList: return new PlayerListMessage(_messageBuffer, messageLength); case MessageType::SelectController: return new SelectControllerMessage(_messageBuffer, messageLength); case MessageType::ForceDisconnect: return new ForceDisconnectMessage(_messageBuffer, messageLength); + case MessageType::ServerInformation: return new ServerInformationMessage(_messageBuffer, messageLength); } } } diff --git a/Core/GameConnection.h b/Core/GameConnection.h index a7dfa72f..b4e3642e 100644 --- a/Core/GameConnection.h +++ b/Core/GameConnection.h @@ -4,7 +4,6 @@ class Socket; class NetMessage; -class ClientConnectionData; struct PlayerInfo { @@ -17,7 +16,6 @@ class GameConnection { protected: shared_ptr _socket; - shared_ptr _connectionData; uint8_t _readBuffer[0x40000] = {}; uint8_t _messageBuffer[0x40000] = {}; int _readPosition = 0; @@ -36,7 +34,7 @@ protected: public: static const uint8_t SpectatorPort = 0xFF; - GameConnection(shared_ptr socket, shared_ptr connectionData); + GameConnection(shared_ptr socket); bool ConnectionError(); void ProcessMessages(); diff --git a/Core/GameServer.cpp b/Core/GameServer.cpp index c4946662..08d5d79b 100644 --- a/Core/GameServer.cpp +++ b/Core/GameServer.cpp @@ -11,10 +11,11 @@ using std::thread; unique_ptr GameServer::Instance; -GameServer::GameServer(uint16_t listenPort, string hostPlayerName) +GameServer::GameServer(uint16_t listenPort, string password, string hostPlayerName) { _stop = false; _port = listenPort; + _password = password; _hostPlayerName = hostPlayerName; _hostControllerPort = 0; ControlManager::RegisterInputRecorder(this); @@ -37,7 +38,7 @@ void GameServer::AcceptConnections() while(true) { shared_ptr socket = _listener->Accept(); if(!socket->ConnectionError()) { - _openConnections.push_back(shared_ptr(new GameServerConnection(socket))); + _openConnections.push_back(shared_ptr(new GameServerConnection(socket, _password))); } else { break; } @@ -121,9 +122,9 @@ void GameServer::Stop() MessageManager::DisplayMessage("NetPlay", "ServerStopped"); } -void GameServer::StartServer(uint16_t port, string hostPlayerName) +void GameServer::StartServer(uint16_t port, string password, string hostPlayerName) { - Instance.reset(new GameServer(port, hostPlayerName)); + Instance.reset(new GameServer(port, password, hostPlayerName)); Instance->_serverThread.reset(new thread(&GameServer::Exec, Instance.get())); } diff --git a/Core/GameServer.h b/Core/GameServer.h index d5e49147..781f1a34 100644 --- a/Core/GameServer.h +++ b/Core/GameServer.h @@ -17,6 +17,7 @@ private: unique_ptr _listener; uint16_t _port; + string _password; list> _openConnections; bool _initialized = false; @@ -30,10 +31,10 @@ private: void Stop(); public: - GameServer(uint16_t port, string hostPlayerName); + GameServer(uint16_t port, string password, string hostPlayerName); virtual ~GameServer(); - static void StartServer(uint16_t port, string hostPlayerName); + static void StartServer(uint16_t port, string password, string hostPlayerName); static void StopServer(); static bool Started(); diff --git a/Core/GameServerConnection.cpp b/Core/GameServerConnection.cpp index 2bc89931..f668e2b3 100644 --- a/Core/GameServerConnection.cpp +++ b/Core/GameServerConnection.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include #include "MessageManager.h" #include "GameServerConnection.h" #include "HandShakeMessage.h" @@ -16,26 +17,46 @@ #include "GameServer.h" #include "ForceDisconnectMessage.h" #include "BaseControlDevice.h" +#include "ServerInformationMessage.h" GameServerConnection* GameServerConnection::_netPlayDevices[BaseControlDevice::PortCount] = { }; -GameServerConnection::GameServerConnection(shared_ptr socket) : GameConnection(socket, nullptr) +GameServerConnection::GameServerConnection(shared_ptr socket, string serverPassword) : GameConnection(socket) { //Server-side connection + _serverPassword = serverPassword; _controllerPort = GameConnection::SpectatorPort; MessageManager::RegisterNotificationListener(this); + SendServerInformation(); } GameServerConnection::~GameServerConnection() { - if(_connectionData) { - MessageManager::DisplayMessage("NetPlay", _connectionData->PlayerName + " (Player " + std::to_string(_controllerPort + 1) + ") disconnected."); + if(!_playerName.empty()) { + MessageManager::DisplayMessage("NetPlay", _playerName + " (Player " + std::to_string(_controllerPort + 1) + ") disconnected."); } UnregisterNetPlayDevice(this); MessageManager::UnregisterNotificationListener(this); } +void GameServerConnection::SendServerInformation() +{ + std::random_device rd; + std::mt19937 engine(rd()); + std::uniform_int_distribution<> dist((int)' ', (int)'~'); + string hash(50, ' '); + for(int i = 0; i < 50; i++) { + int random = dist(engine); + hash[i] = (char)random; + } + + _connectionHash = hash; + + ServerInformationMessage message(hash); + SendNetMessage(message); +} + void GameServerConnection::SendGameInformation() { Console::Pause(); @@ -88,23 +109,27 @@ void GameServerConnection::ProcessHandshakeResponse(HandShakeMessage* message) { //Send the game's current state to the client and register the controller if(message->IsValid()) { - Console::Pause(); + if(message->CheckPassword(_serverPassword, _connectionHash)) { + Console::Pause(); - _controllerPort = message->IsSpectator() ? GameConnection::SpectatorPort : GetFirstFreeControllerPort(); - _connectionData.reset(new ClientConnectionData("", 0, message->GetPlayerName(), false)); + _controllerPort = message->IsSpectator() ? GameConnection::SpectatorPort : GetFirstFreeControllerPort(); + _playerName = message->GetPlayerName(); - string playerPortMessage = _controllerPort == GameConnection::SpectatorPort ? "Spectator" : "Player " + std::to_string(_controllerPort + 1); + string playerPortMessage = _controllerPort == GameConnection::SpectatorPort ? "Spectator" : "Player " + std::to_string(_controllerPort + 1); - MessageManager::DisplayMessage("NetPlay", _connectionData->PlayerName + " (" + playerPortMessage + ") connected."); + MessageManager::DisplayMessage("NetPlay", _playerName + " (" + playerPortMessage + ") connected."); - if(Console::GetMapperInfo().RomName.size() > 0) { - SendGameInformation(); + if(Console::GetMapperInfo().RomName.size() > 0) { + SendGameInformation(); + } + + _handshakeCompleted = true; + RegisterNetPlayDevice(this, _controllerPort); + GameServer::SendPlayerList(); + Console::Resume(); + } else { + SendForceDisconnectMessage("The password you provided did not match - you have been disconnected."); } - - _handshakeCompleted = true; - RegisterNetPlayDevice(this, _controllerPort); - GameServer::SendPlayerList(); - Console::Resume(); } else { SendForceDisconnectMessage("Server is using a different version of Mesen (" + EmulationSettings::GetMesenVersionString() + ") - you have been disconnected."); MessageManager::DisplayMessage("NetPlay", + "NetplayVersionMismatch", message->GetPlayerName()); @@ -119,10 +144,16 @@ void GameServerConnection::ProcessMessage(NetMessage* message) break; case MessageType::InputData: + if(_handshakeCompleted) { + break; + } PushState(((InputDataMessage*)message)->GetInputState()); break; case MessageType::SelectController: + if(_handshakeCompleted) { + break; + } SelectControllerPort(((SelectControllerMessage*)message)->GetPortNumber()); break; @@ -208,11 +239,7 @@ uint8_t GameServerConnection::GetFirstFreeControllerPort() string GameServerConnection::GetPlayerName() { - if(_connectionData) { - return _connectionData->PlayerName; - } else { - return ""; - } + return _playerName; } uint8_t GameServerConnection::GetControllerPort() diff --git a/Core/GameServerConnection.h b/Core/GameServerConnection.h index 7c80387d..1f560479 100644 --- a/Core/GameServerConnection.h +++ b/Core/GameServerConnection.h @@ -15,10 +15,14 @@ private: static GameServerConnection* _netPlayDevices[BaseControlDevice::PortCount]; list _inputData; + string _playerName; int _controllerPort; + string _connectionHash; + string _serverPassword; bool _handshakeCompleted = false; void PushState(ControlDeviceState state); + void SendServerInformation(); void SendGameInformation(); void SelectControllerPort(uint8_t port); @@ -34,7 +38,7 @@ protected: void ProcessMessage(NetMessage* message) override; public: - GameServerConnection(shared_ptr socket); + GameServerConnection(shared_ptr socket, string serverPassword); virtual ~GameServerConnection(); ControlDeviceState GetState(); diff --git a/Core/HandShakeMessage.h b/Core/HandShakeMessage.h index 64f5feca..ce61e480 100644 --- a/Core/HandShakeMessage.h +++ b/Core/HandShakeMessage.h @@ -2,33 +2,38 @@ #include "stdafx.h" #include "NetMessage.h" #include "EmulationSettings.h" +#include "../Utilities/sha1.h" class HandShakeMessage : public NetMessage { private: - const static int CurrentVersion = 1; + const static int CurrentVersion = 2; uint32_t _mesenVersion = 0; uint32_t _protocolVersion = CurrentVersion; char* _playerName = nullptr; uint32_t _playerNameLength = 0; + char* _hashedPassword = nullptr; + uint32_t _hashedPasswordLength = 0; bool _spectator = false; - + protected: virtual void ProtectedStreamState() { Stream(_mesenVersion); Stream(_protocolVersion); StreamArray((void**)&_playerName, _playerNameLength); + StreamArray((void**)&_hashedPassword, _hashedPasswordLength); Stream(_spectator); } public: - HandShakeMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) { } - HandShakeMessage(string playerName, bool spectator) : NetMessage(MessageType::HandShake) + HandShakeMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) {} + HandShakeMessage(string playerName, string hashedPassword, bool spectator) : NetMessage(MessageType::HandShake) { _mesenVersion = EmulationSettings::GetMesenVersion(); _protocolVersion = HandShakeMessage::CurrentVersion; CopyString(&_playerName, _playerNameLength, playerName); + CopyString(&_hashedPassword, _hashedPasswordLength, hashedPassword); _spectator = spectator; } @@ -42,8 +47,20 @@ public: return _protocolVersion == CurrentVersion && _mesenVersion == EmulationSettings::GetMesenVersion(); } + bool CheckPassword(string serverPassword, string connectionHash) + { + return GetPasswordHash(serverPassword, connectionHash) == string(_hashedPassword); + } + bool IsSpectator() { return _spectator; } + + static string GetPasswordHash(string serverPassword, string connectionHash) + { + string saltedPassword = serverPassword + connectionHash; + vector dataToHash = vector(saltedPassword.c_str(), saltedPassword.c_str() + saltedPassword.size()); + return SHA1::GetHash(dataToHash); + } }; diff --git a/Core/MessageType.h b/Core/MessageType.h index 901e244e..c1318cc3 100644 --- a/Core/MessageType.h +++ b/Core/MessageType.h @@ -10,5 +10,6 @@ enum class MessageType : uint8_t GameInformation = 4, PlayerList = 5, SelectController = 6, - ForceDisconnect = 7 + ForceDisconnect = 7, + ServerInformation = 8 }; \ No newline at end of file diff --git a/Core/ServerInformationMessage.h b/Core/ServerInformationMessage.h new file mode 100644 index 00000000..fd14f3ae --- /dev/null +++ b/Core/ServerInformationMessage.h @@ -0,0 +1,28 @@ +#pragma once +#include "stdafx.h" +#include "NetMessage.h" + +class ServerInformationMessage : public NetMessage +{ +private: + char* _hashSalt = nullptr; + uint32_t _hashSaltLength = 0; + +protected: + virtual void ProtectedStreamState() + { + StreamArray((void**)&_hashSalt, _hashSaltLength); + } + +public: + ServerInformationMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) {} + ServerInformationMessage(string hashSalt) : NetMessage(MessageType::ServerInformation) + { + CopyString(&_hashSalt, _hashSaltLength, hashSalt); + } + + string GetHashSalt() + { + return string(_hashSalt); + } +}; diff --git a/GUI.NET/Config/ClientConnection.cs b/GUI.NET/Config/ClientConnection.cs index bd7f9887..cb1ea5eb 100644 --- a/GUI.NET/Config/ClientConnection.cs +++ b/GUI.NET/Config/ClientConnection.cs @@ -10,6 +10,7 @@ namespace Mesen.GUI.Config { public string Host = "localhost"; public UInt16 Port = 8888; + public string Password = ""; public bool Spectator = false; } } diff --git a/GUI.NET/Config/ServerInfo.cs b/GUI.NET/Config/ServerInfo.cs index 23be52fa..1c7cd2a4 100644 --- a/GUI.NET/Config/ServerInfo.cs +++ b/GUI.NET/Config/ServerInfo.cs @@ -10,9 +10,6 @@ namespace Mesen.GUI.Config { public string Name = "Default"; public UInt16 Port = 8888; - public string Password = null; - public int MaxPlayers = 4; - public bool AllowSpectators = true; - public bool PublicServer = false; + public string Password = ""; } } diff --git a/GUI.NET/Controls/MesenNumericUpDown.cs b/GUI.NET/Controls/MesenNumericUpDown.cs index 857e593a..1057bb40 100644 --- a/GUI.NET/Controls/MesenNumericUpDown.cs +++ b/GUI.NET/Controls/MesenNumericUpDown.cs @@ -159,9 +159,9 @@ namespace Mesen.GUI.Controls set { _minimum = value; SetValue(this.Value, true); } } - public decimal Increment { get; set; } + public decimal Increment { get; set; } = 1; - private int _decimalPlaces = 2; + private int _decimalPlaces = 0; public int DecimalPlaces { get { return _decimalPlaces; } diff --git a/GUI.NET/Dependencies/resources.ca.xml b/GUI.NET/Dependencies/resources.ca.xml index 5f37e4a9..e91e2167 100644 --- a/GUI.NET/Dependencies/resources.ca.xml +++ b/GUI.NET/Dependencies/resources.ca.xml @@ -440,6 +440,7 @@
Servidor: Port: + Contrasenya: Uneix-t'hi com a espectador D'acord Cancel·la diff --git a/GUI.NET/Dependencies/resources.en.xml b/GUI.NET/Dependencies/resources.en.xml index ccdd2cfa..ff4bc056 100644 --- a/GUI.NET/Dependencies/resources.en.xml +++ b/GUI.NET/Dependencies/resources.en.xml @@ -441,6 +441,7 @@ Host: Port: + Password: Join as spectator OK Cancel diff --git a/GUI.NET/Dependencies/resources.es.xml b/GUI.NET/Dependencies/resources.es.xml index 94d53aad..39965502 100644 --- a/GUI.NET/Dependencies/resources.es.xml +++ b/GUI.NET/Dependencies/resources.es.xml @@ -438,6 +438,7 @@ Servidor host: Puerto: + Contraseña: Unirse como espectador OK Cancelar diff --git a/GUI.NET/Dependencies/resources.fr.xml b/GUI.NET/Dependencies/resources.fr.xml index 17f5db28..d796905b 100644 --- a/GUI.NET/Dependencies/resources.fr.xml +++ b/GUI.NET/Dependencies/resources.fr.xml @@ -440,6 +440,7 @@ Serveur hôte: Port: + Mot de passe: Se joindre en tant que spectateur OK Annuler diff --git a/GUI.NET/Dependencies/resources.ja.xml b/GUI.NET/Dependencies/resources.ja.xml index 50d759b5..35e0dcc8 100644 --- a/GUI.NET/Dependencies/resources.ja.xml +++ b/GUI.NET/Dependencies/resources.ja.xml @@ -439,6 +439,7 @@ ホスト: ポート: + パスワード: 観客として接続する OK キャンセル diff --git a/GUI.NET/Dependencies/resources.pt.xml b/GUI.NET/Dependencies/resources.pt.xml index cf1d0b27..54266006 100644 --- a/GUI.NET/Dependencies/resources.pt.xml +++ b/GUI.NET/Dependencies/resources.pt.xml @@ -436,6 +436,7 @@ Servidor host: Port: + Senha: Entrar como espectador OK Cancelar diff --git a/GUI.NET/Dependencies/resources.ru.xml b/GUI.NET/Dependencies/resources.ru.xml index 093ee198..4f2a5878 100644 --- a/GUI.NET/Dependencies/resources.ru.xml +++ b/GUI.NET/Dependencies/resources.ru.xml @@ -437,6 +437,7 @@ Имя сервера: Порт: + Пароль: Войти как наблюдатель OK Отмена diff --git a/GUI.NET/Dependencies/resources.uk.xml b/GUI.NET/Dependencies/resources.uk.xml index 5d58e89c..9a3dd506 100644 --- a/GUI.NET/Dependencies/resources.uk.xml +++ b/GUI.NET/Dependencies/resources.uk.xml @@ -437,6 +437,7 @@ Iм'я сервера: Порт: + Пароль: Ввійти як спостерігач OK Вiдмiна diff --git a/GUI.NET/Forms/NetPlay/frmClientConfig.Designer.cs b/GUI.NET/Forms/NetPlay/frmClientConfig.Designer.cs index 63bdbb33..edad42cc 100644 --- a/GUI.NET/Forms/NetPlay/frmClientConfig.Designer.cs +++ b/GUI.NET/Forms/NetPlay/frmClientConfig.Designer.cs @@ -33,12 +33,14 @@ this.lblPort = new System.Windows.Forms.Label(); this.txtHost = new System.Windows.Forms.TextBox(); this.chkSpectator = new System.Windows.Forms.CheckBox(); + this.lblPassword = new System.Windows.Forms.Label(); + this.txtPassword = new System.Windows.Forms.TextBox(); this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // // baseConfigPanel // - this.baseConfigPanel.Location = new System.Drawing.Point(0, 111); + this.baseConfigPanel.Location = new System.Drawing.Point(0, 110); this.baseConfigPanel.Size = new System.Drawing.Size(290, 29); // // tableLayoutPanel1 @@ -46,28 +48,31 @@ this.tableLayoutPanel1.ColumnCount = 2; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.txtPassword, 1, 2); this.tableLayoutPanel1.Controls.Add(this.txtPort, 1, 1); this.tableLayoutPanel1.Controls.Add(this.lblHost, 0, 0); this.tableLayoutPanel1.Controls.Add(this.lblPort, 0, 1); this.tableLayoutPanel1.Controls.Add(this.txtHost, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.chkSpectator, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.chkSpectator, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.lblPassword, 0, 2); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(290, 111); + this.tableLayoutPanel1.Size = new System.Drawing.Size(290, 110); this.tableLayoutPanel1.TabIndex = 0; // // txtPort // this.txtPort.Dock = System.Windows.Forms.DockStyle.Fill; - this.txtPort.Location = new System.Drawing.Point(41, 29); + this.txtPort.Location = new System.Drawing.Point(65, 29); this.txtPort.Name = "txtPort"; - this.txtPort.Size = new System.Drawing.Size(246, 20); + this.txtPort.Size = new System.Drawing.Size(222, 20); this.txtPort.TabIndex = 6; this.txtPort.TextChanged += new System.EventHandler(this.Field_TextChanged); // @@ -94,9 +99,9 @@ // txtHost // this.txtHost.Dock = System.Windows.Forms.DockStyle.Fill; - this.txtHost.Location = new System.Drawing.Point(41, 3); + this.txtHost.Location = new System.Drawing.Point(65, 3); this.txtHost.Name = "txtHost"; - this.txtHost.Size = new System.Drawing.Size(246, 20); + this.txtHost.Size = new System.Drawing.Size(222, 20); this.txtHost.TabIndex = 5; this.txtHost.TextChanged += new System.EventHandler(this.Field_TextChanged); // @@ -104,18 +109,36 @@ // this.chkSpectator.AutoSize = true; this.tableLayoutPanel1.SetColumnSpan(this.chkSpectator, 2); - this.chkSpectator.Location = new System.Drawing.Point(3, 55); + this.chkSpectator.Location = new System.Drawing.Point(3, 81); this.chkSpectator.Name = "chkSpectator"; this.chkSpectator.Size = new System.Drawing.Size(106, 17); this.chkSpectator.TabIndex = 7; this.chkSpectator.Text = "Join as spectator"; this.chkSpectator.UseVisualStyleBackColor = true; // + // lblPassword + // + this.lblPassword.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPassword.AutoSize = true; + this.lblPassword.Location = new System.Drawing.Point(3, 58); + this.lblPassword.Name = "lblPassword"; + this.lblPassword.Size = new System.Drawing.Size(56, 13); + this.lblPassword.TabIndex = 8; + this.lblPassword.Text = "Password:"; + // + // txtPassword + // + this.txtPassword.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtPassword.Location = new System.Drawing.Point(65, 55); + this.txtPassword.Name = "txtPassword"; + this.txtPassword.Size = new System.Drawing.Size(222, 20); + this.txtPassword.TabIndex = 9; + // // frmClientConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(290, 140); + this.ClientSize = new System.Drawing.Size(290, 139); this.Controls.Add(this.tableLayoutPanel1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MaximizeBox = false; @@ -141,5 +164,7 @@ private System.Windows.Forms.Label lblPort; private System.Windows.Forms.TextBox txtHost; private System.Windows.Forms.CheckBox chkSpectator; + private System.Windows.Forms.TextBox txtPassword; + private System.Windows.Forms.Label lblPassword; } } \ No newline at end of file diff --git a/GUI.NET/Forms/NetPlay/frmClientConfig.cs b/GUI.NET/Forms/NetPlay/frmClientConfig.cs index 1c626536..2402cfd9 100644 --- a/GUI.NET/Forms/NetPlay/frmClientConfig.cs +++ b/GUI.NET/Forms/NetPlay/frmClientConfig.cs @@ -21,6 +21,7 @@ namespace Mesen.GUI.Forms.NetPlay Entity = ConfigManager.Config.ClientConnectionInfo; AddBinding("Host", this.txtHost); + AddBinding("Password", this.txtPassword); AddBinding("Spectator", chkSpectator); this.txtPort.Text = ConfigManager.Config.ClientConnectionInfo.Port.ToString(); } diff --git a/GUI.NET/Forms/NetPlay/frmServerConfig.Designer.cs b/GUI.NET/Forms/NetPlay/frmServerConfig.Designer.cs index 4c6f103e..ed335ec1 100644 --- a/GUI.NET/Forms/NetPlay/frmServerConfig.Designer.cs +++ b/GUI.NET/Forms/NetPlay/frmServerConfig.Designer.cs @@ -32,20 +32,16 @@ namespace Mesen.GUI.Forms.NetPlay this.tlpMain = new System.Windows.Forms.TableLayoutPanel(); this.txtPort = new System.Windows.Forms.TextBox(); this.lblPort = new System.Windows.Forms.Label(); - this.chkPublicServer = new System.Windows.Forms.CheckBox(); this.lblServerName = new System.Windows.Forms.Label(); this.txtServerName = new System.Windows.Forms.TextBox(); - this.chkSpectator = new System.Windows.Forms.CheckBox(); - this.lblMaxPlayers = new System.Windows.Forms.Label(); this.lblPassword = new System.Windows.Forms.Label(); this.txtPassword = new System.Windows.Forms.TextBox(); - this.nudNbPlayers = new MesenNumericUpDown(); this.tlpMain.SuspendLayout(); this.SuspendLayout(); // // baseConfigPanel // - this.baseConfigPanel.Location = new System.Drawing.Point(0, 161); + this.baseConfigPanel.Location = new System.Drawing.Point(0, 98); this.baseConfigPanel.Size = new System.Drawing.Size(302, 29); // // tlpMain @@ -55,34 +51,28 @@ namespace Mesen.GUI.Forms.NetPlay this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tlpMain.Controls.Add(this.txtPort, 1, 1); this.tlpMain.Controls.Add(this.lblPort, 0, 1); - this.tlpMain.Controls.Add(this.chkPublicServer, 0, 4); this.tlpMain.Controls.Add(this.lblServerName, 0, 0); this.tlpMain.Controls.Add(this.txtServerName, 1, 0); - this.tlpMain.Controls.Add(this.chkSpectator, 0, 5); - this.tlpMain.Controls.Add(this.lblMaxPlayers, 0, 3); this.tlpMain.Controls.Add(this.lblPassword, 0, 2); this.tlpMain.Controls.Add(this.txtPassword, 1, 2); - this.tlpMain.Controls.Add(this.nudNbPlayers, 1, 3); this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill; this.tlpMain.Location = new System.Drawing.Point(0, 0); this.tlpMain.Name = "tlpMain"; - this.tlpMain.RowCount = 7; - this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpMain.RowCount = 4; this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpMain.Size = new System.Drawing.Size(302, 161); + this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tlpMain.Size = new System.Drawing.Size(302, 98); this.tlpMain.TabIndex = 1; // // txtPort // this.txtPort.Dock = System.Windows.Forms.DockStyle.Fill; - this.txtPort.Location = new System.Drawing.Point(128, 29); + this.txtPort.Location = new System.Drawing.Point(79, 29); this.txtPort.Name = "txtPort"; - this.txtPort.Size = new System.Drawing.Size(171, 20); + this.txtPort.Size = new System.Drawing.Size(220, 20); this.txtPort.TabIndex = 13; this.txtPort.TextChanged += new System.EventHandler(this.Field_ValueChanged); // @@ -96,19 +86,6 @@ namespace Mesen.GUI.Forms.NetPlay this.lblPort.TabIndex = 12; this.lblPort.Text = "Port:"; // - // chkPublicServer - // - this.chkPublicServer.AutoSize = true; - this.tlpMain.SetColumnSpan(this.chkPublicServer, 2); - this.chkPublicServer.Enabled = false; - this.chkPublicServer.Location = new System.Drawing.Point(3, 107); - this.chkPublicServer.Name = "chkPublicServer"; - this.chkPublicServer.Size = new System.Drawing.Size(87, 17); - this.chkPublicServer.TabIndex = 11; - this.chkPublicServer.Text = "Public server"; - this.chkPublicServer.UseVisualStyleBackColor = true; - this.chkPublicServer.CheckedChanged += new System.EventHandler(this.Field_ValueChanged); - // // lblServerName // this.lblServerName.Anchor = System.Windows.Forms.AnchorStyles.Left; @@ -122,35 +99,12 @@ namespace Mesen.GUI.Forms.NetPlay // txtServerName // this.txtServerName.Dock = System.Windows.Forms.DockStyle.Fill; - this.txtServerName.Location = new System.Drawing.Point(128, 3); + this.txtServerName.Location = new System.Drawing.Point(79, 3); this.txtServerName.Name = "txtServerName"; - this.txtServerName.Size = new System.Drawing.Size(171, 20); + this.txtServerName.Size = new System.Drawing.Size(220, 20); this.txtServerName.TabIndex = 5; this.txtServerName.TextChanged += new System.EventHandler(this.Field_ValueChanged); // - // chkSpectator - // - this.chkSpectator.AutoSize = true; - this.tlpMain.SetColumnSpan(this.chkSpectator, 2); - this.chkSpectator.Enabled = false; - this.chkSpectator.Location = new System.Drawing.Point(3, 130); - this.chkSpectator.Name = "chkSpectator"; - this.chkSpectator.Size = new System.Drawing.Size(103, 17); - this.chkSpectator.TabIndex = 7; - this.chkSpectator.Text = "Allow spectators"; - this.chkSpectator.UseVisualStyleBackColor = true; - this.chkSpectator.CheckedChanged += new System.EventHandler(this.Field_ValueChanged); - // - // lblMaxPlayers - // - this.lblMaxPlayers.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.lblMaxPlayers.AutoSize = true; - this.lblMaxPlayers.Location = new System.Drawing.Point(3, 84); - this.lblMaxPlayers.Name = "lblMaxPlayers"; - this.lblMaxPlayers.Size = new System.Drawing.Size(119, 13); - this.lblMaxPlayers.TabIndex = 4; - this.lblMaxPlayers.Text = "Max. number of players:"; - // // lblPassword // this.lblPassword.Anchor = System.Windows.Forms.AnchorStyles.Left; @@ -164,43 +118,18 @@ namespace Mesen.GUI.Forms.NetPlay // txtPassword // this.txtPassword.Dock = System.Windows.Forms.DockStyle.Fill; - this.txtPassword.Enabled = false; - this.txtPassword.Location = new System.Drawing.Point(128, 55); + this.txtPassword.Location = new System.Drawing.Point(79, 55); this.txtPassword.Name = "txtPassword"; - this.txtPassword.Size = new System.Drawing.Size(171, 20); + this.txtPassword.Size = new System.Drawing.Size(220, 20); this.txtPassword.TabIndex = 10; this.txtPassword.UseSystemPasswordChar = true; this.txtPassword.TextChanged += new System.EventHandler(this.Field_ValueChanged); // - // nudNbPlayers - // - this.nudNbPlayers.Enabled = false; - this.nudNbPlayers.Location = new System.Drawing.Point(128, 81); - this.nudNbPlayers.Maximum = new decimal(new int[] { - 4, - 0, - 0, - 0}); - this.nudNbPlayers.Minimum = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.nudNbPlayers.Name = "nudNbPlayers"; - this.nudNbPlayers.Size = new System.Drawing.Size(35, 20); - this.nudNbPlayers.TabIndex = 8; - this.nudNbPlayers.Value = new decimal(new int[] { - 4, - 0, - 0, - 0}); - this.nudNbPlayers.ValueChanged += new System.EventHandler(this.Field_ValueChanged); - // // frmServerConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(302, 190); + this.ClientSize = new System.Drawing.Size(302, 127); this.Controls.Add(this.tlpMain); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MaximizeBox = false; @@ -220,11 +149,7 @@ namespace Mesen.GUI.Forms.NetPlay private System.Windows.Forms.TableLayoutPanel tlpMain; private System.Windows.Forms.Label lblServerName; - private System.Windows.Forms.Label lblMaxPlayers; private System.Windows.Forms.TextBox txtServerName; - private System.Windows.Forms.CheckBox chkSpectator; - private MesenNumericUpDown nudNbPlayers; - private System.Windows.Forms.CheckBox chkPublicServer; private System.Windows.Forms.Label lblPassword; private System.Windows.Forms.TextBox txtPassword; private System.Windows.Forms.Label lblPort; diff --git a/GUI.NET/Forms/NetPlay/frmServerConfig.cs b/GUI.NET/Forms/NetPlay/frmServerConfig.cs index 88be4c82..324681d5 100644 --- a/GUI.NET/Forms/NetPlay/frmServerConfig.cs +++ b/GUI.NET/Forms/NetPlay/frmServerConfig.cs @@ -20,9 +20,6 @@ namespace Mesen.GUI.Forms.NetPlay this.txtServerName.Text = ConfigManager.Config.ServerInfo.Name; this.txtPort.Text = ConfigManager.Config.ServerInfo.Port.ToString(); this.txtPassword.Text = string.Empty; - this.nudNbPlayers.Value = ConfigManager.Config.ServerInfo.MaxPlayers; - this.chkSpectator.Checked = ConfigManager.Config.ServerInfo.AllowSpectators; - this.chkPublicServer.Checked = ConfigManager.Config.ServerInfo.PublicServer; } protected override void UpdateConfig() @@ -30,10 +27,7 @@ namespace Mesen.GUI.Forms.NetPlay ConfigManager.Config.ServerInfo = new ServerInfo() { Name = this.txtServerName.Text, Port = Convert.ToUInt16(this.txtPort.Text), - Password = BitConverter.ToString(System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(this.txtPassword.Text))).Replace("-", ""), - MaxPlayers = (int)this.nudNbPlayers.Value, - AllowSpectators = this.chkSpectator.Checked, - PublicServer = this.chkPublicServer.Checked + Password = this.txtPassword.Text }; } diff --git a/GUI.NET/Forms/frmMain.Tools.cs b/GUI.NET/Forms/frmMain.Tools.cs index dafa340e..a9120dcd 100644 --- a/GUI.NET/Forms/frmMain.Tools.cs +++ b/GUI.NET/Forms/frmMain.Tools.cs @@ -150,7 +150,7 @@ namespace Mesen.GUI.Forms } else { using(frmServerConfig frm = new frmServerConfig()) { if(frm.ShowDialog(sender, this) == System.Windows.Forms.DialogResult.OK) { - InteropEmu.StartServer(ConfigManager.Config.ServerInfo.Port, ConfigManager.Config.Profile.PlayerName); + InteropEmu.StartServer(ConfigManager.Config.ServerInfo.Port, ConfigManager.Config.ServerInfo.Password, ConfigManager.Config.Profile.PlayerName); } } } @@ -164,7 +164,13 @@ namespace Mesen.GUI.Forms using(frmClientConfig frm = new frmClientConfig()) { if(frm.ShowDialog(sender, this) == System.Windows.Forms.DialogResult.OK) { Task.Run(() => { - InteropEmu.Connect(ConfigManager.Config.ClientConnectionInfo.Host, ConfigManager.Config.ClientConnectionInfo.Port, ConfigManager.Config.Profile.PlayerName, ConfigManager.Config.ClientConnectionInfo.Spectator); + InteropEmu.Connect( + ConfigManager.Config.ClientConnectionInfo.Host, + ConfigManager.Config.ClientConnectionInfo.Port, + ConfigManager.Config.ClientConnectionInfo.Password, + ConfigManager.Config.Profile.PlayerName, + ConfigManager.Config.ClientConnectionInfo.Spectator + ); }); } } diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 9be5e96b..ba2af614 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -78,10 +78,10 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void Reset(); [DllImport(DLLPath)] public static extern void ResetLagCounter(); - [DllImport(DLLPath)] public static extern void StartServer(UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string hostPlayerName); + [DllImport(DLLPath)] public static extern void StartServer(UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string password, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string hostPlayerName); [DllImport(DLLPath)] public static extern void StopServer(); [DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsServerRunning(); - [DllImport(DLLPath)] public static extern void Connect([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string host, UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string playerName, [MarshalAs(UnmanagedType.I1)]bool spectator); + [DllImport(DLLPath)] public static extern void Connect([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string host, UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string password, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string playerName, [MarshalAs(UnmanagedType.I1)]bool spectator); [DllImport(DLLPath)] public static extern void Disconnect(); [DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsConnected(); diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 181d5e24..43f0b078 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -262,19 +262,13 @@ namespace InteropEmu { DllExport void __stdcall PowerCycle() { Console::Reset(false); } DllExport void __stdcall ResetLagCounter() { Console::ResetLagCounter(); } - DllExport void __stdcall StartServer(uint16_t port, char* hostPlayerName) { GameServer::StartServer(port, hostPlayerName); } + DllExport void __stdcall StartServer(uint16_t port, char* password, char* hostPlayerName) { GameServer::StartServer(port, password, hostPlayerName); } DllExport void __stdcall StopServer() { GameServer::StopServer(); } DllExport bool __stdcall IsServerRunning() { return GameServer::Started(); } - DllExport void __stdcall Connect(char* host, uint16_t port, char* playerName, bool spectator) + DllExport void __stdcall Connect(char* host, uint16_t port, char* password, char* playerName, bool spectator) { - shared_ptr connectionData(new ClientConnectionData( - host, - port, - playerName, - spectator - )); - + ClientConnectionData connectionData(host, port, password, playerName, spectator); GameClient::Connect(connectionData); }