mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 18:18:18 +00:00
Fix scoreboard showing wrong best time
by requesting the best time again when it initially failed. This is still not perfectly accurate since a player on another server can get a better time, which will not get updated when the current server had no database problems. As reported by thekid36 on Discord: > The best time shown on the scoreboard on the turkish server on a > ddmax.Next map (mapname: 42) is 30min..while the best time should be 4 > min (it's correct on ger2 server) So the way it works is that the best time is loaded from database when loading map. Additionally it gets updated when a new finish is done. If the initial load failed, but a finish with 30 min is done on the server, we get this result
This commit is contained in:
parent
21b3b3b098
commit
694b9cd67d
|
@ -15,7 +15,7 @@
|
||||||
#define TEST_TYPE_NAME "TestDDraceNetwork"
|
#define TEST_TYPE_NAME "TestDDraceNetwork"
|
||||||
|
|
||||||
CGameControllerDDRace::CGameControllerDDRace(class CGameContext *pGameServer) :
|
CGameControllerDDRace::CGameControllerDDRace(class CGameContext *pGameServer) :
|
||||||
IGameController(pGameServer), m_Teams(pGameServer), m_pInitResult(nullptr)
|
IGameController(pGameServer), m_Teams(pGameServer), m_pLoadBestTimeResult(nullptr)
|
||||||
{
|
{
|
||||||
m_pGameType = g_Config.m_SvTestingCommands ? TEST_TYPE_NAME : GAME_TYPE_NAME;
|
m_pGameType = g_Config.m_SvTestingCommands ? TEST_TYPE_NAME : GAME_TYPE_NAME;
|
||||||
|
|
||||||
|
@ -171,13 +171,13 @@ void CGameControllerDDRace::Tick()
|
||||||
m_Teams.ProcessSaveTeam();
|
m_Teams.ProcessSaveTeam();
|
||||||
m_Teams.Tick();
|
m_Teams.Tick();
|
||||||
|
|
||||||
if(m_pInitResult != nullptr && m_pInitResult->m_Completed)
|
if(m_pLoadBestTimeResult != nullptr && m_pLoadBestTimeResult->m_Completed)
|
||||||
{
|
{
|
||||||
if(m_pInitResult->m_Success)
|
if(m_pLoadBestTimeResult->m_Success)
|
||||||
{
|
{
|
||||||
m_CurrentRecord = m_pInitResult->m_CurrentRecord;
|
m_CurrentRecord = m_pLoadBestTimeResult->m_CurrentRecord;
|
||||||
}
|
}
|
||||||
m_pInitResult = nullptr;
|
m_pLoadBestTimeResult = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct CScoreInitResult;
|
struct CScoreLoadBestTimeResult;
|
||||||
class CGameControllerDDRace : public IGameController
|
class CGameControllerDDRace : public IGameController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -40,6 +40,6 @@ public:
|
||||||
std::map<int, std::vector<vec2>> m_TeleOuts;
|
std::map<int, std::vector<vec2>> m_TeleOuts;
|
||||||
std::map<int, std::vector<vec2>> m_TeleCheckOuts;
|
std::map<int, std::vector<vec2>> m_TeleCheckOuts;
|
||||||
|
|
||||||
std::shared_ptr<CScoreInitResult> m_pInitResult;
|
std::shared_ptr<CScoreLoadBestTimeResult> m_pLoadBestTimeResult;
|
||||||
};
|
};
|
||||||
#endif // GAME_SERVER_GAMEMODES_DDRACE_H
|
#endif // GAME_SERVER_GAMEMODES_DDRACE_H
|
||||||
|
|
|
@ -73,11 +73,6 @@ CScore::CScore(CGameContext *pGameServer, CDbConnectionPool *pPool) :
|
||||||
m_pGameServer(pGameServer),
|
m_pGameServer(pGameServer),
|
||||||
m_pServer(pGameServer->Server())
|
m_pServer(pGameServer->Server())
|
||||||
{
|
{
|
||||||
auto InitResult = std::make_shared<CScoreInitResult>();
|
|
||||||
auto Tmp = std::make_unique<CSqlInitData>(InitResult);
|
|
||||||
((CGameControllerDDRace *)(pGameServer->m_pController))->m_pInitResult = InitResult;
|
|
||||||
str_copy(Tmp->m_aMap, g_Config.m_SvMap, sizeof(Tmp->m_aMap));
|
|
||||||
|
|
||||||
uint64_t aSeed[2];
|
uint64_t aSeed[2];
|
||||||
secure_random_fill(aSeed, sizeof(aSeed));
|
secure_random_fill(aSeed, sizeof(aSeed));
|
||||||
m_Prng.Seed(aSeed);
|
m_Prng.Seed(aSeed);
|
||||||
|
@ -109,8 +104,16 @@ CScore::CScore(CGameContext *pGameServer, CDbConnectionPool *pPool) :
|
||||||
Server()->SetErrorShutdown("sql too few words in wordlist");
|
Server()->SetErrorShutdown("sql too few words in wordlist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_pPool->Execute(CScoreWorker::Init, std::move(Tmp), "load best time");
|
void CScore::LoadBestTime()
|
||||||
|
{
|
||||||
|
auto LoadBestTimeResult = std::make_shared<CScoreLoadBestTimeResult>();
|
||||||
|
((CGameControllerDDRace *)(m_pGameServer->m_pController))->m_pLoadBestTimeResult = LoadBestTimeResult;
|
||||||
|
|
||||||
|
auto Tmp = std::make_unique<CSqlLoadBestTimeData>(LoadBestTimeResult);
|
||||||
|
str_copy(Tmp->m_aMap, g_Config.m_SvMap, sizeof(Tmp->m_aMap));
|
||||||
|
m_pPool->Execute(CScoreWorker::LoadBestTime, std::move(Tmp), "load best time");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScore::LoadPlayerData(int ClientID, const char *pName)
|
void CScore::LoadPlayerData(int ClientID, const char *pName)
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
|
|
||||||
CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; }
|
CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; }
|
||||||
|
|
||||||
|
void LoadBestTime();
|
||||||
void MapInfo(int ClientID, const char *pMapName);
|
void MapInfo(int ClientID, const char *pMapName);
|
||||||
void MapVote(int ClientID, const char *pMapName);
|
void MapVote(int ClientID, const char *pMapName);
|
||||||
void LoadPlayerData(int ClientID, const char *pName = "");
|
void LoadPlayerData(int ClientID, const char *pName = "");
|
||||||
|
|
|
@ -94,10 +94,10 @@ bool CTeamrank::SamePlayers(const std::vector<std::string> *pvSortedNames)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CScoreWorker::Init(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize)
|
bool CScoreWorker::LoadBestTime(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize)
|
||||||
{
|
{
|
||||||
const CSqlInitData *pData = dynamic_cast<const CSqlInitData *>(pGameData);
|
auto pData = dynamic_cast<const CSqlLoadBestTimeData *>(pGameData);
|
||||||
CScoreInitResult *pResult = dynamic_cast<CScoreInitResult *>(pGameData->m_pResult.get());
|
auto pResult = dynamic_cast<CScoreLoadBestTimeResult *>(pGameData->m_pResult.get());
|
||||||
|
|
||||||
char aBuf[512];
|
char aBuf[512];
|
||||||
// get the best time
|
// get the best time
|
||||||
|
|
|
@ -62,18 +62,18 @@ struct CScorePlayerResult : ISqlResult
|
||||||
void SetVariant(Variant v);
|
void SetVariant(Variant v);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CScoreInitResult : ISqlResult
|
struct CScoreLoadBestTimeResult : ISqlResult
|
||||||
{
|
{
|
||||||
CScoreInitResult() :
|
CScoreLoadBestTimeResult() :
|
||||||
m_CurrentRecord(0)
|
m_CurrentRecord(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
float m_CurrentRecord;
|
float m_CurrentRecord;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CSqlInitData : ISqlData
|
struct CSqlLoadBestTimeData : ISqlData
|
||||||
{
|
{
|
||||||
CSqlInitData(std::shared_ptr<CScoreInitResult> pResult) :
|
CSqlLoadBestTimeData(std::shared_ptr<CScoreLoadBestTimeResult> pResult) :
|
||||||
ISqlData(std::move(pResult))
|
ISqlData(std::move(pResult))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ struct CTeamrank
|
||||||
|
|
||||||
struct CScoreWorker
|
struct CScoreWorker
|
||||||
{
|
{
|
||||||
static bool Init(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize);
|
static bool LoadBestTime(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize);
|
||||||
|
|
||||||
static bool RandomMap(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize);
|
static bool RandomMap(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize);
|
||||||
static bool RandomUnfinishedMap(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize);
|
static bool RandomUnfinishedMap(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize);
|
||||||
|
|
|
@ -779,7 +779,11 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp)
|
||||||
|
|
||||||
bool NeedToSendNewServerRecord = false;
|
bool NeedToSendNewServerRecord = false;
|
||||||
// update server best time
|
// update server best time
|
||||||
if(GameServer()->m_pController->m_CurrentRecord == 0 || Time < GameServer()->m_pController->m_CurrentRecord)
|
if(GameServer()->m_pController->m_CurrentRecord == 0)
|
||||||
|
{
|
||||||
|
GameServer()->Score()->LoadBestTime();
|
||||||
|
}
|
||||||
|
else if(Time < GameServer()->m_pController->m_CurrentRecord)
|
||||||
{
|
{
|
||||||
// check for nameless
|
// check for nameless
|
||||||
if(g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(ClientID), "nameless tee"))
|
if(g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(ClientID), "nameless tee"))
|
||||||
|
|
|
@ -41,7 +41,7 @@ struct Score : public testing::TestWithParam<IDbConnection *>
|
||||||
Score()
|
Score()
|
||||||
{
|
{
|
||||||
Connect();
|
Connect();
|
||||||
Init();
|
LoadBestTime();
|
||||||
InsertMap();
|
InsertMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +68,11 @@ struct Score : public testing::TestWithParam<IDbConnection *>
|
||||||
ASSERT_FALSE(m_pConn->ExecuteUpdate(&NumInserted, m_aError, sizeof(m_aError))) << m_aError;
|
ASSERT_FALSE(m_pConn->ExecuteUpdate(&NumInserted, m_aError, sizeof(m_aError))) << m_aError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void LoadBestTime()
|
||||||
{
|
{
|
||||||
CSqlInitData initData(std::make_shared<CScoreInitResult>());
|
CSqlLoadBestTimeData loadBestTimeData(std::make_shared<CScoreLoadBestTimeResult>());
|
||||||
str_copy(initData.m_aMap, "Kobra 3", sizeof(initData.m_aMap));
|
str_copy(loadBestTimeData.m_aMap, "Kobra 3", sizeof(loadBestTimeData.m_aMap));
|
||||||
ASSERT_FALSE(CScoreWorker::Init(m_pConn, &initData, m_aError, sizeof(m_aError))) << m_aError;
|
ASSERT_FALSE(CScoreWorker::LoadBestTime(m_pConn, &loadBestTimeData, m_aError, sizeof(m_aError))) << m_aError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertMap()
|
void InsertMap()
|
||||||
|
|
Loading…
Reference in a new issue