mirror of
https://github.com/mangosfour/server.git
synced 2025-12-18 19:37:01 +00:00
Save only changed achievement data at player save. Some code cleanups.
Also increase tempory at stack buffere for utf8 convertion. It used in sql quaries log output and need have apporpriate size support.
This commit is contained in:
parent
588edbcedb
commit
129c0797a7
4 changed files with 125 additions and 56 deletions
|
|
@ -147,41 +147,97 @@ AchievementMgr::AchievementMgr(Player *player)
|
||||||
|
|
||||||
AchievementMgr::~AchievementMgr()
|
AchievementMgr::~AchievementMgr()
|
||||||
{
|
{
|
||||||
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
|
||||||
delete iter->second;
|
|
||||||
m_criteriaProgress.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::SaveToDB()
|
void AchievementMgr::SaveToDB()
|
||||||
{
|
{
|
||||||
if(!m_completedAchievements.empty())
|
if(!m_completedAchievements.empty())
|
||||||
{
|
{
|
||||||
CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = %u", GetPlayer()->GetGUIDLow());
|
bool need_execute = false;
|
||||||
|
std::ostringstream ssdel;
|
||||||
std::ostringstream ss;
|
std::ostringstream ssins;
|
||||||
ss << "INSERT INTO character_achievement (guid, achievement, date) VALUES ";
|
|
||||||
for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++)
|
for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++)
|
||||||
{
|
{
|
||||||
if(iter != m_completedAchievements.begin())
|
if(!iter->second.changed)
|
||||||
ss << ", ";
|
continue;
|
||||||
ss << "("<<GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second << ")";
|
|
||||||
|
/// first new/changed record prefix
|
||||||
|
if(!need_execute)
|
||||||
|
{
|
||||||
|
ssdel << "DELETE FROM character_achievement WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND achievement IN (";
|
||||||
|
ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES ";
|
||||||
|
need_execute = true;
|
||||||
|
}
|
||||||
|
/// next new/changed record prefix
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ssdel << ", ";
|
||||||
|
ssins << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// new/changed record data
|
||||||
|
ssdel << iter->first;
|
||||||
|
ssins << "("<<GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << uint64(iter->second.date) << ")";
|
||||||
|
|
||||||
|
/// mark as saved in db
|
||||||
|
iter->second.changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(need_execute)
|
||||||
|
ssdel << ")";
|
||||||
|
|
||||||
|
if(need_execute)
|
||||||
|
{
|
||||||
|
CharacterDatabase.BeginTransaction ();
|
||||||
|
CharacterDatabase.Execute( ssdel.str().c_str() );
|
||||||
|
CharacterDatabase.Execute( ssins.str().c_str() );
|
||||||
|
CharacterDatabase.CommitTransaction ();
|
||||||
}
|
}
|
||||||
CharacterDatabase.Execute( ss.str().c_str() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!m_criteriaProgress.empty())
|
if(!m_criteriaProgress.empty())
|
||||||
{
|
{
|
||||||
CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = %u", GetPlayer()->GetGUIDLow());
|
/// prepare deleting and insert
|
||||||
|
bool need_execute = false;
|
||||||
std::ostringstream ss;
|
std::ostringstream ssdel;
|
||||||
ss << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES ";
|
std::ostringstream ssins;
|
||||||
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||||
{
|
{
|
||||||
if(iter != m_criteriaProgress.begin())
|
if(!iter->second.changed)
|
||||||
ss << ", ";
|
continue;
|
||||||
ss << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second->counter << ", " << iter->second->date << ")";
|
|
||||||
|
/// first new/changed record prefix
|
||||||
|
if(!need_execute)
|
||||||
|
{
|
||||||
|
ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN (";
|
||||||
|
ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES ";
|
||||||
|
need_execute = true;
|
||||||
|
}
|
||||||
|
/// next new/changed record prefix
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ssdel << ", ";
|
||||||
|
ssins << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// new/changed record data
|
||||||
|
ssdel << iter->first;
|
||||||
|
ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")";
|
||||||
|
|
||||||
|
/// mark as saved in db
|
||||||
|
iter->second.changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(need_execute)
|
||||||
|
ssdel << ")";
|
||||||
|
|
||||||
|
if(need_execute)
|
||||||
|
{
|
||||||
|
CharacterDatabase.BeginTransaction ();
|
||||||
|
CharacterDatabase.Execute( ssdel.str().c_str() );
|
||||||
|
CharacterDatabase.Execute( ssins.str().c_str() );
|
||||||
|
CharacterDatabase.CommitTransaction ();
|
||||||
}
|
}
|
||||||
CharacterDatabase.Execute( ss.str().c_str() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,7 +248,9 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Field *fields = achievementResult->Fetch();
|
Field *fields = achievementResult->Fetch();
|
||||||
m_completedAchievements[fields[0].GetUInt32()] = fields[1].GetUInt32();
|
CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()];
|
||||||
|
ca.date = time_t(fields[1].GetUInt64());
|
||||||
|
ca.changed = false;
|
||||||
} while(achievementResult->NextRow());
|
} while(achievementResult->NextRow());
|
||||||
delete achievementResult;
|
delete achievementResult;
|
||||||
}
|
}
|
||||||
|
|
@ -202,16 +260,19 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Field *fields = criteriaResult->Fetch();
|
Field *fields = criteriaResult->Fetch();
|
||||||
CriteriaProgress *progress = new CriteriaProgress(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt64());
|
|
||||||
|
|
||||||
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(progress->id);
|
uint32 id = fields[0].GetUInt32();
|
||||||
if(!criteria ||
|
uint32 counter = fields[1].GetUInt32();
|
||||||
criteria->timeLimit && progress->date + criteria->timeLimit < time(NULL))
|
time_t date = time_t(fields[2].GetUInt64());
|
||||||
{
|
|
||||||
delete progress;
|
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(id);
|
||||||
|
if(!criteria || criteria->timeLimit && date + criteria->timeLimit < time(NULL))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
m_criteriaProgress[progress->id] = progress;
|
CriteriaProgress& progress = m_criteriaProgress[id];
|
||||||
|
progress.counter = counter;
|
||||||
|
progress.date = date;
|
||||||
|
progress.changed = false;
|
||||||
} while(criteriaResult->NextRow());
|
} while(criteriaResult->NextRow());
|
||||||
delete criteriaResult;
|
delete criteriaResult;
|
||||||
}
|
}
|
||||||
|
|
@ -271,10 +332,10 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
|
||||||
GetPlayer()->SendMessageToSet(&data, true);
|
GetPlayer()->SendMessageToSet(&data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::SendCriteriaUpdate(CriteriaProgress *progress)
|
void AchievementMgr::SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
|
WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
|
||||||
data << uint32(progress->id);
|
data << uint32(id);
|
||||||
|
|
||||||
// the counter is packed like a packed Guid
|
// the counter is packed like a packed Guid
|
||||||
data.appendPackGUID(progress->counter);
|
data.appendPackGUID(progress->counter);
|
||||||
|
|
@ -577,11 +638,11 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CriteriaProgressMap::iterator itr = m_criteriaProgress.find(achievementCriteria->ID);
|
CriteriaProgressMap::const_iterator itr = m_criteriaProgress.find(achievementCriteria->ID);
|
||||||
if(itr == m_criteriaProgress.end())
|
if(itr == m_criteriaProgress.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CriteriaProgress *progress = itr->second;
|
CriteriaProgress const* progress = &itr->second;
|
||||||
|
|
||||||
switch(achievementCriteria->requiredType)
|
switch(achievementCriteria->requiredType)
|
||||||
{
|
{
|
||||||
|
|
@ -706,20 +767,26 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
|
||||||
sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue);
|
sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue);
|
||||||
CriteriaProgress *progress = NULL;
|
CriteriaProgress *progress = NULL;
|
||||||
|
|
||||||
if(m_criteriaProgress.find(entry->ID) == m_criteriaProgress.end())
|
CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
|
||||||
|
|
||||||
|
if(iter == m_criteriaProgress.end())
|
||||||
{
|
{
|
||||||
progress = new CriteriaProgress(entry->ID, newValue);
|
progress = &m_criteriaProgress[entry->ID];
|
||||||
m_criteriaProgress[entry->ID]=progress;
|
progress->counter = 0;
|
||||||
|
progress->date = time(NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
progress = m_criteriaProgress[entry->ID];
|
progress = &iter->second;
|
||||||
if(relative)
|
if(relative)
|
||||||
newValue += progress->counter;
|
newValue += progress->counter;
|
||||||
if(progress->counter == newValue)
|
if(progress->counter == newValue)
|
||||||
return;
|
return;
|
||||||
progress->counter = newValue;
|
progress->counter = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress->changed = true;
|
||||||
|
|
||||||
if(entry->timeLimit)
|
if(entry->timeLimit)
|
||||||
{
|
{
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
|
|
@ -730,7 +797,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
|
||||||
// also it seems illogical, the timeframe will be extended at every criteria update
|
// also it seems illogical, the timeframe will be extended at every criteria update
|
||||||
progress->date = now;
|
progress->date = now;
|
||||||
}
|
}
|
||||||
SendCriteriaUpdate(progress);
|
SendCriteriaUpdate(entry->ID,progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||||
|
|
@ -740,7 +807,9 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendAchievementEarned(achievement);
|
SendAchievementEarned(achievement);
|
||||||
m_completedAchievements[achievement->ID] = time(NULL);
|
CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
|
||||||
|
ca.date = time(NULL);
|
||||||
|
ca.changed = true;
|
||||||
|
|
||||||
// don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement
|
// don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement
|
||||||
// TODO: where do set this instead?
|
// TODO: where do set this instead?
|
||||||
|
|
@ -819,20 +888,20 @@ void AchievementMgr::SendRespondInspectAchievements(Player* player)
|
||||||
*/
|
*/
|
||||||
void AchievementMgr::BuildAllDataPacket(WorldPacket *data)
|
void AchievementMgr::BuildAllDataPacket(WorldPacket *data)
|
||||||
{
|
{
|
||||||
for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter)
|
for(CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter)
|
||||||
{
|
{
|
||||||
*data << uint32(iter->first);
|
*data << uint32(iter->first);
|
||||||
*data << uint32(secsToTimeBitFields(iter->second));
|
*data << uint32(secsToTimeBitFields(iter->second.date));
|
||||||
}
|
}
|
||||||
*data << int32(-1);
|
*data << int32(-1);
|
||||||
|
|
||||||
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||||
{
|
{
|
||||||
*data << uint32(iter->second->id);
|
*data << uint32(iter->first);
|
||||||
data->appendPackGUID(iter->second->counter);
|
data->appendPackGUID(iter->second.counter);
|
||||||
data->append(GetPlayer()->GetPackGUID());
|
data->append(GetPlayer()->GetPackGUID());
|
||||||
*data << uint32(0);
|
*data << uint32(0);
|
||||||
*data << uint32(secsToTimeBitFields(iter->second->date));
|
*data << uint32(secsToTimeBitFields(iter->second.date));
|
||||||
*data << uint32(0);
|
*data << uint32(0);
|
||||||
*data << uint32(0);
|
*data << uint32(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,9 @@
|
||||||
|
|
||||||
struct CriteriaProgress
|
struct CriteriaProgress
|
||||||
{
|
{
|
||||||
CriteriaProgress(uint32 id, uint32 counter, time_t date = time(NULL))
|
|
||||||
{
|
|
||||||
this->id = id;
|
|
||||||
this->counter = counter;
|
|
||||||
this->date = date;
|
|
||||||
}
|
|
||||||
uint32 id;
|
|
||||||
uint32 counter;
|
uint32 counter;
|
||||||
time_t date;
|
time_t date;
|
||||||
|
bool changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CriteriaCastSpellRequirement
|
struct CriteriaCastSpellRequirement
|
||||||
|
|
@ -54,8 +48,14 @@ struct AchievementReward
|
||||||
uint32 itemId;
|
uint32 itemId;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef UNORDERED_MAP<uint32, CriteriaProgress*> CriteriaProgressMap;
|
struct CompletedAchievementData
|
||||||
typedef UNORDERED_MAP<uint32, time_t> CompletedAchievementMap;
|
{
|
||||||
|
time_t date;
|
||||||
|
bool changed;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef UNORDERED_MAP<uint32, CriteriaProgress> CriteriaProgressMap;
|
||||||
|
typedef UNORDERED_MAP<uint32, CompletedAchievementData> CompletedAchievementMap;
|
||||||
|
|
||||||
class Unit;
|
class Unit;
|
||||||
class Player;
|
class Player;
|
||||||
|
|
@ -84,7 +84,7 @@ class AchievementMgr
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SendAchievementEarned(AchievementEntry const* achievement);
|
void SendAchievementEarned(AchievementEntry const* achievement);
|
||||||
void SendCriteriaUpdate(CriteriaProgress *progress);
|
void SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress);
|
||||||
void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false);
|
void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false);
|
||||||
void CompletedCriteria(AchievementCriteriaEntry const* entry);
|
void CompletedCriteria(AchievementCriteriaEntry const* entry);
|
||||||
void CompletedAchievement(AchievementEntry const* entry);
|
void CompletedAchievement(AchievementEntry const* entry);
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ struct RuneInfo
|
||||||
|
|
||||||
struct Runes
|
struct Runes
|
||||||
{
|
{
|
||||||
RuneInfo runes[6];
|
RuneInfo runes[MAX_RUNES];
|
||||||
uint8 runeState; // mask of available runes
|
uint8 runeState; // mask of available runes
|
||||||
|
|
||||||
void SetRuneState(uint8 index, bool set = true)
|
void SetRuneState(uint8 index, bool set = true)
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,7 @@ bool Utf8FitTo(std::string str, std::wstring search);
|
||||||
#if PLATFORM == PLATFORM_WINDOWS
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
#define UTF8PRINTF(OUT,FRM,RESERR) \
|
#define UTF8PRINTF(OUT,FRM,RESERR) \
|
||||||
{ \
|
{ \
|
||||||
char temp_buf[6000]; \
|
char temp_buf[32*1024]; \
|
||||||
va_list ap; \
|
va_list ap; \
|
||||||
va_start(ap, FRM); \
|
va_start(ap, FRM); \
|
||||||
size_t temp_len = vsnprintf(temp_buf,6000,FRM,ap); \
|
size_t temp_len = vsnprintf(temp_buf,6000,FRM,ap); \
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue