3390: Synchronize database thread via atomic_bool instead of use_count from shared pointer r=def- a=Zwelf

All database results are now derived from ISqlResult, to store the synchronization variable there. All accesses to results were changed in score.cpp (`s/pData->m_pResult/pResult/g`) causing a rather big diff. This was necessary, since the database worker has to access the result for each query to notify when a query is complete.

Fixes #3380
<!-- What is the motivation for the changes of this pull request -->

## Checklist

- [ ] Tested the change ingame (already some queries with sqlite, but not all yet)
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [x] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Zwelf <zwelf@strct.cc>
This commit is contained in:
bors[bot] 2020-12-08 17:12:53 +00:00 committed by GitHub
commit 1e599f6b68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 125 additions and 115 deletions

View file

@ -196,6 +196,11 @@ void CDbConnectionPool::Worker()
} }
if(!Success) if(!Success)
dbg_msg("sql", "%s failed on all databases", pThreadData->m_pName); dbg_msg("sql", "%s failed on all databases", pThreadData->m_pName);
if(pThreadData->m_pThreadData->m_pResult != nullptr)
{
pThreadData->m_pThreadData->m_pResult->m_Success = Success;
pThreadData->m_pThreadData->m_pResult->m_Completed.store(true);
}
} }
} }

View file

@ -8,9 +8,27 @@
class IDbConnection; class IDbConnection;
struct ISqlResult
{
// using atomic_bool to indicate completed sql query since usage_count
// from shard_ptr isn't safe in multithreaded environment
// the main thread must only access the remaining result data if set to true
std::atomic_bool m_Completed{false};
// indicate whether the thread indicated a successful completion (returned true)
bool m_Success = false;
virtual ~ISqlResult() = default;
};
struct ISqlData struct ISqlData
{ {
ISqlData(std::shared_ptr<ISqlResult> pResult) :
m_pResult(std::move(pResult))
{
}
virtual ~ISqlData(){}; virtual ~ISqlData(){};
mutable std::shared_ptr<ISqlResult> m_pResult;
}; };
class IConsole; class IConsole;

View file

