mirror of
https://github.com/libretro/Mesen.git
synced 2024-11-23 17:19:39 +00:00
119 lines
2.9 KiB
C++
119 lines
2.9 KiB
C++
#include "stdafx.h"
|
|
#include <thread>
|
|
using std::thread;
|
|
|
|
#include "MessageManager.h"
|
|
#include "GameClient.h"
|
|
#include "Console.h"
|
|
#include "../Utilities/Socket.h"
|
|
#include "ClientConnectionData.h"
|
|
#include "GameClientConnection.h"
|
|
|
|
shared_ptr<GameClient> GameClient::_instance;
|
|
|
|
GameClient::GameClient()
|
|
{
|
|
_stop = false;
|
|
|
|
MessageManager::RegisterNotificationListener(this);
|
|
}
|
|
|
|
GameClient::~GameClient()
|
|
{
|
|
_stop = true;
|
|
if(_clientThread) {
|
|
_clientThread->join();
|
|
}
|
|
MessageManager::UnregisterNotificationListener(this);
|
|
}
|
|
|
|
bool GameClient::Connected()
|
|
{
|
|
shared_ptr<GameClient> instance = _instance;
|
|
return instance ? instance->_connected : false;
|
|
}
|
|
|
|
void GameClient::Connect(ClientConnectionData &connectionData)
|
|
{
|
|
_instance.reset(new GameClient());
|
|
|
|
shared_ptr<GameClient> instance = _instance;
|
|
if(instance) {
|
|
instance->PrivateConnect(connectionData);
|
|
instance->_clientThread.reset(new thread(&GameClient::Exec, instance.get()));
|
|
}
|
|
}
|
|
|
|
void GameClient::Disconnect()
|
|
{
|
|
_instance.reset();
|
|
}
|
|
|
|
shared_ptr<GameClientConnection> GameClient::GetConnection()
|
|
{
|
|
shared_ptr<GameClient> instance = _instance;
|
|
return instance ? instance->_connection : nullptr;
|
|
}
|
|
|
|
void GameClient::PrivateConnect(ClientConnectionData &connectionData)
|
|
{
|
|
_stop = false;
|
|
shared_ptr<Socket> socket(new Socket());
|
|
if(socket->Connect(connectionData.Host.c_str(), connectionData.Port)) {
|
|
_connection.reset(new GameClientConnection(socket, connectionData));
|
|
_connected = true;
|
|
} else {
|
|
MessageManager::DisplayMessage("NetPlay", "CouldNotConnect");
|
|
_connected = false;
|
|
}
|
|
}
|
|
|
|
void GameClient::Exec()
|
|
{
|
|
if(_connected) {
|
|
while(!_stop) {
|
|
if(!_connection->ConnectionError()) {
|
|
_connection->ProcessMessages();
|
|
_connection->SendInput();
|
|
} else {
|
|
_connected = false;
|
|
_connection->Shutdown();
|
|
_connection.reset();
|
|
break;
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(1));
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameClient::ProcessNotification(ConsoleNotificationType type, void* parameter)
|
|
{
|
|
if(type == ConsoleNotificationType::GameLoaded &&
|
|
std::this_thread::get_id() != _clientThread->get_id() &&
|
|
std::this_thread::get_id() != Console::GetEmulationThreadId()
|
|
) {
|
|
//Disconnect if the client tried to manually load a game
|
|
//A deadlock occurs if this is called from the emulation thread while a network message is being processed
|
|
GameClient::Disconnect();
|
|
}
|
|
}
|
|
|
|
void GameClient::SelectController(uint8_t port)
|
|
{
|
|
shared_ptr<GameClientConnection> connection = GetConnection();
|
|
if(connection) {
|
|
connection->SelectController(port);
|
|
}
|
|
}
|
|
|
|
uint8_t GameClient::GetAvailableControllers()
|
|
{
|
|
shared_ptr<GameClientConnection> connection = GetConnection();
|
|
return connection ? connection->GetAvailableControllers() : 0;
|
|
}
|
|
|
|
uint8_t GameClient::GetControllerPort()
|
|
{
|
|
shared_ptr<GameClientConnection> connection = GetConnection();
|
|
return connection ? connection->GetControllerPort() : GameConnection::SpectatorPort;
|
|
} |