Refactor network events for cleaner buffer management.

Naming some previously unnamed events.
This commit is contained in:
HikikoMarmy
2025-07-01 14:00:14 +01:00
parent e15570ceec
commit d2cd5f55c6
102 changed files with 1739 additions and 889 deletions

View File

@@ -1,20 +1,17 @@
#include "NotifyClientDiscovered.h" #include "NotifyClientDiscovered.h"
#include "../../Game/RealmUser.h"
#include "../../Common/Constant.h" NotifyClientDiscovered::NotifyClientDiscovered( sptr_user user ) : GenericMessage( 0x40 )
NotifyClientDiscovered::NotifyClientDiscovered( std::string clientIp, int32_t clientPort ) : GenericMessage( 0x40 )
{ {
this->m_clientIp = std::move( clientIp ); this->m_clientIp = user->m_discoveryAddr;
this->m_clientPort = clientPort; this->m_clientPort = user->m_discoveryPort;
} }
ByteBuffer &NotifyClientDiscovered::Serialize() void NotifyClientDiscovered::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_sz_utf8( m_clientIp ); out.write_sz_utf8( m_clientIp );
m_stream.write_u32( m_clientPort ); out.write_u32( m_clientPort );
return m_stream;
} }

View File

@@ -3,7 +3,7 @@
#include <string> #include <string>
#include "../GenericNetMessage.h" #include "../GenericNetMessage.h"
#include "../../Common/Constant.h" #include "../../Common/ForwardDecl.h"
class NotifyClientDiscovered : public GenericMessage { class NotifyClientDiscovered : public GenericMessage {
private: private:
@@ -11,6 +11,6 @@ private:
int32_t m_clientPort; int32_t m_clientPort;
public: public:
NotifyClientDiscovered( std::string clientIp, int32_t clientPort ); NotifyClientDiscovered( sptr_user user );
ByteBuffer &Serialize() override; void Serialize( ByteBuffer &out ) const override;
}; };

View File

@@ -1,20 +1,19 @@
#include "NotifyClientDiscovered_RTA.h" #include "NotifyClientDiscovered_RTA.h"
#include "../../Common/Constant.h" #include "../../Common/Constant.h"
#include "../../Game/RealmUser.h"
NotifyClientDiscovered_RTA::NotifyClientDiscovered_RTA( std::string clientIp, int32_t clientPort ) : GenericMessage( 0x40 ) NotifyClientDiscovered_RTA::NotifyClientDiscovered_RTA( sptr_user user ) : GenericMessage( 0x40 )
{ {
this->m_clientIp = std::move( clientIp ); this->m_clientIp = user->m_discoveryAddr;
this->m_clientPort = clientPort; this->m_clientPort = user->m_discoveryPort;
} }
ByteBuffer & NotifyClientDiscovered_RTA::Serialize() void NotifyClientDiscovered_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_utf8( m_clientIp ); out.write_utf8( m_clientIp );
m_stream.write_u32( m_clientPort ); out.write_u32( m_clientPort );
return m_stream;
} }

View File

@@ -4,6 +4,7 @@
#include "../GenericNetMessage.h" #include "../GenericNetMessage.h"
#include "../../Common/Constant.h" #include "../../Common/Constant.h"
#include "../../Common/ForwardDecl.h"
class NotifyClientDiscovered_RTA : public GenericMessage { class NotifyClientDiscovered_RTA : public GenericMessage {
private: private:
@@ -11,6 +12,6 @@ private:
int32_t m_clientPort; int32_t m_clientPort;
public: public:
NotifyClientDiscovered_RTA( std::string clientIp, int32_t clientPort ); NotifyClientDiscovered_RTA( sptr_user user );
ByteBuffer &Serialize() override; void Serialize( ByteBuffer &out ) const override;
}; };

View File

@@ -0,0 +1,18 @@
#include "NotifyClientReqConnect.h"
NotifyClientRequestConnect::NotifyClientRequestConnect( std::string clientIp, int32_t clientPort ) : GenericMessage( 0x3F )
{
this->m_clientIp = std::move( clientIp );
this->m_clientPort = clientPort;
}
ByteBuffer &NotifyClientRequestConnect::Serialize()
{
m_stream.write_u16( m_packetId );
m_stream.write_u32( 0 );
m_stream.write_sz_utf8( m_clientIp );
m_stream.write_u32( m_clientPort );
return m_stream;
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <string>
#include "../GenericNetMessage.h"
class NotifyClientRequestConnect : public GenericMessage
{
private:
std::string m_clientIp;
int32_t m_clientPort;
public:
NotifyClientRequestConnect( std::string clientIp, int32_t clientPort );
ByteBuffer &Serialize() override;
};

View File

@@ -1,18 +1,18 @@
#include "NotifyClientRequestConnect.h" #include "NotifyClientRequestConnect.h"
NotifyClientRequestConnect::NotifyClientRequestConnect( std::string clientIp, int32_t clientPort ) : GenericMessage( 0x3F ) #include "../../Game/RealmUser.h"
NotifyClientRequestConnect::NotifyClientRequestConnect( sptr_user user ) : GenericMessage( 0x3F )
{ {
this->m_clientIp = std::move( clientIp ); this->m_clientIp = user->m_discoveryAddr;
this->m_clientPort = clientPort; this->m_clientPort = user->m_discoveryPort;
} }
ByteBuffer &NotifyClientRequestConnect::Serialize() void NotifyClientRequestConnect::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_sz_utf8( m_clientIp ); out.write_sz_utf8( m_clientIp );
m_stream.write_u32( m_clientPort ); out.write_u32( m_clientPort );
return m_stream;
} }

View File

@@ -3,14 +3,14 @@
#include <string> #include <string>
#include "../GenericNetMessage.h" #include "../GenericNetMessage.h"
#include "../../Common/ForwardDecl.h"
class NotifyClientRequestConnect : public GenericMessage class NotifyClientRequestConnect : public GenericMessage {
{
private: private:
std::string m_clientIp; std::string m_clientIp;
int32_t m_clientPort; int32_t m_clientPort;
public: public:
NotifyClientRequestConnect( std::string clientIp, int32_t clientPort ); NotifyClientRequestConnect( sptr_user user );
ByteBuffer &Serialize() override; void Serialize( ByteBuffer &out ) const override;
}; };

View File

@@ -1,22 +1,25 @@
#include "NotifyClientRequestConnect_RTA.h" #include "NotifyClientRequestConnect_RTA.h"
NotifyClientRequestConnect_RTA::NotifyClientRequestConnect_RTA( std::string localAddr, std::string remoteAddr, int32_t port ) : GenericMessage( 0x65 ) #include "../../Game/RealmUser.h"
NotifyClientRequestConnect_RTA::NotifyClientRequestConnect_RTA( sptr_user user ) : GenericMessage( 0x65 )
{ {
this->m_localAddr = localAddr; this->m_remoteAddr = user->m_discoveryAddr;
this->m_remoteAddr = remoteAddr; this->m_remotePort = user->m_discoveryPort;
this->m_port = port;
this->m_localAddr = user->m_localAddr;
this->m_localPort = user->m_localPort;
} }
ByteBuffer &NotifyClientRequestConnect_RTA::Serialize() void NotifyClientRequestConnect_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_utf8( this->m_localAddr); out.write_utf8( this->m_remoteAddr );
m_stream.write_u32( this->m_port ); out.write_u32( this->m_remotePort );
m_stream.write_utf8( this->m_localAddr ); out.write_utf8( this->m_localAddr );
m_stream.write_u32( this->m_port ); out.write_u32( this->m_localPort );
return m_stream;
} }

View File

@@ -4,14 +4,16 @@
#include <string> #include <string>
#include "../GenericNetMessage.h" #include "../GenericNetMessage.h"
#include "../../Common/ForwardDecl.h"
class NotifyClientRequestConnect_RTA : public GenericMessage { class NotifyClientRequestConnect_RTA : public GenericMessage {
private: private:
std::string m_localAddr; std::string m_localAddr;
std::string m_remoteAddr; std::string m_remoteAddr;
int32_t m_port; int32_t m_localPort;
int32_t m_remotePort;
public: public:
NotifyClientRequestConnect_RTA( std::string localAddr, std::string remoteAddr, int32_t port ); NotifyClientRequestConnect_RTA( sptr_user user );
ByteBuffer &Serialize() override; void Serialize( ByteBuffer &out ) const override;
}; };

View File

@@ -4,12 +4,9 @@ NotifyForcedLogout::NotifyForcedLogout() : GenericMessage( 0x41 )
{ {
} }
ByteBuffer &NotifyForcedLogout::Serialize() void NotifyForcedLogout::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
out.write_u32( 0 );
m_stream.write_u32( 0 );
return m_stream;
} }

View File

@@ -7,5 +7,5 @@ private:
public: public:
NotifyForcedLogout(); NotifyForcedLogout();
ByteBuffer &Serialize() override; void Serialize( ByteBuffer &out ) const override;
}; };

View File

@@ -7,17 +7,15 @@ NotifyGameDiscovered::NotifyGameDiscovered( std::string clientIp, int32_t client
this->m_clientType = clientType; this->m_clientType = clientType;
} }
ByteBuffer &NotifyGameDiscovered::Serialize() void NotifyGameDiscovered::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
if( m_clientType == RealmGameType::RETURN_TO_ARMS ) if( m_clientType == RealmGameType::RETURN_TO_ARMS )
m_stream.write_utf8( m_clientIp ); out.write_utf8( m_clientIp );
else else
m_stream.write_sz_utf8( m_clientIp ); out.write_sz_utf8( m_clientIp );
m_stream.write_u32( m_clientPort ); out.write_u32( m_clientPort );
return m_stream;
} }

View File

@@ -14,5 +14,5 @@ private:
public: public:
NotifyGameDiscovered( std::string clientIp, int32_t clientPort, RealmGameType clientType ); NotifyGameDiscovered( std::string clientIp, int32_t clientPort, RealmGameType clientType );
ByteBuffer &Serialize() override; void Serialize(ByteBuffer &out) const override;
}; };

View File

@@ -1,19 +1,19 @@
#include "NotifyReserveUserSlot_RTA.h" #include "NotifyReserveUserSlot_RTA.h"
NotifyReserveUserSlot_RTA::NotifyReserveUserSlot_RTA( std::string discoveryAddr, int32_t discoveryPort ) : GenericMessage( 0x51 ) NotifyReserveUserSlot_RTA::NotifyReserveUserSlot_RTA( int32_t memberId, std::string discoveryAddr, int32_t discoveryPort ) : GenericMessage( 0x51 )
{ {
this->m_discoveryAddr = discoveryAddr; this->m_discoveryAddr = discoveryAddr;
this->m_port = discoveryPort; this->m_port = discoveryPort;
this->m_memberId = memberId;
} }
ByteBuffer &NotifyReserveUserSlot_RTA::Serialize() // This notification is nullsub.
void NotifyReserveUserSlot_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_u32( 0 ); // Maybe slot or character ID? out.write_u32( 0 );
m_stream.write_utf8(""); // Probably IP out.write_utf8( "" );
m_stream.write_u32( 0 ); // Probably Port out.write_u32( 0 );
return m_stream;
} }

View File

@@ -6,8 +6,9 @@ class NotifyReserveUserSlot_RTA : public GenericMessage {
private: private:
std::string m_discoveryAddr; std::string m_discoveryAddr;
int32_t m_port; int32_t m_port;
int32_t m_memberId;
public: public:
NotifyReserveUserSlot_RTA( std::string discoveryAddr, int32_t discoveryPort ); NotifyReserveUserSlot_RTA( int32_t memberId, std::string discoveryAddr, int32_t discoveryPort );
ByteBuffer &Serialize() override; void Serialize(ByteBuffer &out) const override;
}; };

View File

@@ -0,0 +1,18 @@
#include "NotifyRoomMessage.h"
NotifyRoomMessage::NotifyRoomMessage( std::wstring roomName, std::wstring chatHandle, std::wstring message ) : GenericMessage( 0x3D )
{
m_roomName = roomName;
m_chatHandle = chatHandle;
m_message = message;
}
void NotifyRoomMessage::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( 0 );
out.write_utf16( m_roomName );
out.write_utf16( m_chatHandle );
out.write_utf16( m_message );
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include "../GenericNetMessage.h"
class NotifyRoomMessage : public GenericMessage {
private:
std::wstring m_message;
std::wstring m_chatHandle;
std::wstring m_roomName;
public:
NotifyRoomMessage( std::wstring roomName, std::wstring chatHandle, std::wstring message );
void Serialize(ByteBuffer &out) const override;
};

View File

@@ -4,48 +4,46 @@ Notify_4C::Notify_4C() : GenericMessage( 0x4C )
{ {
} }
ByteBuffer &Notify_4C::Serialize() void Notify_4C::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_u32( 0 ); // Unknown out.write_u32( 0 ); // Unknown
m_stream.write_u32( 1 ); // Unknown out.write_u32( 1 ); // Unknown
{ {
m_stream.write_utf16( L"Dummy 1" ); out.write_utf16( L"Dummy 1" );
} }
m_stream.write_u32( 1 ); // Unknown out.write_u32( 1 ); // Unknown
{ {
m_stream.write_u32( 0 ); out.write_u32( 0 );
// Blob // Blob
} }
m_stream.write_u32( 1 ); // Unknown out.write_u32( 1 ); // Unknown
{ {
m_stream.write_u32( 0 ); out.write_u32( 0 );
} }
m_stream.write_u16( 0 ); // Unknown out.write_u16( 0 ); // Unknown
m_stream.write_u32( 1 ); // Unknown out.write_u32( 1 ); // Unknown
{ {
m_stream.write_u16( 0 ); out.write_u16( 0 );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_utf16( L"Dummy 2" ); out.write_utf16( L"Dummy 2" );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_u16( 1 ); out.write_u16( 1 );
} }
m_stream.write_u32( 0 ); // Unknown out.write_u32( 0 ); // Unknown
m_stream.write_utf8( "127.0.0.1" ); out.write_utf8( "127.0.0.1" );
m_stream.write_u32( 0 ); // Unknown out.write_u32( 0 ); // Unknown
m_stream.write_u32( 0 ); // Unknown out.write_u32( 0 ); // Unknown
return m_stream;
} }

View File

@@ -7,5 +7,5 @@ private:
public: public:
Notify_4C(); Notify_4C();
ByteBuffer &Serialize() override; void Serialize(ByteBuffer &out) const override;
}; };

View File

@@ -0,0 +1,22 @@
#include "Notify_65.h"
NotifyClientRequestsConnect2::NotifyClientRequestsConnect2( std::string discoveryAddr, std::string localAddr, int32_t port ) : GenericMessage( 0x65 )
{
m_discoveryAddr = std::move( discoveryAddr );
m_localAddr = std::move( localAddr );
m_port = port;
}
ByteBuffer &NotifyClientRequestsConnect2::Serialize()
{
m_stream.write_u16( m_packetId );
m_stream.write_u32( 0 );
m_stream.write_utf8( m_discoveryAddr );
m_stream.write_u32( m_port );
m_stream.write_utf8( m_localAddr );
m_stream.write_u32( m_port );
return m_stream;
}

14
Network/Event/Notify_65.h Normal file
View File

@@ -0,0 +1,14 @@
#pragma once
#include "../GenericNetMessage.h"
class NotifyClientRequestsConnect2 : public GenericMessage {
private:
std::string m_discoveryAddr;
std::string m_localAddr;
int32_t m_port;
public:
NotifyClientRequestsConnect2( std::string discoveryAddr, std::string localAddr, int32_t port );
ByteBuffer &Serialize() override;
};

View File

@@ -0,0 +1,45 @@
#include "RequestAppendCharacterData.h"
#include "../../Game/CharacterSaveManager.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/RealmUser.h"
#include "../../Database/Database.h"
#include "../../logging.h"
void RequestAppendCharacterData::Deserialize( sptr_byte_stream stream )
{
DeserializeHeader( stream );
auto sessionId = stream->read_encrypted_utf16();
auto length = stream->read_u32();
m_data = stream->read_bytes( length );
m_endOfData = stream->read_u32();
}
sptr_generic_response RequestAppendCharacterData::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr )
{
return std::make_shared< ResultAppendCharacterData >( this, FATAL_ERROR );
}
CharacterSaveManager::Get().AppendSaveData( user->m_sessionId, m_data, m_endOfData );
return std::make_shared< ResultAppendCharacterData >( this, SUCCESS );
}
ResultAppendCharacterData::ResultAppendCharacterData( GenericRequest *request, int32_t reply ) : GenericResponse( *request )
{
m_reply = reply;
}
void ResultAppendCharacterData::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( m_reply );
}

View File

