Merge pull request #1744 from heinrich5991/pr_ddnet_quotefixquote_randommap

Hack around the race condition in random maps selection
This commit is contained in:
Dennis Felsing 2019-05-21 22:51:51 +02:00 committed by GitHub
commit 0eded7e406
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 31 deletions

View file

@ -870,6 +870,12 @@ void CGameContext::OnTick()
} }
} }
if(m_pRandomMapResult && m_pRandomMapResult->m_Done)
{
str_copy(g_Config.m_SvMap, m_pRandomMapResult->m_aMap, sizeof(g_Config.m_SvMap));
m_pRandomMapResult = NULL;
}
#ifdef CONF_DEBUG #ifdef CONF_DEBUG
if(g_Config.m_DbgDummies) if(g_Config.m_DbgDummies)
{ {
@ -2151,11 +2157,11 @@ void CGameContext::ConRandomMap(IConsole::IResult *pResult, void *pUserData)
{ {
CGameContext *pSelf = (CGameContext *)pUserData; CGameContext *pSelf = (CGameContext *)pUserData;
int stars = 0; int Stars = 0;
if (pResult->NumArguments()) if(pResult->NumArguments())
stars = pResult->GetInteger(0); Stars = pResult->GetInteger(0);
pSelf->m_pScore->RandomMap(pSelf->m_VoteCreator, stars); pSelf->m_pScore->RandomMap(&pSelf->m_pRandomMapResult, pSelf->m_VoteCreator, Stars);
} }
void CGameContext::ConRandomUnfinishedMap(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConRandomUnfinishedMap(IConsole::IResult *pResult, void *pUserData)
@ -2166,7 +2172,7 @@ void CGameContext::ConRandomUnfinishedMap(IConsole::IResult *pResult, void *pUse
if (pResult->NumArguments()) if (pResult->NumArguments())
stars = pResult->GetInteger(0); stars = pResult->GetInteger(0);
pSelf->m_pScore->RandomUnfinishedMap(pSelf->m_VoteCreator, stars); pSelf->m_pScore->RandomUnfinishedMap(&pSelf->m_pRandomMapResult, pSelf->m_VoteCreator, stars);
} }
void CGameContext::ConRestart(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConRestart(IConsole::IResult *pResult, void *pUserData)

View file

@ -56,6 +56,7 @@ enum
class IConsole; class IConsole;
class IEngine; class IEngine;
class IStorage; class IStorage;
class CRandomMapResult;
class CGameContext : public IGameServer class CGameContext : public IGameServer
{ {
@ -75,6 +76,8 @@ class CGameContext : public IGameServer
CUuid m_GameUuid; CUuid m_GameUuid;
CMapBugs m_MapBugs; CMapBugs m_MapBugs;
std::shared_ptr<CRandomMapResult> m_pRandomMapResult;
static void CommandCallback(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult, void *pUser); static void CommandCallback(int ClientID, int FlagMask, const char *pCmd, IConsole::IResult *pResult, void *pUser);
static void TeeHistorianWrite(const void *pData, int DataSize, void *pUser); static void TeeHistorianWrite(const void *pData, int DataSize, void *pUser);

View file

@ -1,6 +1,8 @@
#ifndef GAME_SERVER_SCORE_H #ifndef GAME_SERVER_SCORE_H
#define GAME_SERVER_SCORE_H #define GAME_SERVER_SCORE_H
#include <memory>
#include "entities/character.h" #include "entities/character.h"
#include "gamecontext.h" #include "gamecontext.h"
@ -38,6 +40,17 @@ public:
float m_aBestCpTime[NUM_CHECKPOINTS]; float m_aBestCpTime[NUM_CHECKPOINTS];
}; };
// Watch this: TODO(2019-05-20): Temporary fix for the random maps race
// condition. See you in ten years.
class CRandomMapResult
{
public:
bool m_Done;
char m_aMap[64];
CRandomMapResult() : m_Done(false) {}
};
class IScore class IScore
{ {
CPlayerData m_aPlayerData[MAX_CLIENTS]; CPlayerData m_aPlayerData[MAX_CLIENTS];
@ -64,8 +77,8 @@ public:
virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0; virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut=1) = 0;
virtual void ShowPoints(int ClientID, const char *pName, bool Search=false) = 0; virtual void ShowPoints(int ClientID, const char *pName, bool Search=false) = 0;
virtual void RandomMap(int ClientID, int Stars) = 0; virtual void RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int Stars) = 0;
virtual void RandomUnfinishedMap(int ClientID, int Stars) = 0; virtual void RandomUnfinishedMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int Stars) = 0;
virtual void SaveTeam(int Team, const char *pCode, int ClientID, const char *pServer) = 0; virtual void SaveTeam(int Team, const char *pCode, int ClientID, const char *pServer) = 0;
virtual void LoadTeam(const char *pCode, int ClientID) = 0; virtual void LoadTeam(const char *pCode, int ClientID) = 0;

View file

@ -329,18 +329,20 @@ void CFileScore::ShowPoints(int ClientID, const char* pName, bool Search)
GameServer()->SendChatTarget(ClientID, aBuf); GameServer()->SendChatTarget(ClientID, aBuf);
} }
void CFileScore::RandomMap(int ClientID, int stars) void CFileScore::RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int stars)
{ {
char aBuf[512]; char aBuf[512];
str_format(aBuf, sizeof(aBuf), "Random map not supported in file based servers"); str_format(aBuf, sizeof(aBuf), "Random map not supported in file based servers");
GameServer()->SendChatTarget(ClientID, aBuf); GameServer()->SendChatTarget(ClientID, aBuf);
*ppResult = NULL;
} }
void CFileScore::RandomUnfinishedMap(int ClientID, int stars) void CFileScore::RandomUnfinishedMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int stars)
{ {
char aBuf[512]; char aBuf[512];
str_format(aBuf, sizeof(aBuf), "Random unfinished map not supported in file based servers"); str_format(aBuf, sizeof(aBuf), "Random unfinished map not supported in file based servers");
GameServer()->SendChatTarget(ClientID, aBuf); GameServer()->SendChatTarget(ClientID, aBuf);
*ppResult = NULL;
} }
void CFileScore::SaveTeam(int Team, const char* Code, int ClientID, const char* Server) void CFileScore::SaveTeam(int Team, const char* Code, int ClientID, const char* Server)

