Add client_score_kind field to serverinfo

It specifies whether the scores are to be interpreted as times (string
value starting with "time") or as points (string value starting with
"points").
This commit is contained in:
heinrich5991 2022-10-11 21:52:27 +02:00
parent d8053fba7d
commit 623a8935fb
5 changed files with 65 additions and 8 deletions

View file

@ -2218,6 +2218,7 @@ void CServer::UpdateRegisterServerInfo()
"\"size\":%d" "\"size\":%d"
"}," "},"
"\"version\":\"%s\"," "\"version\":\"%s\","
"\"client_score_kind\":\"time\","
"\"clients\":[", "\"clients\":[",
MaxClients, MaxClients,
MaxPlayers, MaxPlayers,
@ -2250,7 +2251,7 @@ void CServer::UpdateRegisterServerInfo()
EscapeJson(aCName, sizeof(aCName), ClientName(i)), EscapeJson(aCName, sizeof(aCName), ClientName(i)),
EscapeJson(aCClan, sizeof(aCClan), ClientClan(i)), EscapeJson(aCClan, sizeof(aCClan), ClientClan(i)),
m_aClients[i].m_Country, 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))); JsonBool(GameServer()->IsClientPlayer(i)));
str_append(aInfo, aClientInfo, sizeof(aInfo)); str_append(aInfo, aClientInfo, sizeof(aInfo));
FirstPlayer = false; FirstPlayer = false;

View file

@ -33,6 +33,14 @@ public:
NUM_LOCS, NUM_LOCS,
}; };
enum
{
CLIENT_SCORE_KIND_UNSPECIFIED,
CLIENT_SCORE_KIND_POINTS,
CLIENT_SCORE_KIND_TIME,
CLIENT_SCORE_KIND_TIME_BACKCOMPAT,
};
class CClient class CClient
{ {
public: public:
@ -62,6 +70,7 @@ public:
int m_MaxPlayers; int m_MaxPlayers;
int m_NumPlayers; int m_NumPlayers;
int m_Flags; int m_Flags;
int m_ClientScoreKind;
TRISTATE m_Favorite; TRISTATE m_Favorite;
TRISTATE m_FavoriteAllowPing; TRISTATE m_FavoriteAllowPing;
bool m_Official; bool m_Official;

View file

@ -64,6 +64,7 @@ bool CServerInfo2::FromJsonRaw(CServerInfo2 *pOut, const json_value *pJson)
const json_value &ServerInfo = *pJson; const json_value &ServerInfo = *pJson;
const json_value &MaxClients = ServerInfo["max_clients"]; const json_value &MaxClients = ServerInfo["max_clients"];
const json_value &MaxPlayers = ServerInfo["max_players"]; const json_value &MaxPlayers = ServerInfo["max_players"];
const json_value &ClientScoreKind = ServerInfo["client_score_kind"];
const json_value &Passworded = ServerInfo["passworded"]; const json_value &Passworded = ServerInfo["passworded"];
const json_value &GameType = ServerInfo["game_type"]; const json_value &GameType = ServerInfo["game_type"];
const json_value &Name = ServerInfo["name"]; 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 || MaxClients.type != json_integer;
Error = Error || MaxPlayers.type != json_integer; Error = Error || MaxPlayers.type != json_integer;
Error = Error || Passworded.type != json_boolean; 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 || GameType.type != json_string || str_has_cc(GameType);
Error = Error || Name.type != json_string || str_has_cc(Name); Error = Error || Name.type != json_string || str_has_cc(Name);
Error = Error || MapName.type != json_string || str_has_cc(MapName); 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_MaxClients = json_int_get(&MaxClients);
pOut->m_MaxPlayers = json_int_get(&MaxPlayers); 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; pOut->m_Passworded = Passworded;
str_copy(pOut->m_aGameType, GameType); str_copy(pOut->m_aGameType, GameType);
str_copy(pOut->m_aName, Name); 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_NumClients != Other.m_NumClients;
Unequal = Unequal || m_MaxPlayers != Other.m_MaxPlayers; Unequal = Unequal || m_MaxPlayers != Other.m_MaxPlayers;
Unequal = Unequal || m_NumPlayers != Other.m_NumPlayers; Unequal = Unequal || m_NumPlayers != Other.m_NumPlayers;
Unequal = Unequal || m_ClientScoreKind != Other.m_ClientScoreKind;
Unequal = Unequal || m_Passworded != Other.m_Passworded; Unequal = Unequal || m_Passworded != Other.m_Passworded;
Unequal = Unequal || str_comp(m_aGameType, Other.m_aGameType) != 0; Unequal = Unequal || str_comp(m_aGameType, Other.m_aGameType) != 0;
Unequal = Unequal || str_comp(m_aName, Other.m_aName) != 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_NumClients = m_NumClients;
Result.m_MaxPlayers = m_MaxPlayers; Result.m_MaxPlayers = m_MaxPlayers;
Result.m_NumPlayers = m_NumPlayers; Result.m_NumPlayers = m_NumPlayers;
Result.m_ClientScoreKind = m_ClientScoreKind;
Result.m_Flags = m_Passworded ? SERVER_FLAG_PASSWORD : 0; Result.m_Flags = m_Passworded ? SERVER_FLAG_PASSWORD : 0;
str_copy(Result.m_aGameType, m_aGameType); str_copy(Result.m_aGameType, m_aGameType);
str_copy(Result.m_aName, m_aName); str_copy(Result.m_aName, m_aName);

View file

@ -25,6 +25,7 @@ public:
int m_NumClients; // Indirectly serialized. int m_NumClients; // Indirectly serialized.
int m_MaxPlayers; int m_MaxPlayers;
int m_NumPlayers; // Not serialized. int m_NumPlayers; // Not serialized.
int m_ClientScoreKind;
bool m_Passworded; bool m_Passworded;
char m_aGameType[16]; char m_aGameType[16];
char m_aName[64]; char m_aName[64];

View file

@ -1133,6 +1133,19 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
static float s_ScrollValue = 0; static float s_ScrollValue = 0;
UiDoListboxStart(&s_VoteList, &ServerScoreBoard, 26.0f, Localize("Scoreboard"), "", pSelectedServer->m_NumReceivedClients, 1, -1, s_ScrollValue); 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++) for(int i = 0; i < pSelectedServer->m_NumReceivedClients; i++)
{ {
CListboxItem Item = UiDoListboxNextItem(&pSelectedServer->m_aClients[i]); CListboxItem Item = UiDoListboxNextItem(&pSelectedServer->m_aClients[i]);
@ -1166,16 +1179,36 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
char aTemp[16]; char aTemp[16];
if(!pSelectedServer->m_aClients[i].m_Player) 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) str_copy(aTemp, "SPEC");
aTemp[0] = 0; }
else else if(ClientScoreKind == CServerInfo::CLIENT_SCORE_KIND_POINTS)
str_time((int64_t)abs(pSelectedServer->m_aClients[i].m_Score) * 100, TIME_HOURS, aTemp, sizeof(aTemp)); {
str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aClients[i].m_Score);
} }
else 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; float ScoreFontSize = 12.0f;
while(ScoreFontSize >= 4.0f && TextRender()->TextWidth(0, ScoreFontSize, aTemp, -1, -1.0f) > Score.w) while(ScoreFontSize >= 4.0f && TextRender()->TextWidth(0, ScoreFontSize, aTemp, -1, -1.0f) > Score.w)