@@ -6,10 +6,11 @@
#include "../GenericNetRequest.h" #include "../GenericNetRequest.h"
#include "../GenericNetResponse.h" #include "../GenericNetResponse.h"
class Request_5D : public GenericRequest class RequestAppendCharacterData : public GenericRequest
{ {
private: private:
std::vector< uint8_t > m_data; std::vector< uint8_t > m_data;
int32_t m_endOfData;
enum CREATE_REPLY { enum CREATE_REPLY {
SUCCESS = 0, SUCCESS = 0,
@@ -17,20 +18,20 @@ private:
GENERAL_ERROR, GENERAL_ERROR,
}; };
public: public:
static std::unique_ptr< Request_5D > Create() static std::unique_ptr< RequestAppendCharacterData > Create()
{ {
return std::make_unique< Request_5D >(); return std::make_unique< RequestAppendCharacterData >();
} }
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override; sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override; void Deserialize( sptr_byte_stream stream ) override;
}; };
class Result_5D : public GenericResponse { class ResultAppendCharacterData : public GenericResponse {
private: private:
int32_t m_reply; int32_t m_reply;
public: public:
Result_5D( GenericRequest *request, int32_t reply ); ResultAppendCharacterData( GenericRequest *request, int32_t reply );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -15,27 +15,21 @@ sptr_generic_response RequestCancelGame::ProcessRequest( sptr_socket socket, spt
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultCancelGame >( this ); return std::make_shared< ResultCancelGame >( this );
} }
if (user->m_isHost) if( user->m_gameType != RealmGameType::CHAMPIONS_OF_NORRATH )
{ {
auto result = GameSessionManager::Get().RequestCancel(user); return std::make_shared< ResultCancelGame >( this );
}
if( false == result ) if( !GameSessionManager::Get().RequestCancel( user ) )
{ {
Log::Error( "Failed to cancel game session for user [%S]", user->m_sessionId.c_str() ); Log::Error( "Failed to cancel game session for user [{}]", user->m_sessionId );
}
}
else
{
user->m_isHost = false;
user->m_gameId = -1;
} }
return std::make_shared< ResultCancelGame >( this ); return std::make_shared< ResultCancelGame >( this );
@@ -46,11 +40,9 @@ ResultCancelGame::ResultCancelGame( GenericRequest *request ) : GenericResponse(
} }
ByteBuffer &ResultCancelGame::Serialize() void ResultCancelGame::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
return m_stream;
} }

View File

@@ -24,5 +24,5 @@ public:
class ResultCancelGame : public GenericResponse { class ResultCancelGame : public GenericResponse {
public: public:
ResultCancelGame( GenericRequest *request ); ResultCancelGame( GenericRequest *request );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -2,6 +2,7 @@
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/GameSessionManager.h" #include "../../Game/GameSessionManager.h"
#include "../../Game/ChatRoomManager.h"
#include "../../logging.h" #include "../../logging.h"
void RequestCancelGame_RTA::Deserialize( sptr_byte_stream stream ) void RequestCancelGame_RTA::Deserialize( sptr_byte_stream stream )
@@ -15,15 +16,34 @@ sptr_generic_response RequestCancelGame_RTA::ProcessRequest( sptr_socket socket,
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultCancelGame_RTA >( this ); return std::make_shared< ResultCancelGame_RTA >( this );
} }
GameSessionManager::Get().RequestCancel( user ); if( user->m_gameType != RealmGameType::RETURN_TO_ARMS )
{
return std::make_shared< ResultCancelGame_RTA >( this );
}
const auto &gameSession = GameSessionManager::Get().FindGame( user->m_gameId, user->m_gameType );
if( gameSession == nullptr )
{
Log::Error( "Game session not found for user [{}]", user->m_sessionId );
return std::make_shared< ResultCancelGame_RTA >( this );
}
if( !GameSessionManager::Get().RequestCancel( user ) )
{
Log::Error( "Failed to cancel game session for user [{}]", user->m_sessionId );
}
if( !ChatRoomManager::Get().LeaveRoom( user, user->m_privateRoomId ) )
{
Log::Error( "Failed to leave private chat room for user [{}]", user->m_username );
}
return std::make_shared< ResultCancelGame_RTA >( this ); return std::make_shared< ResultCancelGame_RTA >( this );
} }
@@ -33,11 +53,9 @@ ResultCancelGame_RTA::ResultCancelGame_RTA( GenericRequest *request ) : GenericR
} }
ByteBuffer &ResultCancelGame_RTA::Serialize() void ResultCancelGame_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
return m_stream;
} }

View File

@@ -24,5 +24,5 @@ public:
class ResultCancelGame_RTA : public GenericResponse { class ResultCancelGame_RTA : public GenericResponse {
public: public:
ResultCancelGame_RTA( GenericRequest *request ); ResultCancelGame_RTA( GenericRequest *request );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -11,11 +11,11 @@ void RequestCreateAccount::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
m_username = Util::WideToUTF8( stream->read_encrypted_utf16() ); m_username = stream->read_encrypted_utf16();
m_password = Util::WideToUTF8( stream->read_encrypted_utf16() ); m_password = stream->read_encrypted_utf16();
m_emailAddress = Util::WideToUTF8( stream->read_encrypted_utf16() ); m_emailAddress = stream->read_encrypted_utf16();
m_dateOfBirth = Util::WideToUTF8( stream->read_encrypted_utf16() ); m_dateOfBirth = stream->read_encrypted_utf16();
m_chatHandle = Util::WideToUTF8( stream->read_encrypted_utf16() ); m_chatHandle = stream->read_encrypted_utf16();
} }
bool RequestCreateAccount::VerifyUserData() bool RequestCreateAccount::VerifyUserData()
@@ -45,34 +45,40 @@ sptr_generic_response RequestCreateAccount::ProcessRequest( sptr_socket socket,
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( nullptr == user || user->m_gameType != RealmGameType::RETURN_TO_ARMS ) if( nullptr == user || user->m_gameType != RealmGameType::RETURN_TO_ARMS )
{ {
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::ERROR_FATAL, L"" ); return std::make_shared< ResultCreateAccount >( this, ERROR_FATAL, L"" );
} }
if( m_username.empty() || m_password.empty() || m_emailAddress.empty() || m_dateOfBirth.empty() || m_chatHandle.empty() ) if( m_username.empty() || m_password.empty() || m_emailAddress.empty() || m_dateOfBirth.empty() || m_chatHandle.empty() )
{ {
Log::Error( "RequestCreateAccount::ProcessRequest() - Missing required fields for account creation." ); Log::Error( "RequestCreateAccount::ProcessRequest() - Missing required fields for account creation." );
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::ERROR_FATAL, L"" ); return std::make_shared< ResultCreateAccount >( this, ERROR_FATAL, L"" );
} }
auto result = Database::Get().CreateNewAccount auto result = Database::Get().CreateNewAccount
( (
m_username, Util::WideToUTF8( m_username ),
m_password, Util::WideToUTF8( m_password ),
m_emailAddress, Util::WideToUTF8( m_emailAddress ),
m_dateOfBirth, Util::WideToUTF8( m_dateOfBirth ),
m_chatHandle Util::WideToUTF8( m_chatHandle )
); );
if( !result ) if( !result )
{ {
Log::Error( "RequestCreateAccount::ProcessRequest() - Failed to create account for user: %s", m_username.c_str() ); Log::Error( "RequestCreateAccount::ProcessRequest() - Failed to create account for user: {}", m_username );
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::ERROR_FATAL, L"" ); return std::make_shared< ResultCreateAccount >( this, ERROR_FATAL, L"" );
} }
return std::make_shared< ResultCreateAccount >( this, CREATE_ACCOUNT_REPLY::SUCCESS, user->m_sessionId ); user->m_isLoggedIn = true;
user->m_sessionId = UserManager::Get().GenerateSessionId();
user->m_accountId = result;
user->m_username = m_username;
user->m_chatHandle = m_chatHandle;
return std::make_shared< ResultCreateAccount >( this, SUCCESS, user->m_sessionId );
} }
ResultCreateAccount::ResultCreateAccount( GenericRequest *request, int32_t reply, std::wstring sessionId ) : GenericResponse( *request ) ResultCreateAccount::ResultCreateAccount( GenericRequest *request, int32_t reply, std::wstring sessionId ) : GenericResponse( *request )
@@ -81,13 +87,11 @@ ResultCreateAccount::ResultCreateAccount( GenericRequest *request, int32_t reply
m_sessionId = sessionId; m_sessionId = sessionId;
} }
ByteBuffer &ResultCreateAccount::Serialize() void ResultCreateAccount::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_encrypted_utf16( m_sessionId ); out.write_encrypted_utf16( m_sessionId );
return m_stream;
} }

View File

@@ -8,17 +8,18 @@
class RequestCreateAccount : public GenericRequest class RequestCreateAccount : public GenericRequest
{ {
private:
enum CREATE_ACCOUNT_REPLY { enum CREATE_ACCOUNT_REPLY {
SUCCESS = 0, SUCCESS = 0,
ERROR_FATAL, ERROR_FATAL,
ERROR_NOT_EXIST ERROR_NOT_EXIST
}; };
std::string m_username; std::wstring m_username;
std::string m_password; std::wstring m_password;
std::string m_emailAddress; std::wstring m_emailAddress;
std::string m_dateOfBirth; std::wstring m_dateOfBirth;
std::string m_chatHandle; std::wstring m_chatHandle;
bool VerifyUserData(); bool VerifyUserData();
@@ -41,5 +42,5 @@ private:
public: public:
ResultCreateAccount( GenericRequest *request, int32_t reply, std::wstring sessionId ); ResultCreateAccount( GenericRequest *request, int32_t reply, std::wstring sessionId );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -1,6 +1,7 @@
#include "RequestCreateNewCharacter_RTA.h" #include "RequestCreateNewCharacter_RTA.h"
#include "../../Database/Database.h" #include "../../Database/Database.h"
#include "../../Game/CharacterSaveManager.h"
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/RealmUser.h" #include "../../Game/RealmUser.h"
#include "../../Game/RealmCharacter.h" #include "../../Game/RealmCharacter.h"
@@ -15,34 +16,37 @@ void RequestCreateNewCharacter_RTA::Deserialize( sptr_byte_stream stream )
auto a = stream->read_u32(); auto a = stream->read_u32();
auto b = stream->read_u32(); auto b = stream->read_u32();
m_newCharacterData = std::make_shared< RealmCharacter >( stream ); m_metaData.Deserialize( stream );
auto characterDataSize = stream->read_u32();
m_characterData = stream->read_bytes( characterDataSize );
} }
sptr_generic_response RequestCreateNewCharacter_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestCreateNewCharacter_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultCreateNewCharacter_RTA >( this, FATAL_ERROR ); return std::make_shared< ResultCreateNewCharacter_RTA >( this, FATAL_ERROR );
} }
auto unpacked = m_newCharacterData->Unpack(); if( user->m_gameType != RealmGameType::RETURN_TO_ARMS )
//Log::PacketToFile( "new_character", unpacked, unpacked.size());
auto characterId = Database::Get().CreateNewCharacter( user->m_accountId, m_newCharacterData->GetMetaData().Serialize(), m_newCharacterData->GetCharacterData() );
if( characterId < 0 )
{ {
Log::Error( "Invalid game type for CreateNewCharacter_RTA request! [{}]", m_sessionId );
return std::make_shared< ResultCreateNewCharacter_RTA >( this, FATAL_ERROR ); return std::make_shared< ResultCreateNewCharacter_RTA >( this, FATAL_ERROR );
} }
Log::Info( "New character created for user: " + std::to_string( user->m_accountId ) + ", Character ID: " + std::to_string( characterId ) ); auto &saveManager = CharacterSaveManager::Get();
if( !saveManager.BeginSaveTask( user, user, 0, m_metaData, CharacterSaveType::NEW_CHARACTER ) )
{
Log::Error( "Failed to begin save task for new character! [{}]", m_sessionId );
return std::make_shared< ResultCreateNewCharacter_RTA >( this, FATAL_ERROR );
}
user->m_characterId = characterId; saveManager.AppendSaveData( user->m_sessionId, m_characterData, false );
user->m_character = m_newCharacterData;
return std::make_shared< ResultCreateNewCharacter_RTA >( this, SUCCESS ); return std::make_shared< ResultCreateNewCharacter_RTA >( this, SUCCESS );
} }
@@ -52,11 +56,9 @@ ResultCreateNewCharacter_RTA::ResultCreateNewCharacter_RTA( GenericRequest *requ
m_reply = reply; m_reply = reply;
} }
ByteBuffer& ResultCreateNewCharacter_RTA::Serialize() void ResultCreateNewCharacter_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
return m_stream;
} }

View File

@@ -9,13 +9,15 @@ class RequestCreateNewCharacter_RTA : public GenericRequest
{ {
private: private:
std::wstring m_sessionId; std::wstring m_sessionId;
sptr_realm_character m_newCharacterData; CharacterSlotData m_metaData;
std::vector< uint8_t > m_characterData;
enum CREATE_REPLY { enum CREATE_REPLY {
SUCCESS = 0, SUCCESS = 0,
FATAL_ERROR, FATAL_ERROR,
GENERAL_ERROR, GENERAL_ERROR,
}; };
public: public:
static std::unique_ptr< RequestCreateNewCharacter_RTA > Create() static std::unique_ptr< RequestCreateNewCharacter_RTA > Create()
{ {
@@ -32,5 +34,5 @@ private:
public: public:
ResultCreateNewCharacter_RTA( GenericRequest *request, int32_t reply ); ResultCreateNewCharacter_RTA( GenericRequest *request, int32_t reply );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -10,31 +10,37 @@ void RequestCreatePrivateGame::Deserialize( sptr_byte_stream stream )
DeserializeHeader( stream ); DeserializeHeader( stream );
m_sessionId = stream->read_encrypted_utf16(); m_sessionId = stream->read_encrypted_utf16();
m_gameInfo = stream->read_utf16(); m_gameName = stream->read_utf16();
} }
sptr_generic_response RequestCreatePrivateGame::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestCreatePrivateGame::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultCreatePrivateGame >( this, CREATE_REPLY::FATAL_ERROR, "", 0 ); return std::make_shared< ResultCreatePrivateGame >( this, FATAL_ERROR, "", 0 );
} }
auto result = GameSessionManager::Get().CreatePrivateGameSession( user, m_gameInfo, user->m_gameType ); if( nullptr != GameSessionManager::Get().FindGame( m_gameName, user->m_gameType ) )
{
Log::Error( "Game name is already in use! [{}]", m_gameName );
return std::make_shared< ResultCreatePrivateGame >( this, GAME_NAME_IN_USE, "", 0 );
}
auto result = GameSessionManager::Get().CreateGameSession_CON( user, L"", m_gameName, L"", true);
if( !result ) if( !result )
{ {
Log::Error( "RequestCreatePrivateGame::ProcessRequest() - Failed to create private game session!" ); Log::Error( "RequestCreatePrivateGame::ProcessRequest() - Failed to create private game session!" );
return std::make_shared< ResultCreatePrivateGame >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 ); return std::make_shared< ResultCreatePrivateGame >( this, GENERAL_ERROR, "", 0 );
} }
Log::Info( "[%S] Create Private Game: %S", m_sessionId.c_str(), m_gameInfo.c_str() ); Log::Info( "[{}] Create Private Game: {}", m_sessionId, m_gameName );
return std::make_shared< ResultCreatePrivateGame >( this, CREATE_REPLY::SUCCESS, Config::service_ip, Config::discovery_port ); return std::make_shared< ResultCreatePrivateGame >( this, SUCCESS, Config::service_ip, Config::discovery_port );
} }
ResultCreatePrivateGame::ResultCreatePrivateGame( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request ) ResultCreatePrivateGame::ResultCreatePrivateGame( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request )
@@ -44,14 +50,12 @@ ResultCreatePrivateGame::ResultCreatePrivateGame( GenericRequest *request, int32
m_discoveryPort = discoveryPort; m_discoveryPort = discoveryPort;
} }
ByteBuffer &ResultCreatePrivateGame::Serialize() void ResultCreatePrivateGame::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_sz_utf8( m_discoveryIp ); out.write_sz_utf8( m_discoveryIp );
m_stream.write( m_discoveryPort ); out.write( m_discoveryPort );
return m_stream;
} }

View File

