2014-07-09 19:05:07 -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"
2015-07-17 20:58:57 -04:00
# include "EmulationSettings.h"
2014-07-09 19:05:07 -04:00
# include "ControlManager.h"
2015-07-01 23:17:14 -04:00
# include "ClientConnectionData.h"
2016-02-05 23:14:27 -05:00
# include "StandardController.h"
2017-11-19 23:08:23 -05:00
# include "Zapper.h"
# include "ArkanoidController.h"
# include "BandaiHyperShot.h"
2016-02-06 15:33:45 -05:00
# include "SelectControllerMessage.h"
# include "PlayerListMessage.h"
2016-02-10 23:07:42 -05:00
# include "ForceDisconnectMessage.h"
2018-06-16 14:02:12 -04:00
# include "ServerInformationMessage.h"
2018-07-02 14:49:19 -04:00
# include "NotificationManager.h"
2014-07-09 19:05:07 -04:00
2018-07-01 15:21:05 -04:00
GameClientConnection : : GameClientConnection ( shared_ptr < Console > console , shared_ptr < Socket > socket , ClientConnectionData & connectionData ) : GameConnection ( console , socket )
2014-07-09 19:05:07 -04:00
{
2018-06-16 14:02:12 -04:00
_connectionData = connectionData ;
2016-12-11 10:56:23 -05:00
_shutdown = false ;
_enableControllers = false ;
_minimumQueueSize = 3 ;
2016-02-19 13:05:04 -05:00
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectedToServer " ) ;
2018-07-01 15:21:05 -04:00
_console - > GetControlManager ( ) - > RegisterInputProvider ( this ) ;
2014-07-09 19:05:07 -04:00
}
GameClientConnection : : ~ GameClientConnection ( )
{
2017-11-14 00:00:00 -05:00
Shutdown ( ) ;
}
void GameClientConnection : : Shutdown ( )
{
if ( ! _shutdown ) {
_shutdown = true ;
DisableControllers ( ) ;
2016-02-05 23:14:27 -05:00
2018-07-01 15:21:05 -04:00
_console - > GetControlManager ( ) - > UnregisterInputProvider ( this ) ;
2018-07-02 14:49:19 -04:00
_console - > GetNotificationManager ( ) - > SendNotification ( ConsoleNotificationType : : DisconnectedFromServer ) ;
2017-11-14 00:00:00 -05:00
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectionLost " ) ;
2017-11-19 23:08:23 -05:00
EmulationSettings : : ClearFlags ( EmulationFlags : : ForceMaxSpeed ) ;
2017-11-14 00:00:00 -05:00
}
2014-07-09 19:05:07 -04:00
}
void GameClientConnection : : SendHandshake ( )
{
2018-06-16 14:02:12 -04:00
HandShakeMessage message ( _connectionData . PlayerName , HandShakeMessage : : GetPasswordHash ( _connectionData . Password , _serverSalt ) , _connectionData . Spectator ) ;
2016-02-06 15:33:45 -05:00
SendNetMessage ( message ) ;
}
void GameClientConnection : : SendControllerSelection ( uint8_t port )
{
SelectControllerMessage message ( port ) ;
2015-08-28 21:01:18 -04:00
SendNetMessage ( message ) ;
2014-07-09 19:05:07 -04:00
}
2016-02-05 23:14:27 -05:00
void GameClientConnection : : ClearInputData ( )
2014-07-09 21:48:54 -04:00
{
2017-11-14 00:00:00 -05:00
LockHandler lock = _writeLock . AcquireSafe ( ) ;
2017-11-19 23:08:23 -05:00
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
2016-02-05 23:14:27 -05:00
_inputSize [ i ] = 0 ;
_inputData [ i ] . clear ( ) ;
2014-07-09 21:48:54 -04:00
}
}
2014-07-09 19:05:07 -04:00
void GameClientConnection : : ProcessMessage ( NetMessage * message )
{
2014-07-09 21:11:02 -04:00
GameInformationMessage * gameInfo ;
2015-07-01 23:17:14 -04:00
switch ( message - > GetType ( ) ) {
2018-06-16 14:02:12 -04:00
case MessageType : : ServerInformation :
_serverSalt = ( ( ServerInformationMessage * ) message ) - > GetHashSalt ( ) ;
SendHandshake ( ) ;
break ;
2014-07-09 19:05:07 -04:00
case MessageType : : SaveState :
if ( _gameLoaded ) {
2016-02-05 23:14:27 -05:00
DisableControllers ( ) ;
2018-07-01 15:21:05 -04:00
_console - > Pause ( ) ;
2016-02-05 23:14:27 -05:00
ClearInputData ( ) ;
2018-07-01 15:21:05 -04:00
( ( SaveStateMessage * ) message ) - > LoadState ( _console ) ;
2016-02-05 23:14:27 -05:00
_enableControllers = true ;
2017-11-19 23:08:23 -05:00
InitControlDevice ( ) ;
2018-07-01 15:21:05 -04:00
_console - > Resume ( ) ;
2014-07-09 19:05:07 -04:00
}
break ;
2016-02-06 15:33:45 -05:00
2014-07-09 19:05:07 -04:00
case MessageType : : MovieData :
if ( _gameLoaded ) {
2016-02-05 23:14:27 -05:00
PushControllerState ( ( ( MovieDataMessage * ) message ) - > GetPortNumber ( ) , ( ( MovieDataMessage * ) message ) - > GetInputState ( ) ) ;
2014-07-09 19:05:07 -04:00
}
break ;
2016-02-06 15:33:45 -05:00
2016-02-10 23:07:42 -05:00
case MessageType : : ForceDisconnect :
2016-02-19 13:05:04 -05:00
MessageManager : : DisplayMessage ( " NetPlay " , ( ( ForceDisconnectMessage * ) message ) - > GetMessage ( ) ) ;
2016-02-10 23:07:42 -05:00
break ;
2016-02-06 15:33:45 -05:00
case MessageType : : PlayerList :
_playerList = ( ( PlayerListMessage * ) message ) - > GetPlayerList ( ) ;
break ;
2014-07-09 19:05:07 -04:00
case MessageType : : GameInformation :
2016-02-05 23:14:27 -05:00
DisableControllers ( ) ;
2018-07-01 15:21:05 -04:00
_console - > Pause ( ) ;
2014-07-09 19:05:07 -04:00
gameInfo = ( GameInformationMessage * ) message ;
2015-07-01 23:17:14 -04:00
if ( gameInfo - > GetPort ( ) ! = _controllerPort ) {
_controllerPort = gameInfo - > GetPort ( ) ;
2016-02-06 15:33:45 -05:00
if ( _controllerPort = = GameConnection : : SpectatorPort ) {
2016-02-19 13:05:04 -05:00
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectedAsSpectator " ) ;
2016-02-06 15:33:45 -05:00
} else {
2016-02-19 13:05:04 -05:00
MessageManager : : DisplayMessage ( " NetPlay " , " ConnectedAsPlayer " , std : : to_string ( _controllerPort + 1 ) ) ;
2016-02-06 15:33:45 -05:00
}
2014-07-09 21:11:02 -04:00
}
2014-07-09 21:48:54 -04:00
2016-02-05 23:14:27 -05:00
ClearInputData ( ) ;
2014-07-09 21:48:54 -04:00
2018-07-01 15:21:05 -04:00
_gameLoaded = AttemptLoadGame ( gameInfo - > GetRomFilename ( ) , gameInfo - > GetCrc32Hash ( ) ) ;
2015-07-01 23:17:14 -04:00
if ( gameInfo - > IsPaused ( ) ) {
2015-07-17 20:58:57 -04:00
EmulationSettings : : SetFlags ( EmulationFlags : : Paused ) ;
2014-07-09 21:48:54 -04:00
} else {
2015-07-17 20:58:57 -04:00
EmulationSettings : : ClearFlags ( EmulationFlags : : Paused ) ;
2014-07-09 21:48:54 -04:00
}
2018-07-01 15:21:05 -04:00
_console - > Resume ( ) ;
2015-08-28 21:01:18 -04:00
break ;
default :
2014-07-09 19:05:07 -04:00
break ;
}
}
2016-02-05 23:14:27 -05:00
2018-07-01 15:21:05 -04:00
bool GameClientConnection : : AttemptLoadGame ( string filename , uint32_t crc32Hash )
{
if ( filename . size ( ) > 0 ) {
HashInfo hashInfo ;
hashInfo . Crc32Hash = crc32Hash ;
if ( _console - > LoadMatchingRom ( filename , hashInfo ) ) {
return true ;
} else {
MessageManager : : DisplayMessage ( " NetPlay " , " CouldNotFindRom " ) ;
return false ;
}
}
return false ;
}
2017-11-19 23:08:23 -05:00
void GameClientConnection : : PushControllerState ( uint8_t port , ControlDeviceState state )
2016-02-05 23:14:27 -05:00
{
LockHandler lock = _writeLock . AcquireSafe ( ) ;
_inputData [ port ] . push_back ( state ) ;
_inputSize [ port ] + + ;
if ( _inputData [ port ] . size ( ) > = _minimumQueueSize ) {
_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())
ClearInputData ( ) ;
_enableControllers = false ;
2017-11-19 23:08:23 -05:00
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
2016-02-05 23:14:27 -05:00
_waitForInput [ i ] . Signal ( ) ;
}
}
2017-11-19 23:08:23 -05:00
bool GameClientConnection : : SetInput ( BaseControlDevice * device )
2016-02-05 23:14:27 -05:00
{
if ( _enableControllers ) {
2017-11-19 23:08:23 -05:00
uint8_t port = device - > GetPort ( ) ;
2016-02-05 23:14:27 -05:00
while ( _inputSize [ port ] = = 0 ) {
_waitForInput [ port ] . Wait ( ) ;
if ( port = = 0 & & _minimumQueueSize < 10 ) {
//Increase buffer size - reduces freezes at the cost of additional lag
_minimumQueueSize + + ;
}
if ( _shutdown | | ! _enableControllers ) {
2017-11-19 23:08:23 -05:00
return true ;
2016-02-05 23:14:27 -05:00
}
}
LockHandler lock = _writeLock . AcquireSafe ( ) ;
2017-11-19 23:08:23 -05:00
ControlDeviceState state = _inputData [ port ] . front ( ) ;
2016-02-05 23:14:27 -05:00
_inputData [ port ] . pop_front ( ) ;
_inputSize [ port ] - - ;
if ( _inputData [ port ] . size ( ) > _minimumQueueSize ) {
//Too much data, catch up
2017-05-19 18:27:39 -04:00
EmulationSettings : : SetFlags ( EmulationFlags : : ForceMaxSpeed ) ;
2016-02-05 23:14:27 -05:00
} else {
2017-05-19 18:27:39 -04:00
EmulationSettings : : ClearFlags ( EmulationFlags : : ForceMaxSpeed ) ;
2016-02-05 23:14:27 -05:00
EmulationSettings : : SetEmulationSpeed ( 100 ) ;
}
2017-11-19 23:08:23 -05:00
device - > SetRawState ( state ) ;
2016-02-05 23:14:27 -05:00
}
2017-11-19 23:08:23 -05:00
return true ;
2016-02-05 23:14:27 -05:00
}
2017-11-19 23:08:23 -05:00
void GameClientConnection : : InitControlDevice ( )
{
if ( _controllerPort = = BaseControlDevice : : ExpDevicePort ) {
2018-07-01 15:21:05 -04:00
_newControlDevice = ControlManager : : CreateExpansionDevice ( EmulationSettings : : GetExpansionDevice ( ) , nullptr ) ;
2017-11-19 23:08:23 -05:00
} else {
//Pretend we are using port 0 (to use player 1's keybindings during netplay)
2018-07-01 15:21:05 -04:00
_newControlDevice = ControlManager : : CreateControllerDevice ( EmulationSettings : : GetControllerType ( _controllerPort ) , 0 , nullptr ) ;
2017-11-19 23:08:23 -05:00
}
}
2016-02-10 19:48:15 -05:00
void GameClientConnection : : ProcessNotification ( ConsoleNotificationType type , void * parameter )
{
if ( type = = ConsoleNotificationType : : ConfigChanged ) {
2017-11-19 23:08:23 -05:00
InitControlDevice ( ) ;
2016-02-10 19:48:15 -05:00
}
}
2014-07-09 19:05:07 -04:00
void GameClientConnection : : SendInput ( )
{
2015-08-23 20:24:24 -04:00
if ( _gameLoaded ) {
2016-02-10 19:48:15 -05:00
if ( _newControlDevice ) {
_controlDevice = _newControlDevice ;
_newControlDevice . reset ( ) ;
}
2017-11-19 23:08:23 -05:00
ControlDeviceState inputState ;
2016-02-14 12:58:35 -05:00
if ( _controlDevice ) {
2017-11-19 23:08:23 -05:00
_controlDevice - > SetStateFromInput ( ) ;
inputState = _controlDevice - > GetRawState ( ) ;
2016-02-05 23:14:27 -05:00
}
2016-02-14 12:58:35 -05:00
2015-08-23 20:24:24 -04:00
if ( _lastInputSent ! = inputState ) {
2015-08-28 21:01:18 -04:00
InputDataMessage message ( inputState ) ;
SendNetMessage ( message ) ;
2015-08-23 20:24:24 -04:00
_lastInputSent = inputState ;
}
2014-07-09 19:05:07 -04:00
}
2016-02-06 15:33:45 -05:00
}
void GameClientConnection : : SelectController ( uint8_t port )
{
SendControllerSelection ( port ) ;
}
uint8_t GameClientConnection : : GetAvailableControllers ( )
{
2017-11-19 23:08:23 -05:00
uint8_t availablePorts = ( 1 < < BaseControlDevice : : PortCount ) - 1 ;
2016-02-06 15:33:45 -05:00
for ( PlayerInfo & playerInfo : _playerList ) {
2017-11-19 23:08:23 -05:00
if ( playerInfo . ControllerPort < BaseControlDevice : : PortCount ) {
2016-02-06 15:33:45 -05:00
availablePorts & = ~ ( 1 < < playerInfo . ControllerPort ) ;
}
}
return availablePorts ;
}
uint8_t GameClientConnection : : GetControllerPort ( )
{
return _controllerPort ;
2014-07-09 19:05:07 -04:00
}