View file

@ -80,8 +80,8 @@ public:
virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut); virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, void *pUserData, int Debut);
virtual void ShowPoints(int ClientID, const char* pName, bool Search); virtual void ShowPoints(int ClientID, const char* pName, bool Search);
virtual void RandomMap(int ClientID, int stars); virtual void RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int stars);
virtual void RandomUnfinishedMap(int ClientID, int stars); virtual void RandomUnfinishedMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int stars);
virtual void SaveTeam(int Team, const char* Code, int ClientID, const char* Server); virtual void SaveTeam(int Team, const char* Code, int ClientID, const char* Server);
virtual void LoadTeam(const char* Code, int ClientID); virtual void LoadTeam(const char* Code, int ClientID);

View file

@ -1259,19 +1259,22 @@ bool CSqlScore::ShowTopPointsThread(CSqlServer* pSqlServer, const CSqlData *pGam
return false; return false;
} }
void CSqlScore::RandomMap(int ClientID, int stars) void CSqlScore::RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int Stars)
{ {
CSqlScoreData *Tmp = new CSqlScoreData(); *ppResult = std::make_shared<CRandomMapResult>();
Tmp->m_Num = stars;
CSqlRandomMap *Tmp = new CSqlRandomMap();
Tmp->m_Num = Stars;
Tmp->m_ClientID = ClientID; Tmp->m_ClientID = ClientID;
Tmp->m_Name = GameServer()->Server()->ClientName(ClientID); Tmp->m_Name = GameServer()->Server()->ClientName(ClientID);
Tmp->m_pResult = *ppResult;
thread_init_and_detach(ExecSqlFunc, new CSqlExecData(RandomMapThread, Tmp), "random map"); thread_init_and_detach(ExecSqlFunc, new CSqlExecData(RandomMapThread, Tmp), "random map");
} }
bool CSqlScore::RandomMapThread(CSqlServer* pSqlServer, const CSqlData *pGameData, bool HandleFailure) bool CSqlScore::RandomMapThread(CSqlServer* pSqlServer, const CSqlData *pGameData, bool HandleFailure)
{ {
const CSqlScoreData *pData = dynamic_cast<const CSqlScoreData *>(pGameData); const CSqlRandomMap *pData = dynamic_cast<const CSqlRandomMap *>(pGameData);
if (HandleFailure) if (HandleFailure)
return true; return true;
@ -1293,11 +1296,9 @@ bool CSqlScore::RandomMapThread(CSqlServer* pSqlServer, const CSqlData *pGameDat
else else
{ {
pSqlServer->GetResults()->next(); pSqlServer->GetResults()->next();
char aMap[128]; std::string Map = pSqlServer->GetResults()->getString("Map");
strcpy(aMap, pSqlServer->GetResults()->getString("Map").c_str()); str_copy(pData->m_pResult->m_aMap, Map.c_str(), sizeof(pData->m_pResult->m_aMap));
pData->m_pResult->m_Done = true;
str_format(aBuf, sizeof(aBuf), "change_map \"%s\"", aMap);
pData->GameServer()->Console()->ExecuteLine(aBuf);
} }
dbg_msg("sql", "voting random map done"); dbg_msg("sql", "voting random map done");
@ -1316,19 +1317,22 @@ bool CSqlScore::RandomMapThread(CSqlServer* pSqlServer, const CSqlData *pGameDat
return false; return false;
} }
void CSqlScore::RandomUnfinishedMap(int ClientID, int stars) void CSqlScore::RandomUnfinishedMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int Stars)
{ {
CSqlScoreData *Tmp = new CSqlScoreData(); *ppResult = std::make_shared<CRandomMapResult>();
Tmp->m_Num = stars;
CSqlRandomMap *Tmp = new CSqlRandomMap();
Tmp->m_Num = Stars;
Tmp->m_ClientID = ClientID; Tmp->m_ClientID = ClientID;
Tmp->m_Name = GameServer()->Server()->ClientName(ClientID); Tmp->m_Name = GameServer()->Server()->ClientName(ClientID);
Tmp->m_pResult = *ppResult;
thread_init_and_detach(ExecSqlFunc, new CSqlExecData(RandomUnfinishedMapThread, Tmp), "random unfinished map"); thread_init_and_detach(ExecSqlFunc, new CSqlExecData(RandomUnfinishedMapThread, Tmp), "random unfinished map");
} }
bool CSqlScore::RandomUnfinishedMapThread(CSqlServer* pSqlServer, const CSqlData *pGameData, bool HandleFailure) bool CSqlScore::RandomUnfinishedMapThread(CSqlServer* pSqlServer, const CSqlData *pGameData, bool HandleFailure)
{ {
const CSqlScoreData *pData = dynamic_cast<const CSqlScoreData *>(pGameData); const CSqlRandomMap *pData = dynamic_cast<const CSqlRandomMap *>(pGameData);
if (HandleFailure) if (HandleFailure)
return true; return true;
@ -1350,11 +1354,9 @@ bool CSqlScore::RandomUnfinishedMapThread(CSqlServer* pSqlServer, const CSqlData
else else
{ {
pSqlServer->GetResults()->next(); pSqlServer->GetResults()->next();
char aMap[128]; std::string Map = pSqlServer->GetResults()->getString("Map");
strcpy(aMap, pSqlServer->GetResults()->getString("Map").c_str()); str_copy(pData->m_pResult->m_aMap, Map.c_str(), sizeof(pData->m_pResult->m_aMap));
pData->m_pResult->m_Done = true;
str_format(aBuf, sizeof(aBuf), "change_map \"%s\"", aMap);
pData->GameServer()->Console()->ExecuteLine(aBuf);
} }
dbg_msg("sql", "voting random unfinished map done"); dbg_msg("sql", "voting random unfinished map done");

View file

@ -136,6 +136,11 @@ struct CSqlTeamLoad : CSqlData
int m_ClientID; int m_ClientID;
}; };
struct CSqlRandomMap : CSqlScoreData
{
std::shared_ptr<CRandomMapResult> m_pResult;
};
class CSqlScore: public IScore class CSqlScore: public IScore
{ {
CGameContext *GameServer() { return m_pGameServer; } CGameContext *GameServer() { return m_pGameServer; }
@ -194,8 +199,8 @@ public:
virtual void ShowPoints(int ClientID, const char* pName, bool Search = false); virtual void ShowPoints(int ClientID, const char* pName, bool Search = false);
virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID, virtual void ShowTopPoints(IConsole::IResult *pResult, int ClientID,
void *pUserData, int Debut = 1); void *pUserData, int Debut = 1);
virtual void RandomMap(int ClientID, int stars); virtual void RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int stars);
virtual void RandomUnfinishedMap(int ClientID, int stars); virtual void RandomUnfinishedMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int stars);
virtual void SaveTeam(int Team, const char* Code, int ClientID, const char* Server); virtual void SaveTeam(int Team, const char* Code, int ClientID, const char* Server);
virtual void LoadTeam(const char* Code, int ClientID); virtual void LoadTeam(const char* Code, int ClientID);