diff options
| author | Shauren <shauren.trinity@gmail.com> | 2025-06-27 15:29:30 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2025-06-27 15:29:30 +0200 |
| commit | 60400d25f5fff2dabd4aa74bbdbc0d2370360a35 (patch) | |
| tree | 54f2ae7ecfdbe1387d6d6e39a4168a9385b1f230 /src/server/game/Entities | |
| parent | e0f3291eab271cb7dc5f39abfc7e2a4744be6ee0 (diff) | |
Core/Players: Implemented PlayerDataElementAccount, PlayerDataElementCharacter, PlayerDataFlagAccount and PlayerDataFlagCharacter
Diffstat (limited to 'src/server/game/Entities')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 326 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 23 |
2 files changed, 348 insertions, 1 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 6b971d69a8c..f05a69123f1 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -105,6 +105,7 @@ #include "PlayerChoice.h" #include "QueryCallback.h" #include "QueryHolder.h" +#include "QueryResultStructured.h" #include "QuestDef.h" #include "QuestObjectiveCriteriaMgr.h" #include "QuestPackets.h" @@ -18618,6 +18619,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol _LoadCUFProfiles(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES)); + _LoadPlayerData(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DATA_ELEMENTS), holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DATA_FLAGS)); + std::unique_ptr<Garrison> garrison = std::make_unique<Garrison>(this); if (garrison->LoadFromDB(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON), holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS), @@ -20165,6 +20168,87 @@ bool Player::_LoadHomeBind(PreparedQueryResult result) return true; } +void Player::_LoadPlayerData(PreparedQueryResult elementsResult, PreparedQueryResult flagsResult) +{ + if (elementsResult) + { + do + { + DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(PreparedResultSet, (playerDataElementCharacterId)(floatValue)(int64Value)) fields { *elementsResult }; + + PlayerDataElementCharacterEntry const* entry = sPlayerDataElementCharacterStore.LookupEntry(fields.playerDataElementCharacterId().GetUInt32()); + if (!entry) + continue; + + auto elementSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::CharacterDataElements, entry->StorageIndex); + + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Type), entry->Type); + + switch (entry->GetType()) + { + case PlayerDataElementType::Int64: + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Int64Value), fields.int64Value().GetInt64()); + break; + case PlayerDataElementType::Float: + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::FloatValue), fields.floatValue().GetFloat()); + break; + default: + break; + } + } while (elementsResult->NextRow()); + } + + if (flagsResult) + { + auto bitVectorSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::BitVectors) + .ModifyValue(&UF::BitVectors::Values, PLAYER_DATA_FLAG_CHARACTER_DATA_INDEX); + + do + { + DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(PreparedResultSet, (storageIndex)(mask)) fields { *flagsResult }; + + SetUpdateFieldValue(bitVectorSetter.ModifyValue(&UF::BitVector::Values, fields.storageIndex().GetUInt32()), fields.mask().GetUInt64()); + } while (flagsResult->NextRow()); + } + + WorldSession::PlayerDataAccount const& accountData = GetSession()->GetPlayerDataAccount(); + for (WorldSession::PlayerDataAccount::Element const& element : accountData.Elements) + { + PlayerDataElementAccountEntry const* entry = sPlayerDataElementAccountStore.LookupEntry(element.Id); + if (!entry) + continue; + + auto elementSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::AccountDataElements, entry->StorageIndex); + + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Type), entry->Type); + + switch (entry->GetType()) + { + case PlayerDataElementType::Int64: + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Int64Value), element.Int64Value); + break; + case PlayerDataElementType::Float: + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::FloatValue), element.FloatValue); + break; + default: + break; + } + } + + if (!accountData.Flags.empty()) + { + auto bitVectorSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::BitVectors) + .ModifyValue(&UF::BitVectors::Values, PLAYER_DATA_FLAG_ACCOUNT_DATA_INDEX); + + for (std::size_t i = 0; i < accountData.Flags.size(); ++i) + SetUpdateFieldValue(bitVectorSetter.ModifyValue(&UF::BitVector::Values, i), accountData.Flags[i].Value); + } +} + /*********************************************************/ /*** SAVE SYSTEM ***/ /*********************************************************/ @@ -20563,6 +20647,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba _SaveInstanceTimeRestrictions(trans); _SaveCurrency(trans); _SaveCUFProfiles(trans); + _SavePlayerData(trans); if (_garrison) _garrison->SaveToDB(trans); @@ -20579,6 +20664,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba GetSession()->GetCollectionMgr()->SaveAccountItemAppearances(loginTransaction); GetSession()->GetCollectionMgr()->SaveAccountTransmogIllusions(loginTransaction); GetSession()->GetCollectionMgr()->SaveAccountWarbandScenes(loginTransaction); + GetSession()->SavePlayerDataAccount(loginTransaction); Battlenet::RealmHandle currentRealmId = sRealmList->GetCurrentRealmId(); @@ -21465,6 +21551,70 @@ void Player::_SaveStats(CharacterDatabaseTransaction trans) const trans->Append(stmt); } +void Player::_SavePlayerData(CharacterDatabaseTransaction trans) +{ + ObjectGuid::LowType guid = GetGUID().GetCounter(); + CharacterDatabasePreparedStatement* stmt; + for (uint32 playerDataElementCharacterId : _playerDataElementsNeedSave) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_DATA_ELEMENTS_CHARACTER); + stmt->setUInt64(0, guid); + stmt->setUInt32(1, playerDataElementCharacterId); + trans->Append(stmt); + + PlayerDataElementCharacterEntry const* entry = sPlayerDataElementCharacterStore.LookupEntry(playerDataElementCharacterId); + if (!entry) + continue; + + UF::PlayerDataElement const& element = m_activePlayerData->CharacterDataElements[entry->StorageIndex]; + switch (entry->GetType()) + { + case PlayerDataElementType::Int64: + if (!element.Int64Value) + continue; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_DATA_ELEMENTS_CHARACTER); + stmt->setUInt64(0, guid); + stmt->setUInt32(1, playerDataElementCharacterId); + stmt->setNull(2); + stmt->setInt64(3, element.Int64Value); + trans->Append(stmt); + break; + case PlayerDataElementType::Float: + if (!element.FloatValue) + continue; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_DATA_ELEMENTS_CHARACTER); + stmt->setUInt64(0, guid); + stmt->setUInt32(1, playerDataElementCharacterId); + stmt->setFloat(2, element.FloatValue); + stmt->setNull(3); + trans->Append(stmt); + break; + } + + } + + for (uint32 storageIndex : _playerDataFlagsNeedSave) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_DATA_FLAGS_CHARACTER); + stmt->setUInt64(0, guid); + stmt->setUInt32(1, storageIndex); + trans->Append(stmt); + + uint64 value = m_activePlayerData->BitVectors->Values[PLAYER_DATA_FLAG_CHARACTER_DATA_INDEX].Values[storageIndex]; + if (!value) + continue; + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_DATA_FLAGS_CHARACTER); + stmt->setUInt64(0, guid); + stmt->setUInt32(1, storageIndex); + stmt->setUInt64(2, value); + trans->Append(stmt); + } + + _playerDataElementsNeedSave.clear(); + _playerDataFlagsNeedSave.clear(); +} + void Player::outDebugValues() const { if (!sLog->ShouldLog("entities.unit", LOG_LEVEL_DEBUG)) @@ -29906,6 +30056,182 @@ bool Player::MeetPlayerCondition(uint32 conditionId) const return ConditionMgr::IsPlayerMeetingCondition(this, conditionId); } +std::variant<int64, float> Player::GetDataElementAccount(uint32 dataElementId) const +{ + PlayerDataElementAccountEntry const* entry = sPlayerDataElementAccountStore.LookupEntry(dataElementId); + if (!entry) + return int64(0); + + switch (entry->GetType()) + { + case PlayerDataElementType::Int64: + if (entry->StorageIndex < std::ssize(m_activePlayerData->AccountDataElements)) + return m_activePlayerData->AccountDataElements[entry->StorageIndex].Int64Value; + return SI64LIT(0); + case PlayerDataElementType::Float: + if (entry->StorageIndex < std::ssize(m_activePlayerData->AccountDataElements)) + return m_activePlayerData->AccountDataElements[entry->StorageIndex].FloatValue; + return 0.0f; + default: + break; + } + + return int64(0); +} + +void Player::SetDataElementAccount(uint32 dataElementId, std::variant<int64, float> value) +{ + PlayerDataElementAccountEntry const* entry = sPlayerDataElementAccountStore.LookupEntry(dataElementId); + if (!entry) + return; + + auto elementSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::AccountDataElements, entry->StorageIndex); + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Type), entry->Type); + + switch (entry->GetType()) + { + case PlayerDataElementType::Int64: + { + int64 int64Value = std::visit([](auto v) { return int64(v); }, value); + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Int64Value), int64Value); + GetSession()->SetPlayerDataElementAccount(dataElementId, int64Value); + break; + } + case PlayerDataElementType::Float: + { + float floatValue = std::visit([](auto v) { return float(v); }, value); + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::FloatValue), floatValue); + GetSession()->SetPlayerDataElementAccount(dataElementId, floatValue); + break; + } + default: + break; + } +} + +std::variant<int64, float> Player::GetDataElementCharacter(uint32 dataElementId) const +{ + PlayerDataElementCharacterEntry const* entry = sPlayerDataElementCharacterStore.LookupEntry(dataElementId); + if (!entry) + return int64(0); + + switch (entry->Type) + { + case 0: + if (entry->StorageIndex < std::ssize(m_activePlayerData->CharacterDataElements)) + return m_activePlayerData->CharacterDataElements[entry->StorageIndex].Int64Value; + return SI64LIT(0); + case 1: + if (entry->StorageIndex < std::ssize(m_activePlayerData->CharacterDataElements)) + return m_activePlayerData->CharacterDataElements[entry->StorageIndex].FloatValue; + return 0.0f; + default: + break; + } + + return int64(0); +} + +void Player::SetDataElementCharacter(uint32 dataElementId, std::variant<int64, float> value) +{ + PlayerDataElementCharacterEntry const* entry = sPlayerDataElementCharacterStore.LookupEntry(dataElementId); + if (!entry) + return; + + auto elementSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::CharacterDataElements, entry->StorageIndex); + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Type), entry->Type); + + switch (entry->Type) + { + case 0: + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::Int64Value), std::visit([](auto v) { return int64(v); }, value)); + break; + case 1: + SetUpdateFieldValue(elementSetter.ModifyValue(&UF::PlayerDataElement::FloatValue), std::visit([](auto v) { return float(v); }, value)); + break; + default: + break; + } + + _playerDataElementsNeedSave.insert(dataElementId); +} + +bool Player::HasDataFlagAccount(uint32 dataFlagId) const +{ + PlayerDataFlagAccountEntry const* entry = sPlayerDataFlagAccountStore.LookupEntry(dataFlagId); + if (!entry) + return false; + + uint32 fieldOffset = entry->StorageIndex / PLAYER_DATA_FLAG_VALUE_BITS; + uint64 flag = UI64LIT(1) << (entry->StorageIndex % PLAYER_DATA_FLAG_VALUE_BITS); + + if (fieldOffset >= m_activePlayerData->BitVectors->Values[PLAYER_DATA_FLAG_ACCOUNT_DATA_INDEX].Values.size()) + return false; + + return (m_activePlayerData->BitVectors->Values[PLAYER_DATA_FLAG_ACCOUNT_DATA_INDEX].Values[fieldOffset] & flag) != 0; +} + +void Player::SetDataFlagAccount(uint32 dataFlagId, bool on) +{ + PlayerDataFlagAccountEntry const* entry = sPlayerDataFlagAccountStore.LookupEntry(dataFlagId); + if (!entry) + return; + + uint32 fieldOffset = entry->StorageIndex / PLAYER_DATA_FLAG_VALUE_BITS; + uint64 flag = UI64LIT(1) << (entry->StorageIndex % PLAYER_DATA_FLAG_VALUE_BITS); + + auto fieldSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::BitVectors) + .ModifyValue(&UF::BitVectors::Values, PLAYER_DATA_FLAG_ACCOUNT_DATA_INDEX) + .ModifyValue(&UF::BitVector::Values, fieldOffset); + + if (on) + SetUpdateFieldFlagValue(fieldSetter, flag); + else + RemoveUpdateFieldFlagValue(fieldSetter, flag); + + GetSession()->SetPlayerDataFlagAccount(dataFlagId, on); +} + +bool Player::HasDataFlagCharacter(uint32 dataFlagId) const +{ + PlayerDataFlagCharacterEntry const* entry = sPlayerDataFlagCharacterStore.LookupEntry(dataFlagId); + if (!entry) + return false; + + uint32 fieldOffset = entry->StorageIndex / PLAYER_DATA_FLAG_VALUE_BITS; + uint64 flag = UI64LIT(1) << (entry->StorageIndex % PLAYER_DATA_FLAG_VALUE_BITS); + + if (fieldOffset >= m_activePlayerData->BitVectors->Values[PLAYER_DATA_FLAG_CHARACTER_DATA_INDEX].Values.size()) + return false; + + return (m_activePlayerData->BitVectors->Values[PLAYER_DATA_FLAG_CHARACTER_DATA_INDEX].Values[fieldOffset] & flag) != 0; +} + +void Player::SetDataFlagCharacter(uint32 dataFlagId, bool on) +{ + PlayerDataFlagCharacterEntry const* entry = sPlayerDataFlagCharacterStore.LookupEntry(dataFlagId); + if (!entry) + return; + + uint32 fieldOffset = entry->StorageIndex / PLAYER_DATA_FLAG_VALUE_BITS; + uint64 flag = UI64LIT(1) << (entry->StorageIndex % PLAYER_DATA_FLAG_VALUE_BITS); + + auto fieldSetter = m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::BitVectors) + .ModifyValue(&UF::BitVectors::Values, PLAYER_DATA_FLAG_CHARACTER_DATA_INDEX) + .ModifyValue(&UF::BitVector::Values, fieldOffset); + + if (on) + SetUpdateFieldFlagValue(fieldSetter, flag); + else + RemoveUpdateFieldFlagValue(fieldSetter, flag); + + _playerDataFlagsNeedSave.insert(fieldOffset); +} + bool Player::IsInFriendlyArea() const { if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(GetAreaId())) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 77c1e44f7dc..2d21399464d 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -33,6 +33,7 @@ #include "PlayerTaxi.h" #include "QuestDef.h" #include "SceneMgr.h" +#include <variant> struct AccessRequirement; struct AchievementEntry; @@ -147,7 +148,8 @@ enum PlayerSkillsConstants enum PlayerDataFlagConstants { - PLAYER_EXPLORED_ZONES_BITS = UF::size_of_value_type<decltype(UF::BitVector::Values)>() * 8, + PLAYER_DATA_FLAG_VALUE_BITS = UF::size_of_value_type<decltype(UF::BitVector::Values)>() * 8, + PLAYER_EXPLORED_ZONES_BITS = PLAYER_DATA_FLAG_VALUE_BITS, PLAYER_DATA_FLAG_EXPLORED_ZONES_INDEX = 1, PLAYER_DATA_FLAG_CHARACTER_DATA_INDEX = 2, @@ -949,6 +951,8 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES, PLAYER_LOGIN_QUERY_LOAD_TRAIT_ENTRIES, PLAYER_LOGIN_QUERY_LOAD_TRAIT_CONFIGS, + PLAYER_LOGIN_QUERY_LOAD_DATA_ELEMENTS, + PLAYER_LOGIN_QUERY_LOAD_DATA_FLAGS, MAX_PLAYER_LOGIN_QUERY }; @@ -2962,6 +2966,18 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player> void SetRequiredMountCapabilityFlag(uint8 flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::RequiredMountCapabilityFlags), flag); } void ReplaceAllRequiredMountCapabilityFlags(uint8 flags) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::RequiredMountCapabilityFlags), flags); } + std::variant<int64, float> GetDataElementAccount(uint32 dataElementId) const; + void SetDataElementAccount(uint32 dataElementId, std::variant<int64, float> value); + + std::variant<int64, float> GetDataElementCharacter(uint32 dataElementId) const; + void SetDataElementCharacter(uint32 dataElementId, std::variant<int64, float> value); + + bool HasDataFlagAccount(uint32 dataFlagId) const; + void SetDataFlagAccount(uint32 dataFlagId, bool on); + + bool HasDataFlagCharacter(uint32 dataFlagId) const; + void SetDataFlagCharacter(uint32 dataFlagId, bool on); + bool IsInFriendlyArea() const; bool IsFriendlyArea(AreaTableEntry const* inArea) const; @@ -3072,6 +3088,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player> void _LoadPetStable(uint32 summonedPetNumber, PreparedQueryResult result); void _LoadCurrency(PreparedQueryResult result); void _LoadCUFProfiles(PreparedQueryResult result); + void _LoadPlayerData(PreparedQueryResult elementsResult, PreparedQueryResult flagsResult); /*********************************************************/ /*** SAVE SYSTEM ***/ @@ -3100,6 +3117,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player> void _SaveInstanceTimeRestrictions(CharacterDatabaseTransaction trans); void _SaveCurrency(CharacterDatabaseTransaction trans); void _SaveCUFProfiles(CharacterDatabaseTransaction trans); + void _SavePlayerData(CharacterDatabaseTransaction trans); /*********************************************************/ /*** ENVIRONMENTAL SYSTEM ***/ @@ -3349,6 +3367,9 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player> void ExecutePendingSpellCastRequest(); bool ProcessItemCast(SpellCastRequest& castRequest, SpellCastTargets const& targets); bool CanExecutePendingSpellCastRequest(); + + Trinity::Containers::FlatSet<uint32> _playerDataElementsNeedSave; + Trinity::Containers::FlatSet<uint32> _playerDataFlagsNeedSave; }; TC_GAME_API void AddItemsSetItem(Player* player, Item const* item); |