@@ -10,7 +10,7 @@ class RequestCreatePrivateGame : public GenericRequest
{ {
private: private:
std::wstring m_sessionId; std::wstring m_sessionId;
std::wstring m_gameInfo; std::wstring m_gameName;
enum CREATE_REPLY { enum CREATE_REPLY {
SUCCESS = 0, SUCCESS = 0,
@@ -38,5 +38,5 @@ private:
public: public:
ResultCreatePrivateGame( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 ); ResultCreatePrivateGame( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -10,48 +10,52 @@ void RequestCreatePrivateGame_RTA::Deserialize( sptr_byte_stream stream )
DeserializeHeader( stream ); DeserializeHeader( stream );
m_sessionId = stream->read_encrypted_utf16(); m_sessionId = stream->read_encrypted_utf16();
m_gameInfo = stream->read_utf16(); m_gameName = stream->read_utf16();
m_localAddr = Util::WideToUTF8( stream->read_utf16() );
m_localPort = stream->read_u32();
} }
sptr_generic_response RequestCreatePrivateGame_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestCreatePrivateGame_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); Log::Packet( stream->get_buffer(), stream->get_length(), false );
auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultCreatePrivateGame2 >( this, CREATE_REPLY::FATAL_ERROR, "", 0 ); return std::make_shared< ResultCreatePrivateGame_RTA >( this, CREATE_REPLY::FATAL_ERROR, "", 0 );
} }
auto result = GameSessionManager::Get().CreatePrivateGameSession( user, m_gameInfo, user->m_gameType ); auto result = GameSessionManager::Get().CreateGameSession_RTA( user, L"", m_gameName, {}, true);
if( !result ) if( !result )
{ {
Log::Error( "RequestCreatePrivateGame2::ProcessRequest() - Failed to create private game session!" ); Log::Error( "RequestCreatePrivateGame2::ProcessRequest() - Failed to create private game session!" );
return std::make_shared< ResultCreatePrivateGame2 >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 ); return std::make_shared< ResultCreatePrivateGame_RTA >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 );
} }
Log::Info( "[%S] Create Private Game: %S", m_sessionId.c_str(), m_gameInfo.c_str() ); user->m_localAddr = m_localAddr;
user->m_localPort = m_localPort;
return std::make_shared< ResultCreatePrivateGame2 >( this, CREATE_REPLY::SUCCESS, Config::service_ip, Config::discovery_port ); Log::Info( "[{}] Create Private Game: {}", m_sessionId, m_gameName );
return std::make_shared< ResultCreatePrivateGame_RTA >( this, CREATE_REPLY::SUCCESS, Config::service_ip, Config::discovery_port );
} }
ResultCreatePrivateGame2::ResultCreatePrivateGame2( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request ) ResultCreatePrivateGame_RTA::ResultCreatePrivateGame_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request )
{ {
m_reply = reply; m_reply = reply;
m_discoveryIp = discoveryIp; m_discoveryIp = discoveryIp;
m_discoveryPort = discoveryPort; m_discoveryPort = discoveryPort;
} }
ByteBuffer &ResultCreatePrivateGame2::Serialize() void ResultCreatePrivateGame_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_sz_utf8( m_discoveryIp ); out.write_utf8( m_discoveryIp );
m_stream.write( m_discoveryPort ); out.write( m_discoveryPort );
return m_stream;
} }

View File

@@ -2,6 +2,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <array>
#include "../GenericNetRequest.h" #include "../GenericNetRequest.h"
#include "../GenericNetResponse.h" #include "../GenericNetResponse.h"
@@ -10,7 +11,9 @@ class RequestCreatePrivateGame_RTA : public GenericRequest
{ {
private: private:
std::wstring m_sessionId; std::wstring m_sessionId;
std::wstring m_gameInfo; std::wstring m_gameName;
std::string m_localAddr;
int32_t m_localPort;
enum CREATE_REPLY { enum CREATE_REPLY {
SUCCESS = 0, SUCCESS = 0,
@@ -30,13 +33,13 @@ public:
void Deserialize( sptr_byte_stream stream ) override; void Deserialize( sptr_byte_stream stream ) override;
}; };
class ResultCreatePrivateGame2 : public GenericResponse { class ResultCreatePrivateGame_RTA : public GenericResponse {
private: private:
int32_t m_reply; int32_t m_reply;
std::string m_discoveryIp; std::string m_discoveryIp;
int32_t m_discoveryPort; int32_t m_discoveryPort;
public: public:
ResultCreatePrivateGame2( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 ); ResultCreatePrivateGame_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -7,22 +7,22 @@
void RequestCreatePrivateRoom::Deserialize( sptr_byte_stream stream ) void RequestCreatePrivateRoom::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
m_sessionId = stream->read_encrypted_utf16();
m_roomName = stream->read_utf16();
} }
sptr_generic_response RequestCreatePrivateRoom::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestCreatePrivateRoom::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
return std::make_shared< ResultCreatePrivateRoom >( this ); return std::make_shared< ResultCreatePrivateRoom >( this );
} }
auto sessionId = stream->read_encrypted_utf16(); auto result = ChatRoomManager::Get().CreateGameChatSession( user, m_roomName );
auto roomName = stream->read_utf16();
auto result = ChatRoomManager::Get().CreatePrivateChatSession( user, roomName );
if( !result ) if( !result )
{ {
@@ -37,11 +37,9 @@ ResultCreatePrivateRoom::ResultCreatePrivateRoom( GenericRequest *request ) : Ge
{ {
} }
ByteBuffer&ResultCreatePrivateRoom::Serialize() void ResultCreatePrivateRoom::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
return m_stream;
} }

View File

@@ -8,6 +8,10 @@
class RequestCreatePrivateRoom : public GenericRequest class RequestCreatePrivateRoom : public GenericRequest
{ {
private:
std::wstring m_sessionId;
std::wstring m_roomName;
public: public:
static std::unique_ptr< RequestCreatePrivateRoom > Create() static std::unique_ptr< RequestCreatePrivateRoom > Create()
{ {
@@ -21,5 +25,5 @@ public:
class ResultCreatePrivateRoom : public GenericResponse { class ResultCreatePrivateRoom : public GenericResponse {
public: public:
ResultCreatePrivateRoom( GenericRequest *request ); ResultCreatePrivateRoom( GenericRequest *request );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -19,30 +19,64 @@ void RequestCreatePublicGame::Deserialize( sptr_byte_stream stream )
auto unknown_d = stream->read_u32(); auto unknown_d = stream->read_u32();
m_gameInfo = stream->read_utf16(); m_gameInfo = stream->read_utf16();
auto [name, stage] = ParseNameAndStage( m_gameInfo );
m_gameName = name;
m_stageName = stage;
}
std::tuple<std::wstring, std::wstring> RequestCreatePublicGame::ParseNameAndStage( const std::wstring &gameInfo )
{
const size_t open = gameInfo.find( L'[' );
const size_t close = gameInfo.find( L']' );
if( open == std::wstring::npos || close == std::wstring::npos || close < open )
return { L"", L"" };
std::wstring name = gameInfo.substr( 0, open );
std::wstring stage = gameInfo.substr( open + 1, close - open - 1 );
if( !name.empty() && iswspace( name.back() ) )
name.pop_back();
return { name, stage };
} }
sptr_generic_response RequestCreatePublicGame::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestCreatePublicGame::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); Log::Packet( stream->get_buffer(), stream->get_length(), false );
auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultCreatePublicGame >( this, CREATE_REPLY::FATAL_ERROR, "", 0 ); return std::make_shared< ResultCreatePublicGame >( this, FATAL_ERROR, "", 0 );
} }
auto result = GameSessionManager::Get().CreatePublicGameSession( user, m_gameInfo, user->m_gameType ); if( nullptr != GameSessionManager::Get().FindGame( m_gameName, user->m_gameType ) )
{
Log::Error( "Game name is already in use! [{}]", m_gameName );
return std::make_shared< ResultCreatePublicGame >( this, GAME_NAME_IN_USE, "", 0 );
}
auto result = GameSessionManager::Get().CreateGameSession_CON( user, m_gameInfo, m_gameName, m_stageName, false );
if( !result ) if( !result )
{ {
Log::Error( "RequestCreatePublicGame::ProcessRequest() - Failed to create public game session!" ); Log::Error( "RequestCreatePublicGame::ProcessRequest() - Failed to create public game session!" );
return std::make_shared< ResultCreatePublicGame >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 ); return std::make_shared< ResultCreatePublicGame >( this, GENERAL_ERROR, "", 0 );
} }
Log::Info( "[%S] Create Public Game: %S", m_sessionId.c_str(), m_gameInfo.c_str() ); Log::Info( "[{}] Create Public Game: {}", m_sessionId, m_gameInfo );
return std::make_shared< ResultCreatePublicGame >(this, CREATE_REPLY::SUCCESS, Config::service_ip, Config::discovery_port); user->m_isHost = true;
user->m_discoveryAddr = "";
user->m_discoveryPort = 0;
return std::make_shared< ResultCreatePublicGame >( this, SUCCESS, Config::service_ip, Config::discovery_port );
} }
// Result // Result
@@ -53,14 +87,12 @@ ResultCreatePublicGame::ResultCreatePublicGame( GenericRequest *request, int32_t
m_discoveryPort = discoveryPort; m_discoveryPort = discoveryPort;
} }
ByteBuffer &ResultCreatePublicGame::Serialize() void ResultCreatePublicGame::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_sz_utf8( m_discoveryIp ); out.write_sz_utf8( m_discoveryIp );
m_stream.write( m_discoveryPort ); out.write( m_discoveryPort );
return m_stream;
} }

View File

@@ -11,6 +11,8 @@ class RequestCreatePublicGame : public GenericRequest
private: private:
std::wstring m_sessionId; std::wstring m_sessionId;
std::wstring m_gameInfo; std::wstring m_gameInfo;
std::wstring m_gameName;
std::wstring m_stageName;
int32_t m_minimumLevel; int32_t m_minimumLevel;
int32_t m_maximumLevel; int32_t m_maximumLevel;
@@ -22,6 +24,7 @@ private:
GAME_NAME_IN_USE = 38, GAME_NAME_IN_USE = 38,
GAME_PENDING = 40, GAME_PENDING = 40,
}; };
public: public:
static std::unique_ptr< RequestCreatePublicGame > Create() static std::unique_ptr< RequestCreatePublicGame > Create()
{ {
@@ -29,6 +32,8 @@ public:
} }
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override; sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override; void Deserialize( sptr_byte_stream stream ) override;
std::tuple< std::wstring, std::wstring > ParseNameAndStage( const std::wstring &gameInfo );
}; };
class ResultCreatePublicGame : public GenericResponse { class ResultCreatePublicGame : public GenericResponse {
@@ -39,5 +44,5 @@ private:
public: public:
ResultCreatePublicGame( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 ); ResultCreatePublicGame( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -2,10 +2,10 @@
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/GameSessionManager.h" #include "../../Game/GameSessionManager.h"
#include "../../Game/ChatRoomManager.h"
#include "../../configuration.h" #include "../../configuration.h"
#include "../../logging.h" #include "../../logging.h"
// Request
void RequestCreatePublicGame_RTA::Deserialize( sptr_byte_stream stream ) void RequestCreatePublicGame_RTA::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
@@ -22,22 +22,65 @@ void RequestCreatePublicGame_RTA::Deserialize( sptr_byte_stream stream )
auto unknown_e = stream->read_u32(); auto unknown_e = stream->read_u32();
auto unknown_f = stream->read_u32(); auto unknown_f = stream->read_u32();
m_localAddr = Util::WideToUTF8(stream->read_utf16()); m_localAddr = Util::WideToUTF8( stream->read_utf16() );
m_localPort = stream->read_u32();
if( !ParseGameInfo() )
{
Log::Error( "Failed to parse game info: {}", m_gameInfo );
}
}
bool RequestCreatePublicGame_RTA::ParseGameInfo()
{
if( m_gameInfo.empty() )
{
Log::Error( "Game info is empty!" );
return false;
}
size_t pipePos = m_gameInfo.find( L'|' );
if( pipePos == std::wstring::npos )
{
Log::Error( "Invalid game info format!" );
return false;
}
std::wstring numbersPart = m_gameInfo.substr( 0, pipePos );
m_gameName = m_gameInfo.substr( pipePos + 1 );
std::wstringstream ss( numbersPart );
std::wstring numStr;
std::array<int8_t, 5> fields = { 0, 0, 0, 0, 0 };
for( size_t i = 0; i < fields.size(); ++i )
{
if( !std::getline( ss, numStr, L',' ) )
return false;
try
{
fields[ i ] = std::stoi( numStr );
}
catch( ... )
{
return false;
}
}
return true;
} }
sptr_generic_response RequestCreatePublicGame_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestCreatePublicGame_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultCreatePublicGame_RTA >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 ); return std::make_shared< ResultCreatePublicGame_RTA >( this, CREATE_REPLY::GENERAL_ERROR, "", 0 );
} }
auto result = GameSessionManager::Get().CreatePublicGameSession( user, m_gameInfo, user->m_gameType ); auto result = GameSessionManager::Get().CreateGameSession_RTA( user, m_gameInfo, m_gameName, m_attributes, false );
if( !result ) if( !result )
{ {
Log::Error( "RequestCreatePublicGame::ProcessRequest() - Failed to create public game session!" ); Log::Error( "RequestCreatePublicGame::ProcessRequest() - Failed to create public game session!" );
@@ -45,8 +88,9 @@ sptr_generic_response RequestCreatePublicGame_RTA::ProcessRequest( sptr_socket s
} }
user->m_localAddr = m_localAddr; user->m_localAddr = m_localAddr;
user->m_localPort = m_localPort;
Log::Info( "[%S] Create Public Game: %S", m_sessionId.c_str(), m_gameInfo.c_str() ); Log::Info( "[{}] Create Public Game: {}", user->m_username, m_gameInfo );
return std::make_shared< ResultCreatePublicGame_RTA >( this, CREATE_REPLY::SUCCESS, Config::service_ip, Config::discovery_port ); return std::make_shared< ResultCreatePublicGame_RTA >( this, CREATE_REPLY::SUCCESS, Config::service_ip, Config::discovery_port );
} }
@@ -59,14 +103,12 @@ ResultCreatePublicGame_RTA::ResultCreatePublicGame_RTA( GenericRequest *request,
m_discoveryPort = discoveryPort; m_discoveryPort = discoveryPort;
} }
ByteBuffer &ResultCreatePublicGame_RTA::Serialize() void ResultCreatePublicGame_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_utf8( m_discoveryIp ); out.write_utf8( m_discoveryIp );
m_stream.write( m_discoveryPort ); out.write( m_discoveryPort );
return m_stream;
} }

View File

@@ -2,6 +2,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <array>
#include "../GenericNetRequest.h" #include "../GenericNetRequest.h"
#include "../GenericNetResponse.h" #include "../GenericNetResponse.h"
@@ -11,8 +12,11 @@ class RequestCreatePublicGame_RTA : public GenericRequest
private: private:
std::wstring m_sessionId; std::wstring m_sessionId;
std::wstring m_gameInfo; std::wstring m_gameInfo;
std::wstring m_gameName;
std::string m_localAddr; std::string m_localAddr;
int32_t m_localPort;
std::array< int8_t, 5 > m_attributes;
enum CREATE_REPLY { enum CREATE_REPLY {
SUCCESS = 0, SUCCESS = 0,
@@ -21,6 +25,7 @@ private:
GAME_NAME_IN_USE = 38, GAME_NAME_IN_USE = 38,
GAME_PENDING = 40, GAME_PENDING = 40,
}; };
public: public:
static std::unique_ptr< RequestCreatePublicGame_RTA > Create() static std::unique_ptr< RequestCreatePublicGame_RTA > Create()
{ {
@@ -28,6 +33,7 @@ public:
} }
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override; sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override; void Deserialize( sptr_byte_stream stream ) override;
bool ParseGameInfo();
}; };
class ResultCreatePublicGame_RTA : public GenericResponse { class ResultCreatePublicGame_RTA : public GenericResponse {
@@ -38,5 +44,5 @@ private:
public: public:
ResultCreatePublicGame_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 ); ResultCreatePublicGame_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0 );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -3,6 +3,7 @@
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/GameSessionManager.h" #include "../../Game/GameSessionManager.h"
#include "../../configuration.h" #include "../../configuration.h"
#include "../../logging.h"
void RequestDoClientDiscovery::Deserialize( sptr_byte_stream stream ) void RequestDoClientDiscovery::Deserialize( sptr_byte_stream stream )
{ {
@@ -16,7 +17,9 @@ sptr_generic_response RequestDoClientDiscovery::ProcessRequest( sptr_socket sock
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); Log::Packet( stream->get_buffer(), stream->get_length(), false );
auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 ); return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 );
@@ -28,7 +31,7 @@ sptr_generic_response RequestDoClientDiscovery::ProcessRequest( sptr_socket sock
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 ); return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::FATAL_ERROR, "", 0 );
} }
if( session->m_currentPlayers >= session->m_maximumPlayers ) if( !session->IsJoinable( user ) )
{ {
return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::GAME_FULL, "", 0 ); return std::make_shared< ResultDoClientDiscovery >( this, DISCOVERY_REPLY::GAME_FULL, "", 0 );
} }
@@ -46,14 +49,12 @@ ResultDoClientDiscovery::ResultDoClientDiscovery( GenericRequest *request, int32
m_discoveryPort = port; m_discoveryPort = port;
} }
ByteBuffer &ResultDoClientDiscovery::Serialize() void ResultDoClientDiscovery::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_sz_utf8( m_discoveryIP ); out.write_sz_utf8( m_discoveryIP );
m_stream.write( m_discoveryPort ); out.write( m_discoveryPort );
return m_stream;
} }

View File

