diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index fd2400840..ef51b866d 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -2218,6 +2218,7 @@ void CServer::UpdateRegisterServerInfo() "\"size\":%d" "}," "\"version\":\"%s\"," + "\"client_score_kind\":\"time\"," "\"clients\":[", MaxClients, MaxPlayers, @@ -2250,7 +2251,7 @@ void CServer::UpdateRegisterServerInfo() EscapeJson(aCName, sizeof(aCName), ClientName(i)), EscapeJson(aCClan, sizeof(aCClan), ClientClan(i)), m_aClients[i].m_Country, - m_aClients[i].m_Score == -1 ? -9999 : m_aClients[i].m_Score == 9999 ? -10000 : -m_aClients[i].m_Score, + m_aClients[i].m_Score == -1 ? -9999 : m_aClients[i].m_Score, JsonBool(GameServer()->IsClientPlayer(i))); str_append(aInfo, aClientInfo, sizeof(aInfo)); FirstPlayer = false; diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 1e9032036..7631b8002 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -33,6 +33,14 @@ public: NUM_LOCS, }; + enum + { + CLIENT_SCORE_KIND_UNSPECIFIED, + CLIENT_SCORE_KIND_POINTS, + CLIENT_SCORE_KIND_TIME, + CLIENT_SCORE_KIND_TIME_BACKCOMPAT, + }; + class CClient { public: @@ -62,6 +70,7 @@ public: int m_MaxPlayers; int m_NumPlayers; int m_Flags; + int m_ClientScoreKind; TRISTATE m_Favorite; TRISTATE m_FavoriteAllowPing; bool m_Official; diff --git a/src/engine/shared/serverinfo.cpp b/src/engine/shared/serverinfo.cpp index 6f045d513..6d5f0feb2 100644 --- a/src/engine/shared/serverinfo.cpp +++ b/src/engine/shared/serverinfo.cpp @@ -64,6 +64,7 @@ bool CServerInfo2::FromJsonRaw(CServerInfo2 *pOut, const json_value *pJson) const json_value &ServerInfo = *pJson; const json_value &MaxClients = ServerInfo["max_clients"]; const json_value &MaxPlayers = ServerInfo["max_players"]; + const json_value &ClientScoreKind = ServerInfo["client_score_kind"]; const json_value &Passworded = ServerInfo["passworded"]; const json_value &GameType = ServerInfo["game_type"]; const json_value &Name = ServerInfo["name"]; @@ -74,6 +75,7 @@ bool CServerInfo2::FromJsonRaw(CServerInfo2 *pOut, const json_value *pJson) Error = Error || MaxClients.type != json_integer; Error = Error || MaxPlayers.type != json_integer; Error = Error || Passworded.type != json_boolean; + Error = Error || (ClientScoreKind.type != json_none && ClientScoreKind.type != json_string); Error = Error || GameType.type != json_string || str_has_cc(GameType); Error = Error || Name.type != json_string || str_has_cc(Name); Error = Error || MapName.type != json_string || str_has_cc(MapName); @@ -85,6 +87,15 @@ bool CServerInfo2::FromJsonRaw(CServerInfo2 *pOut, const json_value *pJson) } pOut->m_MaxClients = json_int_get(&MaxClients); pOut->m_MaxPlayers = json_int_get(&MaxPlayers); + pOut->m_ClientScoreKind = CServerInfo::CLIENT_SCORE_KIND_UNSPECIFIED; + if(ClientScoreKind.type == json_string && str_startswith(ClientScoreKind, "points")) + { + pOut->m_ClientScoreKind = CServerInfo::CLIENT_SCORE_KIND_POINTS; + } + else if(ClientScoreKind.type == json_string && str_startswith(ClientScoreKind, "time")) + { + pOut->m_ClientScoreKind = CServerInfo::CLIENT_SCORE_KIND_TIME; + } pOut->m_Passworded = Passworded; str_copy(pOut->m_aGameType, GameType); str_copy(pOut->m_aName, Name); @@ -138,6 +149,7 @@ bool CServerInfo2::operator==(const CServerInfo2 &Other) const Unequal = Unequal || m_NumClients != Other.m_NumClients; Unequal = Unequal || m_MaxPlayers != Other.m_MaxPlayers; Unequal = Unequal || m_NumPlayers != Other.m_NumPlayers; + Unequal = Unequal || m_ClientScoreKind != Other.m_ClientScoreKind; Unequal = Unequal || m_Passworded != Other.m_Passworded; Unequal = Unequal || str_comp(m_aGameType, Other.m_aGameType) != 0; Unequal = Unequal || str_comp(m_aName, Other.m_aName) != 0; @@ -170,6 +182,7 @@ CServerInfo2::operator CServerInfo() const Result.m_NumClients = m_NumClients; Result.m_MaxPlayers = m_MaxPlayers; Result.m_NumPlayers = m_NumPlayers; + Result.m_ClientScoreKind = m_ClientScoreKind; Result.m_Flags = m_Passworded ? SERVER_FLAG_PASSWORD : 0; str_copy(Result.m_aGameType, m_aGameType); str_copy(Result.m_aName, m_aName); diff --git a/src/engine/shared/serverinfo.h b/src/engine/shared/serverinfo.h index 84f366c00..4c53b07e4 100644 --- a/src/engine/shared/serverinfo.h +++ b/src/engine/shared/serverinfo.h @@ -25,6 +25,7 @@ public: int m_NumClients; // Indirectly serialized. int m_MaxPlayers; int m_NumPlayers; // Not serialized. + int m_ClientScoreKind; bool m_Passworded; char m_aGameType[16]; char m_aName[64]; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 6fec08c97..f00b59cad 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1133,6 +1133,19 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) static float s_ScrollValue = 0; UiDoListboxStart(&s_VoteList, &ServerScoreBoard, 26.0f, Localize("Scoreboard"), "", pSelectedServer->m_NumReceivedClients, 1, -1, s_ScrollValue); + int ClientScoreKind = pSelectedServer->m_ClientScoreKind; + if(ClientScoreKind == CServerInfo::CLIENT_SCORE_KIND_UNSPECIFIED) + { + if((str_find_nocase(pSelectedServer->m_aGameType, "race") || str_find_nocase(pSelectedServer->m_aGameType, "fastcap")) && g_Config.m_ClDDRaceScoreBoard) + { + ClientScoreKind = CServerInfo::CLIENT_SCORE_KIND_TIME_BACKCOMPAT; + } + else + { + ClientScoreKind = CServerInfo::CLIENT_SCORE_KIND_POINTS; + } + } + for(int i = 0; i < pSelectedServer->m_NumReceivedClients; i++) { CListboxItem Item = UiDoListboxNextItem(&pSelectedServer->m_aClients[i]); @@ -1166,16 +1179,36 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) char aTemp[16]; if(!pSelectedServer->m_aClients[i].m_Player) - str_copy(aTemp, "SPEC"); - else if((str_find_nocase(pSelectedServer->m_aGameType, "race") || str_find_nocase(pSelectedServer->m_aGameType, "fastcap")) && g_Config.m_ClDDRaceScoreBoard) { - if(pSelectedServer->m_aClients[i].m_Score == -9999 || pSelectedServer->m_aClients[i].m_Score == 0) - aTemp[0] = 0; - else - str_time((int64_t)abs(pSelectedServer->m_aClients[i].m_Score) * 100, TIME_HOURS, aTemp, sizeof(aTemp)); + str_copy(aTemp, "SPEC"); + } + else if(ClientScoreKind == CServerInfo::CLIENT_SCORE_KIND_POINTS) + { + str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aClients[i].m_Score); } else - str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aClients[i].m_Score); + { + bool Empty = false; + int Time; + if(ClientScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME_BACKCOMPAT) + { + Time = abs(pSelectedServer->m_aClients[i].m_Score); + Empty = Time == 0 || Time == 9999; + } + else + { + Time = pSelectedServer->m_aClients[i].m_Score; + Empty = Time < 0; + } + if(!Empty) + { + str_time((int64_t)Time * 100, TIME_HOURS, aTemp, sizeof(aTemp)); + } + else + { + aTemp[0] = 0; + } + } float ScoreFontSize = 12.0f; while(ScoreFontSize >= 4.0f && TextRender()->TextWidth(0, ScoreFontSize, aTemp, -1, -1.0f) > Score.w)