mirror of
https://github.com/HikikoMarmy/Champions-Reborn-Server.git
synced 2026-04-04 16:49:47 -03:00
204 lines
5.0 KiB
C++
204 lines
5.0 KiB
C++
/*
|
|
* CharacterSaveManager is responsible for managing character saves while online.
|
|
* Because Return To Arms can have any user in the party initiate a save for any
|
|
* other user in the party, we need to keep track of these tasks.
|
|
*
|
|
* Tasks keep track of the user that initiated the save (the owner),
|
|
* and the target user whose character is being saved.
|
|
*/
|
|
|
|
#include "Game/CharacterSaveManager.hpp"
|
|
|
|
#include "Game/RealmUser.hpp"
|
|
#include "Game/RealmUserManager.hpp"
|
|
#include "Database/Database.hpp"
|
|
#include "logging.hpp"
|
|
|
|
CharacterSaveManager::CharacterSaveManager()
|
|
{
|
|
m_tasks.clear();
|
|
}
|
|
|
|
CharacterSaveManager::~CharacterSaveManager()
|
|
{
|
|
m_tasks.clear();
|
|
}
|
|
|
|
bool CharacterSaveManager::BeginSaveTask(
|
|
const sptr_user user,
|
|
const uint32_t characterId,
|
|
const CharacterSlotData &metaData,
|
|
const CharacterSaveType saveType )
|
|
{
|
|
return BeginSaveTask( user, user, characterId, metaData, saveType );
|
|
}
|
|
|
|
bool CharacterSaveManager::BeginSaveTask(
|
|
const sptr_user m_owner,
|
|
const sptr_user m_target,
|
|
const uint32_t characterId,
|
|
const CharacterSlotData &metaData,
|
|
const CharacterSaveType saveType )
|
|
{
|
|
if( !m_owner || !m_target )
|
|
{
|
|
Log::Error( "CreateSaveTask called with empty session IDs!" );
|
|
return false;
|
|
}
|
|
|
|
const auto &sessionId = m_owner->m_sessionId;
|
|
|
|
if( m_tasks.find( sessionId ) != m_tasks.end() )
|
|
{
|
|
m_tasks.erase( sessionId );
|
|
}
|
|
|
|
auto task = std::make_shared< CharacterSaveTask >( saveType, characterId );
|
|
|
|
task->m_ownerUser = m_owner;
|
|
task->m_targetUser = m_target;
|
|
task->m_meta = metaData;
|
|
m_tasks[ sessionId ] = task;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CharacterSaveManager::AppendSaveData( const std::wstring &sessionId, const std::vector<uint8_t> &data, bool endOfData )
|
|
{
|
|
try
|
|
{
|
|
auto it = m_tasks.find( sessionId );
|
|
if( it == m_tasks.end() )
|
|
{
|
|
Log::Error( "AddDataToSaveTask: No task found for session ID [{}].", sessionId );
|
|
return;
|
|
}
|
|
|
|
auto &task = it->second;
|
|
|
|
if( !task->AppendData( data ) )
|
|
{
|
|
Log::Error( "AddDataToSaveTask: Append failed for session ID [{}].", sessionId );
|
|
return;
|
|
}
|
|
|
|
if( !endOfData )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( !task->Validate() )
|
|
{
|
|
Log::Error( "AddDataToSaveTask: Validation failed for session ID [{}].", sessionId );
|
|
return;
|
|
}
|
|
|
|
if( !CommitSaveTask( sessionId ) )
|
|
{
|
|
Log::Error( "AddDataToSaveTask: Commit failed for session ID [{}].", sessionId );
|
|
return;
|
|
}
|
|
|
|
Log::Debug( "AddDataToSaveTask: Final chunk committed for session ID [{}].", sessionId );
|
|
}
|
|
catch( const std::exception &e )
|
|
{
|
|
Log::Error( "AddDataToSaveTask: Exception for session ID [{}]: {}", sessionId, e.what() );
|
|
}
|
|
}
|
|
|
|
bool CharacterSaveManager::CommitSaveTask( const std::wstring &sessionId )
|
|
{
|
|
try
|
|
{
|
|
auto node = m_tasks.extract( sessionId );
|
|
if( !node )
|
|
{
|
|
Log::Error( "CommitSaveTask: Task for session ID [{}] not found.", sessionId );
|
|
return false;
|
|
}
|
|
|
|
const auto &saveTask = node.mapped();
|
|
|
|
if( !saveTask->Validate() )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
auto &targetUser = saveTask->m_targetUser;
|
|
|
|
if( !targetUser )
|
|
{
|
|
Log::Error( "CommitSaveTask: Target user not found." );
|
|
return false;
|
|
}
|
|
|
|
if( saveTask->m_saveType == CharacterSaveType::NEW_CHARACTER )
|
|
{
|
|
auto result = Database::Get().CreateNewCharacter( targetUser->m_accountId, saveTask->m_meta, saveTask->m_data );
|
|
if( !result )
|
|
{
|
|
Log::Error( "CommitSaveTask: Failed to create new character for account ID: {}", targetUser->m_accountId );
|
|
return false;
|
|
}
|
|
|
|
Log::Debug( "CommitSaveTask: New character created with ID {} for account ID: {}", result, targetUser->m_accountId );
|
|
|
|
targetUser->m_characterId = result;
|
|
}
|
|
else
|
|
{
|
|
if( 0 == saveTask->m_characterId )
|
|
{
|
|
Log::Error( "CommitSaveTask: Invalid character ID for save task." );
|
|
return false;
|
|
}
|
|
|
|
auto result = Database::Get().SaveCharacter( targetUser->m_accountId, targetUser->m_characterId, saveTask->m_meta, saveTask->m_data );
|
|
if( !result )
|
|
{
|
|
Log::Error( "CommitSaveTask: Failed to save character for account ID: {}", targetUser->m_accountId );
|
|
return false;
|
|
}
|
|
|
|
Log::Debug( "CommitSaveTask: Character saved for account ID: {}", targetUser->m_accountId );
|
|
}
|
|
}
|
|
catch( const std::exception &e )
|
|
{
|
|
Log::Error( "CommitSaveTask: Exception occurred while committing task for session ID [{}]: {}", sessionId, e.what() );
|
|
return false;
|
|
}
|
|
|
|
Log::Debug( "CommitSaveTask: Task for session ID [{}] committed successfully.", sessionId );
|
|
return true;
|
|
}
|
|
|
|
void CharacterSaveManager::RemoveSaveTask( const std::wstring &sessionId )
|
|
{
|
|
auto it = m_tasks.find( sessionId );
|
|
if( it != m_tasks.end() )
|
|
{
|
|
m_tasks.erase( it );
|
|
Log::Debug( "RemoveSaveTask: Task for session ID [{}] removed.", sessionId );
|
|
}
|
|
else
|
|
{
|
|
Log::Error( "RemoveSaveTask: Task for session ID [{}] not found.", sessionId );
|
|
}
|
|
}
|
|
|
|
sptr_character_save_task CharacterSaveManager::FindSaveTask( const std::wstring &sessionId )
|
|
{
|
|
auto it = m_tasks.find( sessionId );
|
|
if( it != m_tasks.end() )
|
|
{
|
|
return it->second;
|
|
}
|
|
else
|
|
{
|
|
Log::Error( "FindSaveTask: Task for session ID [{}] not found.", sessionId );
|
|
return nullptr;
|
|
}
|
|
}
|