Lobby Server and all of its events

This commit is contained in:
HikikoMarmy
2025-04-14 03:54:56 +01:00
parent 2525d7be5a
commit afc48ae9ff
19 changed files with 287 additions and 147 deletions

View File

@@ -18,10 +18,7 @@ sptr_generic_response RequestCancelGame::ProcessRequest( sptr_user user, sptr_by
return std::make_shared< ResultCancelGame >( this );
}
GameSessionManager::Get().CancelGameSession( user );
// TODO:
// Notify the players via the Discovery Server
GameSessionManager::Get().RequestCancel( user );
return std::make_shared< ResultCancelGame >( this );
}

View File

@@ -23,7 +23,7 @@ sptr_generic_response RequestCreateAccount::ProcessRequest( sptr_user user, sptr
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::ERROR_FATAL, L"" );
}
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::SUCCESS, user->session_id );
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::SUCCESS, user->m_sessionId );
}
ResultCreateAccount::ResultCreateAccount( GenericRequest *request, int32_t reply, std::wstring sessionId ) : GenericResponse( *request )

View File

@@ -14,7 +14,7 @@ sptr_generic_response RequestCreatePrivateGame::ProcessRequest( sptr_user user,
{
Deserialize( stream );
auto result = GameSessionManager::Get().CreatePrivateGameSession( user, m_gameName, 0, 9999 );
auto result = GameSessionManager::Get().CreatePrivateGameSession( user, m_gameName );
if( !result )
{

View File

@@ -24,7 +24,7 @@ sptr_generic_response RequestCreatePublicGame::ProcessRequest( sptr_user user, s
{
Deserialize( stream );
auto result = GameSessionManager::Get().CreatePublicGameSession( user, m_gameName, 0, 9999 );
auto result = GameSessionManager::Get().CreatePublicGameSession( user, m_gameName );
if( !result )
{
@@ -34,8 +34,6 @@ sptr_generic_response RequestCreatePublicGame::ProcessRequest( sptr_user user, s
Log::Info( "[%S] Create Public Game: %S", m_sessionId.c_str(), m_gameName.c_str() );
user->player_level = 999;
return std::make_shared< ResultCreatePublicGame >(this, CREATE_REPLY::SUCCESS, Config::service_ip, Config::discovery_port);
}

View File

@@ -1,8 +1,5 @@
#include "../../global_define.h"
#include "RequestDoClientDiscovery.h"
#include "NotifyClientDiscovered.h"
#include "NotifyGameDiscovered.h"
#include "NotifyClientReqConnect.h"
void RequestDoClientDiscovery::Deserialize( sptr_byte_stream stream )
{
@@ -19,32 +16,18 @@ sptr_generic_response RequestDoClientDiscovery::ProcessRequest( sptr_user user,
auto session = GameSessionManager::Get().FindGame( m_gameId );
if( session == nullptr )
{
Log::Error( "Game session not found! [%d]", m_gameId );
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 );
}
// TODO: Get max size from game data blob
if( session->m_userList.size() >= 4 )
if( session->m_currentPlayers >= session->m_maximumPlayers )
{
Log::Error( "Game session is full! [%d]", m_gameId );
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::GAME_FULL, "", 0 );
}
auto host = session->GetHost();
user->m_gameId = m_gameId;
user->m_isHost = false;
if( host == nullptr )
{
Log::Error( "Game session owner not found! [%d]", m_gameId );
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 );
}
Log::Debug( "[%s] DoClientDiscovery : %d", m_sessionId.c_str(), m_gameId );
user->game_id = m_gameId;
user->discovery_state = DiscoveryState::Initial_Connect;
// Send the discovery server information to the client
return std::make_shared< ResultDoClientDiscovery >(this, DISCOVERY_REPLY::SUCCESS, Config::service_ip, Config::discovery_port );
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::SUCCESS, Config::service_ip, Config::discovery_port );
}
ResultDoClientDiscovery::ResultDoClientDiscovery( GenericRequest *request, int32_t reply, std::string ip, int32_t port ) : GenericResponse( *request )

View File

@@ -13,36 +13,46 @@ sptr_generic_response RequestGetGame::ProcessRequest( sptr_user user, sptr_byte_
{
Deserialize( stream );
Log::Debug( "RequestGetGame : %S", m_sessionId.c_str() );
Log::Debug( "RequestGetGame : %S", m_gameName.c_str() );
if( user == nullptr )
{
Log::Error( "User not found! [%S]", m_sessionId.c_str() );
return std::make_shared< ResultGetGame >( this );
return std::make_shared< ResultGetGame >( this, TIMEOUT );
}
user->is_host = false;
user->is_ready = false;
user->game_id = -1;
auto session = GameSessionManager::Get().FindGame( m_gameName );
return std::make_shared< ResultGetGame >( this );
if( session == nullptr )
{
Log::Error( "Game session not found! [%S]", m_gameName.c_str() );
return std::make_shared< ResultGetGame >( this, NOT_FOUND );
}
if( session->m_currentPlayers >= session->m_maximumPlayers )
{
Log::Error( "Game session is full! [%S]", m_gameName.c_str() );
return std::make_shared< ResultGetGame >( this, TIMEOUT );
}
user->m_isHost = false;
user->m_gameId = session->m_gameIndex;
return std::make_shared< ResultGetGame >( this, SUCCESS );
}
ResultGetGame::ResultGetGame( GenericRequest *request ) : GenericResponse( *request )
ResultGetGame::ResultGetGame( GenericRequest *request, int32_t reply ) : GenericResponse( *request )
{
m_reply = reply;
}
ByteStream & ResultGetGame::Serialize()
ByteStream &ResultGetGame::Serialize()
{
m_stream.write_u16( m_packetId );
m_stream.write_u32( m_requestId );
m_stream.write_u32( 0 );
m_stream.write_u32( m_reply );
m_stream.write_utf16( L"Kelethin" );
m_stream.write_utf16(L"OwnerName");
m_stream.write_u32(0);
m_stream.write_utf16( L"OwnerName" );
m_stream.write_u32( 0 );
return m_stream;
}

View File

@@ -6,6 +6,12 @@ private:
std::wstring m_sessionId;
std::wstring m_gameName;
enum REPLY {
SUCCESS = 0,
TIMEOUT,
NOT_FOUND
};
public:
static std::unique_ptr< RequestGetGame > Create()
{
@@ -16,7 +22,10 @@ public:
};
class ResultGetGame : public GenericResponse {
private:
int32_t m_reply;
public:
ResultGetGame( GenericRequest *request );
ResultGetGame( GenericRequest *request, int32_t reply );
ByteStream &Serialize();
};

View File

@@ -24,13 +24,16 @@ ByteStream &ResultGetRealmStats::Serialize()
m_stream.write_u32( m_requestId );
m_stream.write_u32( 0 );
m_stream.write_u32( 1 ); // Users Logged In Game
m_stream.write_u32( 2 ); // Users Logged In Realm
m_stream.write_u32( 3 ); // Users Running Game
m_stream.write_u32( 4 ); // Users Running Realm
m_stream.write_u32( 5 ); // Users Playing Game
m_stream.write_u32( 6 ); // Users Playing Realm
m_stream.write_u32( 7 ); // unmatchedGamesGame
m_stream.write_u32( 8 ); // unmatchedGamesRealm
// Player count on the game page.
m_stream.write_u32( RealmUserManager::Get().GetUserCount() ); // Users Logged In Game
// I'm not sure this appears anywhere in the game.
m_stream.write_u32( 0 ); // Users Logged In Realm
m_stream.write_u32( 0 ); // Users Running Game
m_stream.write_u32( 0 ); // Users Running Realm
m_stream.write_u32( 0 ); // Users Playing Game
m_stream.write_u32( 0 ); // Users Playing Realm
m_stream.write_u32( 0 ); // unmatchedGamesGame
m_stream.write_u32( 0 ); // unmatchedGamesRealm
return m_stream;
}

View File

@@ -2,8 +2,6 @@
class RequestGetRealmStats : public GenericRequest
{
private:
public:
static std::unique_ptr< RequestGetRealmStats > Create()
{

View File

@@ -13,7 +13,10 @@ sptr_generic_response RequestGetRules::ProcessRequest( sptr_user user, sptr_byte
Deserialize( stream );
// TODO: Get rules/eula based on language
std::wstring rules = L"Welcome to the Norrath Emulated Server!\n\n";
std::wstring rules =
L"Welcome to the Norrath Emulated Server!\n\n"
L"This server is currently in development\n"
L"and may not be fully functional.\n\n";
return std::make_shared< ResultGetRules >( this, rules );
}

View File

@@ -1,5 +1,4 @@
#include "../../global_define.h"
#include "RequestLogin.h"
void RequestLogin::Deserialize( sptr_byte_stream stream )
@@ -31,7 +30,7 @@ sptr_generic_response RequestLogin::ProcessRequest( sptr_user user, sptr_byte_st
Log::Debug( "RequestLogin : Champions of Norrath v1.0" );
}
return std::make_shared< ResultLogin >( this, LOGIN_REPLY::SUCCESS, user->session_id );
return std::make_shared< ResultLogin >( this, LOGIN_REPLY::SUCCESS, user->m_sessionId );
}
ResultLogin::ResultLogin( GenericRequest *request, int32_t reply, std::wstring sessionId ) : GenericResponse( *request )

View File

@@ -11,7 +11,6 @@ sptr_generic_response RequestLogout::ProcessRequest( sptr_user user, sptr_byte_s
{
Deserialize( stream );
// TODO: Any other cleanup here?
Log::Debug( "[%S] Logout", m_sessionId.c_str() );
return std::make_shared< ResultLogout >( this, 0 );

View File

@@ -15,7 +15,7 @@ void RequestMatchGame::Deserialize( sptr_byte_stream stream )
auto unknown_e = stream->read_u32();
// Match Game Node Count
for( int i = 0; i < unknown_e; i++ )
for( uint32_t i = 0; i < unknown_e; i++ )
{
auto node_a = stream->read_u16();
auto node_b = stream->read_u32();
@@ -40,13 +40,14 @@ sptr_generic_response RequestMatchGame::ProcessRequest( sptr_user user, sptr_byt
Deserialize( stream );
Log::Debug( "RequestMatchGame : %S", m_sessionId.c_str() );
Log::Packet( stream->data, stream->data.size(), false );
return std::make_shared< ResultMatchGame >( this );
}
ResultMatchGame::ResultMatchGame( GenericRequest *request ) : GenericResponse( *request )
{
}
ByteStream &ResultMatchGame::Serialize()
@@ -56,35 +57,36 @@ ByteStream &ResultMatchGame::Serialize()
m_stream.write_u32( 0 );
auto publicGameList = GameSessionManager::Get().GetAvailableGameSessionList();
auto publicGameCount = static_cast< uint32_t >( publicGameList.size() );
m_stream.write_u32(publicGameList.size());
m_stream.write_u32( publicGameCount );
{
for (auto& game : publicGameList)
m_stream.write_utf16(game->m_gameLocation);
for( auto &game : publicGameList )
m_stream.write_utf16( game->m_gameLocation );
}
m_stream.write_u32(publicGameList.size());
m_stream.write_u32( publicGameCount );
{
for (auto& game : publicGameList)
m_stream.write_utf16(game->m_gameName);
for( auto &game : publicGameList )
m_stream.write_utf16( game->m_gameName );
}
m_stream.write_u32(publicGameList.size());
m_stream.write_u32( publicGameCount );
{
for (auto& game : publicGameList)
m_stream.write_utf16(game->m_ownerName);
for( auto &game : publicGameList )
m_stream.write_utf16( game->m_ownerName );
}
m_stream.write_u32(publicGameList.size());
m_stream.write_u32( publicGameCount );
{
for (auto& game : publicGameList)
m_stream.write_u32(game->m_gameIndex);
for( auto &game : publicGameList )
m_stream.write_u32( game->m_gameIndex );
}
m_stream.write_u32(publicGameList.size());
m_stream.write_u32( publicGameCount );
{
for (auto& game : publicGameList)
m_stream.write_utf8(game->m_gameData);
for( auto &game : publicGameList )
m_stream.write_utf8( game->m_gameData );
}
return m_stream;

View File

@@ -12,8 +12,6 @@ sptr_generic_response RequestTouchSession::ProcessRequest( sptr_user user, sptr_
{
Deserialize( stream );
Log::Debug( "RequestTouchSession : %S", m_sessionId.c_str() );
return std::make_shared< ResultTouchSession >( this );
}

View File

@@ -11,11 +11,9 @@ void RequestUpdateGameData::Deserialize( sptr_byte_stream stream )
sptr_generic_response RequestUpdateGameData::ProcessRequest( sptr_user user, sptr_byte_stream stream )
{
Deserialize( stream);
Deserialize( stream );
Log::Packet( stream->data, stream->data.size(), false );
auto gameSession = GameSessionManager::Get().FindGame( user->game_id );
auto gameSession = GameSessionManager::Get().FindGame( user->m_gameId );
if( gameSession == nullptr )
{
@@ -23,14 +21,41 @@ sptr_generic_response RequestUpdateGameData::ProcessRequest( sptr_user user, spt
return std::make_shared< ResultUpdateGameData >( this );
}
if( m_gameData.size() != 256 )
{
Log::Error( "Game data size is not 256 bytes! [%S]", m_sessionId.c_str() );
return std::make_shared< ResultUpdateGameData >( this );
}
gameSession->m_gameData = m_gameData;
// Parse Game Data. Not the most ideal way to do this, but it works.
char currentPlayers = 0;
char maxPlayers = 0;
char description[ 200 ] = { 0 };
int result = sscanf( m_gameData.c_str(), " %hhd / %hhd :%199[^\r\n]", &currentPlayers, &maxPlayers, description );
if( result >= 2 )
{
gameSession->m_currentPlayers = currentPlayers;
gameSession->m_maximumPlayers = maxPlayers;
gameSession->m_description = ( result == 3 ) ? description : ""; // Empty if not parsed
}
else
{
Log::Debug( "Failed to parse game info from: %s", m_gameData.c_str() );
}
std::string ip = std::string( m_gameData.c_str() + 220, 24 );
user->m_localAddr = ip;
return std::make_shared< ResultUpdateGameData >( this );
}
ResultUpdateGameData::ResultUpdateGameData( GenericRequest *request ) : GenericResponse( *request )
{
}
ByteStream &ResultUpdateGameData::Serialize()

View File

@@ -5,7 +5,6 @@ class RequestUpdateGameData : public GenericRequest
private:
std::wstring m_sessionId;
std::string m_gameData;
std::string m_hardwareIp;
public:
static std::unique_ptr< RequestUpdateGameData > Create()