@@ -36,5 +36,5 @@ private:
public: public:
ResultDoClientDiscovery( GenericRequest *request, int32_t reply, std::string ip = "", int32_t port = 0); ResultDoClientDiscovery( GenericRequest *request, int32_t reply, std::string ip = "", int32_t port = 0);
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -0,0 +1,61 @@
#include "RequestDoClientDiscovery_RTA.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/GameSessionManager.h"
#include "../../configuration.h"
#include "../../logging.h"
void RequestDoClientDiscovery_RTA::Deserialize( sptr_byte_stream stream )
{
DeserializeHeader( stream );
m_sessionId = stream->read_encrypted_utf16();
m_gameId = stream->read_u32();
m_localAddr = stream->read_utf16();
m_localPort = stream->read_u32();
}
sptr_generic_response RequestDoClientDiscovery_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
Log::Packet( stream->get_buffer(), stream->get_length(), false );
auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr )
{
Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultDoClientDiscovery_RTA >( this, TIMEOUT );
}
auto session = GameSessionManager::Get().FindGame( m_gameId, user->m_gameType );
if( session == nullptr )
{
Log::Error( "Game session not found! [{}]", m_gameId );
return std::make_shared< ResultDoClientDiscovery_RTA >( this, NOT_FOUND );
}
user->m_isHost = false;
user->m_gameId = session->m_gameId;
user->m_localAddr = Util::WideToUTF8(m_localAddr);
user->m_localPort = m_localPort;
return std::make_shared< ResultDoClientDiscovery_RTA >( this, SUCCESS, Config::service_ip, Config::discovery_port );
}
ResultDoClientDiscovery_RTA::ResultDoClientDiscovery_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request )
{
m_reply = reply;
m_discoveryIp = discoveryIp;
m_discoveryPort = discoveryPort;
}
void ResultDoClientDiscovery_RTA::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( m_reply );
out.write_utf8( m_discoveryIp );
out.write_u32( m_discoveryPort );
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include <memory>
#include <string>
#include "../GenericNetRequest.h"
#include "../GenericNetResponse.h"
class RequestDoClientDiscovery_RTA : public GenericRequest {
private:
std::wstring m_sessionId;
std::wstring m_localAddr;
int32_t m_localPort;
uint32_t m_gameId;
enum REPLY {
SUCCESS = 0,
TIMEOUT,
NOT_FOUND
};
public:
static std::unique_ptr< RequestDoClientDiscovery_RTA > Create()
{
return std::make_unique< RequestDoClientDiscovery_RTA >();
}
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override;
};
class ResultDoClientDiscovery_RTA : public GenericResponse {
private:
int32_t m_reply;
std::string m_discoveryIp;
int32_t m_discoveryPort;
public:
ResultDoClientDiscovery_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0);
void Serialize( ByteBuffer &out ) const;
};

View File

@@ -1,44 +1,85 @@
#include "RequestEnterRoom.h" #include "RequestEnterRoom.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/ChatRoomManager.h"
#include "../../logging.h"
void RequestEnterRoom::Deserialize( sptr_byte_stream stream ) void RequestEnterRoom::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
auto sessionId = stream->read_encrypted_utf16();
m_roomName = stream->read_utf16();
} }
sptr_generic_response RequestEnterRoom::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestEnterRoom::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto publicKey = stream->read_utf8(); const auto user = UserManager::Get().FindUserBySocket( socket );
auto unknown = stream->read_u32(); if( !user )
return std::make_shared< ResultEnterRoom >( this );
}
ResultEnterRoom::ResultEnterRoom( GenericRequest *request ) : GenericResponse( *request )
{
}
ByteBuffer& ResultEnterRoom::Serialize()
{
m_stream.write_u16( m_packetId );
m_stream.write_u32( m_trackId );
m_stream.write_u32( 0 );
m_stream.write_utf16( L"Room Name" );
m_stream.write_utf16( L"Room Banner" );
m_stream.write_u32( 3 );
{ {
m_stream.write_utf16( L"Name1" ); Log::Error( "User not found for socket!" );
m_stream.write_utf16( L"Name2" ); return std::make_shared< ResultEnterRoom >( this, GENERAL_ERROR, nullptr );
m_stream.write_utf16( L"Name3" );
} }
m_stream.write_u32( 1 ); if( !ChatRoomManager::Get().JoinRoom( user, m_roomName ) )
{ {
m_stream.write_utf16( L"Name1" ); Log::Error( "Failed to join room [{}] for user [{}]", m_roomName, user->m_username );
return std::make_shared< ResultEnterRoom >( this, GENERAL_ERROR, nullptr );
} }
return m_stream; const auto room = ChatRoomManager::Get().FindRoom( m_roomName );
if( !room )
{
Log::Error( "Chat room [{}] not found after joining", m_roomName );
return std::make_shared< ResultEnterRoom >( this, GENERAL_ERROR, nullptr );
}
return std::make_shared< ResultEnterRoom >( this, SUCCESS, room );
}
ResultEnterRoom::ResultEnterRoom( GenericRequest *request, int32_t reply, sptr_chat_room_session room ) : GenericResponse( *request )
{
m_reply = reply;
m_room = room;
}
void ResultEnterRoom::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( m_reply );
if( m_room )
{
out.write_utf16( m_room->m_name );
out.write_utf16( m_room->m_banner );
out.write_u32( static_cast< uint32_t >( m_room->m_members.size() ) );
for( const auto &m : m_room->m_members )
{
if( auto member = m.lock() )
{
out.write_utf16( member->m_chatHandle );
}
else
{
out.write_utf16( L"Unknown" );
}
}
out.write_u32( static_cast< uint32_t >( m_room->m_moderators.size() ) );
for( const auto &m : m_room->m_moderators )
{
if( auto member = m.lock() )
{
out.write_utf16( member->m_chatHandle );
}
else
{
out.write_utf16( L"" );
}
}
}
} }

View File

@@ -6,8 +6,18 @@
#include "../GenericNetRequest.h" #include "../GenericNetRequest.h"
#include "../GenericNetResponse.h" #include "../GenericNetResponse.h"
#include "../../Game/ChatRoomSession.h"
class RequestEnterRoom : public GenericRequest class RequestEnterRoom : public GenericRequest
{ {
private:
std::wstring m_roomName;
enum REPLY {
SUCCESS = 0,
GENERAL_ERROR
};
public: public:
static std::unique_ptr< RequestEnterRoom > Create() static std::unique_ptr< RequestEnterRoom > Create()
{ {
@@ -19,7 +29,11 @@ public:
}; };
class ResultEnterRoom : public GenericResponse { class ResultEnterRoom : public GenericResponse {
private:
int32_t m_reply;
sptr_chat_room_session m_room;
public: public:
ResultEnterRoom( GenericRequest *request ); ResultEnterRoom( GenericRequest *request, int32_t reply, sptr_chat_room_session room );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -5,8 +5,6 @@
#include "../../Database/Database.h" #include "../../Database/Database.h"
#include "../../logging.h" #include "../../logging.h"
#include "../../Common/RLEZ.hpp"
void RequestGetNetCharacterData_RTA::Deserialize( sptr_byte_stream stream ) void RequestGetNetCharacterData_RTA::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
@@ -17,12 +15,12 @@ void RequestGetNetCharacterData_RTA::Deserialize( sptr_byte_stream stream )
sptr_generic_response RequestGetNetCharacterData_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestGetNetCharacterData_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize(stream); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
return std::make_shared< ResultGetNetCharacterData_RTA >( this, FATAL_ERROR, nullptr ); return std::make_shared< ResultGetNetCharacterData_RTA >( this, FATAL_ERROR );
} }
auto result = Database::Get().LoadCharacterData( user->m_accountId, m_characterId ); auto result = Database::Get().LoadCharacterData( user->m_accountId, m_characterId );
@@ -30,79 +28,81 @@ sptr_generic_response RequestGetNetCharacterData_RTA::ProcessRequest( sptr_socke
if( !result ) if( !result )
{ {
Log::Error( "Failed to load character data for account ID: " + std::to_string( user->m_accountId ) + ", character ID: " + std::to_string( m_characterId ) ); Log::Error( "Failed to load character data for account ID: " + std::to_string( user->m_accountId ) + ", character ID: " + std::to_string( m_characterId ) );
return std::make_shared< ResultGetNetCharacterData_RTA >( this, FATAL_ERROR, nullptr ); return std::make_shared< ResultGetNetCharacterData_RTA >( this, FATAL_ERROR );
} }
user->m_characterId = m_characterId; user->m_characterId = result->m_characterId;
user->m_character = result; user->m_character = result;
auto characterName = result->GetMetaData().GetValue( L"name" ); return SendCharacterData( socket, result );
Log::Debug( "Character data loaded for account ID: %lld, character ID: %d, name: %ls", user->m_accountId, m_characterId, characterName.c_str() );
return std::make_shared< ResultGetNetCharacterData_RTA >( this, SUCCESS, result );
} }
ResultGetNetCharacterData_RTA::ResultGetNetCharacterData_RTA( GenericRequest *request, int32_t reply, sptr_realm_character data ) : GenericResponse( *request ) sptr_generic_response RequestGetNetCharacterData_RTA::SendCharacterData( sptr_socket socket, sptr_realm_character character )
{
const auto &data = character->m_data;
const auto data_size = data.size();
size_t position = 0;
sptr_generic_response finalChunk = nullptr;
while( position < data_size )
{
const size_t chunk_size = std::min<size_t>( 1024, data_size - position );
std::vector<uint8_t> chunk_data( data.begin() + position, data.begin() + position + chunk_size );
const int32_t isFinalChunk = ( position + chunk_size >= data_size );
auto response = std::make_shared<ResultGetNetCharacterData_RTA>( this, SUCCESS, std::move( chunk_data ), isFinalChunk );
if( isFinalChunk )
{
finalChunk = response;
}
else
{
socket->send( response );
}
position += chunk_size;
}
return finalChunk;
}
ResultGetNetCharacterData_RTA::ResultGetNetCharacterData_RTA( GenericRequest *request, int32_t reply, std::optional<std::vector<uint8_t>> data, std::optional<int32_t> endOfData ) : GenericResponse( *request )
{ {
m_reply = reply; m_reply = reply;
m_data = data;
if( !data.has_value() )
{
m_chunk.clear();
}
else
{
m_chunk = data.value();
}
if( !endOfData.has_value() )
{
m_endOfData = 0;
}
else
{
m_endOfData = endOfData.value();
}
} }
ByteBuffer& ResultGetNetCharacterData_RTA::Serialize() void ResultGetNetCharacterData_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
if( !m_reply ) if( !m_reply )
{ {
const auto &characterData = m_data->m_characterData; out.write_u32( static_cast< uint32_t >( m_chunk.size() ) );
out.write_bytes( m_chunk );
// Erase first 4 bytes out.write_u32( m_endOfData );
//characterData.erase(characterData.begin(), characterData.begin() + 4);
//const auto unpacked = RLEZ::Decompress(characterData);
//const auto repacked = RLEZ::Compress(unpacked);
//Log::PacketToFile( "characterData_1", characterData, characterData.size() );
//Log::PacketToFile( "characterData_2", unpacked, unpacked.size() );
//Log::PacketToFile( "characterData_3", repacked, repacked.size() );
m_stream.write_u32( characterData.size());
m_stream.write_bytes( characterData );
for (int i = 0; i < 136; i++)
{
m_stream.write_u8(0xFF);
} }
for (int i = 0; i < 5; i++)
{
m_stream.write_u32(0);
m_stream.write_u32(3);
m_stream.write_u32(0);
m_stream.write_u8(0);
}
m_stream.write_u32(0);
m_stream.write_u32(0);
m_stream.write_u32(0);
m_stream.write_u32(0);
m_stream.write_u8(0);
m_stream.write_u8(5);
m_stream.write_u8(3);
m_stream.write_u8(0);
m_stream.write_u8(0);
m_stream.write_u8(3);
m_stream.write_u8(1);
m_stream.write_u32(1); // End Of Stream
}
//Log::Packet( m_stream.get_buffer(), m_stream.get_length(), false);
return m_stream;
} }

View File

@@ -27,14 +27,20 @@ public:
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override; sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override; void Deserialize( sptr_byte_stream stream ) override;
sptr_generic_response SendCharacterData(sptr_socket socket, sptr_realm_character data);
}; };
class ResultGetNetCharacterData_RTA : public GenericResponse { class ResultGetNetCharacterData_RTA : public GenericResponse {
private: private:
int32_t m_reply; int32_t m_reply;
sptr_realm_character m_data; int32_t m_endOfData;
std::vector< uint8_t > m_chunk;
public: public:
ResultGetNetCharacterData_RTA( GenericRequest *request, int32_t reply, sptr_realm_character data ); ResultGetNetCharacterData_RTA( GenericRequest *request, int32_t reply,
ByteBuffer &Serialize(); std::optional< std::vector< uint8_t > > data = std::nullopt,
std::optional < int32_t > endOfData = std::nullopt );
void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -20,17 +20,15 @@ ResultGetEncryptionKey::ResultGetEncryptionKey( GenericRequest *request ) : Gene
m_symKey = RealmCrypt::getSymmetricKey(); m_symKey = RealmCrypt::getSymmetricKey();
} }
ByteBuffer& ResultGetEncryptionKey::Serialize() void ResultGetEncryptionKey::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
auto encrypted = RealmCrypt::encryptSymmetric( m_symKey ); auto encrypted = RealmCrypt::encryptSymmetric( m_symKey );
m_stream.write_u32( encrypted.size() + 4 ); out.write_u32( encrypted.size() + 4 );
m_stream.write_u32( m_symKey.size() ); out.write_u32( m_symKey.size() );
m_stream.write_bytes( encrypted ); out.write_bytes( encrypted );
return m_stream;
} }

View File

@@ -23,5 +23,5 @@ public:
std::vector< uint8_t > m_symKey; std::vector< uint8_t > m_symKey;
ResultGetEncryptionKey( GenericRequest *request ); ResultGetEncryptionKey( GenericRequest *request );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -0,0 +1,38 @@
#include "RequestGetFriendList.h"
void RequestGetFriendList::Deserialize( sptr_byte_stream stream )
{
DeserializeHeader( stream );
}
sptr_generic_response RequestGetFriendList::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
auto publicKey = stream->read_utf8();
auto unknown = stream->read_u32();
return std::make_shared< ResultGetFriendList >( this );
}
ResultGetFriendList::ResultGetFriendList( GenericRequest *request ) : GenericResponse( *request )
{
}
void ResultGetFriendList::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( 0 );
// Friends
out.write_u32(1);
out.write_utf16(L"String_1");
out.write_u32(1);
out.write_utf16(L"String_2");
// Ignore
out.write_u32(1);
out.write_utf16(L"String_3");
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <memory>
#include <string>
#include "../GenericNetRequest.h"
#include "../GenericNetResponse.h"
class RequestGetFriendList : public GenericRequest
{
public:
static std::unique_ptr< RequestGetFriendList > Create()
{
return std::make_unique< RequestGetFriendList >();
}
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override;
};
class ResultGetFriendList : public GenericResponse {
public:
ResultGetFriendList( GenericRequest *request );
void Serialize( ByteBuffer &out ) const;
};

View File

@@ -17,10 +17,10 @@ sptr_generic_response RequestGetGame::ProcessRequest( sptr_socket socket, sptr_b
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultGetGame >( this, TIMEOUT ); return std::make_shared< ResultGetGame >( this, TIMEOUT );
} }
@@ -28,28 +28,28 @@ sptr_generic_response RequestGetGame::ProcessRequest( sptr_socket socket, sptr_b
if( session == nullptr ) if( session == nullptr )
{ {
Log::Error( "Game session not found! [%S]", m_gameName.c_str() ); Log::Error( "Game session not found! [{}]", m_gameName );
return std::make_shared< ResultGetGame >( this, NOT_FOUND ); return std::make_shared< ResultGetGame >( this, NOT_FOUND );
} }
if( session->m_currentPlayers >= session->m_maximumPlayers ) if( session->m_currentPlayers >= session->m_maximumPlayers )
{ {
Log::Error( "Game session is full! [%S]", m_gameName.c_str() ); Log::Error( "Game session is full! [{}]", m_gameName );
return std::make_shared< ResultGetGame >( this, TIMEOUT ); return std::make_shared< ResultGetGame >( this, TIMEOUT );
} }
auto host_user = session->m_owner.lock(); auto host_user = session->GetOwner();
if( host_user == nullptr ) if( host_user == nullptr )
{ {
Log::Error( "Game session owner not found! [%S]", m_gameName.c_str() ); Log::Error( "Game session owner not found! [{}]", m_gameName );
return std::make_shared< ResultGetGame >( this, TIMEOUT ); return std::make_shared< ResultGetGame >( this, TIMEOUT );
} }
user->m_isHost = false; user->m_isHost = false;
user->m_gameId = session->m_gameIndex; user->m_gameId = session->m_gameId;
return std::make_shared< ResultGetGame >( this, SUCCESS, session->m_gameIndex ); return std::make_shared< ResultGetGame >( this, SUCCESS, session->m_gameId );
} }
ResultGetGame::ResultGetGame( GenericRequest *request, int32_t reply, int32_t gameId ) : GenericResponse( *request ) ResultGetGame::ResultGetGame( GenericRequest *request, int32_t reply, int32_t gameId ) : GenericResponse( *request )
@@ -58,17 +58,15 @@ ResultGetGame::ResultGetGame( GenericRequest *request, int32_t reply, int32_t ga
m_gameId = gameId; m_gameId = gameId;
} }
ByteBuffer &ResultGetGame::Serialize() void ResultGetGame::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
// TODO: These may come in from the UpdateGameData event // TODO: These may come in from the UpdateGameData event
m_stream.write_utf16( L"Kelethin" ); out.write_utf16( L"Kelethin" );
m_stream.write_utf16( L"OwnerName" ); out.write_utf16( L"OwnerName" );
m_stream.write_u32( m_gameId ); out.write_u32( m_gameId );
return m_stream;
} }