@ -995,9 +995,9 @@ void CGameContext::OnTick()
} }
} }
if(m_SqlRandomMapResult != nullptr && m_SqlRandomMapResult.use_count() == 1) if(m_SqlRandomMapResult != nullptr && m_SqlRandomMapResult->m_Completed)
{ {
if(m_SqlRandomMapResult->m_Done) if(m_SqlRandomMapResult->m_Success)
{ {
if(PlayerExists(m_SqlRandomMapResult->m_ClientID) && m_SqlRandomMapResult->m_aMessage[0] != '\0') if(PlayerExists(m_SqlRandomMapResult->m_ClientID) && m_SqlRandomMapResult->m_aMessage[0] != '\0')
SendChatTarget(m_SqlRandomMapResult->m_ClientID, m_SqlRandomMapResult->m_aMessage); SendChatTarget(m_SqlRandomMapResult->m_ClientID, m_SqlRandomMapResult->m_aMessage);

View file

@ -27,9 +27,9 @@ void CGameControllerDDRace::Tick()
IGameController::Tick(); IGameController::Tick();
m_Teams.ProcessSaveTeam(); m_Teams.ProcessSaveTeam();
if(m_pInitResult != nullptr && m_pInitResult.use_count() == 1) if(m_pInitResult != nullptr && m_pInitResult->m_Completed)
{ {
if(m_pInitResult->m_Done) if(m_pInitResult->m_Success)
{ {
m_CurrentRecord = m_pInitResult->m_CurrentRecord; m_CurrentRecord = m_pInitResult->m_CurrentRecord;
} }

View file

@ -169,12 +169,12 @@ void CPlayer::Tick()
#ifdef CONF_DEBUG #ifdef CONF_DEBUG
if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS - g_Config.m_DbgDummies) if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS - g_Config.m_DbgDummies)
#endif #endif
if(m_ScoreQueryResult != nullptr && m_ScoreQueryResult.use_count() == 1) if(m_ScoreQueryResult != nullptr && m_ScoreQueryResult->m_Completed)
{ {
ProcessScoreResult(*m_ScoreQueryResult); ProcessScoreResult(*m_ScoreQueryResult);
m_ScoreQueryResult = nullptr; m_ScoreQueryResult = nullptr;
} }
if(m_ScoreFinishResult != nullptr && m_ScoreFinishResult.use_count() == 1) if(m_ScoreFinishResult != nullptr && m_ScoreFinishResult->m_Completed)
{ {
ProcessScoreResult(*m_ScoreFinishResult); ProcessScoreResult(*m_ScoreFinishResult);
m_ScoreFinishResult = nullptr; m_ScoreFinishResult = nullptr;
@ -932,7 +932,7 @@ void CPlayer::SpectatePlayerName(const char *pName)
void CPlayer::ProcessScoreResult(CScorePlayerResult &Result) void CPlayer::ProcessScoreResult(CScorePlayerResult &Result)
{ {
if(Result.m_Done) // SQL request was successful if(Result.m_Success) // SQL request was successful
{ {
switch(Result.m_MessageKind) switch(Result.m_MessageKind)
{ {

View file

@ -18,8 +18,7 @@
#include <fstream> #include <fstream>
#include <random> #include <random>
CScorePlayerResult::CScorePlayerResult() : CScorePlayerResult::CScorePlayerResult()
m_Done(false)
{ {
SetVariant(Variant::DIRECT); SetVariant(Variant::DIRECT);
} }
@ -187,6 +186,7 @@ CScore::CScore(CGameContext *pGameServer, CDbConnectionPool *pPool) :
bool CScore::Init(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::Init(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlInitData *pData = dynamic_cast<const CSqlInitData *>(pGameData); const CSqlInitData *pData = dynamic_cast<const CSqlInitData *>(pGameData);
CScoreInitResult *pResult = dynamic_cast<CScoreInitResult *>(pGameData->m_pResult.get());
char aBuf[512]; char aBuf[512];
// get the best time // get the best time
@ -197,9 +197,8 @@ bool CScore::Init(IDbConnection *pSqlServer, const ISqlData *pGameData)
pSqlServer->BindString(1, pData->m_Map); pSqlServer->BindString(1, pData->m_Map);
if(pSqlServer->Step()) if(pSqlServer->Step())
pData->m_pResult->m_CurrentRecord = pSqlServer->GetFloat(1); pResult->m_CurrentRecord = pSqlServer->GetFloat(1);
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -212,7 +211,8 @@ void CScore::LoadPlayerData(int ClientID)
bool CScore::LoadPlayerDataThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::LoadPlayerDataThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
pData->m_pResult->SetVariant(CScorePlayerResult::PLAYER_INFO); CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
pResult->SetVariant(CScorePlayerResult::PLAYER_INFO);
char aBuf[512]; char aBuf[512];
// get best race time // get best race time
@ -233,15 +233,15 @@ bool CScore::LoadPlayerDataThread(IDbConnection *pSqlServer, const ISqlData *pGa
{ {
// get the best time // get the best time
float Time = pSqlServer->GetFloat(1); float Time = pSqlServer->GetFloat(1);
pData->m_pResult->m_Data.m_Info.m_Time = Time; pResult->m_Data.m_Info.m_Time = Time;
pData->m_pResult->m_Data.m_Info.m_Score = -Time; pResult->m_Data.m_Info.m_Score = -Time;
pData->m_pResult->m_Data.m_Info.m_HasFinishScore = true; pResult->m_Data.m_Info.m_HasFinishScore = true;
if(g_Config.m_SvCheckpointSave) if(g_Config.m_SvCheckpointSave)
{ {
for(int i = 0; i < NUM_CHECKPOINTS; i++) for(int i = 0; i < NUM_CHECKPOINTS; i++)
{ {
pData->m_pResult->m_Data.m_Info.m_CpTime[i] = pSqlServer->GetFloat(i + 2); pResult->m_Data.m_Info.m_CpTime[i] = pSqlServer->GetFloat(i + 2);
} }
} }
} }
@ -264,9 +264,8 @@ bool CScore::LoadPlayerDataThread(IDbConnection *pSqlServer, const ISqlData *pGa
int CurrentYear, CurrentMonth, CurrentDay; int CurrentYear, CurrentMonth, CurrentDay;
int StampYear, StampMonth, StampDay; int StampYear, StampMonth, StampDay;
if(sscanf(aCurrent, "%d-%d-%d", &CurrentYear, &CurrentMonth, &CurrentDay) == 3 && sscanf(aStamp, "%d-%d-%d", &StampYear, &StampMonth, &StampDay) == 3 && CurrentMonth == StampMonth && CurrentDay == StampDay) if(sscanf(aCurrent, "%d-%d-%d", &CurrentYear, &CurrentMonth, &CurrentDay) == 3 && sscanf(aStamp, "%d-%d-%d", &StampYear, &StampMonth, &StampDay) == 3 && CurrentMonth == StampMonth && CurrentDay == StampDay)
pData->m_pResult->m_Data.m_Info.m_Birthday = CurrentYear - StampYear; pResult->m_Data.m_Info.m_Birthday = CurrentYear - StampYear;
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -280,7 +279,8 @@ void CScore::MapVote(int ClientID, const char *MapName)
bool CScore::MapVoteThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::MapVoteThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
auto *paMessages = pData->m_pResult->m_Data.m_aaMessages; CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
char aFuzzyMap[128]; char aFuzzyMap[128];
str_copy(aFuzzyMap, pData->m_Name, sizeof(aFuzzyMap)); str_copy(aFuzzyMap, pData->m_Name, sizeof(aFuzzyMap));
@ -308,8 +308,8 @@ bool CScore::MapVoteThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
if(pSqlServer->Step()) if(pSqlServer->Step())
{ {
pData->m_pResult->SetVariant(CScorePlayerResult::MAP_VOTE); pResult->SetVariant(CScorePlayerResult::MAP_VOTE);
auto *MapVote = &pData->m_pResult->m_Data.m_MapVote; auto *MapVote = &pResult->m_Data.m_MapVote;
pSqlServer->GetString(1, MapVote->m_Map, sizeof(MapVote->m_Map)); pSqlServer->GetString(1, MapVote->m_Map, sizeof(MapVote->m_Map));
pSqlServer->GetString(2, MapVote->m_Server, sizeof(MapVote->m_Server)); pSqlServer->GetString(2, MapVote->m_Server, sizeof(MapVote->m_Server));
str_copy(MapVote->m_Reason, "/map", sizeof(MapVote->m_Reason)); str_copy(MapVote->m_Reason, "/map", sizeof(MapVote->m_Reason));
@ -319,14 +319,13 @@ bool CScore::MapVoteThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
} }
else else
{ {
pData->m_pResult->SetVariant(CScorePlayerResult::DIRECT); pResult->SetVariant(CScorePlayerResult::DIRECT);
str_format(paMessages[0], sizeof(paMessages[0]), str_format(paMessages[0], sizeof(paMessages[0]),
"No map like \"%s\" found. " "No map like \"%s\" found. "
"Try adding a '%%' at the start if you don't know the first character. " "Try adding a '%%' at the start if you don't know the first character. "
"Example: /map %%castle for \"Out of Castle\"", "Example: /map %%castle for \"Out of Castle\"",
pData->m_Name); pData->m_Name);
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -340,6 +339,7 @@ void CScore::MapInfo(int ClientID, const char *MapName)
bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
char aFuzzyMap[128]; char aFuzzyMap[128];
str_copy(aFuzzyMap, pData->m_Name, sizeof(aFuzzyMap)); str_copy(aFuzzyMap, pData->m_Name, sizeof(aFuzzyMap));
@ -435,7 +435,7 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
", your time: %s", aBuf); ", your time: %s", aBuf);
} }
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"\"%s\" by %s on %s, %s, %d %s%s, %d %s by %d %s%s%s", "\"%s\" by %s on %s, %s, %d %s%s, %d %s by %d %s%s%s",
aMap, aMapper, aServer, aStars, aMap, aMapper, aServer, aStars,
Points, Points == 1 ? "point" : "points", Points, Points == 1 ? "point" : "points",
@ -446,10 +446,9 @@ bool CScore::MapInfoThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
} }
else else
{ {
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"No map like \"%s\" found.", pData->m_Name); "No map like \"%s\" found.", pData->m_Name);
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -479,7 +478,8 @@ void CScore::SaveScore(int ClientID, float Time, const char *pTimestamp, float C
bool CScore::SaveScoreThread(IDbConnection *pSqlServer, const ISqlData *pGameData, bool Failure) bool CScore::SaveScoreThread(IDbConnection *pSqlServer, const ISqlData *pGameData, bool Failure)
{ {
const CSqlScoreData *pData = dynamic_cast<const CSqlScoreData *>(pGameData); const CSqlScoreData *pData = dynamic_cast<const CSqlScoreData *>(pGameData);
auto *paMessages = pData->m_pResult->m_Data.m_aaMessages; CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
char aBuf[1024]; char aBuf[1024];
@ -539,8 +539,6 @@ bool CScore::SaveScoreThread(IDbConnection *pSqlServer, const ISqlData *pGameDat
pSqlServer->BindString(5, pData->m_GameUuid); pSqlServer->BindString(5, pData->m_GameUuid);
pSqlServer->Print(); pSqlServer->Print();
pSqlServer->Step(); pSqlServer->Step();
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -658,6 +656,7 @@ void CScore::ShowRank(int ClientID, const char *pName)
bool CScore::ShowRankThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::ShowRankThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
// check sort method // check sort method
char aBuf[600]; char aBuf[600];
@ -684,26 +683,24 @@ bool CScore::ShowRankThread(IDbConnection *pSqlServer, const ISqlData *pGameData
str_time_float(Time, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)); str_time_float(Time, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf));
if(g_Config.m_SvHideScore) if(g_Config.m_SvHideScore)
{ {
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"Your time: %s", aBuf); "Your time: %s", aBuf);
} }
else else
{ {
char aName[MAX_NAME_LENGTH]; char aName[MAX_NAME_LENGTH];
pSqlServer->GetString(2, aName, sizeof(aName)); pSqlServer->GetString(2, aName, sizeof(aName));
pData->m_pResult->m_MessageKind = CScorePlayerResult::ALL; pResult->m_MessageKind = CScorePlayerResult::ALL;
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"%d. %s Time: %s, requested by %s", "%d. %s Time: %s, requested by %s",
Rank, aName, aBuf, pData->m_RequestingPlayer); Rank, aName, aBuf, pData->m_RequestingPlayer);
} }
} }
else else
{ {
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"%s is not ranked", pData->m_Name); "%s is not ranked", pData->m_Name);
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -717,6 +714,7 @@ void CScore::ShowTeamRank(int ClientID, const char *pName)
bool CScore::ShowTeamRankThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::ShowTeamRankThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
// check sort method // check sort method
char aBuf[2400]; char aBuf[2400];
@ -764,23 +762,22 @@ bool CScore::ShowTeamRankThread(IDbConnection *pSqlServer, const ISqlData *pGame
if(g_Config.m_SvHideScore) if(g_Config.m_SvHideScore)
{ {
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"Your team time: %s", aBuf); "Your team time: %s", aBuf);
} }
else else
{ {
pData->m_pResult->m_MessageKind = CScorePlayerResult::ALL; pResult->m_MessageKind = CScorePlayerResult::ALL;
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"%d. %s Team time: %s, requested by %s", "%d. %s Team time: %s, requested by %s",
Rank, aFormattedNames, aBuf, pData->m_RequestingPlayer); Rank, aFormattedNames, aBuf, pData->m_RequestingPlayer);
} }
} }
else else
{ {
str_format(pData->m_pResult->m_Data.m_aaMessages[0], sizeof(pData->m_pResult->m_Data.m_aaMessages[0]), str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
"%s has no team ranks", pData->m_Name); "%s has no team ranks", pData->m_Name);
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -794,6 +791,7 @@ void CScore::ShowTop5(int ClientID, int Offset)
bool CScore::ShowTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::ShowTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
int LimitStart = maximum(abs(pData->m_Offset) - 1, 0); int LimitStart = maximum(abs(pData->m_Offset) - 1, 0);
const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC"; const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC";
@ -818,7 +816,7 @@ bool CScore::ShowTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData
pSqlServer->BindString(1, pData->m_Map); pSqlServer->BindString(1, pData->m_Map);
// show top5 // show top5
str_copy(pData->m_pResult->m_Data.m_aaMessages[0], "----------- Top 5 -----------", sizeof(pData->m_pResult->m_Data.m_aaMessages[0])); str_copy(pResult->m_Data.m_aaMessages[0], "----------- Top 5 -----------", sizeof(pResult->m_Data.m_aaMessages[0]));
int Line = 1; int Line = 1;
while(pSqlServer->Step()) while(pSqlServer->Step())
@ -828,13 +826,12 @@ bool CScore::ShowTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData
float Time = pSqlServer->GetFloat(2); float Time = pSqlServer->GetFloat(2);
str_time_float(Time, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)); str_time_float(Time, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf));
int Rank = pSqlServer->GetInt(3); int Rank = pSqlServer->GetInt(3);
str_format(pData->m_pResult->m_Data.m_aaMessages[Line], sizeof(pData->m_pResult->m_Data.m_aaMessages[Line]), str_format(pResult->m_Data.m_aaMessages[Line], sizeof(pResult->m_Data.m_aaMessages[Line]),
"%d. %s Time: %s", Rank, aName, aBuf); "%d. %s Time: %s", Rank, aName, aBuf);
Line++; Line++;
} }
str_copy(pData->m_pResult->m_Data.m_aaMessages[Line], "-------------------------------", sizeof(pData->m_pResult->m_Data.m_aaMessages[Line])); str_copy(pResult->m_Data.m_aaMessages[Line], "-------------------------------", sizeof(pResult->m_Data.m_aaMessages[Line]));
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -848,7 +845,8 @@ void CScore::ShowTeamTop5(int ClientID, int Offset)
bool CScore::ShowTeamTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::ShowTeamTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
auto *paMessages = pData->m_pResult->m_Data.m_aaMessages; CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
int LimitStart = maximum(abs(pData->m_Offset) - 1, 0); int LimitStart = maximum(abs(pData->m_Offset) - 1, 0);
const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC"; const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC";
@ -917,7 +915,6 @@ bool CScore::ShowTeamTop5Thread(IDbConnection *pSqlServer, const ISqlData *pGame
} }
str_copy(paMessages[Line], "-------------------------------", sizeof(paMessages[Line])); str_copy(paMessages[Line], "-------------------------------", sizeof(paMessages[Line]));
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -938,7 +935,8 @@ void CScore::ShowTimes(int ClientID, const char *pName, int Offset)
bool CScore::ShowTimesThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::ShowTimesThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
auto *paMessages = pData->m_pResult->m_Data.m_aaMessages; CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
int LimitStart = maximum(abs(pData->m_Offset) - 1, 0); int LimitStart = maximum(abs(pData->m_Offset) - 1, 0);
const char *pOrder = pData->m_Offset >= 0 ? "DESC" : "ASC"; const char *pOrder = pData->m_Offset >= 0 ? "DESC" : "ASC";
@ -982,7 +980,6 @@ bool CScore::ShowTimesThread(IDbConnection *pSqlServer, const ISqlData *pGameDat
if(!pSqlServer->Step()) if(!pSqlServer->Step())
{ {
str_copy(paMessages[0], "There are no times in the specified range", sizeof(paMessages[0])); str_copy(paMessages[0], "There are no times in the specified range", sizeof(paMessages[0]));
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -1027,7 +1024,6 @@ bool CScore::ShowTimesThread(IDbConnection *pSqlServer, const ISqlData *pGameDat
} while(pSqlServer->Step()); } while(pSqlServer->Step());
str_copy(paMessages[Line], "----------------------------------------------------", sizeof(paMessages[Line])); str_copy(paMessages[Line], "----------------------------------------------------", sizeof(paMessages[Line]));
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -1041,7 +1037,8 @@ void CScore::ShowPoints(int ClientID, const char *pName)
bool CScore::ShowPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::ShowPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
auto *paMessages = pData->m_pResult->m_Data.m_aaMessages; CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
char aBuf[512]; char aBuf[512];
str_format(aBuf, sizeof(aBuf), str_format(aBuf, sizeof(aBuf),
@ -1061,7 +1058,7 @@ bool CScore::ShowPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameDa
int Count = pSqlServer->GetInt(2); int Count = pSqlServer->GetInt(2);
char aName[MAX_NAME_LENGTH]; char aName[MAX_NAME_LENGTH];
pSqlServer->GetString(3, aName, sizeof(aName)); pSqlServer->GetString(3, aName, sizeof(aName));
pData->m_pResult->m_MessageKind = CScorePlayerResult::ALL; pResult->m_MessageKind = CScorePlayerResult::ALL;
str_format(paMessages[0], sizeof(paMessages[0]), str_format(paMessages[0], sizeof(paMessages[0]),
"%d. %s Points: %d, requested by %s", "%d. %s Points: %d, requested by %s",
Rank, aName, Count, pData->m_RequestingPlayer); Rank, aName, Count, pData->m_RequestingPlayer);
@ -1071,8 +1068,6 @@ bool CScore::ShowPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameDa
str_format(paMessages[0], sizeof(paMessages[0]), str_format(paMessages[0], sizeof(paMessages[0]),
"%s has not collected any points so far", pData->m_Name); "%s has not collected any points so far", pData->m_Name);
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -1086,7 +1081,8 @@ void CScore::ShowTopPoints(int ClientID, int Offset)
bool CScore::ShowTopPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::ShowTopPointsThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
auto *paMessages = pData->m_pResult->m_Data.m_aaMessages; CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
int LimitStart = maximum(abs(pData->m_Offset) - 1, 0); int LimitStart = maximum(abs(pData->m_Offset) - 1, 0);
const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC"; const char *pOrder = pData->m_Offset >= 0 ? "ASC" : "DESC";
@ -1121,7 +1117,6 @@ bool CScore::ShowTopPointsThread(IDbConnection *pSqlServer, const ISqlData *pGam
} }
str_copy(paMessages[Line], "-------------------------------", sizeof(paMessages[Line])); str_copy(paMessages[Line], "-------------------------------", sizeof(paMessages[Line]));
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -1142,6 +1137,7 @@ void CScore::RandomMap(int ClientID, int Stars)
bool CScore::RandomMapThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::RandomMapThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlRandomMapRequest *pData = dynamic_cast<const CSqlRandomMapRequest *>(pGameData); const CSqlRandomMapRequest *pData = dynamic_cast<const CSqlRandomMapRequest *>(pGameData);
CScoreRandomMapResult *pResult = dynamic_cast<CScoreRandomMapResult *>(pGameData->m_pResult.get());
char aBuf[512]; char aBuf[512];
if(0 <= pData->m_Stars && pData->m_Stars <= 5) if(0 <= pData->m_Stars && pData->m_Stars <= 5)
@ -1168,14 +1164,12 @@ bool CScore::RandomMapThread(IDbConnection *pSqlServer, const ISqlData *pGameDat
if(pSqlServer->Step()) if(pSqlServer->Step())
{ {
pSqlServer->GetString(1, pData->m_pResult->m_Map, sizeof(pData->m_pResult->m_Map)); pSqlServer->GetString(1, pResult->m_Map, sizeof(pResult->m_Map));
} }
else else
{ {
str_copy(pData->m_pResult->m_aMessage, "No maps found on this server!", sizeof(pData->m_pResult->m_aMessage)); str_copy(pResult->m_aMessage, "No maps found on this server!", sizeof(pResult->m_aMessage));
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -1196,6 +1190,7 @@ void CScore::RandomUnfinishedMap(int ClientID, int Stars)
bool CScore::RandomUnfinishedMapThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::RandomUnfinishedMapThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlRandomMapRequest *pData = dynamic_cast<const CSqlRandomMapRequest *>(pGameData); const CSqlRandomMapRequest *pData = dynamic_cast<const CSqlRandomMapRequest *>(pGameData);
CScoreRandomMapResult *pResult = dynamic_cast<CScoreRandomMapResult *>(pGameData->m_pResult.get());
char aBuf[512]; char aBuf[512];
if(pData->m_Stars >= 0) if(pData->m_Stars >= 0)
@ -1236,14 +1231,12 @@ bool CScore::RandomUnfinishedMapThread(IDbConnection *pSqlServer, const ISqlData
if(pSqlServer->Step()) if(pSqlServer->Step())
{ {
pSqlServer->GetString(1, pData->m_pResult->m_Map, sizeof(pData->m_pResult->m_Map)); pSqlServer->GetString(1, pResult->m_Map, sizeof(pResult->m_Map));
} }
else else
{ {
str_copy(pData->m_pResult->m_aMessage, "You have no more unfinished maps on this server!", sizeof(pData->m_pResult->m_aMessage)); str_copy(pResult->m_aMessage, "You have no more unfinished maps on this server!", sizeof(pResult->m_aMessage));
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }
@ -1257,6 +1250,7 @@ void CScore::SaveTeam(int ClientID, const char *Code, const char *Server)
return; return;
auto SaveResult = std::make_shared<CScoreSaveResult>(ClientID, pController); auto SaveResult = std::make_shared<CScoreSaveResult>(ClientID, pController);
SaveResult->m_SaveID = RandomUuid();
int Result = SaveResult->m_SavedTeam.save(Team); int Result = SaveResult->m_SavedTeam.save(Team);
if(CSaveTeam::HandleSaveError(Result, ClientID, GameServer())) if(CSaveTeam::HandleSaveError(Result, ClientID, GameServer()))
return; return;
@ -1265,7 +1259,6 @@ void CScore::SaveTeam(int ClientID, const char *Code, const char *Server)
auto Tmp = std::unique_ptr<CSqlTeamSave>(new CSqlTeamSave(SaveResult)); auto Tmp = std::unique_ptr<CSqlTeamSave>(new CSqlTeamSave(SaveResult));
str_copy(Tmp->m_Code, Code, sizeof(Tmp->m_Code)); str_copy(Tmp->m_Code, Code, sizeof(Tmp->m_Code));
str_copy(Tmp->m_Map, g_Config.m_SvMap, sizeof(Tmp->m_Map)); str_copy(Tmp->m_Map, g_Config.m_SvMap, sizeof(Tmp->m_Map));
Tmp->m_pResult->m_SaveID = RandomUuid();
str_copy(Tmp->m_Server, Server, sizeof(Tmp->m_Server)); str_copy(Tmp->m_Server, Server, sizeof(Tmp->m_Server));
str_copy(Tmp->m_ClientName, this->Server()->ClientName(ClientID), sizeof(Tmp->m_ClientName)); str_copy(Tmp->m_ClientName, this->Server()->ClientName(ClientID), sizeof(Tmp->m_ClientName));
Tmp->m_aGeneratedCode[0] = '\0'; Tmp->m_aGeneratedCode[0] = '\0';
@ -1278,11 +1271,12 @@ void CScore::SaveTeam(int ClientID, const char *Code, const char *Server)
bool CScore::SaveTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData, bool Failure) bool CScore::SaveTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData, bool Failure)
{ {
const CSqlTeamSave *pData = dynamic_cast<const CSqlTeamSave *>(pGameData); const CSqlTeamSave *pData = dynamic_cast<const CSqlTeamSave *>(pGameData);
CScoreSaveResult *pResult = dynamic_cast<CScoreSaveResult *>(pGameData->m_pResult.get());
char aSaveID[UUID_MAXSTRSIZE]; char aSaveID[UUID_MAXSTRSIZE];
FormatUuid(pData->m_pResult->m_SaveID, aSaveID, UUID_MAXSTRSIZE); FormatUuid(pResult->m_SaveID, aSaveID, UUID_MAXSTRSIZE);
char *pSaveState = pData->m_pResult->m_SavedTeam.GetString(); char *pSaveState = pResult->m_SavedTeam.GetString();
char aBuf[65536]; char aBuf[65536];
char aTable[512]; char aTable[512];
@ -1335,43 +1329,43 @@ bool CScore::SaveTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData
{ {
if(str_comp(pData->m_Server, g_Config.m_SvSqlServerName) == 0) if(str_comp(pData->m_Server, g_Config.m_SvSqlServerName) == 0)
{ {
str_format(pData->m_pResult->m_aMessage, sizeof(pData->m_pResult->m_aMessage), str_format(pResult->m_aMessage, sizeof(pResult->m_aMessage),
"Team successfully saved by %s. Use '/load %s' to continue", "Team successfully saved by %s. Use '/load %s' to continue",
pData->m_ClientName, Code); pData->m_ClientName, Code);
} }
else else
{ {
str_format(pData->m_pResult->m_aMessage, sizeof(pData->m_pResult->m_aMessage), str_format(pResult->m_aMessage, sizeof(pResult->m_aMessage),
"Team successfully saved by %s. Use '/load %s' on %s to continue", "Team successfully saved by %s. Use '/load %s' on %s to continue",
pData->m_ClientName, Code, pData->m_Server); pData->m_ClientName, Code, pData->m_Server);
} }
} }
else else
{ {
str_copy(pData->m_pResult->m_aBroadcast, str_copy(pResult->m_aBroadcast,
"Database connection failed, teamsave written to a file instead. Admins will add it manually in a few days.", "Database connection failed, teamsave written to a file instead. Admins will add it manually in a few days.",
sizeof(pData->m_pResult->m_aBroadcast)); sizeof(pResult->m_aBroadcast));
if(str_comp(pData->m_Server, g_Config.m_SvSqlServerName) == 0) if(str_comp(pData->m_Server, g_Config.m_SvSqlServerName) == 0)
{ {
str_format(pData->m_pResult->m_aMessage, sizeof(pData->m_pResult->m_aMessage), str_format(pResult->m_aMessage, sizeof(pResult->m_aMessage),
"Team successfully saved by %s. The database connection failed, using generated save code instead to avoid collisions. Use '/load %s' to continue", "Team successfully saved by %s. The database connection failed, using generated save code instead to avoid collisions. Use '/load %s' to continue",
pData->m_ClientName, Code); pData->m_ClientName, Code);
} }
else else
{ {
str_format(pData->m_pResult->m_aMessage, sizeof(pData->m_pResult->m_aMessage), str_format(pResult->m_aMessage, sizeof(pResult->m_aMessage),
"Team successfully saved by %s. The database connection failed, using generated save code instead to avoid collisions. Use '/load %s' on %s to continue", "Team successfully saved by %s. The database connection failed, using generated save code instead to avoid collisions. Use '/load %s' on %s to continue",
pData->m_ClientName, Code, pData->m_Server); pData->m_ClientName, Code, pData->m_Server);
} }
} }
pData->m_pResult->m_Status = CScoreSaveResult::SAVE_SUCCESS; pResult->m_Status = CScoreSaveResult::SAVE_SUCCESS;
} }
else else
{ {
dbg_msg("sql", "ERROR: This save-code already exists"); dbg_msg("sql", "ERROR: This save-code already exists");
pData->m_pResult->m_Status = CScoreSaveResult::SAVE_FAILED; pResult->m_Status = CScoreSaveResult::SAVE_FAILED;
str_copy(pData->m_pResult->m_aMessage, "This save-code already exists", sizeof(pData->m_pResult->m_aMessage)); str_copy(pResult->m_aMessage, "This save-code already exists", sizeof(pResult->m_aMessage));
} }
pSqlServer->Unlock(); pSqlServer->Unlock();
@ -1421,7 +1415,8 @@ void CScore::LoadTeam(const char *Code, int ClientID)
bool CScore::LoadTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData, bool Failure) bool CScore::LoadTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData, bool Failure)
{ {
const CSqlTeamLoad *pData = dynamic_cast<const CSqlTeamLoad *>(pGameData); const CSqlTeamLoad *pData = dynamic_cast<const CSqlTeamLoad *>(pGameData);
pData->m_pResult->m_Status = CScoreSaveResult::LOAD_FAILED; CScoreSaveResult *pResult = dynamic_cast<CScoreSaveResult *>(pGameData->m_pResult.get());
pResult->m_Status = CScoreSaveResult::LOAD_FAILED;
char aTable[512]; char aTable[512];
str_format(aTable, sizeof(aTable), "%s_saves WRITE", pSqlServer->GetPrefix()); str_format(aTable, sizeof(aTable), "%s_saves WRITE", pSqlServer->GetPrefix());
@ -1454,45 +1449,45 @@ bool CScore::LoadTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData
if(!pSqlServer->Step()) if(!pSqlServer->Step())
{ {
str_copy(pData->m_pResult->m_aMessage, "No such savegame for this map", sizeof(pData->m_pResult->m_aMessage)); str_copy(pResult->m_aMessage, "No such savegame for this map", sizeof(pResult->m_aMessage));
goto end; goto end;
} }
int Since = pSqlServer->GetInt(2); int Since = pSqlServer->GetInt(2);
if(Since < g_Config.m_SvSaveGamesDelay) if(Since < g_Config.m_SvSaveGamesDelay)
{ {
str_format(pData->m_pResult->m_aMessage, sizeof(pData->m_pResult->m_aMessage), str_format(pResult->m_aMessage, sizeof(pResult->m_aMessage),
"You have to wait %d seconds until you can load this savegame", "You have to wait %d seconds until you can load this savegame",
g_Config.m_SvSaveGamesDelay - Since); g_Config.m_SvSaveGamesDelay - Since);
goto end; goto end;
} }
char aSaveID[UUID_MAXSTRSIZE]; char aSaveID[UUID_MAXSTRSIZE];
memset(pData->m_pResult->m_SaveID.m_aData, 0, sizeof(pData->m_pResult->m_SaveID.m_aData)); memset(pResult->m_SaveID.m_aData, 0, sizeof(pResult->m_SaveID.m_aData));
if(!pSqlServer->IsNull(3)) if(!pSqlServer->IsNull(3))
{ {
pSqlServer->GetString(3, aSaveID, sizeof(aSaveID)); pSqlServer->GetString(3, aSaveID, sizeof(aSaveID));
if(str_length(aSaveID) + 1 != UUID_MAXSTRSIZE) if(str_length(aSaveID) + 1 != UUID_MAXSTRSIZE)
{ {
str_copy(pData->m_pResult->m_aMessage, "Unable to load savegame: SaveID corrupted", sizeof(pData->m_pResult->m_aMessage)); str_copy(pResult->m_aMessage, "Unable to load savegame: SaveID corrupted", sizeof(pResult->m_aMessage));
goto end; goto end;
} }
ParseUuid(&pData->m_pResult->m_SaveID, aSaveID); ParseUuid(&pResult->m_SaveID, aSaveID);
} }
char aSaveString[65536]; char aSaveString[65536];
pSqlServer->GetString(1, aSaveString, sizeof(aSaveString)); pSqlServer->GetString(1, aSaveString, sizeof(aSaveString));
int Num = pData->m_pResult->m_SavedTeam.FromString(aSaveString); int Num = pResult->m_SavedTeam.FromString(aSaveString);
if(Num != 0) if(Num != 0)
{ {
str_copy(pData->m_pResult->m_aMessage, "Unable to load savegame: data corrupted", sizeof(pData->m_pResult->m_aMessage)); str_copy(pResult->m_aMessage, "Unable to load savegame: data corrupted", sizeof(pResult->m_aMessage));
goto end; goto end;
} }
bool CanLoad = pData->m_pResult->m_SavedTeam.MatchPlayers( bool CanLoad = pResult->m_SavedTeam.MatchPlayers(
pData->m_aClientNames, pData->m_aClientID, pData->m_NumPlayer, pData->m_aClientNames, pData->m_aClientID, pData->m_NumPlayer,
pData->m_pResult->m_aMessage, sizeof(pData->m_pResult->m_aMessage)); pResult->m_aMessage, sizeof(pResult->m_aMessage));
if(!CanLoad) if(!CanLoad)
goto end; goto end;
@ -1507,8 +1502,8 @@ bool CScore::LoadTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData
pSqlServer->Print(); pSqlServer->Print();
pSqlServer->Step(); pSqlServer->Step();
pData->m_pResult->m_Status = CScoreSaveResult::LOAD_SUCCESS; pResult->m_Status = CScoreSaveResult::LOAD_SUCCESS;
str_copy(pData->m_pResult->m_aMessage, "Loading successfully done", sizeof(pData->m_pResult->m_aMessage)); str_copy(pResult->m_aMessage, "Loading successfully done", sizeof(pResult->m_aMessage));
} }
end: end:
pSqlServer->Unlock(); pSqlServer->Unlock();
@ -1525,7 +1520,8 @@ void CScore::GetSaves(int ClientID)
bool CScore::GetSavesThread(IDbConnection *pSqlServer, const ISqlData *pGameData) bool CScore::GetSavesThread(IDbConnection *pSqlServer, const ISqlData *pGameData)
{ {
const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData); const CSqlPlayerRequest *pData = dynamic_cast<const CSqlPlayerRequest *>(pGameData);
auto *paMessages = pData->m_pResult->m_Data.m_aaMessages; CScorePlayerResult *pResult = dynamic_cast<CScorePlayerResult *>(pGameData->m_pResult.get());
auto *paMessages = pResult->m_Data.m_aaMessages;
char aSaveLike[128] = ""; char aSaveLike[128] = "";
str_append(aSaveLike, "%\n", sizeof(aSaveLike)); str_append(aSaveLike, "%\n", sizeof(aSaveLike));
@ -1568,7 +1564,5 @@ bool CScore::GetSavesThread(IDbConnection *pSqlServer, const ISqlData *pGameData
NumSaves, NumSaves == 1 ? "" : "s", NumSaves, NumSaves == 1 ? "" : "s",
pData->m_Map, aLastSavedString); pData->m_Map, aLastSavedString);
} }
pData->m_pResult->m_Done = true;
return true; return true;
} }

