mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Thread save loading of player time and birthday
This commit is contained in:
parent
e9242f45f1
commit
dbf6ac88f6
|
@ -1077,8 +1077,7 @@ void CGameContext::OnClientEnter(int ClientID)
|
|||
|
||||
// Can't set score here as LoadScore() is threaded, run it in
|
||||
// LoadScoreThreaded() instead
|
||||
Score()->LoadScore(ClientID);
|
||||
Score()->CheckBirthday(ClientID);
|
||||
Score()->LoadPlayerData(ClientID);
|
||||
|
||||
{
|
||||
int Empty = -1;
|
||||
|
@ -1878,18 +1877,8 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
// reload scores
|
||||
|
||||
Score()->PlayerData(ClientID)->Reset();
|
||||
Score()->LoadScore(ClientID);
|
||||
Score()->PlayerData(ClientID)->m_CurrentTime = Score()->PlayerData(ClientID)->m_BestTime;
|
||||
|
||||
// -9999 stands for no time and isn't displayed in scoreboard, so
|
||||
// shift the time by a second if the player actually took 9999
|
||||
// seconds to finish the map.
|
||||
if(!Score()->PlayerData(ClientID)->m_BestTime)
|
||||
m_apPlayers[ClientID]->m_Score = -9999;
|
||||
else if((int)Score()->PlayerData(ClientID)->m_BestTime == -9999)
|
||||
m_apPlayers[ClientID]->m_Score = -10000;
|
||||
else
|
||||
m_apPlayers[ClientID]->m_Score = Score()->PlayerData(ClientID)->m_BestTime;
|
||||
m_apPlayers[ClientID]->m_Score = -9999;
|
||||
Score()->LoadPlayerData(ClientID);
|
||||
}
|
||||
Server()->SetClientClan(ClientID, pMsg->m_pClan);
|
||||
Server()->SetClientCountry(ClientID, pMsg->m_Country);
|
||||
|
|
|
@ -808,6 +808,29 @@ void CPlayer::ProcessSqlResult()
|
|||
case CSqlPlayerResult::MAP_VOTE:
|
||||
// TODO: start vote
|
||||
break;
|
||||
case CSqlPlayerResult::PLAYER_INFO:
|
||||
GameServer()->Score()->PlayerData(m_ClientID)->Set(
|
||||
m_SqlQueryResult->m_Data.m_Info.m_Time,
|
||||
m_SqlQueryResult->m_Data.m_Info.m_CpTime
|
||||
);
|
||||
printf("%d", m_SqlQueryResult->m_Data.m_Info.m_Score);
|
||||
m_Score = m_SqlQueryResult->m_Data.m_Info.m_Score;
|
||||
m_HasFinishScore = m_SqlQueryResult->m_Data.m_Info.m_HasFinishScore;
|
||||
Server()->ExpireServerInfo();
|
||||
int Birthday = m_SqlQueryResult->m_Data.m_Info.m_Birthday;
|
||||
if(Birthday != 0)
|
||||
{
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"Happy DDNet birthday to %s for finishing their first map %d year%s ago!",
|
||||
Server()->ClientName(m_ClientID), Birthday, Birthday > 1 ? "s" : "");
|
||||
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, m_ClientID);
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"Happy DDNet birthday, %s!\nYou have finished your first map exactly %d year%s ago!",
|
||||
Server()->ClientName(m_ClientID), Birthday, Birthday > 1 ? "s" : "");
|
||||
GameServer()->SendBroadcast(aBuf, m_ClientID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_SqlQueryResult = nullptr;
|
||||
|
|
|
@ -19,6 +19,7 @@ public:
|
|||
{
|
||||
Reset();
|
||||
}
|
||||
~CPlayerData() {}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
|
@ -31,6 +32,7 @@ public:
|
|||
void Set(float Time, float CpTime[NUM_CHECKPOINTS])
|
||||
{
|
||||
m_BestTime = Time;
|
||||
m_CurrentTime = Time;
|
||||
for(int i = 0; i < NUM_CHECKPOINTS; i++)
|
||||
m_aBestCpTime[i] = CpTime[i];
|
||||
}
|
||||
|
@ -62,8 +64,7 @@ public:
|
|||
|
||||
virtual void MapInfo(int ClientID, const char *pMapName) = 0;
|
||||
virtual void MapVote(int ClientID, const char *pMapName) = 0;
|
||||
virtual void CheckBirthday(int ClientID) = 0;
|
||||
virtual void LoadScore(int ClientID) = 0;
|
||||
virtual void LoadPlayerData(int ClientID) = 0;
|
||||
virtual void SaveScore(int ClientID, float Time, const char *pTimestamp, float aCpTime[NUM_CHECKPOINTS], bool NotEligible) = 0;
|
||||
|
||||
virtual void SaveTeamScore(int *pClientIDs, unsigned int Size, float Time, const char *pTimestamp) = 0;
|
||||
|
|
|
@ -205,12 +205,7 @@ void CFileScore::UpdatePlayer(int ID, float Score,
|
|||
Save();
|
||||
}
|
||||
|
||||
void CFileScore::CheckBirthday(int ClientID)
|
||||
{
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
void CFileScore::LoadScore(int ClientID)
|
||||
void CFileScore::LoadPlayerData(int ClientID)
|
||||
{
|
||||
CPlayerScore *pPlayer = SearchScore(ClientID, 0);
|
||||
if (pPlayer)
|
||||
|
|
|
@ -60,8 +60,7 @@ public:
|
|||
CFileScore(CGameContext *pGameServer);
|
||||
~CFileScore();
|
||||
|
||||
virtual void CheckBirthday(int ClientID);
|
||||
virtual void LoadScore(int ClientID);
|
||||
virtual void LoadPlayerData(int ClientID);
|
||||
virtual void MapInfo(int ClientID, const char* MapName);
|
||||
virtual void MapVote(int ClientID, const char* MapName);
|
||||
virtual void SaveScore(int ClientID, float Time, const char *pTimestamp,
|
||||
|
|
|
@ -20,11 +20,31 @@
|
|||
std::atomic_int CSqlScore::ms_InstanceCount(0);
|
||||
|
||||
CSqlPlayerResult::CSqlPlayerResult() :
|
||||
m_Done(0),
|
||||
m_MessageKind(DIRECT)
|
||||
m_Done(0)
|
||||
{
|
||||
for(int i = 0; i < (int)(sizeof(m_aaMessages)/sizeof(m_aaMessages[0])); i++)
|
||||
m_aaMessages[i][0] = 0;
|
||||
SetVariant(Variant::DIRECT);
|
||||
}
|
||||
|
||||
void CSqlPlayerResult::SetVariant(Variant v)
|
||||
{
|
||||
m_MessageKind = v;
|
||||
switch(v)
|
||||
{
|
||||
case DIRECT:
|
||||
case ALL:
|
||||
for(int i = 0; i < (int)(sizeof(m_aaMessages)/sizeof(m_aaMessages[0])); i++)
|
||||
m_aaMessages[i][0] = 0;
|
||||
break;
|
||||
case MAP_VOTE:
|
||||
break;
|
||||
case PLAYER_INFO:
|
||||
m_Data.m_Info.m_Score = -9999;
|
||||
m_Data.m_Info.m_Birthday = 0;
|
||||
m_Data.m_Info.m_HasFinishScore = false;
|
||||
m_Data.m_Info.m_Time = 0;
|
||||
for(int i = 0; i < NUM_CHECKPOINTS; i++)
|
||||
m_Data.m_Info.m_CpTime[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CSqlResult::CSqlResult() :
|
||||
|
@ -205,72 +225,16 @@ bool CSqlScore::Init(CSqlServer* pSqlServer, const CSqlData<CSqlResult> *pGameDa
|
|||
return false;
|
||||
}
|
||||
|
||||
void CSqlScore::CheckBirthday(int ClientID)
|
||||
void CSqlScore::LoadPlayerData(int ClientID)
|
||||
{
|
||||
/*
|
||||
CSqlPlayerRequest *Tmp = new CSqlPlayerRequest();
|
||||
Tmp->m_ClientID = ClientID;
|
||||
Tmp->m_Name = Server()->ClientName(ClientID);
|
||||
thread_init_and_detach(ExecSqlFunc, new CSqlExecData(CheckBirthdayThread, Tmp), "birthday check");
|
||||
*/
|
||||
}
|
||||
|
||||
bool CSqlScore::CheckBirthdayThread(CSqlServer* pSqlServer, const CSqlData<CSqlResult> *pGameData, bool HandleFailure)
|
||||
{
|
||||
/* TODO
|
||||
const CSqlPlayerData *pData = dynamic_cast<const CSqlPlayerData *>(pGameData);
|
||||
|
||||
if (HandleFailure)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
char aBuf[512];
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "select year(Current) - year(Stamp) as YearsAgo from (select CURRENT_TIMESTAMP as Current, min(Timestamp) as Stamp from %s_race WHERE Name='%s') as l where dayofmonth(Current) = dayofmonth(Stamp) and month(Current) = month(Stamp) and year(Current) > year(Stamp);", pSqlServer->GetPrefix(), pData->m_Name.ClrStr());
|
||||
pSqlServer->executeSqlQuery(aBuf);
|
||||
|
||||
if(pSqlServer->GetResults()->next())
|
||||
{
|
||||
int yearsAgo = pSqlServer->GetResults()->getInt("YearsAgo");
|
||||
str_format(aBuf, sizeof(aBuf), "Happy DDNet birthday to %s for finishing their first map %d year%s ago!", pData->m_Name.Str(), yearsAgo, yearsAgo > 1 ? "s" : "");
|
||||
pData->GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, pData->m_ClientID);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "Happy DDNet birthday, %s!\nYou have finished your first map exactly %d year%s ago!", pData->m_Name.Str(), yearsAgo, yearsAgo > 1 ? "s" : "");
|
||||
|
||||
pData->GameServer()->SendBroadcast(aBuf, pData->m_ClientID);
|
||||
}
|
||||
|
||||
dbg_msg("sql", "checking birthday done");
|
||||
return true;
|
||||
}
|
||||
catch (sql::SQLException &e)
|
||||
{
|
||||
dbg_msg("sql", "MySQL ERROR: %s", e.what());
|
||||
dbg_msg("sql", "ERROR: could not check birthday");
|
||||
}
|
||||
return false;
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSqlScore::LoadScore(int ClientID)
|
||||
{
|
||||
/*
|
||||
CSqlPlayerData *Tmp = new CSqlPlayerData();
|
||||
Tmp->m_ClientID = ClientID;
|
||||
Tmp->m_Name = Server()->ClientName(ClientID);
|
||||
|
||||
thread_init_and_detach(ExecSqlFunc, new CSqlExecData(LoadScoreThread, Tmp), "load score");
|
||||
*/
|
||||
ExecPlayerThread(LoadPlayerDataThread, "load player data", ClientID, "", 0);
|
||||
}
|
||||
|
||||
// update stuff
|
||||
bool CSqlScore::LoadScoreThread(CSqlServer* pSqlServer, const CSqlData<CSqlResult> *pGameData, bool HandleFailure)
|
||||
bool CSqlScore::LoadPlayerDataThread(CSqlServer* pSqlServer, const CSqlData<CSqlPlayerResult> *pGameData, bool HandleFailure)
|
||||
{
|
||||
/*
|
||||
const CSqlPlayerData *pData = dynamic_cast<const CSqlPlayerData *>(pGameData);
|
||||
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
|
||||
pData->m_pResult->SetVariant(CSqlPlayerResult::PLAYER_INFO);
|
||||
|
||||
if (HandleFailure)
|
||||
return true;
|
||||
|
@ -278,20 +242,27 @@ bool CSqlScore::LoadScoreThread(CSqlServer* pSqlServer, const CSqlData<CSqlResul
|
|||
try
|
||||
{
|
||||
char aBuf[512];
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "SELECT * FROM %s_race WHERE Map='%s' AND Name='%s' ORDER BY time ASC LIMIT 1;", pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_Name.ClrStr());
|
||||
// get best race time
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"SELECT * "
|
||||
"FROM %s_race "
|
||||
"WHERE Map='%s' AND Name='%s' "
|
||||
"ORDER BY Time ASC "
|
||||
"LIMIT 1;",
|
||||
pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_RequestingPlayer.ClrStr());
|
||||
pSqlServer->executeSqlQuery(aBuf);
|
||||
if(pSqlServer->GetResults()->next())
|
||||
{
|
||||
// get the best time
|
||||
float Time = (float)pSqlServer->GetResults()->getDouble("Time");
|
||||
pData->PlayerData(pData->m_ClientID)->m_BestTime = Time;
|
||||
pData->PlayerData(pData->m_ClientID)->m_CurrentTime = Time;
|
||||
if(pData->GameServer()->m_apPlayers[pData->m_ClientID])
|
||||
{
|
||||
pData->GameServer()->m_apPlayers[pData->m_ClientID]->m_Score = -Time;
|
||||
pData->GameServer()->m_apPlayers[pData->m_ClientID]->m_HasFinishScore = true;
|
||||
}
|
||||
pData->m_pResult->m_Data.m_Info.m_Time = Time;
|
||||
pData->m_pResult->m_Data.m_Info.m_Score = -Time;
|
||||
pData->m_pResult->m_Data.m_Info.m_HasFinishScore = true;
|
||||
// -9999 stands for no time and isn't displayed in scoreboard, so
|
||||
// shift the time by a second if the player actually took 9999
|
||||
// seconds to finish the map.
|
||||
if(pData->m_pResult->m_Data.m_Info.m_Score == -9999)
|
||||
pData->m_pResult->m_Data.m_Info.m_Score = -10000;
|
||||
|
||||
char aColumn[8];
|
||||
if(g_Config.m_SvCheckpointSave)
|
||||
|
@ -299,12 +270,31 @@ bool CSqlScore::LoadScoreThread(CSqlServer* pSqlServer, const CSqlData<CSqlResul
|
|||
for(int i = 0; i < NUM_CHECKPOINTS; i++)
|
||||
{
|
||||
str_format(aColumn, sizeof(aColumn), "cp%d", i+1);
|
||||
pData->PlayerData(pData->m_ClientID)->m_aBestCpTime[i] = (float)pSqlServer->GetResults()->getDouble(aColumn);
|
||||
pData->m_pResult->m_Data.m_Info.m_CpTime[i] = (float)pSqlServer->GetResults()->getDouble(aColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbg_msg("sql", "Getting best time done");
|
||||
// birthday check
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"SELECT YEAR(Current) - YEAR(Stamp) AS YearsAgo "
|
||||
"FROM ("
|
||||
"SELECT CURRENT_TIMESTAMP AS Current, MIN(Timestamp) AS Stamp "
|
||||
"FROM %s_race "
|
||||
"WHERE Name='%s'"
|
||||
") AS l "
|
||||
"WHERE DAYOFMONTH(Current) = DAYOFMONTH(Stamp) AND MONTH(Current) = MONTH(Stamp) "
|
||||
"AND YEAR(Current) > YEAR(Stamp);",
|
||||
pSqlServer->GetPrefix(), pData->m_RequestingPlayer.ClrStr());
|
||||
pSqlServer->executeSqlQuery(aBuf);
|
||||
|
||||
if(pSqlServer->GetResults()->next())
|
||||
{
|
||||
int YearsAgo = pSqlServer->GetResults()->getInt("YearsAgo");
|
||||
pData->m_pResult->m_Data.m_Info.m_Birthday = YearsAgo;
|
||||
}
|
||||
pData->m_pResult->m_Done = true;
|
||||
dbg_msg("sql", "Finished loading player data");
|
||||
return true;
|
||||
}
|
||||
catch (sql::SQLException &e)
|
||||
|
@ -312,13 +302,6 @@ bool CSqlScore::LoadScoreThread(CSqlServer* pSqlServer, const CSqlData<CSqlResul
|
|||
dbg_msg("sql", "MySQL Error: %s", e.what());
|
||||
dbg_msg("sql", "ERROR: Could not update account");
|
||||
}
|
||||
catch (CGameContextError &e)
|
||||
{
|
||||
dbg_msg("sql", "WARNING: Aborted loading score due to reload/change of map.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,16 +12,28 @@ class CSqlServer;
|
|||
|
||||
class CSqlPlayerResult {
|
||||
public:
|
||||
CSqlPlayerResult();
|
||||
std::atomic_bool m_Done;
|
||||
CSqlPlayerResult();
|
||||
|
||||
enum
|
||||
enum Variant
|
||||
{
|
||||
DIRECT,
|
||||
ALL,
|
||||
MAP_VOTE, // 3 Messages: Reason, Server, Map
|
||||
PLAYER_INFO,
|
||||
} m_MessageKind;
|
||||
char m_aaMessages[7][512];
|
||||
union {
|
||||
struct {
|
||||
float m_Time;
|
||||
float m_CpTime[NUM_CHECKPOINTS];
|
||||
int m_Score;
|
||||
int m_HasFinishScore;
|
||||
int m_Birthday; // 0 indicates no birthday
|
||||
} m_Info;
|
||||
} m_Data; // PLAYER_INFO
|
||||
|
||||
void SetVariant(Variant v);
|
||||
};
|
||||
|
||||
class CSqlSaveResult {
|
||||
|
@ -98,12 +110,6 @@ struct CSqlData
|
|||
virtual ~CSqlData() = default;
|
||||
};
|
||||
|
||||
struct CSqlPlayerData : CSqlData<CSqlResult>
|
||||
{
|
||||
int m_ClientID;
|
||||
sqlstr::CSqlString<MAX_NAME_LENGTH> m_Name;
|
||||
};
|
||||
|
||||
// used for mapinfo
|
||||
struct CSqlMapData : CSqlData<CSqlPlayerResult>
|
||||
{
|
||||
|
@ -222,9 +228,8 @@ class CSqlScore: public IScore
|
|||
static bool RandomMapThread(CSqlServer* pSqlServer, const CSqlData<CSqlResult> *pGameData, bool HandleFailure = false);
|
||||
static bool RandomUnfinishedMapThread(CSqlServer* pSqlServer, const CSqlData<CSqlResult> *pGameData, bool HandleFailure = false);
|
||||
static bool MapVoteThread(CSqlServer* pSqlServer, const CSqlData<CSqlPlayerResult> *pGameData, bool HandleFailure = false);
|
||||
static bool CheckBirthdayThread(CSqlServer* pSqlServer, const CSqlData<CSqlResult> *pGameData, bool HandleFailure = false);
|
||||
static bool LoadScoreThread(CSqlServer* pSqlServer, const CSqlData<CSqlResult> *pGameData, bool HandleFailure = false);
|
||||
|
||||
static bool LoadPlayerDataThread(CSqlServer* pSqlServer, const CSqlData<CSqlPlayerResult> *pGameData, bool HandleFailure = false);
|
||||
static bool MapInfoThread(CSqlServer* pSqlServer, const CSqlData<CSqlPlayerResult> *pGameData, bool HandleFailure = false);
|
||||
static bool ShowRankThread(CSqlServer* pSqlServer, const CSqlData<CSqlPlayerResult> *pGameData, bool HandleFailure = false);
|
||||
static bool ShowTeamRankThread(CSqlServer* pSqlServer, const CSqlData<CSqlPlayerResult> *pGameData, bool HandleFailure = false);
|
||||
|
@ -272,9 +277,8 @@ public:
|
|||
virtual void RandomMap(int ClientID, int Stars);
|
||||
virtual void RandomUnfinishedMap(int ClientID, int Stars);
|
||||
virtual void MapVote(int ClientID, const char* MapName);
|
||||
virtual void CheckBirthday(int ClientID);
|
||||
virtual void LoadScore(int ClientID);
|
||||
|
||||
virtual void LoadPlayerData(int ClientID);
|
||||
// Requested by players (fails if another request by this player is active)
|
||||
virtual void MapInfo(int ClientID, const char* MapName);
|
||||
virtual void ShowRank(int ClientID, const char* pName);
|
||||
|
|
Loading…
Reference in a new issue