2019-10-20 20:05:39 -04:00
# include "stdafx.h"
# include "GameClientConnection.h"
# include "HandShakeMessage.h"
# include "InputDataMessage.h"
# include "MovieDataMessage.h"
# include "GameInformationMessage.h"
# include "SaveStateMessage.h"
# include "Console.h"
# include "EmuSettings.h"
# include "ControlManager.h"
# include "ClientConnectionData.h"
# include "SnesController.h"
# include "SelectControllerMessage.h"
# include "PlayerListMessage.h"
# include "ForceDisconnectMessage.h"
# include "ServerInformationMessage.h"
# include "NotificationManager.h"
# include "RomFinder.h"
2021-03-10 11:13:28 -05:00
GameClientConnection : : GameClientConnection ( shared_ptr < Console > console , shared_ptr < Socket > socket , ClientConnectionData & connectionData ) : GameConnection ( console , socket )
2019-10-20 20:05:39 -04:00
{
_connectionData = connectionData ;
_shutdown = false ;
_enableControllers = false ;
_minimumQueueSize = 3 ;
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectedToServer " ) ;
}
GameClientConnection : : ~ GameClientConnection ( )
{
Shutdown ( ) ;
}
void GameClientConnection : : Shutdown ( )
{
2021-03-10 11:13:28 -05:00
if ( ! _shutdown ) {
2019-10-20 20:05:39 -04:00
_shutdown = true ;
DisableControllers ( ) ;
shared_ptr < ControlManager > controlManager = _console - > GetControlManager ( ) ;
2021-03-10 11:13:28 -05:00
if ( controlManager ) {
2019-10-20 20:05:39 -04:00
controlManager - > UnregisterInputProvider ( this ) ;
}
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectionLost " ) ;
_console - > GetSettings ( ) - > ClearFlag ( EmulationFlags : : MaximumSpeed ) ;
}
}
void GameClientConnection : : SendHandshake ( )
{
2021-03-10 11:13:28 -05:00
HandShakeMessage message ( _connectionData . PlayerName , HandShakeMessage : : GetPasswordHash ( _connectionData . Password , _serverSalt ) , _connectionData . Spectator , _console - > GetSettings ( ) - > GetVersion ( ) ) ;
2019-10-20 20:05:39 -04:00
SendNetMessage ( message ) ;
}
void GameClientConnection : : SendControllerSelection ( uint8_t port )
{
SelectControllerMessage message ( port ) ;
SendNetMessage ( message ) ;
}
void GameClientConnection : : ClearInputData ( )
{
LockHandler lock = _writeLock . AcquireSafe ( ) ;
2021-03-10 11:13:28 -05:00
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
2019-10-20 20:05:39 -04:00
_inputSize [ i ] = 0 ;
_inputData [ i ] . clear ( ) ;
}
}
void GameClientConnection : : ProcessMessage ( NetMessage * message )
{
GameInformationMessage * gameInfo ;
2021-03-10 11:13:28 -05:00
switch ( message - > GetType ( ) ) {
case MessageType : : ServerInformation :
_serverSalt = ( ( ServerInformationMessage * ) message ) - > GetHashSalt ( ) ;
SendHandshake ( ) ;
break ;
case MessageType : : SaveState :
if ( _gameLoaded ) {
DisableControllers ( ) ;
_console - > Lock ( ) ;
ClearInputData ( ) ;
( ( SaveStateMessage * ) message ) - > LoadState ( _console ) ;
_enableControllers = true ;
InitControlDevice ( ) ;
_console - > Unlock ( ) ;
}
break ;
2019-10-20 20:05:39 -04:00
2021-03-10 11:13:28 -05:00
case MessageType : : MovieData :
if ( _gameLoaded ) {
PushControllerState ( ( ( MovieDataMessage * ) message ) - > GetPortNumber ( ) , ( ( MovieDataMessage * ) message ) - > GetInputState ( ) ) ;
}
break ;
2019-10-20 20:05:39 -04:00
2021-03-10 11:13:28 -05:00
case MessageType : : ForceDisconnect :
MessageManager : : DisplayMessage ( " NetPlay " , ( ( ForceDisconnectMessage * ) message ) - > GetMessage ( ) ) ;
break ;
2019-10-20 20:05:39 -04:00
2021-03-10 11:13:28 -05:00
case MessageType : : PlayerList :
_playerList = ( ( PlayerListMessage * ) message ) - > GetPlayerList ( ) ;
break ;
2020-12-19 23:30:09 +03:00
2021-03-10 11:13:28 -05:00
case MessageType : : GameInformation :
DisableControllers ( ) ;
_console - > Lock ( ) ;
gameInfo = ( GameInformationMessage * ) message ;
if ( gameInfo - > GetPort ( ) ! = _controllerPort ) {
_controllerPort = gameInfo - > GetPort ( ) ;
if ( _controllerPort = = GameConnection : : SpectatorPort ) {
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectedAsSpectator " ) ;
} else {
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectedAsPlayer " , std : : to_string ( _controllerPort + 1 ) ) ;
}
2020-12-19 23:30:09 +03:00
}
2019-10-20 20:05:39 -04:00
2021-03-10 11:13:28 -05:00
ClearInputData ( ) ;
_console - > Unlock ( ) ;
2019-10-20 20:05:39 -04:00
2021-03-10 11:13:28 -05:00
_gameLoaded = AttemptLoadGame ( gameInfo - > GetRomFilename ( ) , gameInfo - > GetSha1Hash ( ) ) ;
if ( ! _gameLoaded ) {
_console - > Stop ( true ) ;
} else {
_console - > GetControlManager ( ) - > UnregisterInputProvider ( this ) ;
_console - > GetControlManager ( ) - > RegisterInputProvider ( this ) ;
if ( gameInfo - > IsPaused ( ) ) {
_console - > Pause ( ) ;
} else {
_console - > Resume ( ) ;
}
2019-10-20 20:05:39 -04:00
}
2021-03-10 11:13:28 -05:00
break ;
default :
break ;
2019-10-20 20:05:39 -04:00
}
}
bool GameClientConnection : : AttemptLoadGame ( string filename , string sha1Hash )
{
2021-03-10 11:13:28 -05:00
if ( filename . size ( ) > 0 ) {
if ( ! RomFinder : : LoadMatchingRom ( _console . get ( ) , filename , sha1Hash ) ) {
2019-10-20 20:05:39 -04:00
MessageManager : : DisplayMessage ( " NetPlay " , " CouldNotFindRom " , filename ) ;
return false ;
2021-03-10 11:13:28 -05:00
} else {
2019-10-20 20:05:39 -04:00
return true ;
}
}
return false ;
}
void GameClientConnection : : PushControllerState ( uint8_t port , ControlDeviceState state )
{
LockHandler lock = _writeLock . AcquireSafe ( ) ;
_inputData [ port ] . push_back ( state ) ;
_inputSize [ port ] + + ;
2021-03-10 11:13:28 -05:00
if ( _inputData [ port ] . size ( ) > = _minimumQueueSize ) {
2019-10-20 20:05:39 -04:00
_waitForInput [ port ] . Signal ( ) ;
}
}
void GameClientConnection : : DisableControllers ( )
{
//Used to prevent deadlocks when client is trying to fill its buffer while the host changes the current game/settings/etc. (i.e situations where we need to call Console::Pause())
_enableControllers = false ;
2019-10-24 20:52:20 -04:00
ClearInputData ( ) ;
2021-03-10 11:13:28 -05:00
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
2019-10-20 20:05:39 -04:00
_waitForInput [ i ] . Signal ( ) ;
}
}
2021-03-10 11:13:28 -05:00
bool GameClientConnection : : SetInput ( BaseControlDevice * device )
2019-10-20 20:05:39 -04:00
{
2021-03-10 11:13:28 -05:00
if ( _enableControllers ) {
2019-10-20 20:05:39 -04:00
uint8_t port = device - > GetPort ( ) ;
2021-03-10 11:13:28 -05:00
while ( _inputSize [ port ] = = 0 ) {
2019-10-20 20:05:39 -04:00
_waitForInput [ port ] . Wait ( ) ;
2021-03-10 11:13:28 -05:00
if ( port = = 0 & & _minimumQueueSize < 10 ) {
2019-10-20 20:05:39 -04:00
//Increase buffer size - reduces freezes at the cost of additional lag
_minimumQueueSize + + ;
}
2021-03-10 11:13:28 -05:00
if ( _shutdown | | ! _enableControllers ) {
2019-10-20 20:05:39 -04:00
return true ;
}
}
LockHandler lock = _writeLock . AcquireSafe ( ) ;
2021-03-10 11:13:28 -05:00
if ( _shutdown | | ! _enableControllers | | _inputSize [ port ] = = 0 ) {
2019-10-24 20:52:20 -04:00
return true ;
}
2019-10-20 20:05:39 -04:00
ControlDeviceState state = _inputData [ port ] . front ( ) ;
_inputData [ port ] . pop_front ( ) ;
_inputSize [ port ] - - ;
2021-03-10 11:13:28 -05:00
if ( _inputData [ port ] . size ( ) > _minimumQueueSize ) {
2019-10-20 20:05:39 -04:00
//Too much data, catch up
_console - > GetSettings ( ) - > SetFlag ( EmulationFlags : : MaximumSpeed ) ;
2021-03-10 11:13:28 -05:00
} else {
2019-10-20 20:05:39 -04:00
_console - > GetSettings ( ) - > ClearFlag ( EmulationFlags : : MaximumSpeed ) ;
}
device - > SetRawState ( state ) ;
}
return true ;
}
void GameClientConnection : : InitControlDevice ( )
{
//Pretend we are using port 0 (to use player 1's keybindings during netplay)
2021-03-10 11:13:28 -05:00
_newControlDevice = ControlManager : : CreateControllerDevice ( _console - > GetSettings ( ) - > GetInputConfig ( ) . Controllers [ _controllerPort ] . Type , 0 , _console . get ( ) ) ;
2019-10-20 20:05:39 -04:00
}
void GameClientConnection : : ProcessNotification ( ConsoleNotificationType type , void * parameter )
{
2021-03-10 11:13:28 -05:00
if ( type = = ConsoleNotificationType : : ConfigChanged ) {
2019-10-20 20:05:39 -04:00
InitControlDevice ( ) ;
2021-03-10 11:13:28 -05:00
} else if ( type = = ConsoleNotificationType : : GameLoaded ) {
2019-10-20 20:05:39 -04:00
_console - > GetControlManager ( ) - > RegisterInputProvider ( this ) ;
}
}
void GameClientConnection : : SendInput ( )
{
2021-03-10 11:13:28 -05:00
if ( _gameLoaded ) {
if ( _newControlDevice ) {
2019-10-20 20:05:39 -04:00
_controlDevice = _newControlDevice ;
_newControlDevice . reset ( ) ;
}
ControlDeviceState inputState ;
2021-03-10 11:13:28 -05:00
if ( _controlDevice ) {
2019-10-20 20:05:39 -04:00
_controlDevice - > SetStateFromInput ( ) ;
inputState = _controlDevice - > GetRawState ( ) ;
}
2021-03-10 11:13:28 -05:00
if ( _lastInputSent ! = inputState ) {
2019-10-20 20:05:39 -04:00
InputDataMessage message ( inputState ) ;
SendNetMessage ( message ) ;
_lastInputSent = inputState ;
}
}
}
void GameClientConnection : : SelectController ( uint8_t port )
{
SendControllerSelection ( port ) ;
}
uint8_t GameClientConnection : : GetAvailableControllers ( )
{
uint8_t availablePorts = ( 1 < < BaseControlDevice : : PortCount ) - 1 ;
2021-03-10 11:13:28 -05:00
for ( PlayerInfo & playerInfo : _playerList ) {
if ( playerInfo . ControllerPort < BaseControlDevice : : PortCount ) {
2019-10-20 20:05:39 -04:00
availablePorts & = ~ ( 1 < < playerInfo . ControllerPort ) ;
}
}
return availablePorts ;
}
uint8_t GameClientConnection : : GetControllerPort ( )
{
return _controllerPort ;
2021-03-10 11:13:28 -05:00
}