feat(Core/Player): restore additional saves behind a config bitmask (#26825)
This commit is contained in:
@@ -1838,6 +1838,20 @@ PlayerSave.Stats.MinLevel = 0
|
|||||||
|
|
||||||
PlayerSave.Stats.SaveOnlyOnLogout = 1
|
PlayerSave.Stats.SaveOnlyOnLogout = 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# PlayerSave.AdditionalSaves
|
||||||
|
# Description: Bitmask of player data to save to the database a few seconds after
|
||||||
|
# important changes instead of waiting for the next periodic save
|
||||||
|
# (PlayerSaveInterval). Reduces the progress lost on a server crash.
|
||||||
|
# Combine the values to enable multiple triggers.
|
||||||
|
# Values: 1 - Inventory and gold (after looting an item of rare or better quality)
|
||||||
|
# 2 - Quest status (after quest status changes)
|
||||||
|
# 4 - Achievements (after completing an achievement)
|
||||||
|
# Default: 0 - (Disabled)
|
||||||
|
# 7 - (All of the above)
|
||||||
|
|
||||||
|
PlayerSave.AdditionalSaves = 0
|
||||||
|
|
||||||
#
|
#
|
||||||
# CleanCharacterDB
|
# CleanCharacterDB
|
||||||
# Description: Clean out deprecated achievements, skills, spells and talents from the db.
|
# Description: Clean out deprecated achievements, skills, spells and talents from the db.
|
||||||
|
|||||||
@@ -2333,6 +2333,8 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_player->AdditionalSavingAddMask(ADDITIONAL_SAVING_ACHIEVEMENTS);
|
||||||
|
|
||||||
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL) && !_player->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_REALM_FIRST_ACHIEVEMENTS))
|
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL) && !_player->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_REALM_FIRST_ACHIEVEMENTS))
|
||||||
sAchievementMgr->SetRealmCompleted(achievement);
|
sAchievementMgr->SetRealmCompleted(achievement);
|
||||||
|
|
||||||
|
|||||||
@@ -988,6 +988,7 @@ enum AdditionalSaving
|
|||||||
ADDITIONAL_SAVING_NONE = 0x00,
|
ADDITIONAL_SAVING_NONE = 0x00,
|
||||||
ADDITIONAL_SAVING_INVENTORY_AND_GOLD = 0x01,
|
ADDITIONAL_SAVING_INVENTORY_AND_GOLD = 0x01,
|
||||||
ADDITIONAL_SAVING_QUEST_STATUS = 0x02,
|
ADDITIONAL_SAVING_QUEST_STATUS = 0x02,
|
||||||
|
ADDITIONAL_SAVING_ACHIEVEMENTS = 0x04,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PlayerCommandStates
|
enum PlayerCommandStates
|
||||||
@@ -2618,7 +2619,7 @@ public:
|
|||||||
bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY); }
|
bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY); }
|
||||||
|
|
||||||
// saving
|
// saving
|
||||||
void AdditionalSavingAddMask(uint8 mask) { m_additionalSaveTimer = 2000; m_additionalSaveMask |= mask; }
|
void AdditionalSavingAddMask(uint8 mask);
|
||||||
// arena spectator
|
// arena spectator
|
||||||
[[nodiscard]] bool IsSpectator() const { return m_ExtraFlags & PLAYER_EXTRA_SPECTATOR_ON; }
|
[[nodiscard]] bool IsSpectator() const { return m_ExtraFlags & PLAYER_EXTRA_SPECTATOR_ON; }
|
||||||
void SetIsSpectator(bool on);
|
void SetIsSpectator(bool on);
|
||||||
@@ -2814,6 +2815,7 @@ protected:
|
|||||||
void _SaveCharacter(bool create, CharacterDatabaseTransaction trans);
|
void _SaveCharacter(bool create, CharacterDatabaseTransaction trans);
|
||||||
void _SaveInstanceTimeRestrictions(CharacterDatabaseTransaction trans);
|
void _SaveInstanceTimeRestrictions(CharacterDatabaseTransaction trans);
|
||||||
void _SavePlayerSettings(CharacterDatabaseTransaction trans);
|
void _SavePlayerSettings(CharacterDatabaseTransaction trans);
|
||||||
|
void UpdateAdditionalSaves(uint32 p_time);
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
/*** ENVIRONMENTAL SYSTEM ***/
|
/*** ENVIRONMENTAL SYSTEM ***/
|
||||||
|
|||||||
@@ -7254,6 +7254,18 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create, bool logo
|
|||||||
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flag data to be saved by UpdateAdditionalSaves a moment after an important change,
|
||||||
|
// filtered by the PlayerSave.AdditionalSaves config mask
|
||||||
|
void Player::AdditionalSavingAddMask(uint8 mask)
|
||||||
|
{
|
||||||
|
mask &= sWorld->getIntConfig(CONFIG_ADDITIONAL_SAVES);
|
||||||
|
if (!mask)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_additionalSaveTimer = 2000;
|
||||||
|
m_additionalSaveMask |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
// fast save function for item/money cheating preventing - save only inventory and money state
|
// fast save function for item/money cheating preventing - save only inventory and money state
|
||||||
void Player::SaveInventoryAndGoldToDB(CharacterDatabaseTransaction trans)
|
void Player::SaveInventoryAndGoldToDB(CharacterDatabaseTransaction trans)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -332,6 +332,8 @@ void Player::Update(uint32 p_time)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateAdditionalSaves(p_time);
|
||||||
|
|
||||||
// Handle Water/drowning
|
// Handle Water/drowning
|
||||||
HandleDrowning(p_time);
|
HandleDrowning(p_time);
|
||||||
|
|
||||||
@@ -2399,3 +2401,49 @@ void Player::ProcessSpellQueue()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save only the data flagged by AdditionalSavingAddMask shortly after
|
||||||
|
// important changes, so a crash loses at most a few seconds of them
|
||||||
|
void Player::UpdateAdditionalSaves(uint32 p_time)
|
||||||
|
{
|
||||||
|
if (!m_additionalSaveTimer || GetSession()->isLogingOut())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_additionalSaveTimer > p_time)
|
||||||
|
{
|
||||||
|
m_additionalSaveTimer -= p_time;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 mask = m_additionalSaveMask;
|
||||||
|
m_additionalSaveTimer = 0;
|
||||||
|
m_additionalSaveMask = 0;
|
||||||
|
|
||||||
|
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
||||||
|
|
||||||
|
if (mask & ADDITIONAL_SAVING_INVENTORY_AND_GOLD)
|
||||||
|
SaveInventoryAndGoldToDB(trans);
|
||||||
|
|
||||||
|
if (mask & ADDITIONAL_SAVING_QUEST_STATUS)
|
||||||
|
{
|
||||||
|
_SaveQuestStatus(trans);
|
||||||
|
|
||||||
|
// if nothing changed, nothing will happen
|
||||||
|
_SaveDailyQuestStatus(trans);
|
||||||
|
_SaveWeeklyQuestStatus(trans);
|
||||||
|
_SaveSeasonalQuestStatus(trans);
|
||||||
|
_SaveMonthlyQuestStatus(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask & ADDITIONAL_SAVING_ACHIEVEMENTS)
|
||||||
|
{
|
||||||
|
m_achievementMgr->SaveToDB(trans);
|
||||||
|
|
||||||
|
// achievements are often earned together with skill or gold changes
|
||||||
|
// (professions, riding, wealth), save those too to keep the DB consistent
|
||||||
|
_SaveSkills(trans);
|
||||||
|
SaveGoldToDB(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
CharacterDatabase.CommitTransaction(trans);
|
||||||
|
}
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ void WorldConfig::BuildConfigCache()
|
|||||||
SetConfigValue<uint32>(CONFIG_INTERVAL_SAVE, "PlayerSaveInterval", 900000);
|
SetConfigValue<uint32>(CONFIG_INTERVAL_SAVE, "PlayerSaveInterval", 900000);
|
||||||
SetConfigValue<uint32>(CONFIG_INTERVAL_DISCONNECT_TOLERANCE, "DisconnectToleranceInterval", 0);
|
SetConfigValue<uint32>(CONFIG_INTERVAL_DISCONNECT_TOLERANCE, "DisconnectToleranceInterval", 0);
|
||||||
SetConfigValue<bool>(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT, "PlayerSave.Stats.SaveOnlyOnLogout", true);
|
SetConfigValue<bool>(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT, "PlayerSave.Stats.SaveOnlyOnLogout", true);
|
||||||
|
SetConfigValue<uint32>(CONFIG_ADDITIONAL_SAVES, "PlayerSave.AdditionalSaves", 0);
|
||||||
SetConfigValue<bool>(CONFIG_VALIDATE_SKILL_LEARNED_BY_SPELLS, "ValidateSkillLearnedBySpells", true);
|
SetConfigValue<bool>(CONFIG_VALIDATE_SKILL_LEARNED_BY_SPELLS, "ValidateSkillLearnedBySpells", true);
|
||||||
|
|
||||||
SetConfigValue<uint32>(CONFIG_MIN_LEVEL_STAT_SAVE, "PlayerSave.Stats.MinLevel", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value < MAX_LEVEL; }, "< MAX_LEVEL");
|
SetConfigValue<uint32>(CONFIG_MIN_LEVEL_STAT_SAVE, "PlayerSave.Stats.MinLevel", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value < MAX_LEVEL; }, "< MAX_LEVEL");
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ enum ServerConfigs
|
|||||||
CONFIG_ALLOW_PLAYER_COMMANDS,
|
CONFIG_ALLOW_PLAYER_COMMANDS,
|
||||||
CONFIG_CLEAN_CHARACTER_DB,
|
CONFIG_CLEAN_CHARACTER_DB,
|
||||||
CONFIG_STATS_SAVE_ONLY_ON_LOGOUT,
|
CONFIG_STATS_SAVE_ONLY_ON_LOGOUT,
|
||||||
|
CONFIG_ADDITIONAL_SAVES,
|
||||||
CONFIG_ALLOW_TWO_SIDE_ACCOUNTS,
|
CONFIG_ALLOW_TWO_SIDE_ACCOUNTS,
|
||||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR,
|
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR,
|
||||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT,
|
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT,
|
||||||
|
|||||||
Reference in New Issue
Block a user