View File

@@ -33,5 +33,5 @@ private:
public: public:
ResultGetGame( GenericRequest *request, int32_t reply, int32_t gameId = 0 ); ResultGetGame( GenericRequest *request, int32_t reply, int32_t gameId = 0 );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -2,7 +2,7 @@
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/GameSessionManager.h" #include "../../Game/GameSessionManager.h"
#include "../../configuration.h" #include "../../Game/RealmUser.h"
#include "../../logging.h" #include "../../logging.h"
void RequestGetGame_RTA::Deserialize( sptr_byte_stream stream ) void RequestGetGame_RTA::Deserialize( sptr_byte_stream stream )
@@ -10,65 +10,71 @@ void RequestGetGame_RTA::Deserialize( sptr_byte_stream stream )
DeserializeHeader( stream ); DeserializeHeader( stream );
m_sessionId = stream->read_encrypted_utf16(); m_sessionId = stream->read_encrypted_utf16();
m_gameId = stream->read_u32(); m_gameName = stream->read_utf16();
m_localAddr = Util::WideToUTF8(stream->read_utf16());
} }
sptr_generic_response RequestGetGame_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestGetGame_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Log::Packet( stream->get_buffer(), stream->get_length(), false );
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultGetGame_RTA >( this, TIMEOUT ); return std::make_shared< ResultGetGame_RTA >( this, TIMEOUT );
} }
auto session = GameSessionManager::Get().FindGame( m_gameId, user->m_gameType ); auto session = GameSessionManager::Get().FindGame( m_gameName, user->m_gameType );
if( session == nullptr ) if( session == nullptr )
{ {
Log::Error( "Game session not found! [%d]", m_gameId ); Log::Error( "Game session not found! [{}]", m_gameName );
return std::make_shared< ResultGetGame_RTA >( this, NOT_FOUND ); return std::make_shared< ResultGetGame_RTA >( this, NOT_FOUND );
} }
if( session->m_currentPlayers >= session->m_maximumPlayers ) if( session->m_currentPlayers >= session->m_maximumPlayers )
{ {
Log::Error( "Game session is full! [%d]", m_gameId ); Log::Error( "Game session is full! [{}]", m_gameName );
return std::make_shared< ResultGetGame_RTA >( this, TIMEOUT ); return std::make_shared< ResultGetGame_RTA >( this, TIMEOUT );
} }
auto host_user = session->m_owner.lock(); auto host_user = session->GetOwner();
if( host_user == nullptr ) if( host_user == nullptr )
{ {
Log::Error( "Game session owner not found! [%d]", m_gameId ); Log::Error( "Game session owner not found! [{}]", m_gameName );
return std::make_shared< ResultGetGame_RTA >( this, TIMEOUT ); return std::make_shared< ResultGetGame_RTA >( this, TIMEOUT );
} }
user->m_isHost = false; user->m_isHost = false;
user->m_gameId = session->m_gameIndex; user->m_gameId = session->m_gameId;
user->m_localAddr = m_localAddr;
return std::make_shared< ResultGetGame_RTA >( this, SUCCESS, Config::service_ip, Config::discovery_port ); return std::make_shared< ResultGetGame_RTA >( this, SUCCESS, session->m_gameId, host_user->m_discoveryAddr, host_user->m_localAddr, host_user->m_discoveryPort );
} }
ResultGetGame_RTA::ResultGetGame_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp, int32_t discoveryPort ) : GenericResponse( *request ) ResultGetGame_RTA::ResultGetGame_RTA( GenericRequest *request, int32_t reply, int32_t gameId, std::string discoveryAddr, std::string localAddr, int32_t discoveryPort ) : GenericResponse( *request )
{ {
m_reply = reply; m_reply = reply;
m_discoveryIp = discoveryIp; m_gameId = gameId;
m_discoveryPort = discoveryPort; m_discoveryAddr = Util::UTF8ToWide( discoveryAddr );
m_localAddr = Util::UTF8ToWide( localAddr );
m_port = discoveryPort;
} }
ByteBuffer &ResultGetGame_RTA::Serialize() void ResultGetGame_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_utf8( m_discoveryIp ); out.write_utf16( L"Test" );
m_stream.write_u32( m_discoveryPort ); out.write_u32( m_gameId );
return m_stream; out.write_utf16( m_discoveryAddr );
out.write_u32( m_port );
out.write_utf16( m_localAddr );
out.write_u32( m_port );
} }

View File

@@ -9,9 +9,7 @@
class RequestGetGame_RTA : public GenericRequest { class RequestGetGame_RTA : public GenericRequest {
private: private:
std::wstring m_sessionId; std::wstring m_sessionId;
std::string m_localAddr; std::wstring m_gameName;
uint32_t m_gameId;
enum REPLY { enum REPLY {
SUCCESS = 0, SUCCESS = 0,
@@ -31,10 +29,13 @@ public:
class ResultGetGame_RTA : public GenericResponse { class ResultGetGame_RTA : public GenericResponse {
private: private:
int32_t m_reply; int32_t m_reply;
std::string m_discoveryIp; int32_t m_gameId;
int32_t m_discoveryPort;
std::wstring m_discoveryAddr;
std::wstring m_localAddr;
int32_t m_port;
public: public:
ResultGetGame_RTA( GenericRequest *request, int32_t reply, std::string discoveryIp = "", int32_t discoveryPort = 0); ResultGetGame_RTA( GenericRequest *request, int32_t reply, int32_t gameId = -1, std::string discoveryAddr = "", std::string localAddr = "", int32_t discoveryPort = 0 );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -1,6 +1,7 @@
#include "RequestGetNetCharacterList_RTA.h" #include "RequestGetNetCharacterList_RTA.h"
#include "../../Game/RealmUser.h" #include "../../Game/RealmUser.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/RealmCharacterMetaKV.h" #include "../../Game/RealmCharacterMetaKV.h"
#include "../../Database/Database.h" #include "../../Database/Database.h"
#include "../../logging.h" #include "../../logging.h"
@@ -14,29 +15,35 @@ sptr_generic_response RequestGetNetCharacterList_RTA::ProcessRequest( sptr_socke
{ {
Deserialize( stream ); Deserialize( stream );
//auto result = Database::Get().LoadCharacterList( user->m_accountId ); auto user = UserManager::Get().FindUserBySocket( socket );
if( !user )
{
return std::make_shared< ResultGetNetCharacterList_RTA >( this, FATAL_ERROR, std::nullopt );
}
auto result = std::map< int32_t, RealmCharacterMetaData >(); auto result = Database::Get().LoadCharacterSlots( user->m_accountId );
return std::make_shared< ResultGetNetCharacterList_RTA >( this, SUCCESS, result ); return std::make_shared< ResultGetNetCharacterList_RTA >( this, SUCCESS, result );
} }
ResultGetNetCharacterList_RTA::ResultGetNetCharacterList_RTA( GenericRequest *request, int32_t reply, std::map< int32_t, RealmCharacterMetaData > list ) : GenericResponse( *request ) ResultGetNetCharacterList_RTA::ResultGetNetCharacterList_RTA( GenericRequest *request, int32_t reply, std::optional< std::map< uint32_t, CharacterSlotData > > list ) : GenericResponse( *request )
{ {
m_reply = reply; m_reply = reply;
m_characterList = std::move( list );
if( list != std::nullopt )
{
m_characterList = list.value();
}
} }
ByteBuffer &ResultGetNetCharacterList_RTA::Serialize() void ResultGetNetCharacterList_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
if( 0 == m_reply )
{
// Character Count // Character Count
m_stream.write_u32( static_cast< int >( m_characterList.size() ) ); out.write_u32( static_cast< int >( m_characterList.size() ) );
// Character List // Character List
for( auto &character : m_characterList ) for( auto &character : m_characterList )
@@ -44,22 +51,15 @@ ByteBuffer &ResultGetNetCharacterList_RTA::Serialize()
const auto &KV = character.second.GetMetaData(); const auto &KV = character.second.GetMetaData();
// Character ID // Character ID
m_stream.write_u32( character.first ); out.write_u32( character.first );
// Number of Key-Value pairs // Number of Key-Value pairs
m_stream.write_u32( static_cast< uint32_t >( KV.size() ) ); out.write_u32( static_cast< uint32_t >( KV.size() ) );
for( auto &pair : KV ) for( auto &pair : KV )
{ {
m_stream.write_utf16( pair.first ); out.write_utf16( pair.first );
m_stream.write_utf16( pair.second ); out.write_utf16( pair.second );
} }
} }
}
else
{
m_stream.write_u32( 0 ); // No characters
}
return m_stream;
} }

View File

@@ -31,9 +31,9 @@ public:
class ResultGetNetCharacterList_RTA : public GenericResponse { class ResultGetNetCharacterList_RTA : public GenericResponse {
private: private:
int32_t m_reply; int32_t m_reply;
std::map< int32_t, RealmCharacterMetaData > m_characterList; std::map< uint32_t, CharacterSlotData > m_characterList;
public: public:
ResultGetNetCharacterList_RTA( GenericRequest *request, int32_t reply, std::map< int32_t, RealmCharacterMetaData > list ); ResultGetNetCharacterList_RTA( GenericRequest *request, int32_t reply, std::optional< std::map< uint32_t, CharacterSlotData > > list );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -1,5 +1,7 @@
#include "RequestGetPublicRooms.h" #include "RequestGetPublicRooms.h"
#include "../../Game/ChatRoomManager.h"
void RequestGetPublicRooms::Deserialize( sptr_byte_stream stream ) void RequestGetPublicRooms::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
@@ -9,39 +11,45 @@ sptr_generic_response RequestGetPublicRooms::ProcessRequest( sptr_socket socket,
{ {
Deserialize( stream ); Deserialize( stream );
auto publicKey = stream->read_utf8(); const auto publicRooms = ChatRoomManager::Get().GetPublicRoomList();
return std::make_shared< ResultGetPublicRooms >( this ); return std::make_shared< ResultGetPublicRooms >( this, publicRooms );
} }
ResultGetPublicRooms::ResultGetPublicRooms( GenericRequest *request ) : GenericResponse( *request ) ResultGetPublicRooms::ResultGetPublicRooms( GenericRequest *request, std::vector< sptr_chat_room_session > rooms ) : GenericResponse( *request )
{ {
m_rooms = std::move( rooms );
} }
ByteBuffer& ResultGetPublicRooms::Serialize() void ResultGetPublicRooms::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
m_stream.write_u32( 0); const auto numRoom = static_cast< uint32_t >( m_rooms.size() );
for( int i = 0; i < 0; i++ )
{
m_stream.write_utf16( L"Room Name" );
m_stream.write_utf16( L"Room Banner" );
m_stream.write_u32( 3 ); out.write_u32( numRoom );
for( const auto &room : m_rooms )
{ {
m_stream.write_utf16( L"Name1" ); out.write_utf16( room->m_name );
m_stream.write_utf16( L"Name2" );
m_stream.write_utf16( L"Name3" );
} }
m_stream.write_u32( 1 ); out.write_u32( numRoom );
for( const auto &room : m_rooms )
{ {
m_stream.write_utf16( L"Name1" ); out.write_utf16( L"UNKNOWN" );
}
} }
return m_stream; out.write_u32( numRoom );
for( const auto &room : m_rooms )
{
out.write_u32( 88 );
}
out.write_u32( numRoom );
for( const auto &room : m_rooms )
{
out.write_u32( 99 );
}
} }

View File

@@ -6,6 +6,8 @@
#include "../GenericNetRequest.h" #include "../GenericNetRequest.h"
#include "../GenericNetResponse.h" #include "../GenericNetResponse.h"
#include "../../Game/ChatRoomSession.h"
class RequestGetPublicRooms : public GenericRequest class RequestGetPublicRooms : public GenericRequest
{ {
public: public:
@@ -19,7 +21,10 @@ public:
}; };
class ResultGetPublicRooms : public GenericResponse { class ResultGetPublicRooms : public GenericResponse {
private:
std::vector< sptr_chat_room_session > m_rooms;
public: public:
ResultGetPublicRooms( GenericRequest *request ); ResultGetPublicRooms( GenericRequest *request, std::vector< sptr_chat_room_session > rooms );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -19,22 +19,21 @@ ResultGetRealmStats::ResultGetRealmStats( GenericRequest *request ) : GenericRes
} }
ByteBuffer &ResultGetRealmStats::Serialize() void ResultGetRealmStats::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
// Player count on the game page. // Player count on the game page.
m_stream.write_u32( RealmUserManager::Get().GetUserCount() ); // Users Logged In Game out.write_u32( UserManager::Get().GetUserCount() ); // Users Logged In Game
// I'm not sure this appears anywhere in the game. // I'm not sure this appears anywhere in the game.
m_stream.write_u32( 0 ); // Users Logged In Realm out.write_u32( 0 ); // Users Logged In Realm
m_stream.write_u32( 0 ); // Users Running Game out.write_u32( 0 ); // Users Running Game
m_stream.write_u32( 0 ); // Users Running Realm out.write_u32( 0 ); // Users Running Realm
m_stream.write_u32( 0 ); // Users Playing Game out.write_u32( 0 ); // Users Playing Game
m_stream.write_u32( 0 ); // Users Playing Realm out.write_u32( 0 ); // Users Playing Realm
m_stream.write_u32( 0 ); // unmatchedGamesGame out.write_u32( 0 ); // unmatchedGamesGame
m_stream.write_u32( 0 ); // unmatchedGamesRealm out.write_u32( 0 ); // unmatchedGamesRealm
return m_stream;
} }

View File

@@ -20,5 +20,5 @@ public:
class ResultGetRealmStats : public GenericResponse { class ResultGetRealmStats : public GenericResponse {
public: public:
ResultGetRealmStats( GenericRequest *request ); ResultGetRealmStats( GenericRequest *request );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -1,43 +1,88 @@
#include "RequestGetRoom.h" #include "RequestGetRoom.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/ChatRoomManager.h"
#include "../../logging.h"
void RequestGetRoom::Deserialize( sptr_byte_stream stream ) void RequestGetRoom::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
auto sessionId = stream->read_encrypted_utf16(); m_sessionId = stream->read_encrypted_utf16();
m_roomName = stream->read_utf16();
} }
sptr_generic_response RequestGetRoom::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestGetRoom::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
return std::make_shared< ResultGetRoom >( this ); Log::Packet( stream->get_buffer(), stream->get_length(), false );
}
ResultGetRoom::ResultGetRoom( GenericRequest *request ) : GenericResponse( *request ) const auto user = UserManager::Get().FindUserBySocket( socket );
{ if( !user )
}
ByteBuffer &ResultGetRoom::Serialize()
{
m_stream.write_u16( m_packetId );
m_stream.write_u32( m_trackId );
m_stream.write_u32( 0 );
m_stream.write_utf16( L"Room Name" );
m_stream.write_utf16( L"Room Banner" );
m_stream.write_u32( 3 );
{ {
m_stream.write_utf16( L"Name1" ); return std::make_shared< ResultGetRoom >( this, GENERAL_ERROR );
m_stream.write_utf16( L"Name2" );
m_stream.write_utf16( L"Name3" );
} }
m_stream.write_u32( 1 ); sptr_chat_room_session targetRoom = nullptr;
if( m_roomName.empty() )
{ {
m_stream.write_utf16( L"Name1" ); targetRoom = ChatRoomManager::Get().FindRoom( user->m_privateRoomId );
}
else
{
targetRoom = ChatRoomManager::Get().FindRoom( user->m_publicRoomId );
} }
return m_stream; return std::make_shared< ResultGetRoom >( this, SUCCESS, targetRoom );
}
ResultGetRoom::ResultGetRoom( GenericRequest *request, int32_t reply, sptr_chat_room_session room ) : GenericResponse( *request )
{
m_reply = reply;
m_room = room;
}
void ResultGetRoom::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( m_reply );
if( m_room )
{
out.write_utf16( m_room->m_name );
out.write_utf16( m_room->m_banner );
out.write_u32( static_cast< uint32_t >( m_room->m_members.size() ) );
for( const auto &m : m_room->m_members )
{
const auto &member = m.lock();
if( member )
{
out.write_utf16( member->m_chatHandle );
}
else
{
out.write_utf16( L"" );
}
}
out.write_u32( static_cast< uint32_t >( m_room->m_moderators.size() ) );
for( const auto &m : m_room->m_moderators )
{
if( auto member = m.lock() )
{
out.write_utf16( member->m_chatHandle );
}
else
{
out.write_utf16( L"" );
}
}
}
} }

