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
if(g_Config.m_DbgDummies)
{
@ -2151,11 +2157,11 @@ void CGameContext::ConRandomMap(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
int stars = 0;
if (pResult->NumArguments())
stars = pResult->GetInteger(0);
int Stars = 0;
if(pResult->NumArguments())
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)
@ -2166,7 +2172,7 @@ void CGameContext::ConRandomUnfinishedMap(IConsole::IResult *pResult, void *pUse
if (pResult->NumArguments())
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)

View file

@ -56,6 +56,7 @@ enum
class IConsole;
class IEngine;
class IStorage;
class CRandomMapResult;
class CGameContext : public IGameServer
{
@ -75,6 +76,8 @@ class CGameContext : public IGameServer
CUuid m_GameUuid;
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 TeeHistorianWrite(const void *pData, int DataSize, void *pUser);

View file

@ -1,6 +1,8 @@
#ifndef GAME_SERVER_SCORE_H
#define GAME_SERVER_SCORE_H
#include <memory>
#include "entities/character.h"
#include "gamecontext.h"
@ -38,6 +40,17 @@ public:
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
{
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 ShowPoints(int ClientID, const char *pName, bool Search=false) = 0;
virtual void RandomMap(int ClientID, int Stars) = 0;
virtual void RandomUnfinishedMap(int ClientID, int Stars) = 0;
virtual void RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, 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 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);
}
void CFileScore::RandomMap(int ClientID, int stars)
void CFileScore::RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, int ClientID, int stars)
{
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "Random map not supported in file based servers");
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];
str_format(aBuf, sizeof(aBuf), "Random unfinished map not supported in file based servers");
GameServer()->SendChatTarget(ClientID, aBuf);
*ppResult = NULL;
}
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 ShowPoints(int ClientID, const char* pName, bool Search);
virtual void RandomMap(int ClientID, int stars);
virtual void RandomUnfinishedMap(int ClientID, int stars);
virtual void RandomMap(std::shared_ptr<CRandomMapResult> *ppResult, 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 LoadTeam(const char* Code, int ClientID);

View file

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

View file

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