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"
"},"
"\"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;

View file

@ -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;

View file

@ -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);

View file

@ -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];

View file

@ -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)