1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-23 13:17:45 +00:00
sapphire/src/servers/Server_Zone/Actor/PlayerSql.cpp
Mordred Admin 924a4b3973 Majorly simplified and improved the cmake setup.
Going forward it will be alot easier to maintain.

TODO: simplify path definitions

Conflicts:
	src/servers/Server_Lobby/CMakeLists.txt
	src/servers/Server_REST/CMakeLists.txt
	src/servers/Server_Zone/CMakeLists.txt
2017-09-13 11:46:17 +02:00

450 lines
16 KiB
C++

#include <src/servers/Server_Common/Common.h>
#include <src/servers/Server_Common/Network/GamePacket.h>
#include <src/servers/Server_Common/Database/Database.h>
#include <src/servers/Server_Common/Util/Util.h>
#include <src/servers/Server_Common/Util/UtilMath.h>
#include <src/servers/Server_Common/Config/XMLConfig.h>
#include <src/servers/Server_Common/Logging/Logger.h>
#include <src/servers/Server_Common/Exd/ExdData.h>
#include <src/servers/Server_Common/Network/PacketContainer.h>
#include <set>
#include <stdio.h>
#include <time.h>
#include "Player.h"
#include "src/servers/Server_Zone/Zone/ZoneMgr.h"
#include "src/servers/Server_Zone/Zone/Zone.h"
#include "src/servers/Server_Zone/ServerZone.h"
#include "src/servers/Server_Zone/Forwards.h"
#include "src/servers/Server_Zone/Network/GameConnection.h"
#include "src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h"
#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
#include "src/servers/Server_Zone/Inventory/Inventory.h"
extern Core::Logger g_log;
extern Core::Db::Database g_database;
extern Core::ServerZone g_serverZone;
extern Core::ZoneMgr g_zoneMgr;
extern Core::Data::ExdData g_exdData;
using namespace Core::Common;
using namespace Core::Network::Packets;
using namespace Core::Network::Packets::Server;
// load player from the db
bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
{
// TODO: can't help but think that the whole player loading could be handled better...
const std::string char_id_str = std::to_string( charId );
auto pQR = g_database.query( "SELECT "
"c.Name, "
"c.PrimaryTerritoryId, "
"c.Hp, "
"c.Mp, "
"c.Gp, "
"c.Mode, "
"c.Pos_0_0, "
"c.Pos_0_1, "
"c.Pos_0_2, "
"c.Pos_0_3, "
"c.FirstLogin, " // 10
"c.Customize, "
"c.ModelMainWeapon, "
"c.ModelSubWeapon, "
"c.ModelEquip, "
"cd.GuardianDeity, "
"cd.BirthDay, "
"cd.BirthMonth, "
"cd.Status, "
"cd.Class, "
"cd.Homepoint, " // 20
"cd.HowTo, "
"c.ContentId, "
"c.Voice, "
"cd.QuestCompleteFlags, "
"cd.QuestTracking, "
"c.IsNewGame, "
"cd.Aetheryte, "
"cd.unlocks, "
"cd.Discovery, "
"cd.StartTown, " // 30
"cd.TotalPlayTime, "
"c.IsNewAdventurer, "
"cd.GrandCompany, "
"cd.GrandCompanyRank, "
"cd.CFPenaltyUntil, "
"cd.OpeningSequence, "
"cd.GMRank "
"FROM charabase AS c "
" INNER JOIN charadetail AS cd "
" ON c.CharacterId = cd.CharacterId "
"WHERE c.CharacterId = " + char_id_str + ";" );
if( !pQR )
{
g_log.error( "Player id " + char_id_str + " does not exist!" );
return false;
}
m_updateFlags = PlayerSyncFlags::None;
m_id = charId;
Db::Field *field = pQR->fetch();
strcpy( m_name, field[0].getString().c_str() );
ZonePtr pCurrZone = g_zoneMgr.getZone( field[1].get< int32_t >() );
m_zoneId = field[1].get< int32_t >();
// see if a valid zone could be found for the character
if( !pCurrZone )
{
g_log.error( "[" + char_id_str + "] Zone " + std::to_string( field[1].get< int32_t >() ) + "not found!" );
g_log.error( "[" + char_id_str + "] Setting default zone instead" );
// default to new gridania
// TODO: should probably just abort and mark character as corrupt
pCurrZone = g_zoneMgr.getZone( 132 );
m_pos.x = 0.0f;
m_pos.y = 0.0f;
m_pos.z = 0.0f;
setRotation( 0.0f );
}
m_hp = field[2].get< uint16_t >();
m_mp = field[3].get< uint16_t >();
m_tp = 0;
m_pos.x = field[6].getFloat();
m_pos.y = field[7].getFloat();
m_pos.z = field[8].getFloat();
setRotation( field[9].getFloat() );
field[11].getBinary( reinterpret_cast< char* >( m_customize ), sizeof( m_customize ) );
m_modelMainWeapon = field[12].get< uint64_t >();
field[14].getBinary( reinterpret_cast< char* >( m_modelEquip ), sizeof( m_modelEquip ) );
m_guardianDeity = field[15].get< uint8_t >();
m_birthDay = field[16].get< uint8_t >();
m_birthMonth = field[17].get< uint8_t >();
m_status = static_cast< ActorStatus >( field[18].get< uint8_t >() );
m_class = static_cast< ClassJob >( field[19].get< uint8_t >() );
m_homePoint = field[20].get< uint8_t >();
field[21].getBinary( reinterpret_cast< char* >( m_howTo ), sizeof( m_howTo ) );
m_contentId = field[22].get< uint64_t >();
m_voice = field[23].get< uint32_t >();
field[24].getBinary( reinterpret_cast< char* >( m_questCompleteFlags ), sizeof( m_questCompleteFlags ) );
field[25].getBinary( reinterpret_cast< char* >( m_questTracking ), sizeof( m_questTracking ) );
m_bNewGame = field[26].getBool();
field[27].getBinary( reinterpret_cast< char* >( m_aetheryte ), sizeof( m_aetheryte ) );
field[28].getBinary( reinterpret_cast< char* >( m_unlocks ), sizeof( m_unlocks ) );
field[29].getBinary( reinterpret_cast< char* >( m_discovery ), sizeof( m_discovery ) );
m_startTown = field[30].get< int8_t >();
m_playTime = field[31].get< uint32_t >();
m_bNewAdventurer = field[32].getBool();
m_gc = field[33].get< uint8_t >();
field[34].getBinary( reinterpret_cast< char* >( m_gcRank ), sizeof( m_gcRank ) );
m_cfPenaltyUntil = field[35].get< uint32_t >();
m_openingSequence = field[36].get< uint32_t >();
m_gmRank = field[37].get< uint8_t >();
m_pCell = nullptr;
if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() )
g_log.error( "Player id " + char_id_str + " data corrupt!" );
m_maxHp = getMaxHp();
m_maxMp = getMaxMp();
m_modelSubWeapon = 0;
m_lastTickTime = 0;
auto pPlayer = getAsPlayer();
m_pInventory = InventoryPtr( new Inventory( pPlayer ) );
pPlayer->calculateStats();
// first login, run the script event
if( m_bNewGame )
{
//g_scriptMgr.onPlayerFirstEnterWorld( pPlayer );
m_bNewGame = false;
m_hp = getMaxHp();
m_mp = getMaxMp();
setSyncFlag( PlayerSyncFlags::NewGame );
}
if( m_hp > getMaxHp() )
m_hp = getMaxHp();
if( m_mp > getMaxMp() )
m_mp = getMaxMp();
if( m_hp == 0 )
m_status = ActorStatus::Dead;
// if( m_bNewAdventurer )
// setStateFlag( PlayerStateFlag::NewAdventurer );
setStateFlag( PlayerStateFlag::BetweenAreas );
m_pInventory->load();
initHateSlotQueue();
initSpawnIdQueue();
m_pStatusEffectContainer = StatusEffect::StatusEffectContainerPtr( new StatusEffect::StatusEffectContainer( shared_from_this() ) );
if( !m_playerIdToSpawnIdMap.empty() )
m_playerIdToSpawnIdMap.clear();
return true;
}
bool Core::Entity::Player::loadClassData()
{
auto pQR = g_database.query( "SELECT * FROM characlass WHERE CharacterId = " + std::to_string( m_id ) + ";" );
if( !pQR )
return false;
Db::Field* field = pQR->fetch();
for( uint8_t i = 0; i < 25; i++ )
{
uint8_t index = i * 2;
m_classArray[i] = field[index].get< uint8_t >();
m_expArray[i] = field[index + 1].get< uint32_t >();
}
return true;
}
bool Core::Entity::Player::loadSearchInfo()
{
auto pQR = g_database.query( "SELECT * FROM charainfosearch WHERE CharacterId = " + std::to_string( m_id ) + ";" );
if( !pQR )
return false;
Db::Field* field = pQR->fetch();
m_searchSelectClass = field[1].get< uint8_t >();
m_searchSelectRegion = field[2].get< uint8_t >();
sprintf( m_searchMessage, field[3].getString().c_str() );
return true;
}
void Core::Entity::Player::createUpdateSql()
{
// if nothing to update, don't bother.
if( m_updateFlags == PlayerSyncFlags::None )
return;
std::set< std::string > charaBaseSet;
std::set< std::string > charaDetailSet;
std::set< std::string > charaClassSet;
std::set< std::string > charaQuestSet;
std::set< std::string > charaInfoSearchSet;
std::string dbName = g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Mysql.Database", "sapphire" );
std::string updateCharaBase = "UPDATE " + dbName + ".charabase SET ";
std::string updateCharaDetail = "UPDATE " + dbName + ".charadetail SET ";
std::string updateCharaClass = "UPDATE " + dbName + ".characlass SET ";
std::string updateCharaQuest = "UPDATE " + dbName + ".charaquest SET ";
std::string updateCharaInfoSearch = "UPDATE " + dbName + ".charainfosearch SET ";
std::string condition = " UPDATE_DATE = NOW() WHERE CharacterId = " + std::to_string( m_id ) + ";";
if( m_updateFlags & PlayerSyncFlags::Position )
{
charaBaseSet.insert( " Pos_0_0 = " + std::to_string( m_pos.x ) );
charaBaseSet.insert( " Pos_0_1 = " + std::to_string( m_pos.y ) );
charaBaseSet.insert( " Pos_0_2 = " + std::to_string( m_pos.z ) );
charaBaseSet.insert( " Pos_0_3 = " + std::to_string( getRotation() ) );
charaBaseSet.insert( " PrimaryTerritoryId = " + std::to_string( m_zoneId ) );
}
if( m_updateFlags & PlayerSyncFlags::HomePoint )
charaDetailSet.insert( " Homepoint = " + std::to_string( m_homePoint ) );
if( m_updateFlags & PlayerSyncFlags::Discovery )
charaDetailSet.insert( " Discovery = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_discovery ), sizeof( m_discovery ) ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::PlayTime )
charaDetailSet.insert( " TotalPlayTime = " + std::to_string( m_playTime ) );
if( m_updateFlags & PlayerSyncFlags::Unlocks )
charaDetailSet.insert( " unlocks = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_unlocks ), sizeof( m_unlocks ) ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::QuestTracker )
charaDetailSet.insert( " QuestTracking = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_questTracking ), sizeof( m_questTracking ) ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::HowTo )
charaDetailSet.insert( " HowTo = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_howTo ), sizeof( m_howTo ) ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::Aetherytes )
charaDetailSet.insert( " Aetheryte = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_aetheryte ), sizeof( m_aetheryte ) ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::NewGame )
charaBaseSet.insert( " IsNewGame = " + std::to_string( static_cast< uint32_t >( m_bNewGame ) ) );
if( m_updateFlags & PlayerSyncFlags::NewAdventurer )
charaBaseSet.insert( " IsNewAdventurer = " + std::to_string( static_cast< uint32_t >( m_bNewAdventurer ) ) );
if( m_updateFlags & PlayerSyncFlags::GC )
{
charaDetailSet.insert( " GrandCompany = " + std::to_string( m_gc ) );
charaDetailSet.insert( " GrandCompanyRank = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_gcRank ), sizeof( m_gcRank ) ) ) + "')" );
}
if( m_updateFlags & PlayerSyncFlags::CFPenaltyTime )
{
charaDetailSet.insert( " CFPenaltyUntil = " + std::to_string( m_cfPenaltyUntil ) );
}
if( m_updateFlags & PlayerSyncFlags::ExpLevel )
{
uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( getClass() )].exp_idx;
charaClassSet.insert( " Lv_" + std::to_string( classJobIndex ) + " = " + std::to_string( static_cast< uint32_t >( getLevel() ) ) );
charaClassSet.insert( " Exp_" + std::to_string( classJobIndex ) + " = " + std::to_string( getExp() ) );
}
if( m_updateFlags & PlayerSyncFlags::Status )
{
charaBaseSet.insert( " Hp = " + std::to_string( getHp() ) );
charaBaseSet.insert( " Mp = " + std::to_string( getMp() ) );
charaBaseSet.insert( " Mode = " + std::to_string( static_cast< uint32_t >( getStance() ) ) );
charaBaseSet.insert( " ModelEquip = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_modelEquip ), 40 ) ) + "')" );
charaDetailSet.insert( " Class = " + std::to_string( static_cast< uint32_t >( getClass() ) ) );
charaDetailSet.insert( " Status = " + std::to_string( static_cast< uint8_t >( getStatus() ) ) );
}
if( m_updateFlags & PlayerSyncFlags::OpeningSeq )
{
charaDetailSet.insert( " OpeningSequence = " + std::to_string( static_cast< uint8_t >( getOpeningSequence() ) ) );
}
if( m_updateFlags & PlayerSyncFlags::Quests )
{
charaDetailSet.insert( " QuestCompleteFlags = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_questCompleteFlags ), 200 ) ) + "')" );
for( int32_t i = 0; i < 30; i++ )
{
if( m_activeQuests[i] != nullptr )
{
charaQuestSet.insert( " QuestId_" + std::to_string( i ) + " = " + std::to_string( m_activeQuests[i]->c.questId ) );
charaQuestSet.insert( " Sequence_" + std::to_string( i ) + " = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.sequence ) ) );
charaQuestSet.insert( " Flags_" + std::to_string( i ) + " = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.flags ) ) );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_0 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8A ) ) );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_1 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8B ) ) );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_2 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8C ) ) );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_3 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8D ) ) );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_4 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8E ) ) );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_5 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8F ) ) );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_6 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.padding1 ) ) );
}
else
{
charaQuestSet.insert( " QuestId_" + std::to_string( i ) + " = 0" );
charaQuestSet.insert( " Sequence_" + std::to_string( i ) + " = 0" );
charaQuestSet.insert( " Flags_" + std::to_string( i ) + " = 0" );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_0 = 0" );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_1 = 0" );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_2 = 0" );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_3 = 0" );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_4 = 0" );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_5 = 0" );
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_6 = 0" );
}
}
}
if( m_updateFlags & PlayerSyncFlags::SearchInfo )
{
charaInfoSearchSet.insert( " SelectClassId = " + std::to_string( m_searchSelectClass ) );
charaInfoSearchSet.insert( " SelectRegion = " + std::to_string( m_searchSelectRegion ) );
charaInfoSearchSet.insert( " SearchComment = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_searchMessage ), sizeof( m_searchMessage ) ) + "')" ) );
}
if( !charaInfoSearchSet.empty() )
{
for( auto entry : charaInfoSearchSet )
updateCharaInfoSearch += entry + ", ";
updateCharaInfoSearch += condition;
g_database.execute( updateCharaInfoSearch );
}
if( !charaBaseSet.empty() )
{
for( auto entry : charaBaseSet )
updateCharaBase += entry + ", ";
updateCharaBase += condition;
g_database.execute( updateCharaBase );
}
if( !charaDetailSet.empty() )
{
for( auto entry : charaDetailSet )
updateCharaDetail += entry + ", ";
updateCharaDetail += condition;
g_database.execute( updateCharaDetail );
}
if( !charaClassSet.empty() )
{
for( auto entry : charaClassSet )
updateCharaClass += entry + ", ";
updateCharaClass += condition;
g_database.execute( updateCharaClass );
}
if( !charaQuestSet.empty() )
{
for( auto entry : charaQuestSet )
updateCharaQuest += entry + ", ";
updateCharaQuest += condition;
g_database.execute( updateCharaQuest );
}
m_updateFlags = PlayerSyncFlags::None;
}