refactor(Core/PlayerSettings): Refactor Player settings handling for efficiency (#22494)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Andrew
2025-07-19 06:38:04 -03:00
committed by GitHub
parent c6a53849c7
commit 3ca377fed3
3 changed files with 58 additions and 80 deletions
+2 -2
View File
@@ -2639,8 +2639,8 @@ public:
std::string GetPlayerName(); std::string GetPlayerName();
// Settings // Settings
[[nodiscard]] PlayerSetting GetPlayerSetting(std::string source, uint8 index); [[nodiscard]] PlayerSetting GetPlayerSetting(std::string const& source, uint8 index);
void UpdatePlayerSetting(std::string source, uint8 index, uint32 value); void UpdatePlayerSetting(std::string const& source, uint8 index, uint32 value);
void SendSystemMessage(std::string_view msg, bool escapeCharacters = false); void SendSystemMessage(std::string_view msg, bool escapeCharacters = false);
@@ -28,117 +28,92 @@ void Player::_LoadCharacterSettings(PreparedQueryResult result)
m_charSettingsMap.clear(); m_charSettingsMap.clear();
if (!sWorld->getBoolConfig(CONFIG_PLAYER_SETTINGS_ENABLED)) if (!sWorld->getBoolConfig(CONFIG_PLAYER_SETTINGS_ENABLED))
{
return; return;
}
if (result) if (!result)
return;
do
{ {
do Field* fields = result->Fetch();
std::string source = fields[0].Get<std::string>();
std::string data = fields[1].Get<std::string>();
std::vector<std::string_view> tokens = Acore::Tokenize(data, ' ', false);
PlayerSettingVector settings;
settings.reserve(tokens.size()); // reserve capacity but don't resize
for (auto const& token : tokens)
{ {
Field* fields = result->Fetch(); if (token.empty())
continue;
std::string source = fields[0].Get<std::string>(); // Try to parse the value safely
std::string data = fields[1].Get<std::string>(); if (auto parsed = Acore::StringTo<uint32>(token))
settings.emplace_back(*parsed);
}
std::vector<std::string_view> tokens = Acore::Tokenize(data, ' ', false); m_charSettingsMap.emplace(std::move(source), std::move(settings));
PlayerSettingVector setting; } while (result->NextRow());
setting.resize(tokens.size());
uint32 count = 0;
for (auto& token : tokens)
{
if (token.empty())
{
continue;
}
PlayerSetting set;
set.value = Acore::StringTo<uint32>(token).value();
setting[count] = set;
++count;
}
m_charSettingsMap[source] = setting;
} while (result->NextRow());
}
} }
PlayerSetting Player::GetPlayerSetting(std::string source, uint8 index) PlayerSetting Player::GetPlayerSetting(std::string const& source, uint8 index)
{ {
auto itr = m_charSettingsMap.find(source); auto it = m_charSettingsMap.find(source);
if (it == m_charSettingsMap.end() || static_cast<size_t>(index) >= it->second.size())
if (itr == m_charSettingsMap.end())
{
// Settings not found, this will initialize a new entry.
UpdatePlayerSetting(source, index, 0);
return GetPlayerSetting(source, index);
}
PlayerSettingVector settingVector = itr->second;
if (settingVector.size() < (uint8)(index + 1))
{ {
UpdatePlayerSetting(source, index, 0); UpdatePlayerSetting(source, index, 0);
return GetPlayerSetting(source, index); return m_charSettingsMap[source][index];
} }
return itr->second[index]; return it->second[index];
} }
void Player::_SavePlayerSettings(CharacterDatabaseTransaction trans) void Player::_SavePlayerSettings(CharacterDatabaseTransaction trans)
{ {
if (!sWorld->getBoolConfig(CONFIG_PLAYER_SETTINGS_ENABLED)) if (!sWorld->getBoolConfig(CONFIG_PLAYER_SETTINGS_ENABLED))
{
return; return;
}
for (auto& itr : m_charSettingsMap) for (auto const& [source, settings] : m_charSettingsMap)
{ {
std::ostringstream data; if (settings.empty())
continue;
for (auto& setting : itr.second) std::ostringstream data;
{ data << settings[0].value;
data << setting.value << ' ';
} for (size_t i = 1; i < settings.size(); ++i)
data << ' ' << settings[i].value;
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_SETTINGS); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_SETTINGS);
stmt->SetData(0, GetGUID().GetCounter()); stmt->SetData(0, GetGUID().GetCounter());
stmt->SetData(1, itr.first); stmt->SetData(1, source);
stmt->SetData(2, data.str()); stmt->SetData(2, data.str());
trans->Append(stmt); trans->Append(stmt);
} }
} }
void Player::UpdatePlayerSetting(std::string source, uint8 index, uint32 value) void Player::UpdatePlayerSetting(std::string const& source, uint8 index, uint32 value)
{ {
auto itr = m_charSettingsMap.find(source); auto it = m_charSettingsMap.find(source);
uint8 size = index + 1; size_t const requiredSize = static_cast<size_t>(index) + 1;
if (itr == m_charSettingsMap.end()) if (it == m_charSettingsMap.end())
{ {
// Settings not found, initialize a new entry. // Settings not found, create new vector of appropriate size
PlayerSettingVector setting; PlayerSettingVector settings(requiredSize); // default-initialized PlayerSetting
setting.resize(size); settings[index].value = value;
for (uint32 itr = 0; itr <= index; ++itr) m_charSettingsMap.emplace(source, std::move(settings));
{
PlayerSetting set;
set.value = itr == index ? value : 0;
setting[itr] = set;
}
m_charSettingsMap[source] = setting;
} }
else else
{ {
if (size > itr->second.size()) PlayerSettingVector& settings = it->second;
{ if (settings.size() < requiredSize)
itr->second.resize(size); settings.resize(requiredSize); // new elements default to zero
}
itr->second[index].value = value; settings[index].value = value;
} }
} }
@@ -37,12 +37,15 @@ enum AnnouncerFlags : uint8
struct PlayerSetting struct PlayerSetting
{ {
PlayerSetting() = default;
explicit PlayerSetting(uint32 val) : value(val) { }
uint32 value; uint32 value;
[[nodiscard]] bool HasFlag(uint32 flag) { return (value & flag) != 0; } [[nodiscard]] bool HasFlag(uint32 flag) const { return (value & flag) != 0; }
[[nodiscard]] bool IsEnabled(uint32 equals = 1) { return value == equals; } [[nodiscard]] bool IsEnabled(uint32 equals = 1) const { return value == equals; }
void AddFlag(uint32 flag) { value = value | flag; } void AddFlag(uint32 flag) { value |= flag; }
void RemoveFlag(uint32 flag) { value = value &~ flag; } void RemoveFlag(uint32 flag) { value &= ~flag; }
}; };
typedef std::vector<PlayerSetting> PlayerSettingVector; typedef std::vector<PlayerSetting> PlayerSettingVector;