mirror of
https://github.com/HikikoMarmy/Champions-Reborn-Server.git
synced 2026-04-05 08:59:54 -03:00
Refactoring game sessions for better RTA support
This commit is contained in:
@@ -1,17 +1,24 @@
|
|||||||
|
|
||||||
#include "GameSession.h"
|
#include "GameSession.h"
|
||||||
|
|
||||||
GameSession::GameSession()
|
#include "RealmUser.h"
|
||||||
{
|
#include "../../logging.h"
|
||||||
m_owner.reset();
|
|
||||||
|
GameSession::GameSession( uint32_t index ) : m_gameId( index )
|
||||||
|
{
|
||||||
|
m_members.fill( std::weak_ptr< RealmUser >() );
|
||||||
|
|
||||||
m_gameIndex = 0;
|
|
||||||
m_type = GameType::Public;
|
|
||||||
m_state = GameState::NotReady;
|
m_state = GameState::NotReady;
|
||||||
m_currentPlayers = 0;
|
m_currentPlayers = 0;
|
||||||
m_maximumPlayers = 0;
|
m_maximumPlayers = 4;
|
||||||
|
|
||||||
m_hostPort = 0;
|
m_difficulty = 0;
|
||||||
|
m_gameMode = 0;
|
||||||
|
m_mission = 0;
|
||||||
|
m_unknown = 0;
|
||||||
|
m_networkSave = 0;
|
||||||
|
|
||||||
|
m_hostNatPort = 0;
|
||||||
m_hostLocalAddr.clear();
|
m_hostLocalAddr.clear();
|
||||||
m_hostExternalAddr.clear();
|
m_hostExternalAddr.clear();
|
||||||
m_gameName.clear();
|
m_gameName.clear();
|
||||||
@@ -22,19 +29,167 @@ GameSession::GameSession()
|
|||||||
|
|
||||||
GameSession::~GameSession()
|
GameSession::~GameSession()
|
||||||
{
|
{
|
||||||
m_owner.reset();
|
m_members.fill( std::weak_ptr< RealmUser >() );
|
||||||
|
|
||||||
m_gameIndex = 0;
|
m_gameId = 0;
|
||||||
m_type = GameType::Public;
|
m_type = GameType::Public;
|
||||||
m_state = GameState::NotReady;
|
m_state = GameState::NotReady;
|
||||||
m_currentPlayers = 0;
|
m_currentPlayers = 0;
|
||||||
m_maximumPlayers = 0;
|
m_maximumPlayers = 0;
|
||||||
|
|
||||||
m_hostPort = 0;
|
m_difficulty = 0;
|
||||||
|
m_gameMode = 0;
|
||||||
|
m_mission = 0;
|
||||||
|
m_unknown = 0;
|
||||||
|
m_networkSave = 0;
|
||||||
|
|
||||||
|
m_hostNatPort = 0;
|
||||||
m_hostLocalAddr.clear();
|
m_hostLocalAddr.clear();
|
||||||
m_hostExternalAddr.clear();
|
m_hostExternalAddr.clear();
|
||||||
m_gameName.clear();
|
m_gameName.clear();
|
||||||
m_ownerName.clear();
|
m_ownerName.clear();
|
||||||
m_gameData.clear();
|
m_gameData.clear();
|
||||||
m_description.clear();
|
m_description.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameSession::IsJoinable( sptr_user user ) const
|
||||||
|
{
|
||||||
|
if( user )
|
||||||
|
{
|
||||||
|
if( user->m_memberId >= 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for( const auto &m : m_members )
|
||||||
|
{
|
||||||
|
if( m.expired() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto &member = m.lock();
|
||||||
|
if( member->m_sessionId == user->m_sessionId )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( m_state == GameState::Open && m_currentPlayers < m_maximumPlayers );
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr_user GameSession::GetOwner() const
|
||||||
|
{
|
||||||
|
if( !m_members[ 0 ].expired() )
|
||||||
|
{
|
||||||
|
return m_members[ 0 ].lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr_user GameSession::GetMember( int32_t index ) const
|
||||||
|
{
|
||||||
|
if( index < 0 || index >= static_cast< int32_t >( m_members.size() ) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if( !m_members[ index ].expired() )
|
||||||
|
{
|
||||||
|
return m_members[ index ].lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr_user GameSession::GetMemberBySessionId( const std::wstring &sessionId ) const
|
||||||
|
{
|
||||||
|
for( const auto &m : m_members )
|
||||||
|
{
|
||||||
|
if( m.expired() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto &member = m.lock();
|
||||||
|
if( member->m_sessionId == sessionId )
|
||||||
|
{
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<sptr_user> GameSession::GetMembers() const
|
||||||
|
{
|
||||||
|
std::vector< sptr_user > members;
|
||||||
|
for( const auto &m : m_members )
|
||||||
|
{
|
||||||
|
if( !m.expired() )
|
||||||
|
{
|
||||||
|
members.push_back( m.lock() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameSession::AddMember( sptr_user user )
|
||||||
|
{
|
||||||
|
if( !user || user->m_memberId >= 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int8_t freeIndex = -1;
|
||||||
|
|
||||||
|
for( int8_t i = 0; i < static_cast< int8_t >( m_members.size() ); ++i )
|
||||||
|
{
|
||||||
|
auto memberPtr = m_members[ i ].lock();
|
||||||
|
|
||||||
|
if( memberPtr )
|
||||||
|
{
|
||||||
|
if( memberPtr->m_sessionId == user->m_sessionId )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if( freeIndex == -1 )
|
||||||
|
{
|
||||||
|
freeIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( freeIndex == -1 )
|
||||||
|
{
|
||||||
|
Log::Error( "Game session is full! [{}]", m_gameName );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
user->m_memberId = freeIndex;
|
||||||
|
user->m_gameId = m_gameId;
|
||||||
|
|
||||||
|
m_members[ freeIndex ] = user;
|
||||||
|
m_currentPlayers++;
|
||||||
|
|
||||||
|
Log::Info( "Added user [{}] to game session [{}] at index {}",
|
||||||
|
user->m_username, m_gameName, freeIndex );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameSession::RemoveMember( sptr_user user )
|
||||||
|
{
|
||||||
|
if( !user || user->m_memberId < 0 || user->m_memberId >= static_cast< int8_t >( m_members.size() ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int8_t index = static_cast< int8_t >( user->m_memberId );
|
||||||
|
auto memberPtr = m_members[ index ].lock();
|
||||||
|
|
||||||
|
if( !memberPtr || memberPtr->m_sessionId != user->m_sessionId )
|
||||||
|
{
|
||||||
|
Log::Error( "User [{}] not found in game session [{}] at index {}",
|
||||||
|
user->m_username, m_gameName, index );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
user->m_memberId = -1;
|
||||||
|
user->m_gameId = -1;
|
||||||
|
|
||||||
|
m_members[ index ].reset();
|
||||||
|
m_currentPlayers--;
|
||||||
|
|
||||||
|
Log::Info( "Removed user [{}] from game session [{}] at index {}",
|
||||||
|
user->m_username, m_gameName, index );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -7,42 +9,57 @@
|
|||||||
|
|
||||||
class GameSession {
|
class GameSession {
|
||||||
public:
|
public:
|
||||||
GameSession();
|
enum class GameType {
|
||||||
~GameSession();
|
|
||||||
|
|
||||||
enum class GameType
|
|
||||||
{
|
|
||||||
Public,
|
Public,
|
||||||
Private
|
Private
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class GameState
|
enum class GameState {
|
||||||
{
|
|
||||||
NotReady,
|
NotReady,
|
||||||
Open,
|
Open,
|
||||||
Started
|
Started
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GameSession( uint32_t index );
|
||||||
|
~GameSession();
|
||||||
|
|
||||||
|
bool IsJoinable( sptr_user user = nullptr ) const;
|
||||||
|
|
||||||
|
sptr_user GetOwner() const;
|
||||||
|
sptr_user GetMember( int32_t index ) const;
|
||||||
|
sptr_user GetMemberBySessionId( const std::wstring &sessionId ) const;
|
||||||
|
std::vector< sptr_user > GetMembers() const;
|
||||||
|
bool AddMember( sptr_user user );
|
||||||
|
bool RemoveMember( sptr_user user );
|
||||||
|
|
||||||
|
public:
|
||||||
GameType m_type;
|
GameType m_type;
|
||||||
GameState m_state;
|
GameState m_state;
|
||||||
|
|
||||||
std::weak_ptr< RealmUser > m_owner;
|
std::array< wptr_user, 4 > m_members;
|
||||||
|
|
||||||
int32_t m_gameIndex;
|
int32_t m_gameId;
|
||||||
|
|
||||||
std::wstring m_gameName;
|
std::wstring m_gameName;
|
||||||
std::wstring m_ownerName;
|
std::wstring m_ownerName;
|
||||||
std::wstring m_playerCount;
|
std::wstring m_playerCount;
|
||||||
|
|
||||||
std::string m_gameData;
|
std::string m_gameData;
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
|
|
||||||
std::string m_hostLocalAddr;
|
std::string m_hostLocalAddr;
|
||||||
std::string m_hostExternalAddr;
|
std::string m_hostExternalAddr;
|
||||||
int32_t m_hostPort;
|
int32_t m_hostLocalPort;
|
||||||
|
int32_t m_hostNatPort;
|
||||||
|
|
||||||
int8_t m_currentPlayers;
|
int8_t m_currentPlayers;
|
||||||
int8_t m_maximumPlayers;
|
int8_t m_maximumPlayers;
|
||||||
|
|
||||||
|
int8_t m_difficulty;
|
||||||
|
int8_t m_gameMode;
|
||||||
|
int8_t m_mission;
|
||||||
|
int8_t m_unknown;
|
||||||
|
int8_t m_networkSave;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr< GameSession > sptr_game_session;
|
typedef std::shared_ptr< GameSession > sptr_game_session;
|
||||||
@@ -1,17 +1,16 @@
|
|||||||
#include "GameSessionManager.h"
|
#include "GameSessionManager.h"
|
||||||
|
|
||||||
#include "RealmUser.h"
|
#include "RealmUser.h"
|
||||||
|
#include "../Network/Event/NotifyGameDiscovered.h"
|
||||||
#include "../Network/Event/NotifyClientDiscovered.h"
|
#include "../Network/Event/NotifyClientDiscovered.h"
|
||||||
#include "../Network/Event/NotifyClientDiscovered_RTA.h"
|
#include "../Network/Event/NotifyClientDiscovered_RTA.h"
|
||||||
#include "../Network/Event/NotifyClientRequestConnect.h"
|
#include "../Network/Event/NotifyClientRequestConnect.h"
|
||||||
#include "../Network/Event/NotifyClientRequestConnect_RTA.h"
|
#include "../Network/Event/NotifyClientRequestConnect_RTA.h"
|
||||||
#include "../Network/Event/NotifyGameDiscovered.h"
|
|
||||||
#include "../Network/Event/NotifyReserveUserSlot_RTA.h"
|
|
||||||
#include "../../logging.h"
|
#include "../../logging.h"
|
||||||
|
|
||||||
GameSessionManager::GameSessionManager()
|
GameSessionManager::GameSessionManager()
|
||||||
{
|
{
|
||||||
m_gameIndex = 0;
|
m_uniqueGameIndex = 0;
|
||||||
m_gameSessionList[ 0 ].clear();
|
m_gameSessionList[ 0 ].clear();
|
||||||
m_gameSessionList[ 1 ].clear();
|
m_gameSessionList[ 1 ].clear();
|
||||||
}
|
}
|
||||||
@@ -32,86 +31,101 @@ void GameSessionManager::OnDisconnectUser( sptr_user user )
|
|||||||
if( !session )
|
if( !session )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto owner = session->m_owner.lock();
|
const auto owner = session->GetOwner();
|
||||||
if( !owner )
|
if( !owner )
|
||||||
{
|
{
|
||||||
Log::Error( "Game session owner not found! [%d]", gameId );
|
Log::Error( "Game session owner not found! [{}]", gameId );
|
||||||
ForceTerminateGame( gameId, gameType );
|
ForceTerminateGame( gameId, gameType );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( owner->m_sessionId == user->m_sessionId )
|
if( owner->m_sessionId == user->m_sessionId )
|
||||||
{
|
{
|
||||||
Log::Info( "Game session owner disconnected! [%d]", gameId );
|
Log::Info( "Game session owner disconnected! [{}]", gameId );
|
||||||
ForceTerminateGame( gameId, gameType );
|
ForceTerminateGame( gameId, gameType );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameSessionManager::CreatePublicGameSession( sptr_user owner, std::wstring gameName, RealmGameType clientType )
|
bool GameSessionManager::CreateGameSession_CON( sptr_user user,
|
||||||
|
const std::wstring gameInfo,
|
||||||
|
const std::wstring name,
|
||||||
|
const std::wstring stage,
|
||||||
|
bool isPrivateGame )
|
||||||
{
|
{
|
||||||
auto new_session = std::make_shared< GameSession >();
|
if( name.empty() )
|
||||||
|
{
|
||||||
|
Log::Error( "Invalid parameters for creating game session!" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
new_session->m_type = GameSession::GameType::Public;
|
auto new_session = std::make_shared< GameSession >( m_uniqueGameIndex++ );
|
||||||
new_session->m_gameIndex = m_gameIndex;
|
|
||||||
new_session->m_hostLocalAddr.clear();
|
|
||||||
new_session->m_hostExternalAddr.clear();
|
|
||||||
new_session->m_gameName = gameName;
|
|
||||||
new_session->m_currentPlayers = 1;
|
|
||||||
new_session->m_maximumPlayers = 4;
|
|
||||||
|
|
||||||
new_session->m_gameData.resize( 256 );
|
if( isPrivateGame )
|
||||||
|
{
|
||||||
|
new_session->m_type = GameSession::GameType::Private;
|
||||||
|
new_session->m_gameName = name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_session->m_type = GameSession::GameType::Public;
|
||||||
|
new_session->m_gameName = name + L" [" + stage + L"]";
|
||||||
|
}
|
||||||
|
|
||||||
owner->m_isHost = true;
|
user->m_isHost = true;
|
||||||
owner->m_discoveryAddr = "";
|
user->m_gameId = new_session->m_gameId;
|
||||||
|
user->m_discoveryAddr = "";
|
||||||
|
user->m_discoveryPort = 0;
|
||||||
|
|
||||||
owner->m_gameId = m_gameIndex;
|
new_session->AddMember( user );
|
||||||
new_session->m_owner = owner;
|
|
||||||
|
|
||||||
std::lock_guard< std::mutex > lock( m_dataMutex );
|
std::lock_guard< std::mutex > lock( m_dataMutex );
|
||||||
m_gameSessionList[ clientType ].push_back( new_session );
|
m_gameSessionList[ RealmGameType::CHAMPIONS_OF_NORRATH ].push_back( new_session );
|
||||||
|
|
||||||
m_gameIndex++;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameSessionManager::CreatePrivateGameSession( sptr_user owner, std::wstring gameName, RealmGameType clientType )
|
bool GameSessionManager::CreateGameSession_RTA(
|
||||||
|
sptr_user user,
|
||||||
|
const std::wstring gameInfo,
|
||||||
|
const std::wstring name,
|
||||||
|
const std::array< int8_t, 5 > &attributes,
|
||||||
|
const bool isPrivateGame )
|
||||||
{
|
{
|
||||||
// Check if the game name or host session id is already in use
|
if( nullptr != FindGame( name, RealmGameType::RETURN_TO_ARMS ) )
|
||||||
for( const auto &gameSession : m_gameSessionList[ clientType ] )
|
|
||||||
{
|
{
|
||||||
if( gameSession->m_type != GameSession::GameType::Private )
|
Log::Error( "Game name is already in use! [{}]", name );
|
||||||
continue;
|
return false;
|
||||||
|
|
||||||
if( gameSession->m_gameName == gameName )
|
|
||||||
{
|
|
||||||
Log::Error( "Game name is already in use! [%S]", gameName.c_str() );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto new_session = std::make_shared< GameSession >();
|
auto new_session = std::make_shared< GameSession >( m_uniqueGameIndex++ );
|
||||||
|
|
||||||
new_session->m_type = GameSession::GameType::Private;
|
if( isPrivateGame )
|
||||||
new_session->m_gameIndex = m_gameIndex;
|
{
|
||||||
new_session->m_hostLocalAddr.clear();
|
new_session->m_type = GameSession::GameType::Private;
|
||||||
new_session->m_hostExternalAddr.clear();
|
}
|
||||||
new_session->m_gameName = gameName;
|
else
|
||||||
new_session->m_currentPlayers = 1;
|
{
|
||||||
new_session->m_maximumPlayers = 4;
|
new_session->m_type = GameSession::GameType::Public;
|
||||||
|
|
||||||
new_session->m_gameData.resize( 256 );
|
new_session->m_gameData = Util::WideToUTF8( gameInfo );
|
||||||
|
new_session->m_difficulty = attributes[ 0 ];
|
||||||
|
new_session->m_gameMode = attributes[ 1 ];
|
||||||
|
new_session->m_unknown = attributes[ 2 ];
|
||||||
|
new_session->m_mission = attributes[ 3 ];
|
||||||
|
new_session->m_networkSave = attributes[ 4 ];
|
||||||
|
}
|
||||||
|
|
||||||
owner->m_isHost = true;
|
new_session->m_gameName = name;
|
||||||
owner->m_discoveryAddr = "";
|
|
||||||
|
|
||||||
owner->m_gameId = m_gameIndex;
|
user->m_isHost = true;
|
||||||
new_session->m_owner = owner;
|
user->m_gameId = new_session->m_gameId;
|
||||||
|
user->m_discoveryAddr = "";
|
||||||
|
user->m_discoveryPort = 0;
|
||||||
|
|
||||||
|
new_session->AddMember( user );
|
||||||
|
|
||||||
std::lock_guard< std::mutex > lock( m_dataMutex );
|
std::lock_guard< std::mutex > lock( m_dataMutex );
|
||||||
m_gameSessionList[ clientType ].push_back( new_session );
|
m_gameSessionList[ RealmGameType::RETURN_TO_ARMS ].push_back( new_session );
|
||||||
|
|
||||||
m_gameIndex++;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -128,7 +142,7 @@ bool GameSessionManager::ForceTerminateGame( int32_t gameId, RealmGameType clien
|
|||||||
const auto &gameList = m_gameSessionList[ clientType ];
|
const auto &gameList = m_gameSessionList[ clientType ];
|
||||||
const auto it = std::find_if( gameList.begin(), gameList.end(), [ &gameId ]( sptr_game_session gameSession )
|
const auto it = std::find_if( gameList.begin(), gameList.end(), [ &gameId ]( sptr_game_session gameSession )
|
||||||
{
|
{
|
||||||
return gameSession->m_gameIndex == gameId;
|
return gameSession->m_gameId == gameId;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
if( it != m_gameSessionList[ clientType ].end() )
|
if( it != m_gameSessionList[ clientType ].end() )
|
||||||
@@ -148,7 +162,7 @@ sptr_game_session GameSessionManager::FindGame( const int32_t gameId, const Real
|
|||||||
|
|
||||||
for( auto &gameSession : m_gameSessionList[ gameType ] )
|
for( auto &gameSession : m_gameSessionList[ gameType ] )
|
||||||
{
|
{
|
||||||
if( gameSession->m_gameIndex == gameId )
|
if( gameSession->m_gameId == gameId )
|
||||||
{
|
{
|
||||||
return gameSession;
|
return gameSession;
|
||||||
}
|
}
|
||||||
@@ -182,7 +196,7 @@ bool GameSessionManager::RequestOpen( sptr_user user )
|
|||||||
|
|
||||||
if( session == nullptr )
|
if( session == nullptr )
|
||||||
{
|
{
|
||||||
Log::Error( "Game session not found! [%d]", gameId );
|
Log::Error( "Game session not found! [{}]", gameId );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,13 +207,15 @@ bool GameSessionManager::RequestOpen( sptr_user user )
|
|||||||
|
|
||||||
if( user->m_discoveryAddr.empty() )
|
if( user->m_discoveryAddr.empty() )
|
||||||
{
|
{
|
||||||
Log::Error( "User discovery address is empty! [%d]", gameId );
|
Log::Error( "User discovery address is empty! [{}]", gameId );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->m_hostExternalAddr = user->m_discoveryAddr;
|
|
||||||
session->m_hostLocalAddr = user->m_localAddr;
|
session->m_hostLocalAddr = user->m_localAddr;
|
||||||
session->m_hostPort = user->m_discoveryPort;
|
session->m_hostLocalPort = user->m_localPort;
|
||||||
|
|
||||||
|
session->m_hostExternalAddr = user->m_discoveryAddr;
|
||||||
|
session->m_hostNatPort = user->m_discoveryPort;
|
||||||
|
|
||||||
session->m_state = GameSession::GameState::Open;
|
session->m_state = GameSession::GameState::Open;
|
||||||
|
|
||||||
@@ -207,14 +223,11 @@ bool GameSessionManager::RequestOpen( sptr_user user )
|
|||||||
NotifyGameDiscovered msg( user->m_discoveryAddr, user->m_discoveryPort, user->m_gameType );
|
NotifyGameDiscovered msg( user->m_discoveryAddr, user->m_discoveryPort, user->m_gameType );
|
||||||
user->sock->send( msg );
|
user->sock->send( msg );
|
||||||
|
|
||||||
Log::Info( "Game Session [%d] Discoverable on %s", gameId, user->m_discoveryAddr.c_str() );
|
Log::Info( "Game Session [{}] Discoverable on {}", gameId, user->m_discoveryAddr );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE:
|
|
||||||
// This might solely be for a user that is LEAVING the game (I.E "CancelJoining")
|
|
||||||
// instead of a game being cancelled overall. RTA has a dedicated endgame event.
|
|
||||||
bool GameSessionManager::RequestCancel( sptr_user user )
|
bool GameSessionManager::RequestCancel( sptr_user user )
|
||||||
{
|
{
|
||||||
if( !user || user->m_gameId < 0 )
|
if( !user || user->m_gameId < 0 )
|
||||||
@@ -229,7 +242,7 @@ bool GameSessionManager::RequestCancel( sptr_user user )
|
|||||||
const auto it = std::find_if( gameList.begin(), gameList.end(),
|
const auto it = std::find_if( gameList.begin(), gameList.end(),
|
||||||
[ gameId ]( const sptr_game_session &gameSession )
|
[ gameId ]( const sptr_game_session &gameSession )
|
||||||
{
|
{
|
||||||
return gameSession->m_gameIndex == gameId;
|
return gameSession->m_gameId == gameId;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
if( it == gameList.end() )
|
if( it == gameList.end() )
|
||||||
@@ -237,21 +250,22 @@ bool GameSessionManager::RequestCancel( sptr_user user )
|
|||||||
|
|
||||||
const auto &session = *it;
|
const auto &session = *it;
|
||||||
|
|
||||||
auto owner = session->m_owner.lock();
|
if( false == session->RemoveMember( user ) )
|
||||||
if( !owner )
|
|
||||||
{
|
{
|
||||||
Log::Error( "Game session owner not found! [%d]", gameId );
|
Log::Error( "Failed to remove user [{}] from game session [{}]", user->m_username, gameId );
|
||||||
ForceTerminateGame( gameId, gameType );
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( owner->m_sessionId != user->m_sessionId )
|
if( session->m_currentPlayers <= 0 )
|
||||||
{
|
{
|
||||||
Log::Error( "User is not the host! [%d]", gameId );
|
Log::Info( "Game session [{}] is empty, removing it", gameId );
|
||||||
return false;
|
gameList.erase( it );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::Info( "User [{}] left game session [{}], remaining players: {}",
|
||||||
|
user->m_username, gameId, session->m_currentPlayers );
|
||||||
}
|
}
|
||||||
|
|
||||||
gameList.erase( it );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,28 +277,28 @@ bool GameSessionManager::RequestJoin( sptr_user join_user )
|
|||||||
|
|
||||||
if( session == nullptr )
|
if( session == nullptr )
|
||||||
{
|
{
|
||||||
Log::Error( "Game session not found! [%d]", gameId );
|
Log::Error( "Game session not found! [{}]", gameId );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( session->m_state != GameSession::GameState::Open )
|
if( session->m_state != GameSession::GameState::Open )
|
||||||
{
|
{
|
||||||
Log::Error( "Game session not open! [%d]", gameId );
|
Log::Error( "Game session not open! [{}]", gameId );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto host_user = session->m_owner.lock();
|
auto host_user = session->GetOwner();
|
||||||
|
|
||||||
if( host_user == nullptr )
|
if( host_user == nullptr )
|
||||||
{
|
{
|
||||||
Log::Error( "Host not found! [%d]", gameId );
|
Log::Error( "Host not found! [{}]", gameId );
|
||||||
ForceTerminateGame( gameId, gameType );
|
ForceTerminateGame( gameId, gameType );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( host_user->m_discoveryAddr.empty() )
|
if( host_user->m_discoveryAddr.empty() )
|
||||||
{
|
{
|
||||||
Log::Error( "User discovery address is empty! [%d]", gameId );
|
Log::Error( "User discovery address is empty! [{}]", gameId );
|
||||||
ForceTerminateGame( gameId, gameType );
|
ForceTerminateGame( gameId, gameType );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -300,7 +314,7 @@ bool GameSessionManager::RequestJoin( sptr_user join_user )
|
|||||||
ProcessJoinArms( join_user, host_user );
|
ProcessJoinArms( join_user, host_user );
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::Info( "User [%S] Joining game session... [%d]", join_user->m_sessionId.c_str(), gameId );
|
Log::Info( "User [{}] Joining game session... [{}]", join_user->m_sessionId, gameId );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -308,16 +322,16 @@ bool GameSessionManager::RequestJoin( sptr_user join_user )
|
|||||||
// NOTE:
|
// NOTE:
|
||||||
// Request Start seems to be for RTA only.
|
// Request Start seems to be for RTA only.
|
||||||
// CON will disconnect from the server at start time.
|
// CON will disconnect from the server at start time.
|
||||||
bool GameSessionManager::RequestStart(sptr_user user)
|
bool GameSessionManager::RequestStart( sptr_user user )
|
||||||
{
|
{
|
||||||
const auto gameId = user->m_gameId;
|
const auto gameId = user->m_gameId;
|
||||||
const auto gameType = user->m_gameType;
|
const auto gameType = user->m_gameType;
|
||||||
|
|
||||||
auto session = FindGame( gameId, gameType );
|
auto session = FindGame( gameId, gameType );
|
||||||
|
|
||||||
if( session == nullptr )
|
if( session == nullptr )
|
||||||
{
|
{
|
||||||
Log::Error( "Game session not found! [%d]", gameId );
|
Log::Error( "Game session not found! [{}]", gameId );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,13 +339,13 @@ bool GameSessionManager::RequestStart(sptr_user user)
|
|||||||
|
|
||||||
session->m_state = GameSession::GameState::Started;
|
session->m_state = GameSession::GameState::Started;
|
||||||
|
|
||||||
// Temp (or permanent) remove the game from the list.
|
// Remove the game from the list.
|
||||||
auto &gameList = m_gameSessionList[ gameType ];
|
auto &gameList = m_gameSessionList[ gameType ];
|
||||||
|
|
||||||
const auto it = std::find_if( gameList.begin(), gameList.end(),
|
const auto it = std::find_if( gameList.begin(), gameList.end(),
|
||||||
[ gameId ]( const sptr_game_session &gameSession )
|
[ gameId ]( const sptr_game_session &gameSession )
|
||||||
{
|
{
|
||||||
return gameSession->m_gameIndex == gameId;
|
return gameSession->m_gameId == gameId;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
if( it != gameList.end() )
|
if( it != gameList.end() )
|
||||||
@@ -339,7 +353,7 @@ bool GameSessionManager::RequestStart(sptr_user user)
|
|||||||
gameList.erase( it );
|
gameList.erase( it );
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::Info( "Game session [%d] started", gameId );
|
Log::Info( "Game session [{}] started", gameId );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -386,56 +400,30 @@ std::vector<sptr_game_session> GameSessionManager::GetPrivateGameSessionList( co
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameSessionManager::ProcessJoinNorrath(sptr_user join, sptr_user host)
|
void GameSessionManager::ProcessJoinNorrath( sptr_user join, sptr_user host )
|
||||||
{
|
{
|
||||||
std::string hostAddr = host->m_discoveryAddr;
|
// Tell the joining user its own address
|
||||||
std::string joinAddr = join->m_discoveryAddr;
|
NotifyClientDiscovered msgClientDiscovered( join );
|
||||||
|
join->sock->send( msgClientDiscovered );
|
||||||
if (hostAddr == joinAddr)
|
|
||||||
{
|
|
||||||
hostAddr = host->m_localAddr;
|
|
||||||
// I don't think the joiner ever reports its local address for CON.
|
|
||||||
// At best, we can report the hosts local IP and hope communication works.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the joining user the hosts address.
|
|
||||||
NotifyClientDiscovered msgClientDiscovered( hostAddr, host->m_discoveryPort );
|
|
||||||
join->sock->send(msgClientDiscovered);
|
|
||||||
|
|
||||||
// Tell the host the joining user's address.
|
// Tell the host the joining user's address.
|
||||||
NotifyClientRequestConnect msgNotifyReqConnect(
|
NotifyClientRequestConnect msgNotifyReqConnect( join );
|
||||||
joinAddr,
|
host->sock->send( msgNotifyReqConnect );
|
||||||
join->m_discoveryPort
|
|
||||||
);
|
|
||||||
|
|
||||||
host->sock->send(msgNotifyReqConnect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameSessionManager::ProcessJoinArms(sptr_user join, sptr_user host)
|
void GameSessionManager::ProcessJoinArms( sptr_user join, sptr_user host )
|
||||||
{
|
{
|
||||||
std::string hostAddr = host->m_discoveryAddr;
|
Log::Debug("Join User IPs : [{}:{}] -> [{}:{}]",
|
||||||
std::string joinAddr = join->m_discoveryAddr;
|
join->m_localAddr, join->m_localPort, join->m_discoveryAddr, join->m_discoveryPort );
|
||||||
|
|
||||||
if (hostAddr == joinAddr)
|
Log::Debug("Host User IPs : [{}:{}] -> [{}:{}]",
|
||||||
{
|
host->m_localAddr, host->m_localPort, host->m_discoveryAddr, host->m_discoveryPort );
|
||||||
hostAddr = host->m_localAddr;
|
|
||||||
joinAddr = join->m_localAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the joining user the hosts address.
|
// Tell the joining user its own address
|
||||||
NotifyClientDiscovered_RTA msgClientDiscovered(hostAddr, host->m_discoveryPort);
|
NotifyClientDiscovered_RTA msgClientDiscovered( join );
|
||||||
join->sock->send(msgClientDiscovered);
|
join->sock->send( msgClientDiscovered );
|
||||||
|
|
||||||
// Reserve a slot for the joining user.
|
|
||||||
NotifyReserveUserSlot_RTA msgNotifyReserveUser(joinAddr, join->m_discoveryPort);
|
|
||||||
host->sock->send(msgNotifyReserveUser);
|
|
||||||
|
|
||||||
// Tell the host the joining user's address.
|
// Tell the host the joining user's address.
|
||||||
NotifyClientRequestConnect_RTA msgNotifyReqConnect(
|
NotifyClientRequestConnect_RTA msgNotifyReqConnect( join );
|
||||||
joinAddr,
|
host->sock->send( msgNotifyReqConnect );
|
||||||
join->m_discoveryAddr,
|
|
||||||
join->m_discoveryPort
|
|
||||||
);
|
|
||||||
|
|
||||||
host->sock->send(msgNotifyReqConnect);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,15 @@
|
|||||||
|
|
||||||
#include "GameSession.h"
|
#include "GameSession.h"
|
||||||
|
|
||||||
|
#include "../Common/Constant.h"
|
||||||
|
|
||||||
class GameSessionManager {
|
class GameSessionManager {
|
||||||
private:
|
private:
|
||||||
static inline std::unique_ptr< GameSessionManager > m_instance;
|
static inline std::unique_ptr< GameSessionManager > m_instance;
|
||||||
static inline std::mutex m_mutex;
|
static inline std::mutex m_mutex;
|
||||||
static inline std::mutex m_dataMutex;
|
static inline std::mutex m_dataMutex;
|
||||||
|
|
||||||
int32_t m_gameIndex;
|
int32_t m_uniqueGameIndex;
|
||||||
std::vector< sptr_game_session > m_gameSessionList[ 2 ];
|
std::vector< sptr_game_session > m_gameSessionList[ 2 ];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -34,8 +36,18 @@ public:
|
|||||||
|
|
||||||
void OnDisconnectUser( sptr_user user );
|
void OnDisconnectUser( sptr_user user );
|
||||||
|
|
||||||
bool CreatePublicGameSession( sptr_user user, const std::wstring gameName, const RealmGameType clientType );
|
bool CreateGameSession_CON( sptr_user user,
|
||||||
bool CreatePrivateGameSession( sptr_user user, const std::wstring gameName, const RealmGameType clientType );
|
const std::wstring gameInfo,
|
||||||
|
const std::wstring name,
|
||||||
|
const std::wstring stage,
|
||||||
|
const bool isPrivateGame );
|
||||||
|
|
||||||
|
bool CreateGameSession_RTA( sptr_user user,
|
||||||
|
const std::wstring gameInfo,
|
||||||
|
const std::wstring name,
|
||||||
|
const std::array< int8_t, 5 > &attributes,
|
||||||
|
const bool isPrivateGame );
|
||||||
|
|
||||||
bool ForceTerminateGame( const int32_t gameId, RealmGameType clientType );
|
bool ForceTerminateGame( const int32_t gameId, RealmGameType clientType );
|
||||||
sptr_game_session FindGame( const int32_t gameId, RealmGameType clientType );
|
sptr_game_session FindGame( const int32_t gameId, RealmGameType clientType );
|
||||||
sptr_game_session FindGame( const std::wstring &gameName, RealmGameType clientType );
|
sptr_game_session FindGame( const std::wstring &gameName, RealmGameType clientType );
|
||||||
|
|||||||
Reference in New Issue
Block a user