View File

@@ -6,7 +6,18 @@
#include "../GenericNetRequest.h" #include "../GenericNetRequest.h"
#include "../GenericNetResponse.h" #include "../GenericNetResponse.h"
#include "../../Game/ChatRoomSession.h"
class RequestGetRoom : public GenericRequest { class RequestGetRoom : public GenericRequest {
private:
std::wstring m_sessionId;
std::wstring m_roomName;
enum CREATE_ACCOUNT_REPLY {
SUCCESS = 0,
GENERAL_ERROR = 1,
};
public: public:
static std::unique_ptr< RequestGetRoom > Create() static std::unique_ptr< RequestGetRoom > Create()
{ {
@@ -18,7 +29,11 @@ public:
}; };
class ResultGetRoom : public GenericResponse { class ResultGetRoom : public GenericResponse {
private:
int32_t m_reply;
sptr_chat_room_session m_room;
public: public:
ResultGetRoom( GenericRequest *request ); ResultGetRoom( GenericRequest *request, int32_t reply, sptr_chat_room_session room = nullptr );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -16,7 +16,7 @@ sptr_generic_response RequestGetRules::ProcessRequest( sptr_socket socket, sptr_
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
return std::make_shared< ResultGetRules >( this, L"" ); return std::make_shared< ResultGetRules >( this, L"" );
@@ -26,18 +26,18 @@ sptr_generic_response RequestGetRules::ProcessRequest( sptr_socket socket, sptr_
// and move it info a MOTD file. // and move it info a MOTD file.
std::wstring rules; std::wstring rules;
if (user->m_gameType == RealmGameType::RETURN_TO_ARMS) if( user->m_gameType == RealmGameType::RETURN_TO_ARMS )
{ {
rules = L"Welcome to the Norrath Emulated Server!\n\n" rules = L"Welcome to the Champions Emulated Server!\n\n"
L"RETURN TO ARMS network support is currently a\n" L"RETURN TO ARMS network support is currently a\n"
L"work in progress and can not guarantee stability.\n\n" L"work in progress and can not guarantee stability.\n\n"
L"[IMPORTANT]:\n" L"[IMPORTANT]:\n"
L"Please note that ONLINE character data will not be saved.\n" L"Please note that ONLINE character saves may be unstable.\n"
L"You must import an offline save file for now.\n"; L"Use them at your own risk.\n";
} }
else else
{ {
rules = L"Welcome to the Norrath Emulated Server!\n\n" rules = L"Welcome to the Champions Emulated Server!\n\n"
L"This server is currently in development\n" L"This server is currently in development\n"
L"and may not be fully functional.\n\n"; L"and may not be fully functional.\n\n";
} }
@@ -50,13 +50,13 @@ ResultGetRules::ResultGetRules( GenericRequest *request, std::wstring rules ) :
m_rules = rules; m_rules = rules;
} }
ByteBuffer &ResultGetRules::Serialize() void ResultGetRules::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
out.write_utf16( m_rules );
m_stream.write_utf16( m_rules );
return m_stream;
} }

View File

@@ -27,5 +27,5 @@ private:
public: public:
ResultGetRules( GenericRequest *request, std::wstring rules ); ResultGetRules( GenericRequest *request, std::wstring rules );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -32,18 +32,16 @@ ResultGetServerAddress::ResultGetServerAddress( GenericRequest *request, std::st
m_gameType = gameType; m_gameType = gameType;
} }
ByteBuffer &ResultGetServerAddress::Serialize() void ResultGetServerAddress::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
if( m_gameType == RealmGameType::RETURN_TO_ARMS ) if( m_gameType == RealmGameType::RETURN_TO_ARMS )
m_stream.write_utf8( m_ip ); out.write_utf8( m_ip );
else else
m_stream.write_sz_utf8( m_ip ); out.write_sz_utf8( m_ip );
m_stream.write( m_port ); out.write( m_port );
return m_stream;
} }

View File

@@ -25,5 +25,5 @@ public:
RealmGameType m_gameType; RealmGameType m_gameType;
ResultGetServerAddress( GenericRequest *request, std::string ip, int32_t port, RealmGameType clientType ); ResultGetServerAddress( GenericRequest *request, std::string ip, int32_t port, RealmGameType clientType );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -0,0 +1,45 @@
#include "RequestLeaveRoom.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/ChatRoomManager.h"
#include "../../logging.h"
void RequestLeaveRoom::Deserialize( sptr_byte_stream stream )
{
DeserializeHeader( stream );
auto sessionId = stream->read_encrypted_utf16();
m_roomName = stream->read_utf16();
}
sptr_generic_response RequestLeaveRoom::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
const auto user = UserManager::Get().FindUserBySocket( socket );
if( !user )
{
Log::Error( "User not found for socket!" );
return std::make_shared< ResultLeaveRoom >( this, GENERAL_ERROR );
}
if( !ChatRoomManager::Get().LeaveRoom( user, m_roomName ) )
{
Log::Error( "Could not remove user [{}] from room [{}]", user->m_username, m_roomName );
return std::make_shared< ResultLeaveRoom >( this, GENERAL_ERROR );
}
return std::make_shared< ResultLeaveRoom >( this, SUCCESS );
}
ResultLeaveRoom::ResultLeaveRoom( GenericRequest *request, int32_t reply ) : GenericResponse( *request )
{
m_reply = reply;
}
void ResultLeaveRoom::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( m_reply );
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include <memory>
#include <string>
#include "../GenericNetRequest.h"
#include "../GenericNetResponse.h"
class RequestLeaveRoom : public GenericRequest
{
private:
std::wstring m_roomName;
enum REPLY {
SUCCESS = 0,
GENERAL_ERROR
};
public:
static std::unique_ptr< RequestLeaveRoom > Create()
{
return std::make_unique< RequestLeaveRoom >();
}
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override;
};
class ResultLeaveRoom : public GenericResponse {
private:
int32_t m_reply;
public:
ResultLeaveRoom( GenericRequest *request, int32_t reply );
void Serialize( ByteBuffer &out ) const;
};

View File

@@ -10,58 +10,77 @@ void RequestLogin::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
m_username = Util::WideToUTF8( stream->read_encrypted_utf16() ); m_username = stream->read_encrypted_utf16();
m_password = Util::WideToUTF8( stream->read_encrypted_utf16() ); m_password = stream->read_encrypted_utf16();
} }
sptr_generic_response RequestLogin::ProcessLoginCON(sptr_user user) sptr_generic_response RequestLogin::ProcessLoginCON( sptr_user user )
{ {
if (m_username != "foo" && m_password != "bar") if( m_username != L"foo" && m_password != L"bar" )
{ {
// Network Beta CoN uses login information, but it's invalid because of version 2.0 // Network Beta CoN uses login information, but it's invalid because of version 2.0
// which used "foo" and "bar" as the login credentials. // which used "foo" and "bar" as the login credentials.
Log::Debug("RequestLogin : Champions of Norrath v1.0"); Log::Debug( "RequestLogin : Champions of Norrath v1.0" );
// TODO: Either block this, or add support for the network beta. // TODO: Either block this, or add support for the network beta.
return std::make_shared< ResultLogin >(this, LOGIN_REPLY::ACCOUNT_INVALID, L""); return std::make_shared< ResultLogin >( this, LOGIN_REPLY::ACCOUNT_INVALID, L"" );
} }
user->m_isLoggedIn = true;
user->m_accountId = -1; user->m_accountId = -1;
user->m_sessionId = RealmUserManager::Get().GenerateSessionId(); user->m_sessionId = UserManager::Get().GenerateSessionId();
return std::make_shared< ResultLogin >(this, SUCCESS, user->m_sessionId); return std::make_shared< ResultLogin >( this, SUCCESS, user->m_sessionId );
} }
sptr_generic_response RequestLogin::ProcessLoginRTA(sptr_user user) sptr_generic_response RequestLogin::ProcessLoginRTA( sptr_user user )
{ {
// Return to Arms uses login information. // Return to Arms uses login information.
Log::Debug("RequestLogin : Return to Arms"); Log::Debug( "RequestLogin : Return to Arms" );
auto &UserManager = UserManager::Get();
auto &Database = Database::Get();
// Verify the account exists // Verify the account exists
auto accountId = Database::Get().VerifyAccount(m_username, m_password); auto accountId = Database.VerifyAccount( m_username, m_password );
if (accountId < 0) if( accountId < 0 )
{ {
Log::Error("RequestLogin::ProcessRequest() - Invalid account ID: " + std::to_string(accountId)); Log::Error( "RequestLogin::ProcessRequest() - Invalid account ID: " + std::to_string( accountId ) );
return std::make_shared< ResultLogin >(this, ACCOUNT_INVALID, L""); return std::make_shared< ResultLogin >( this, ACCOUNT_INVALID, L"" );
} }
user->m_accountId = accountId; // Check if the user is already logged in
user->m_sessionId = RealmUserManager::Get().GenerateSessionId(); for( const auto &existingUser : UserManager.GetUserList() )
{
if( existingUser->m_username == m_username || existingUser->m_accountId == accountId )
{
return std::make_shared< ResultLogin >( this, FATAL_ERROR, L"" );
}
}
Database::Get().CreateSession( auto [result, chatHandle] = Database.LoadAccount( accountId );
// Login Success
user->m_isLoggedIn = true;
user->m_username = m_username;
user->m_accountId = accountId;
user->m_chatHandle = chatHandle;
user->m_sessionId = UserManager.GenerateSessionId();
Database.CreateSession(
user->m_accountId, user->m_accountId,
user->m_sessionId, user->m_sessionId,
user->sock->remote_ip); user->sock->remote_ip );
return std::make_shared< ResultLogin >(this, SUCCESS, user->m_sessionId); return std::make_shared< ResultLogin >( this, SUCCESS, user->m_sessionId );
} }
sptr_generic_response RequestLogin::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestLogin::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "RequestLogin::ProcessRequest() - User not found" ); Log::Error( "RequestLogin::ProcessRequest() - User not found" );
@@ -90,14 +109,12 @@ ResultLogin::ResultLogin( GenericRequest *request, int32_t reply, std::wstring s
m_sessionId = sessionId; m_sessionId = sessionId;
} }
ByteBuffer &ResultLogin::Serialize() void ResultLogin::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
m_stream.write_encrypted_utf16( m_sessionId ); out.write_encrypted_utf16( m_sessionId );
m_stream.write_encrypted_utf16( L"UNKNOWN DUMMY STRING" ); out.write_encrypted_utf16( L"UNKNOWN DUMMY STRING" );
return m_stream;
} }

View File

@@ -15,8 +15,8 @@ private:
ACCOUNT_INVALID = 4, ACCOUNT_INVALID = 4,
}; };
std::string m_username; std::wstring m_username;
std::string m_password; std::wstring m_password;
std::wstring m_sessionId; std::wstring m_sessionId;
public: public:
@@ -39,5 +39,5 @@ private:
public: public:
ResultLogin( GenericRequest *request, int32_t reply, std::wstring sessionId ); ResultLogin( GenericRequest *request, int32_t reply, std::wstring sessionId );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -13,9 +13,9 @@ sptr_generic_response RequestLogout::ProcessRequest( sptr_socket socket, sptr_by
{ {
Deserialize( stream ); Deserialize( stream );
RealmUserManager::Get().RemoveUser( socket ); UserManager::Get().RemoveUser( socket );
Log::Debug( "[%S] Logout", m_sessionId.c_str() ); Log::Debug( "[{}] Logout", m_sessionId );
return std::make_shared< ResultLogout >( this, 0 ); return std::make_shared< ResultLogout >( this, 0 );
} }
@@ -25,11 +25,9 @@ ResultLogout::ResultLogout( GenericRequest *request, int32_t reply ) : GenericRe
m_reply = reply; m_reply = reply;
} }
ByteBuffer &ResultLogout::Serialize() void ResultLogout::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
return m_stream;
} }

View File

@@ -25,5 +25,5 @@ private:
int32_t m_reply; int32_t m_reply;
public: public:
ResultLogout( GenericRequest *request, int32_t reply ); ResultLogout( GenericRequest *request, int32_t reply );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -51,49 +51,47 @@ ResultMatchGame::ResultMatchGame( GenericRequest *request, std::string userIp )
m_userIp = userIp; m_userIp = userIp;
} }
ByteBuffer &ResultMatchGame::Serialize() void ResultMatchGame::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
const auto publicGameList = GameSessionManager::Get().GetAvailableGameSessionList( RealmGameType::CHAMPIONS_OF_NORRATH ); const auto publicGameList = GameSessionManager::Get().GetAvailableGameSessionList( RealmGameType::CHAMPIONS_OF_NORRATH );
const auto publicGameCount = static_cast< uint32_t >( publicGameList.size() ); const auto publicGameCount = static_cast< uint32_t >( publicGameList.size() );
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
{ {
if( m_userIp == game->m_hostExternalAddr ) if( m_userIp == game->m_hostExternalAddr )
m_stream.write_utf16( std::format( L"{}:{}", Util::UTF8ToWide( game->m_hostLocalAddr ), game->m_hostPort ) ); out.write_utf16( std::format( L"{}:{}", Util::UTF8ToWide( game->m_hostLocalAddr ), game->m_hostNatPort ) );
else else
m_stream.write_utf16( std::format( L"{}:{}", Util::UTF8ToWide( game->m_hostExternalAddr ), game->m_hostPort ) ); out.write_utf16( std::format( L"{}:{}", Util::UTF8ToWide( game->m_hostExternalAddr ), game->m_hostNatPort ) );
} }
} }
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
m_stream.write_utf16( game->m_gameName ); out.write_utf16( game->m_gameName );
} }
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
m_stream.write_utf16( game->m_ownerName ); out.write_utf16( game->m_ownerName );
} }
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
m_stream.write_u32( game->m_gameIndex ); out.write_u32( game->m_gameId );
} }
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
m_stream.write_utf8( game->m_gameData ); out.write_utf8( game->m_gameData );
} }
return m_stream;
} }

View File

@@ -24,5 +24,5 @@ private:
public: public:
ResultMatchGame( GenericRequest *request, std::string userIp ); ResultMatchGame( GenericRequest *request, std::string userIp );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -13,9 +13,16 @@ sptr_generic_response RequestMatchGame_RTA::ProcessRequest( sptr_socket socket,
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
UserManager::Get().Disconnect( socket, "User not found!" );
return std::make_shared< ResultMatchGame_RTA >( this, "" );
}
if( !user->m_isLoggedIn )
{
UserManager::Get().Disconnect( user, "User is not logged in!" );
return std::make_shared< ResultMatchGame_RTA >( this, "" ); return std::make_shared< ResultMatchGame_RTA >( this, "" );
} }
@@ -27,72 +34,60 @@ ResultMatchGame_RTA::ResultMatchGame_RTA( GenericRequest *request, std::string u
m_userIp = userIp; m_userIp = userIp;
} }
ByteBuffer&ResultMatchGame_RTA::Serialize() void ResultMatchGame_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
const auto publicGameList = GameSessionManager::Get().GetAvailableGameSessionList( RealmGameType::RETURN_TO_ARMS ); const auto publicGameList = GameSessionManager::Get().GetAvailableGameSessionList( RealmGameType::RETURN_TO_ARMS );
const auto publicGameCount = static_cast< uint32_t >( publicGameList.size() ); const auto publicGameCount = static_cast< uint32_t >( publicGameList.size() );
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
m_stream.write_utf16( game->m_gameName ); out.write_utf16( Util::UTF8ToWide( game->m_gameData ) );
} }
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
m_stream.write_utf16( game->m_playerCount ); out.write_utf16( game->m_playerCount );
} }
m_stream.write_u32( publicGameCount ); out.write_u32( publicGameCount );
{ {
for( const auto &game : publicGameList ) for( const auto &game : publicGameList )
m_stream.write_u32( game->m_gameIndex ); out.write_u32( game->m_gameId );
} }
m_stream.write_u32( publicGameCount ); // Something about filtering.
out.write_u32( publicGameCount );
{ {
m_stream.write_u32( 0 ); // Size out.write_u32( 0 ); // Size
// Blob Data
} }
m_stream.write_u32( publicGameCount ); out.write_u32(publicGameCount);
{ {
for( const auto &game : publicGameList ) for (const auto& game : publicGameList)
{ out.write_utf16(Util::UTF8ToWide(game->m_hostExternalAddr));
if( m_userIp == game->m_hostExternalAddr )
m_stream.write_utf16( Util::UTF8ToWide( game->m_hostLocalAddr ) );
else
m_stream.write_utf16( Util::UTF8ToWide( game->m_hostExternalAddr ) );
}
} }
m_stream.write_u32( publicGameCount ); out.write_u32(publicGameCount);
{ {
for( const auto &game : publicGameList ) for (const auto& game : publicGameList)
m_stream.write_u32( game->m_hostPort ); out.write_u32(game->m_hostNatPort);
} }
m_stream.write_u32( publicGameCount ); out.write_u32(publicGameCount);
{ {
for( const auto &game : publicGameList ) for (const auto& game : publicGameList)
{ out.write_utf16(Util::UTF8ToWide(game->m_hostLocalAddr));
if( m_userIp == game->m_hostExternalAddr )
m_stream.write_utf16( Util::UTF8ToWide( game->m_hostLocalAddr ) );
else
m_stream.write_utf16( Util::UTF8ToWide( game->m_hostExternalAddr ) );
}
} }
m_stream.write_u32( publicGameCount ); out.write_u32(publicGameCount);
{ {
for( const auto &game : publicGameList ) for (const auto& game : publicGameList)
m_stream.write_u32( game->m_hostPort ); out.write_u32(game->m_hostLocalPort);
} }
return m_stream;
} }

