aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-06-27 15:29:30 +0200
committerShauren <shauren.trinity@gmail.com>2025-06-27 15:29:30 +0200
commit60400d25f5fff2dabd4aa74bbdbc0d2370360a35 (patch)
tree54f2ae7ecfdbe1387d6d6e39a4168a9385b1f230 /src/server/game/Entities
parente0f3291eab271cb7dc5f39abfc7e2a4744be6ee0 (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.cpp326
-rw-r--r--src/server/game/Entities/Player/Player.h23
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);