From 694b9cd67d704ff54768a1f79b883adec01defc2 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 31 Dec 2022 12:23:21 +0100 Subject: [PATCH] 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 --- src/game/server/gamemodes/DDRace.cpp | 10 +++++----- src/game/server/gamemodes/DDRace.h | 4 ++-- src/game/server/score.cpp | 15 +++++++++------ src/game/server/score.h | 1 + src/game/server/scoreworker.cpp | 6 +++--- src/game/server/scoreworker.h | 10 +++++----- src/game/server/teams.cpp | 6 +++++- src/test/score.cpp | 10 +++++----- 8 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/game/server/gamemodes/DDRace.cpp b/src/game/server/gamemodes/DDRace.cpp index ecd81b9f8..fa8f5a260 100644 --- a/src/game/server/gamemodes/DDRace.cpp +++ b/src/game/server/gamemodes/DDRace.cpp @@ -15,7 +15,7 @@ #define TEST_TYPE_NAME "TestDDraceNetwork" 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; @@ -171,13 +171,13 @@ void CGameControllerDDRace::Tick() m_Teams.ProcessSaveTeam(); 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; } } diff --git a/src/game/server/gamemodes/DDRace.h b/src/game/server/gamemodes/DDRace.h index df9bd602f..b2b95fe7b 100644 --- a/src/game/server/gamemodes/DDRace.h +++ b/src/game/server/gamemodes/DDRace.h @@ -8,7 +8,7 @@ #include #include -struct CScoreInitResult; +struct CScoreLoadBestTimeResult; class CGameControllerDDRace : public IGameController { public: @@ -40,6 +40,6 @@ public: std::map> m_TeleOuts; std::map> m_TeleCheckOuts; - std::shared_ptr m_pInitResult; + std::shared_ptr m_pLoadBestTimeResult; }; #endif // GAME_SERVER_GAMEMODES_DDRACE_H diff --git a/src/game/server/score.cpp b/src/game/server/score.cpp index 66c3d2059..ecbcce618 100644 --- a/src/game/server/score.cpp +++ b/src/game/server/score.cpp @@ -73,11 +73,6 @@ CScore::CScore(CGameContext *pGameServer, CDbConnectionPool *pPool) : m_pGameServer(pGameServer), m_pServer(pGameServer->Server()) { - auto InitResult = std::make_shared(); - auto Tmp = std::make_unique(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]; secure_random_fill(aSeed, sizeof(aSeed)); m_Prng.Seed(aSeed); @@ -109,8 +104,16 @@ CScore::CScore(CGameContext *pGameServer, CDbConnectionPool *pPool) : Server()->SetErrorShutdown("sql too few words in wordlist"); return; } +} - m_pPool->Execute(CScoreWorker::Init, std::move(Tmp), "load best time"); +void CScore::LoadBestTime() +{ + auto LoadBestTimeResult = std::make_shared(); + ((CGameControllerDDRace *)(m_pGameServer->m_pController))->m_pLoadBestTimeResult = LoadBestTimeResult; + + auto Tmp = std::make_unique(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) diff --git a/src/game/server/score.h b/src/game/server/score.h index bbedf8dd1..84380068b 100644 --- a/src/game/server/score.h +++ b/src/game/server/score.h @@ -44,6 +44,7 @@ public: CPlayerData *PlayerData(int ID) { return &m_aPlayerData[ID]; } + void LoadBestTime(); void MapInfo(int ClientID, const char *pMapName); void MapVote(int ClientID, const char *pMapName); void LoadPlayerData(int ClientID, const char *pName = ""); diff --git a/src/game/server/scoreworker.cpp b/src/game/server/scoreworker.cpp index 562f8cbf3..db3a1e121 100644 --- a/src/game/server/scoreworker.cpp +++ b/src/game/server/scoreworker.cpp @@ -94,10 +94,10 @@ bool CTeamrank::SamePlayers(const std::vector *pvSortedNames) 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(pGameData); - CScoreInitResult *pResult = dynamic_cast(pGameData->m_pResult.get()); + auto pData = dynamic_cast(pGameData); + auto pResult = dynamic_cast(pGameData->m_pResult.get()); char aBuf[512]; // get the best time diff --git a/src/game/server/scoreworker.h b/src/game/server/scoreworker.h index 7b6114fca..54c388c04 100644 --- a/src/game/server/scoreworker.h +++ b/src/game/server/scoreworker.h @@ -62,18 +62,18 @@ struct CScorePlayerResult : ISqlResult void SetVariant(Variant v); }; -struct CScoreInitResult : ISqlResult +struct CScoreLoadBestTimeResult : ISqlResult { - CScoreInitResult() : + CScoreLoadBestTimeResult() : m_CurrentRecord(0) { } float m_CurrentRecord; }; -struct CSqlInitData : ISqlData +struct CSqlLoadBestTimeData : ISqlData { - CSqlInitData(std::shared_ptr pResult) : + CSqlLoadBestTimeData(std::shared_ptr pResult) : ISqlData(std::move(pResult)) { } @@ -274,7 +274,7 @@ struct CTeamrank 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 RandomUnfinishedMap(IDbConnection *pSqlServer, const ISqlData *pGameData, char *pError, int ErrorSize); diff --git a/src/game/server/teams.cpp b/src/game/server/teams.cpp index 8e6ca9955..b1676ed14 100644 --- a/src/game/server/teams.cpp +++ b/src/game/server/teams.cpp @@ -779,7 +779,11 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp) bool NeedToSendNewServerRecord = false; // 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 if(g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(ClientID), "nameless tee")) diff --git a/src/test/score.cpp b/src/test/score.cpp index a2d78a4e8..98df4a714 100644 --- a/src/test/score.cpp +++ b/src/test/score.cpp @@ -41,7 +41,7 @@ struct Score : public testing::TestWithParam Score() { Connect(); - Init(); + LoadBestTime(); InsertMap(); } @@ -68,11 +68,11 @@ struct Score : public testing::TestWithParam ASSERT_FALSE(m_pConn->ExecuteUpdate(&NumInserted, m_aError, sizeof(m_aError))) << m_aError; } - void Init() + void LoadBestTime() { - CSqlInitData initData(std::make_shared()); - str_copy(initData.m_aMap, "Kobra 3", sizeof(initData.m_aMap)); - ASSERT_FALSE(CScoreWorker::Init(m_pConn, &initData, m_aError, sizeof(m_aError))) << m_aError; + CSqlLoadBestTimeData loadBestTimeData(std::make_shared()); + str_copy(loadBestTimeData.m_aMap, "Kobra 3", sizeof(loadBestTimeData.m_aMap)); + ASSERT_FALSE(CScoreWorker::LoadBestTime(m_pConn, &loadBestTimeData, m_aError, sizeof(m_aError))) << m_aError; } void InsertMap()