View File

@@ -24,5 +24,5 @@ private:
public: public:
ResultMatchGame_RTA( GenericRequest *request, std::string userIp ); ResultMatchGame_RTA( GenericRequest *request, std::string userIp );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -1,6 +1,8 @@
#include "RequestSaveCharacter_RTA.h" #include "RequestSaveCharacter_RTA.h"
#include "../../Database/Database.h" #include "../../Database/Database.h"
#include "../../Game/GameSessionManager.h"
#include "../../Game/CharacterSaveManager.h"
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/RealmUser.h" #include "../../Game/RealmUser.h"
#include "../../Game/RealmCharacter.h" #include "../../Game/RealmCharacter.h"
@@ -12,53 +14,59 @@ void RequestSaveCharacter_RTA::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
m_sessionId_A = stream->read_encrypted_utf16(); m_sessionId = stream->read_encrypted_utf16();
m_sessionId_B = stream->read_encrypted_utf16(); m_memberSessionId = stream->read_encrypted_utf16();
m_characterId = stream->read_u32(); m_targetCharacterId = stream->read_u32();
auto a = stream->read_u32(); auto a = stream->read_u32();
auto b = stream->read_u32(); auto b = stream->read_u32();
m_characterData = std::make_shared< RealmCharacter >( stream ); m_metaData.Deserialize( stream );
auto characterDataSize = stream->read_u32();
m_characterData = stream->read_bytes( characterDataSize );
} }
sptr_generic_response RequestSaveCharacter_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response RequestSaveCharacter_RTA::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto &userManager = UserManager::Get();
auto user = userManager.FindUserBySocket( socket );
if( user == nullptr || user->m_accountId == -1 )
{
// Try to recover the user through session records.
user = UserManager::Get().RecoverUserBySession( m_sessionId, socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId_A.c_str() ); Log::Error( "Failed to recover user by session ID: {}", m_sessionId );
return std::make_shared< ResultSaveCharacter_RTA >( this, FATAL_ERROR ); return std::make_shared< ResultSaveCharacter_RTA >( this, FATAL_ERROR );
} }
//auto unpacked = RLEZ::Decompress( m_characterData->GetCharacterData() ); Log::Debug( "Recovered user by session ID: {}", m_sessionId );
}
//Log::PacketToFile( "save_character_comp", stream->get_buffer(), stream->get_length()); sptr_user targetUser = user;
//Log::PacketToFile( "save_character_decomp", unpacked, unpacked.size());
Log::Packet(stream->get_buffer(), stream->get_length(), false); if( m_sessionId != m_memberSessionId )
Log::Debug( "Processing RequestSaveCharacter_RTA for user: " + std::to_string( user->m_accountId ) );
Log::Debug( "Session ID A: " + Util::WideToUTF8( m_sessionId_A ) );
Log::Debug( "Session ID B: " + Util::WideToUTF8( m_sessionId_B ) );
Log::Debug( "Character ID: " + std::to_string( m_characterId ) );
//if( m_characterId != user->m_characterId )
//{
// Log::Error( "Character ID mismatch for user: " + Util::WideToUTF8( user->m_sessionId ) + ". Expected: " + std::to_string(user->m_characterId) + ", Received: " + std::to_string(m_characterId));
// return std::make_shared< ResultSaveCharacter_RTA >( this, GENERAL_ERROR );
//}
auto result = Database::Get().SaveCharacter( user->m_accountId, user->m_characterId, m_characterData->GetMetaData().Serialize(), m_characterData->GetCharacterData() );
if( false == result )
{ {
targetUser = userManager.FindUserBySessionId( m_memberSessionId );
}
if( targetUser == nullptr || targetUser->m_accountId == -1 )
{
Log::Error( "Target user not found or invalid account ID for session: {}", m_memberSessionId );
return std::make_shared< ResultSaveCharacter_RTA >( this, FATAL_ERROR ); return std::make_shared< ResultSaveCharacter_RTA >( this, FATAL_ERROR );
} }
user->m_character = std::move(m_characterData); auto characterId = targetUser->m_characterId;
auto &saveManager = CharacterSaveManager::Get();
if( saveManager.BeginSaveTask( user, targetUser, characterId, m_metaData, CharacterSaveType::SAVE_CHARACTER ) )
{
saveManager.AppendSaveData( user->m_sessionId, m_characterData, false );
}
return std::make_shared< ResultSaveCharacter_RTA >( this, SUCCESS ); return std::make_shared< ResultSaveCharacter_RTA >( this, SUCCESS );
} }
@@ -68,11 +76,9 @@ ResultSaveCharacter_RTA::ResultSaveCharacter_RTA( GenericRequest *request, int32
m_reply = reply; m_reply = reply;
} }
ByteBuffer& ResultSaveCharacter_RTA::Serialize() void ResultSaveCharacter_RTA::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
return m_stream;
} }

View File

@@ -8,18 +8,19 @@
class RequestSaveCharacter_RTA : public GenericRequest class RequestSaveCharacter_RTA : public GenericRequest
{ {
private: private:
std::wstring m_sessionId_A; std::wstring m_sessionId;
std::wstring m_sessionId_B; std::wstring m_memberSessionId;
std::vector< uint8_t > m_data; uint32_t m_targetCharacterId;
uint32_t m_characterId;
sptr_realm_character m_characterData; CharacterSlotData m_metaData;
std::vector< uint8_t > m_characterData;
enum CREATE_REPLY { enum CREATE_REPLY {
SUCCESS = 0, SUCCESS = 0,
FATAL_ERROR, FATAL_ERROR,
GENERAL_ERROR, GENERAL_ERROR,
}; };
public: public:
static std::unique_ptr< RequestSaveCharacter_RTA > Create() static std::unique_ptr< RequestSaveCharacter_RTA > Create()
{ {
@@ -36,5 +37,5 @@ private:
public: public:
ResultSaveCharacter_RTA( GenericRequest *request, int32_t reply ); ResultSaveCharacter_RTA( GenericRequest *request, int32_t reply );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -0,0 +1,69 @@
#include "RequestSendRoomMessage.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/ChatRoomManager.h"
#include "NotifyRoomMessage.h"
#include "../../logging.h"
void RequestSendRoomMessage::Deserialize( sptr_byte_stream stream )
{
DeserializeHeader( stream );
auto sessionId = stream->read_encrypted_utf16();
m_roomName = stream->read_utf16();
m_message = stream->read_utf16();
}
sptr_generic_response RequestSendRoomMessage::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
Log::Packet( stream->get_buffer(), stream->get_length(), false );
const auto user = UserManager::Get().FindUserBySocket( socket );
if( !user )
{
Log::Error( "User not found for socket!" );
return std::make_shared< ResultSendRoomMessage >( this, GENERAL_ERROR );
}
const auto room = ChatRoomManager::Get().FindRoom( m_roomName );
if( !room )
{
Log::Error( "Chat room not found: {}", m_roomName );
return std::make_shared< ResultSendRoomMessage >( this, GENERAL_ERROR );
}
if( !room->IsMember( user ) )
{
Log::Error( "User [{}] is not a member of chat room [{}]", user->m_chatHandle, m_roomName );
return std::make_shared< ResultSendRoomMessage >( this, GENERAL_ERROR );
}
NotifyRoomMessage msg( m_roomName, user->m_chatHandle, m_message );
for( const auto &member : room->m_members )
{
auto memberUser = member.lock();
if( !memberUser )
continue;
memberUser->sock->send( msg );
}
return std::make_shared< ResultSendRoomMessage >( this, SUCCESS );
}
ResultSendRoomMessage::ResultSendRoomMessage( GenericRequest *request, int32_t reply ) : GenericResponse( *request )
{
m_reply = reply;
}
void ResultSendRoomMessage::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( m_reply );
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <memory>
#include <string>
#include "../GenericNetRequest.h"
#include "../GenericNetResponse.h"
class RequestSendRoomMessage : public GenericRequest
{
private:
std::wstring m_roomName;
std::wstring m_message;
enum REPLY {
SUCCESS = 0,
GENERAL_ERROR
};
public:
static std::unique_ptr< RequestSendRoomMessage > Create()
{
return std::make_unique< RequestSendRoomMessage >();
}
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override;
};
class ResultSendRoomMessage : public GenericResponse {
private:
int32_t m_reply;
public:
ResultSendRoomMessage( GenericRequest *request, int32_t reply );
void Serialize( ByteBuffer &out ) const;
};

View File

@@ -2,6 +2,7 @@
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/GameSessionManager.h" #include "../../Game/GameSessionManager.h"
#include "../../Game/ChatRoomManager.h"
#include "../../Game/RealmUser.h" #include "../../Game/RealmUser.h"
#include "../../logging.h" #include "../../logging.h"
@@ -16,7 +17,7 @@ sptr_generic_response RequestStartGame::ProcessRequest( sptr_socket socket, sptr
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
return std::make_shared< ResultStartGame >( this, FATAL_ERROR ); return std::make_shared< ResultStartGame >( this, FATAL_ERROR );
@@ -29,7 +30,16 @@ sptr_generic_response RequestStartGame::ProcessRequest( sptr_socket socket, sptr
return std::make_shared< ResultStartGame >( this, FATAL_ERROR ); return std::make_shared< ResultStartGame >( this, FATAL_ERROR );
} }
GameSessionManager::Get().RequestStart(user); if( !GameSessionManager::Get().RequestStart( user ) )
{
Log::Error( "Failed to start game session [{}]", user->m_gameId );
return std::make_shared< ResultStartGame >( this, FATAL_ERROR );
}
if( !ChatRoomManager::Get().CloseGameChatSession( session->m_gameName ) )
{
Log::Error( "Failed to close chat room for game session [{}]", session->m_gameName );
}
return std::make_shared< ResultStartGame >( this, SUCCESS ); return std::make_shared< ResultStartGame >( this, SUCCESS );
} }
@@ -39,11 +49,9 @@ ResultStartGame::ResultStartGame( GenericRequest *request, int32_t reply ) : Gen
m_reply = reply; m_reply = reply;
} }
ByteBuffer& ResultStartGame::Serialize() void ResultStartGame::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( m_reply ); out.write_u32( m_reply );
return m_stream;
} }

View File

@@ -32,5 +32,5 @@ private:
public: public:
ResultStartGame( GenericRequest *request, int32_t reply ); ResultStartGame( GenericRequest *request, int32_t reply );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -14,11 +14,11 @@ sptr_generic_response RequestTouchSession::ProcessRequest( sptr_socket socket, s
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr ) if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultTouchSession >( this ); return std::make_shared< ResultTouchSession >( this );
} }
@@ -30,11 +30,9 @@ ResultTouchSession::ResultTouchSession( GenericRequest *request ) : GenericRespo
} }
ByteBuffer &ResultTouchSession::Serialize() void ResultTouchSession::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
return m_stream;
} }

View File

@@ -23,5 +23,5 @@ public:
class ResultTouchSession : public GenericResponse { class ResultTouchSession : public GenericResponse {
public: public:
ResultTouchSession( GenericRequest *request ); ResultTouchSession( GenericRequest *request );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -13,54 +13,58 @@ void RequestUpdateGameData::Deserialize( sptr_byte_stream stream )
m_gameData = stream->read_utf8(); m_gameData = stream->read_utf8();
} }
sptr_generic_response RequestUpdateGameData::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) bool RequestUpdateGameData::ParseGameData( sptr_game_session session )
{ {
Deserialize( stream ); if( session == nullptr || m_gameData.size() < 256 )
auto user = RealmUserManager::Get().FindUserBySocket( socket );
if( user == nullptr )
{ {
Log::Error( "User not found! [%S]", m_sessionId.c_str() ); Log::Error( "Invalid game session or game data size! [{}]", m_sessionId );
return std::make_shared< ResultUpdateGameData >( this ); return false;
} }
auto gameSession = GameSessionManager::Get().FindGame( user->m_gameId, user->m_gameType ); session->m_gameData = m_gameData;
if( gameSession == nullptr ) int8_t currentPlayers = 0;
{ int8_t maxPlayers = 0;
Log::Error( "Game not found! [%S]", m_sessionId.c_str() );
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 }; char description[ 200 ] = { 0 };
int result = sscanf( m_gameData.c_str(), " %hhd / %hhd :%199[^\r\n]", &currentPlayers, &maxPlayers, description ); int result = sscanf( m_gameData.c_str(), " %hhd / %hhd :%199[^\r\n]", &currentPlayers, &maxPlayers, description );
if( result >= 2 ) if( result >= 2 )
{ {
gameSession->m_currentPlayers = currentPlayers; session->m_currentPlayers = currentPlayers;
gameSession->m_maximumPlayers = maxPlayers; session->m_maximumPlayers = maxPlayers;
gameSession->m_description = ( result == 3 ) ? description : ""; // Empty if not parsed session->m_description = ( result == 3 ) ? description : "";
} }
else else
{ {
Log::Debug( "Failed to parse game info from: %s", m_gameData.c_str() ); Log::Debug( "Failed to parse game info from: {}", m_gameData );
} }
std::string ip = std::string( m_gameData.c_str() + 220, 24 ); return true;
user->m_localAddr = ip; }
sptr_generic_response RequestUpdateGameData::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr )
{
Log::Error( "User not found! [{}]", m_sessionId );
return std::make_shared< ResultUpdateGameData >( this );
}
auto gameSession = GameSessionManager::Get().FindGame( user->m_gameId, user->m_gameType );
if( !ParseGameData( gameSession ) )
{
Log::Error( "Failed to parse game data! [{}]", m_sessionId );
return std::make_shared< ResultUpdateGameData >( this );
}
const auto localAddr = std::string( m_gameData.c_str() + 220, 24 );
user->m_localAddr = localAddr;
return std::make_shared< ResultUpdateGameData >( this ); return std::make_shared< ResultUpdateGameData >( this );
} }
@@ -70,11 +74,9 @@ ResultUpdateGameData::ResultUpdateGameData( GenericRequest *request ) : GenericR
} }
ByteBuffer &ResultUpdateGameData::Serialize() void ResultUpdateGameData::Serialize( ByteBuffer &out ) const
{ {
m_stream.write_u16( m_packetId ); out.write_u16( m_packetId );
m_stream.write_u32( m_trackId ); out.write_u32( m_trackId );
m_stream.write_u32( 0 ); out.write_u32( 0 );
return m_stream;
} }

View File

@@ -6,6 +6,8 @@
#include "../GenericNetRequest.h" #include "../GenericNetRequest.h"
#include "../GenericNetResponse.h" #include "../GenericNetResponse.h"
#include "../../Game/GameSession.h"
class RequestUpdateGameData : public GenericRequest class RequestUpdateGameData : public GenericRequest
{ {
private: private:
@@ -19,10 +21,11 @@ public:
} }
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override; sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override; void Deserialize( sptr_byte_stream stream ) override;
bool ParseGameData( sptr_game_session session );
}; };
class ResultUpdateGameData : public GenericResponse { class ResultUpdateGameData : public GenericResponse {
public: public:
ResultUpdateGameData( GenericRequest *request ); ResultUpdateGameData( GenericRequest *request );
ByteBuffer &Serialize(); void Serialize( ByteBuffer &out ) const;
}; };

View File