View file

@ -25,9 +25,8 @@ enum
TIMESTAMP_STR_LENGTH = 20, // 2019-04-02 19:38:36 TIMESTAMP_STR_LENGTH = 20, // 2019-04-02 19:38:36
}; };
struct CScorePlayerResult struct CScorePlayerResult : ISqlResult
{ {
std::atomic_bool m_Done;
CScorePlayerResult(); CScorePlayerResult();
enum enum
@ -66,11 +65,9 @@ struct CScorePlayerResult
void SetVariant(Variant v); void SetVariant(Variant v);
}; };
struct CScoreRandomMapResult struct CScoreRandomMapResult : ISqlResult
{ {
std::atomic_bool m_Done;
CScoreRandomMapResult(int ClientID) : CScoreRandomMapResult(int ClientID) :
m_Done(false),
m_ClientID(ClientID) m_ClientID(ClientID)
{ {
m_Map[0] = '\0'; m_Map[0] = '\0';
@ -81,7 +78,7 @@ struct CScoreRandomMapResult
char m_aMessage[512]; char m_aMessage[512];
}; };
struct CScoreSaveResult struct CScoreSaveResult : ISqlResult
{ {
CScoreSaveResult(int PlayerID, IGameController *Controller) : CScoreSaveResult(int PlayerID, IGameController *Controller) :
m_Status(SAVE_FAILED), m_Status(SAVE_FAILED),
@ -106,14 +103,12 @@ struct CScoreSaveResult
CUuid m_SaveID; CUuid m_SaveID;
}; };
struct CScoreInitResult struct CScoreInitResult : ISqlResult
{ {
CScoreInitResult() : CScoreInitResult() :
m_Done(false),
m_CurrentRecord(0) m_CurrentRecord(0)
{ {
} }
std::atomic_bool m_Done;
float m_CurrentRecord; float m_CurrentRecord;
}; };
@ -150,10 +145,9 @@ public:
struct CSqlInitData : ISqlData struct CSqlInitData : ISqlData
{ {
CSqlInitData(std::shared_ptr<CScoreInitResult> pResult) : CSqlInitData(std::shared_ptr<CScoreInitResult> pResult) :
m_pResult(std::move(pResult)) ISqlData(std::move(pResult))
{ {
} }
std::shared_ptr<CScoreInitResult> m_pResult;
// current map // current map
char m_Map[MAX_MAP_LENGTH]; char m_Map[MAX_MAP_LENGTH];
@ -162,10 +156,10 @@ struct CSqlInitData : ISqlData
struct CSqlPlayerRequest : ISqlData struct CSqlPlayerRequest : ISqlData
{ {
CSqlPlayerRequest(std::shared_ptr<CScorePlayerResult> pResult) : CSqlPlayerRequest(std::shared_ptr<CScorePlayerResult> pResult) :
m_pResult(std::move(pResult)) ISqlData(std::move(pResult))
{ {
} }
std::shared_ptr<CScorePlayerResult> m_pResult;
// object being requested, either map (128 bytes) or player (16 bytes) // object being requested, either map (128 bytes) or player (16 bytes)
char m_Name[MAX_MAP_LENGTH]; char m_Name[MAX_MAP_LENGTH];
// current map // current map
@ -178,10 +172,9 @@ struct CSqlPlayerRequest : ISqlData
struct CSqlRandomMapRequest : ISqlData struct CSqlRandomMapRequest : ISqlData
{ {
CSqlRandomMapRequest(std::shared_ptr<CScoreRandomMapResult> pResult) : CSqlRandomMapRequest(std::shared_ptr<CScoreRandomMapResult> pResult) :
m_pResult(std::move(pResult)) ISqlData(std::move(pResult))
{ {
} }
std::shared_ptr<CScoreRandomMapResult> m_pResult;
char m_ServerType[32]; char m_ServerType[32];
char m_CurrentMap[MAX_MAP_LENGTH]; char m_CurrentMap[MAX_MAP_LENGTH];
@ -192,12 +185,11 @@ struct CSqlRandomMapRequest : ISqlData
struct CSqlScoreData : ISqlData struct CSqlScoreData : ISqlData
{ {
CSqlScoreData(std::shared_ptr<CScorePlayerResult> pResult) : CSqlScoreData(std::shared_ptr<CScorePlayerResult> pResult) :
m_pResult(std::move(pResult)) ISqlData(std::move(pResult))
{ {
} }
virtual ~CSqlScoreData(){};
std::shared_ptr<CScorePlayerResult> m_pResult; virtual ~CSqlScoreData(){};
char m_Map[MAX_MAP_LENGTH]; char m_Map[MAX_MAP_LENGTH];
char m_GameUuid[UUID_MAXSTRSIZE]; char m_GameUuid[UUID_MAXSTRSIZE];
@ -214,6 +206,11 @@ struct CSqlScoreData : ISqlData
struct CSqlTeamScoreData : ISqlData struct CSqlTeamScoreData : ISqlData
{ {
CSqlTeamScoreData() :
ISqlData(nullptr)
{
}
char m_GameUuid[UUID_MAXSTRSIZE]; char m_GameUuid[UUID_MAXSTRSIZE];
char m_Map[MAX_MAP_LENGTH]; char m_Map[MAX_MAP_LENGTH];
float m_Time; float m_Time;
@ -225,13 +222,11 @@ struct CSqlTeamScoreData : ISqlData
struct CSqlTeamSave : ISqlData struct CSqlTeamSave : ISqlData
{ {
CSqlTeamSave(std::shared_ptr<CScoreSaveResult> pResult) : CSqlTeamSave(std::shared_ptr<CScoreSaveResult> pResult) :
m_pResult(std::move(pResult)) ISqlData(std::move(pResult))
{ {
} }
virtual ~CSqlTeamSave(){}; virtual ~CSqlTeamSave(){};
std::shared_ptr<CScoreSaveResult> m_pResult;
char m_ClientName[MAX_NAME_LENGTH]; char m_ClientName[MAX_NAME_LENGTH];
char m_Map[MAX_MAP_LENGTH]; char m_Map[MAX_MAP_LENGTH];
char m_Code[128]; char m_Code[128];
@ -242,13 +237,11 @@ struct CSqlTeamSave : ISqlData
struct CSqlTeamLoad : ISqlData struct CSqlTeamLoad : ISqlData
{ {
CSqlTeamLoad(std::shared_ptr<CScoreSaveResult> pResult) : CSqlTeamLoad(std::shared_ptr<CScoreSaveResult> pResult) :
m_pResult(std::move(pResult)) ISqlData(std::move(pResult))
{ {
} }
virtual ~CSqlTeamLoad(){}; virtual ~CSqlTeamLoad(){};
std::shared_ptr<CScoreSaveResult> m_pResult;
char m_Code[128]; char m_Code[128];
char m_Map[MAX_MAP_LENGTH]; char m_Map[MAX_MAP_LENGTH];
char m_RequestingPlayer[MAX_NAME_LENGTH]; char m_RequestingPlayer[MAX_NAME_LENGTH];

View file

@ -681,7 +681,7 @@ void CGameTeams::ProcessSaveTeam()
{ {
for(int Team = 0; Team < MAX_CLIENTS; Team++) for(int Team = 0; Team < MAX_CLIENTS; Team++)
{ {
if(m_pSaveTeamResult[Team] == nullptr || m_pSaveTeamResult[Team].use_count() != 1) if(m_pSaveTeamResult[Team] == nullptr || !m_pSaveTeamResult[Team]->m_Completed)
continue; continue;
if(m_pSaveTeamResult[Team]->m_aBroadcast[0] != '\0') if(m_pSaveTeamResult[Team]->m_aBroadcast[0] != '\0')
GameServer()->SendBroadcast(m_pSaveTeamResult[Team]->m_aBroadcast, -1); GameServer()->SendBroadcast(m_pSaveTeamResult[Team]->m_aBroadcast, -1);