diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 20dd7542..1fbcb7e6 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -370,6 +370,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index f0a30f19..5fa0d3fa 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -545,6 +545,9 @@ NetPlay\Messages + + NetPlay\Messages + diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp index 7bebd9f5..50f8f1ce 100644 --- a/Core/EmulationSettings.cpp +++ b/Core/EmulationSettings.cpp @@ -17,6 +17,10 @@ uint32_t EmulationSettings::PpuPaletteArgb[64] = { 0xFFB5EBF2, 0xFFB8B8B8, 0xFF000000, 0xFF000000, }; +uint16_t EmulationSettings::_versionMajor = 0; +uint8_t EmulationSettings::_versionMinor = 1; +uint8_t EmulationSettings::_versionRevision = 0; + uint32_t EmulationSettings::_flags = 0; uint32_t EmulationSettings::_audioLatency = 20000; diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index 1ca1703c..8b8b4766 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -143,6 +143,11 @@ struct KeyMappingSet class EmulationSettings { private: + //Version 0.1.0 + static uint16_t _versionMajor; + static uint8_t _versionMinor; + static uint8_t _versionRevision; + static uint32_t PpuPaletteArgb[64]; static uint32_t _flags; @@ -170,12 +175,12 @@ private: public: static uint32_t GetMesenVersion() { - //Version 0.1.0 - uint16_t major = 0; - uint8_t minor = 1; - uint8_t revision = 0; + return (_versionMajor << 16) | (_versionMinor << 8) | _versionRevision; + } - return (major << 16) | (minor << 8) | revision; + static string GetMesenVersionString() + { + return std::to_string(_versionMajor) + "." + std::to_string(_versionMinor) + "." + std::to_string(_versionRevision); } static void SetFlags(EmulationFlags flags) diff --git a/Core/ForceDisconnectMessage.h b/Core/ForceDisconnectMessage.h new file mode 100644 index 00000000..894bd16a --- /dev/null +++ b/Core/ForceDisconnectMessage.h @@ -0,0 +1,33 @@ +#pragma once +#include "stdafx.h" +#include "MessageManager.h" +#include "NetMessage.h" +#include "Console.h" +#include "RomLoader.h" +#include "../Utilities/FolderUtilities.h" + +class ForceDisconnectMessage : public NetMessage +{ +private: + char* _disconnectMessage = nullptr; + uint32_t _messageLength = 0; + +protected: + virtual void ProtectedStreamState() + { + StreamArray((void**)&_disconnectMessage, _messageLength); + } + +public: + ForceDisconnectMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) { } + + ForceDisconnectMessage(string message) : NetMessage(MessageType::ForceDisconnect) + { + CopyString(&_disconnectMessage, _messageLength, message); + } + + string GetMessage() + { + return _disconnectMessage; + } +}; \ No newline at end of file diff --git a/Core/GameClientConnection.cpp b/Core/GameClientConnection.cpp index c52aa140..0bda8677 100644 --- a/Core/GameClientConnection.cpp +++ b/Core/GameClientConnection.cpp @@ -12,6 +12,7 @@ #include "StandardController.h" #include "SelectControllerMessage.h" #include "PlayerListMessage.h" +#include "ForceDisconnectMessage.h" GameClientConnection::GameClientConnection(shared_ptr socket, shared_ptr connectionData) : GameConnection(socket, connectionData) { @@ -76,6 +77,10 @@ void GameClientConnection::ProcessMessage(NetMessage* message) } break; + case MessageType::ForceDisconnect: + MessageManager::DisplayMessage("Net Play", ((ForceDisconnectMessage*)message)->GetMessage()); + break; + case MessageType::PlayerList: _playerList = ((PlayerListMessage*)message)->GetPlayerList(); break; diff --git a/Core/GameConnection.cpp b/Core/GameConnection.cpp index 1cab2c29..910b3c33 100644 --- a/Core/GameConnection.cpp +++ b/Core/GameConnection.cpp @@ -8,6 +8,7 @@ #include "PlayerListMessage.h" #include "SelectControllerMessage.h" #include "ClientConnectionData.h" +#include "ForceDisconnectMessage.h" GameConnection::GameConnection(shared_ptr socket, shared_ptr connectionData) { @@ -58,6 +59,7 @@ NetMessage* GameConnection::ReadMessage() case MessageType::GameInformation: return new GameInformationMessage(_messageBuffer, messageLength); case MessageType::PlayerList: return new PlayerListMessage(_messageBuffer, messageLength); case MessageType::SelectController: return new SelectControllerMessage(_messageBuffer, messageLength); + case MessageType::ForceDisconnect: return new ForceDisconnectMessage(_messageBuffer, messageLength); } } return nullptr; @@ -70,6 +72,11 @@ void GameConnection::SendNetMessage(NetMessage &message) _socketLock.Release(); } +void GameConnection::Disconnect() +{ + _socket->Close(); +} + bool GameConnection::ConnectionError() { return _socket->ConnectionError(); diff --git a/Core/GameConnection.h b/Core/GameConnection.h index ba233014..ad7e94a3 100644 --- a/Core/GameConnection.h +++ b/Core/GameConnection.h @@ -31,6 +31,9 @@ private: virtual void ProcessMessage(NetMessage* message) = 0; +protected: + void Disconnect(); + public: static const uint8_t SpectatorPort = 0xFF; GameConnection(shared_ptr socket, shared_ptr connectionData); diff --git a/Core/GameServerConnection.cpp b/Core/GameServerConnection.cpp index 847a9a37..bd97030d 100644 --- a/Core/GameServerConnection.cpp +++ b/Core/GameServerConnection.cpp @@ -14,6 +14,7 @@ #include "SelectControllerMessage.h" #include "PlayerListMessage.h" #include "GameServer.h" +#include "ForceDisconnectMessage.h" GameServerConnection* GameServerConnection::_netPlayDevices[4] = { nullptr,nullptr,nullptr,nullptr }; @@ -28,8 +29,6 @@ GameServerConnection::~GameServerConnection() { if(_connectionData) { MessageManager::DisplayToast("Net Play", _connectionData->PlayerName + " (Player " + std::to_string(_controllerPort + 1) + ") disconnected.", _connectionData->AvatarData, _connectionData->AvatarSize); - } else { - MessageManager::DisplayMessage("Net Play", "Player " + std::to_string(_controllerPort + 1) + " disconnected."); } UnregisterNetPlayDevice(this); @@ -54,6 +53,13 @@ void GameServerConnection::SendMovieData(uint8_t state, uint8_t port) } } +void GameServerConnection::SendForceDisconnectMessage(string disconnectMessage) +{ + ForceDisconnectMessage message(disconnectMessage); + SendNetMessage(message); + Disconnect(); +} + void GameServerConnection::PushState(uint32_t state) { if(_inputData.size() == 0 || state != _inputData.back()) { @@ -96,6 +102,9 @@ void GameServerConnection::ProcessHandshakeResponse(HandShakeMessage* message) 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("Net Play", message->GetPlayerName() + " is not running the same version of Mesen and has been disconnected"); } } diff --git a/Core/GameServerConnection.h b/Core/GameServerConnection.h index 9e0521d9..efeffc4c 100644 --- a/Core/GameServerConnection.h +++ b/Core/GameServerConnection.h @@ -20,6 +20,8 @@ private: void SendGameInformation(); void SelectControllerPort(uint8_t port); + void SendForceDisconnectMessage(string disconnectMessage); + void ProcessHandshakeResponse(HandShakeMessage* message); static void RegisterNetPlayDevice(GameServerConnection* connection, uint8_t port); diff --git a/Core/HandShakeMessage.h b/Core/HandShakeMessage.h index f55e4665..f01e62c0 100644 --- a/Core/HandShakeMessage.h +++ b/Core/HandShakeMessage.h @@ -1,11 +1,13 @@ #pragma once #include "stdafx.h" #include "NetMessage.h" +#include "EmulationSettings.h" class HandShakeMessage : public NetMessage { private: const static int CurrentVersion = 1; + uint32_t _mesenVersion = 0; uint32_t _protocolVersion = CurrentVersion; char* _playerName = nullptr; uint32_t _playerNameLength = 0; @@ -16,6 +18,7 @@ private: protected: virtual void ProtectedStreamState() { + Stream(_mesenVersion); Stream(_protocolVersion); StreamArray((void**)&_playerName, _playerNameLength); StreamArray(&_avatarData, _avatarSize); @@ -26,13 +29,14 @@ public: HandShakeMessage(void* buffer, uint32_t length) : NetMessage(buffer, length) { } HandShakeMessage(string playerName, uint8_t* avatarData, uint32_t avatarSize, bool spectator) : NetMessage(MessageType::HandShake) { - _protocolVersion = 1; + _mesenVersion = EmulationSettings::GetMesenVersion(); + _protocolVersion = HandShakeMessage::CurrentVersion; CopyString(&_playerName, _playerNameLength, playerName); _avatarSize = avatarSize; _avatarData = avatarData; _spectator = spectator; } - + string GetPlayerName() { return string(_playerName); @@ -50,7 +54,7 @@ public: bool IsValid() { - return _protocolVersion == CurrentVersion; + return _protocolVersion == CurrentVersion && _mesenVersion == EmulationSettings::GetMesenVersion(); } bool IsSpectator() diff --git a/Core/MessageType.h b/Core/MessageType.h index 99d03822..901e244e 100644 --- a/Core/MessageType.h +++ b/Core/MessageType.h @@ -10,4 +10,5 @@ enum class MessageType : uint8_t GameInformation = 4, PlayerList = 5, SelectController = 6, + ForceDisconnect = 7 }; \ No newline at end of file