@@ -0,0 +1,61 @@
#include "RequestUserJoinSuccess.h"
#include "../../Game/GameSessionManager.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/RealmUser.h"
#include "../../Database/Database.h"
#include "../../logging.h"
void RequestUserJoinSuccess::Deserialize( sptr_byte_stream stream )
{
DeserializeHeader( stream );
m_sessionId = stream->read_encrypted_utf16();
m_ownerSessionId = stream->read_encrypted_utf16();
}
sptr_generic_response RequestUserJoinSuccess::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
Log::Packet( stream->get_buffer(), stream->get_length(), false );
auto user = UserManager::Get().FindUserBySocket( socket );
if( user == nullptr )
{
return std::make_shared< ResultUserJoinSuccess >( this, FATAL_ERROR );
}
auto gameSession = GameSessionManager::Get().FindGame( user->m_gameId, user->m_gameType );
if( gameSession == nullptr )
{
Log::Error( "Game session not found for user: {}", user->m_username );
return std::make_shared< ResultUserJoinSuccess >( this, FATAL_ERROR );
}
if( !gameSession->IsJoinable() )
{
Log::Error( "Game session is not open for user: {}", user->m_username );
return std::make_shared< ResultUserJoinSuccess >( this, FATAL_ERROR );
}
if( !gameSession->AddMember( user ) )
{
Log::Error( "Failed to add user {} to game session {}", user->m_username, gameSession->m_gameId );
return std::make_shared< ResultUserJoinSuccess >( this, FATAL_ERROR );
}
return std::make_shared< ResultUserJoinSuccess >( this, SUCCESS );
}
ResultUserJoinSuccess::ResultUserJoinSuccess( GenericRequest *request, int32_t reply ) : GenericResponse( *request )
{
m_reply = reply;
}
void ResultUserJoinSuccess::Serialize( ByteBuffer &out ) const
{
out.write_u16( m_packetId );
out.write_u32( m_trackId );
out.write_u32( m_reply );
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <memory>
#include <string>
#include "../GenericNetRequest.h"
#include "../GenericNetResponse.h"
class RequestUserJoinSuccess : public GenericRequest
{
private:
std::wstring m_sessionId;
std::wstring m_ownerSessionId;
enum CREATE_REPLY {
SUCCESS = 0,
FATAL_ERROR,
GENERAL_ERROR,
};
public:
static std::unique_ptr< RequestUserJoinSuccess > Create()
{
return std::make_unique< RequestUserJoinSuccess >();
}
sptr_generic_response ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) override;
void Deserialize( sptr_byte_stream stream ) override;
};
class ResultUserJoinSuccess : public GenericResponse {
private:
int32_t m_reply;
public:
ResultUserJoinSuccess( GenericRequest *request, int32_t reply );
void Serialize( ByteBuffer &out ) const;
};

View File

@@ -1,67 +0,0 @@
#include "Request_5D.h"
#include "../../Game/RealmUserManager.h"
#include "../../Game/RealmUser.h"
#include "../../Database/Database.h"
#include "../../logging.h"
#include "../../Common/RLEZ.hpp"
void Request_5D::Deserialize( sptr_byte_stream stream )
{
DeserializeHeader( stream );
auto sessionId = stream->read_encrypted_utf16();
auto length = stream->read_u32();
m_data = stream->read_bytes( length );
auto unknown = stream->read_u32();
}
sptr_generic_response Request_5D::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket );
if( user == nullptr )
{
return std::make_shared< Result_5D >( this, FATAL_ERROR );
}
//auto unpacked = RLEZ::Decompress( m_data );
//Log::PacketToFile( "5D_data_comp", m_data, m_data.size());
//Log::PacketToFile( "5D_data_decomp", unpacked, unpacked.size());
//auto &myCharacter = user->m_character;
//if( nullptr == myCharacter )
//{
// return std::make_shared< Result_5D >( this, FATAL_ERROR );
//}
//myCharacter->SetInventoryData( m_data );
//auto result = Database::Get().SaveInventory( user->m_accountId, user->m_characterId, m_data );
//if( !result )
//{
// Log::Error( "Failed to save inventory for account ID: " + std::to_string( user->m_accountId ) + ", character ID: " + std::to_string( user->m_characterId ) );
// return std::make_shared< Result_5D >( this, FATAL_ERROR );
//}
return std::make_shared< Result_5D >( this, SUCCESS );
}
Result_5D::Result_5D( GenericRequest *request, int32_t reply ) : GenericResponse( *request )
{
m_reply = reply;
}
ByteBuffer& Result_5D::Serialize()
{
m_stream.write_u16( m_packetId );
m_stream.write_u32( m_trackId );
m_stream.write_u32( m_reply );
return m_stream;
}

View File

@@ -1,5 +1,6 @@
#include "Request_5F.h" #include "Request_5F.h"
#include "../../Game/GameSessionManager.h"
#include "../../Game/RealmUserManager.h" #include "../../Game/RealmUserManager.h"
#include "../../Game/RealmUser.h" #include "../../Game/RealmUser.h"
#include "../../Database/Database.h" #include "../../Database/Database.h"
@@ -9,21 +10,49 @@ void Request_5F::Deserialize( sptr_byte_stream stream )
{ {
DeserializeHeader( stream ); DeserializeHeader( stream );
auto sessionId_a = stream->read_encrypted_utf16(); m_sessionId = stream->read_encrypted_utf16();
auto sessionId_b = stream->read_encrypted_utf16(); m_memberSessionId = stream->read_encrypted_utf16();
} }
sptr_generic_response Request_5F::ProcessRequest( sptr_socket socket, sptr_byte_stream stream ) sptr_generic_response Request_5F::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{ {
Deserialize( stream ); Deserialize( stream );
auto user = RealmUserManager::Get().FindUserBySocket( socket ); Log::Packet( stream->get_buffer(), stream->get_length(), false );
if( user == nullptr )
{
return std::make_shared< Result_5F >( this, FATAL_ERROR );
}
Log::Debug( "Request_5F From user ID : %d", user->m_accountId ); //auto user = UserManager::Get().FindUserBySocket( socket );
//if( user == nullptr )
//{
// return std::make_shared< Result_5F >( this, FATAL_ERROR );
//}
//
//auto targetUser = UserManager::Get().FindUserBySessionId( m_memberSessionId );
//if( targetUser == nullptr || targetUser->m_accountId == -1 )
//{
// Log::Error( "Target user not found or invalid account ID for session: %S", m_memberSessionId.c_str() );
// return std::make_shared< Result_5F >( this, FATAL_ERROR );
//}
//
//auto gameSession = GameSessionManager::Get().FindGame( user->m_gameId, user->m_gameType );
//if( gameSession == nullptr )
//{
// Log::Error( "Game session not found for user: %S", user->m_sessionId.c_str() );
// return std::make_shared< Result_5F >( this, FATAL_ERROR );
//}
//
//if( !gameSession->IsJoinable() )
//{
// Log::Error( "Game session is not open for user: %S", user->m_sessionId.c_str() );
// return std::make_shared< Result_5F >( this, FATAL_ERROR );
//}
//
//if( !gameSession->AddMember( targetUser ) )
//{
// Log::Error( "Failed to add user %S to game session %d", targetUser->m_sessionId.c_str(), gameSession->m_gameIndex );
// return std::make_shared< Result_5F >( this, FATAL_ERROR );
//}
// TODO: Here is more like finalize/confirm joined
return std::make_shared< Result_5F >( this, SUCCESS ); return std::make_shared< Result_5F >( this, SUCCESS );
} }

View File

@@ -9,7 +9,8 @@
class Request_5F : public GenericRequest class Request_5F : public GenericRequest
{ {
private: private:
std::vector< uint8_t > m_data; std::wstring m_sessionId;
std::wstring m_memberSessionId;
enum CREATE_REPLY { enum CREATE_REPLY {
SUCCESS = 0, SUCCESS = 0,

View File

@@ -17,11 +17,12 @@
/* 000F */ #include "Event/RequestGetRealmStats.h" /* 000F */ #include "Event/RequestGetRealmStats.h"
/* 0011 */ #include "Event/RequestGetRoom.h" /* 0011 */ #include "Event/RequestGetRoom.h"
/* 0015 */ #include "Event/RequestLeaveRoom.h"
/* 0016 */ #include "Event/RequestLogin.h" /* 0016 */ #include "Event/RequestLogin.h"
/* 0017 */ #include "Event/RequestLogout.h" /* 0017 */ #include "Event/RequestLogout.h"
/* 0018 */ #include "Event/RequestMatchGame.h" /* 0018 */ #include "Event/RequestMatchGame.h"
/* 0022 */ #include "Event/RequestSendRoomMessage.h"
/* 0023 */ #include "Event/RequestStartGame.h" /* 0023 */ #include "Event/RequestStartGame.h"
/* 0024 */ #include "Event/RequestTouchSession.h" /* 0024 */ #include "Event/RequestTouchSession.h"
/* 0025 */ #include "Event/RequestDoClientDiscovery.h" /* 0025 */ #include "Event/RequestDoClientDiscovery.h"
@@ -35,17 +36,18 @@
/* 0054 */ #include "Event/RequestCreatePublicGame_RTA.h" /* 0054 */ #include "Event/RequestCreatePublicGame_RTA.h"
/* 0055 */ #include "Event/RequestMatchGame_RTA.h" /* 0055 */ #include "Event/RequestMatchGame_RTA.h"
/* 0056 */ #include "Event/RequestCreatePrivateGame_RTA.h" /* 0056 */ #include "Event/RequestCreatePrivateGame_RTA.h"
/* 0057 */ #include "Event/RequestGetGame_RTA.h"
/* 0058 */ #include "Event/RequestCreateNewCharacter_RTA.h" /* 0058 */ #include "Event/RequestCreateNewCharacter_RTA.h"
/* 005B */ #include "Event/RequestGetNetCharacterList_RTA.h" /* 005B */ #include "Event/RequestGetNetCharacterList_RTA.h"
/* 005C */ #include "Event/RequestGetCharacterData_RTA.h" /* 005C */ #include "Event/RequestGetCharacterData_RTA.h"
/* 005D */ #include "Event/Request_5D.h" /* 005D */ #include "Event/RequestAppendCharacterData.h"
/* 005E */ #include "Event/RequestSaveCharacter_RTA.h" /* 005E */ #include "Event/RequestSaveCharacter_RTA.h"
/* 005F */ #include "Event/Request_5F.h" /* 005F */ #include "Event/RequestUserJoinSuccess.h"
/* 0060 */ #include "Event/RequestCancelGame_RTA.h" /* 0060 */ #include "Event/RequestCancelGame_RTA.h"
/* 0061 */ #include "Event/Request_61.h" /* 0061 */ #include "Event/RequestGetFriendList.h"
/* 0066 */ #include "Event/RequestGetGame_RTA.h" /* 0066 */ #include "Event/RequestDoClientDiscovery_RTA.h"
const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > > REQUEST_EVENT = const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > > REQUEST_EVENT =
@@ -100,6 +102,11 @@ const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > >
return std::make_unique< RequestGetRoom >(); return std::make_unique< RequestGetRoom >();
} }
}, },
{ 0x0015, []() -> std::unique_ptr< GenericRequest >
{
return std::make_unique< RequestLeaveRoom >();
}
},
{ 0x0016, []() -> std::unique_ptr< GenericRequest > { 0x0016, []() -> std::unique_ptr< GenericRequest >
{ {
return std::make_unique< RequestLogin >(); return std::make_unique< RequestLogin >();
@@ -115,6 +122,11 @@ const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > >
return std::make_unique< RequestMatchGame >(); return std::make_unique< RequestMatchGame >();
} }
}, },
{ 0x0022, []() -> std::unique_ptr< GenericRequest >
{
return std::make_unique< RequestSendRoomMessage >();
}
},
{ 0x0023, []() -> std::unique_ptr< GenericRequest > { 0x0023, []() -> std::unique_ptr< GenericRequest >
{ {
return std::make_unique< RequestStartGame >(); return std::make_unique< RequestStartGame >();
@@ -165,6 +177,11 @@ const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > >
return std::make_unique< RequestCreatePrivateGame_RTA >(); return std::make_unique< RequestCreatePrivateGame_RTA >();
} }
}, },
{ 0x0057, []() -> std::unique_ptr< GenericRequest >
{
return std::make_unique< RequestGetGame_RTA >();
}
},
{ 0x0058, []() -> std::unique_ptr< GenericRequest > { 0x0058, []() -> std::unique_ptr< GenericRequest >
{ {
return std::make_unique< RequestCreateNewCharacter_RTA >(); return std::make_unique< RequestCreateNewCharacter_RTA >();
@@ -182,7 +199,7 @@ const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > >
}, },
{ 0x005D, []() -> std::unique_ptr< GenericRequest > { 0x005D, []() -> std::unique_ptr< GenericRequest >
{ {
return std::make_unique< Request_5D >(); return std::make_unique< RequestAppendCharacterData >();
} }
}, },
{ 0x005E, []() -> std::unique_ptr< GenericRequest > { 0x005E, []() -> std::unique_ptr< GenericRequest >
@@ -192,7 +209,7 @@ const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > >
}, },
{ 0x005F, []() -> std::unique_ptr< GenericRequest > { 0x005F, []() -> std::unique_ptr< GenericRequest >
{ {
return std::make_unique< Request_5F >(); return std::make_unique< RequestUserJoinSuccess >();
} }
}, },
{ 0x0060, []() -> std::unique_ptr< GenericRequest > { 0x0060, []() -> std::unique_ptr< GenericRequest >
@@ -202,12 +219,12 @@ const std::map< int16_t, std::function< std::unique_ptr< GenericRequest >() > >
}, },
{ 0x0061, []() -> std::unique_ptr< GenericRequest > { 0x0061, []() -> std::unique_ptr< GenericRequest >
{ {
return std::make_unique< Request_61 >(); return std::make_unique< RequestGetFriendList >();
} }
}, },
{ 0x0066, []() -> std::unique_ptr< GenericRequest > { 0x0066, []() -> std::unique_ptr< GenericRequest >
{ {
return std::make_unique< RequestGetGame_RTA >(); return std::make_unique< RequestDoClientDiscovery_RTA >();
} }
}, },
}; };

View File

@@ -13,7 +13,7 @@ public:
} }
virtual ~GenericMessage() = default; virtual ~GenericMessage() = default;
virtual ByteBuffer& Serialize() = 0; virtual void Serialize( ByteBuffer &out ) const = 0;
}; };
typedef std::shared_ptr< GenericMessage > sptr_generic_message; typedef std::shared_ptr< GenericMessage > sptr_generic_message;

View File

@@ -1,18 +1 @@
#include "GenericNetRequest.h" #include "GenericNetRequest.h"
sptr_generic_response GenericRequest::ProcessRequest( sptr_socket socket, sptr_byte_stream stream )
{
throw std::runtime_error( "ProcessRequest not implemented for GenericRequest" );
}
sptr_generic_response GenericRequest::ProcessRequest( sptr_byte_stream stream )
{
throw std::runtime_error( "ProcessRequest not implemented for GenericRequest" );
}
void GenericRequest::DeserializeHeader( sptr_byte_stream stream )
{
m_packetId = stream->read_u16();
m_trackId = stream->read_u32();
auto version = stream->read_u32(); // 2 for CON and 6 for RTA
};

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include "../Common/ByteStream.h" #include "../Common/ByteStream.h"
class GenericResponse; class GenericResponse;
@@ -12,18 +13,30 @@ using sptr_user = std::shared_ptr< RealmUser >;
class RealmSocket; class RealmSocket;
using sptr_socket = std::shared_ptr< RealmSocket >; using sptr_socket = std::shared_ptr< RealmSocket >;
class GenericRequest class GenericRequest {
{
public: public:
int16_t m_packetId; int16_t m_packetId;
uint32_t m_trackId; uint32_t m_trackId;
virtual ~GenericRequest() = default; virtual ~GenericRequest() = default;
virtual sptr_generic_response ProcessRequest( sptr_socket user, sptr_byte_stream stream ); virtual sptr_generic_response ProcessRequest( sptr_socket user, sptr_byte_stream stream )
virtual sptr_generic_response ProcessRequest( sptr_byte_stream stream ); {
throw std::runtime_error( "ProcessRequest not implemented for GenericRequest" );
}
virtual sptr_generic_response ProcessRequest( sptr_byte_stream stream )
{
throw std::runtime_error( "ProcessRequest not implemented for GenericRequest" );
}
void DeserializeHeader( sptr_byte_stream stream )
{
m_packetId = stream->read_u16();
m_trackId = stream->read_u32();
auto version = stream->read_u32(); // 2 for CON and 6 for RTA
};
void DeserializeHeader( sptr_byte_stream stream );
virtual void Deserialize( sptr_byte_stream stream ) = 0; virtual void Deserialize( sptr_byte_stream stream ) = 0;
}; };

View File

@@ -17,7 +17,7 @@ public:
} }
virtual ~GenericResponse() = default; virtual ~GenericResponse() = default;
virtual ByteBuffer& Serialize() = 0; virtual void Serialize( ByteBuffer& out ) const = 0;
}; };
typedef std::shared_ptr< GenericResponse > sptr_generic_response; using sptr_generic_response = std::shared_ptr< GenericResponse >;

Some files were not shown because too many files have changed in this diff Show More