clean time score handling, with positive time values

This commit is contained in:
Edgar 2023-05-22 16:32:48 +02:00
parent 8a3d8fc53f
commit 1d30462e50
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
8 changed files with 64 additions and 48 deletions

View file

@ -589,26 +589,32 @@ void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
if(ClientScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME)
{
// time is sent as a positive value, but sometimes buggy servers sent it as negative
Score0 = -absolute(Score0);
Score1 = -absolute(Score1);
if(Score0 == -9999)
Score0 = INT_MIN;
if(Score1 == -9999)
Score1 = INT_MIN;
// time is sent as a positive value to the http master, counting 0, if there is a time (finished)
// only positive times are meant to represent an actual time.
if(Score0 != Score1)
{
if(Score0 < 0)
return false;
if(Score1 < 0)
return true;
return Score0 < Score1;
}
}
else if(ClientScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME_BACKCOMPAT)
else
{
if(Score0 == -9999)
Score0 = INT_MIN;
if(Score1 == -9999)
Score1 = INT_MIN;
}
if(ClientScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME_BACKCOMPAT)
{
if(Score0 == -9999)
Score0 = INT_MIN;
if(Score1 == -9999)
Score1 = INT_MIN;
}
if(Score0 > Score1)
return true;
if(Score0 < Score1)
return false;
if(Score0 > Score1)
return true;
if(Score0 < Score1)
return false;
}
return str_comp_nocase(p0.m_aName, p1.m_aName) < 0;
}

View file

@ -3,6 +3,7 @@
#ifndef ENGINE_SERVER_H
#define ENGINE_SERVER_H
#include <optional>
#include <type_traits>
#include <base/hash.h>
@ -207,7 +208,7 @@ public:
virtual void SetClientName(int ClientID, char const *pName) = 0;
virtual void SetClientClan(int ClientID, char const *pClan) = 0;
virtual void SetClientCountry(int ClientID, int Country) = 0;
virtual void SetClientScore(int ClientID, int Score) = 0;
virtual void SetClientScore(int ClientID, std::optional<int> Score) = 0;
virtual void SetClientFlags(int ClientID, int Flags) = 0;
virtual int SnapNewID() = 0;
@ -334,7 +335,7 @@ public:
/**
* Used to report custom player info to master servers.
*
*
* @param aBuf Should be the json key values to add, starting with a ',' beforehand, like: ',"skin": "default", "team": 1'
* @param i The client id.
*/

View file

@ -473,12 +473,12 @@ void CServer::SetClientCountry(int ClientID, int Country)
m_aClients[ClientID].m_Country = Country;
}
void CServer::SetClientScore(int ClientID, int Score)
void CServer::SetClientScore(int ClientID, std::optional<int> Score)
{
if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
return;
if(!m_aClients[ClientID].m_Score.has_value() || m_aClients[ClientID].m_Score.value() != Score)
if(m_aClients[ClientID].m_Score != Score)
ExpireServerInfo();
m_aClients[ClientID].m_Score = Score;
@ -2017,7 +2017,24 @@ void CServer::CacheServerInfo(CCache *pCache, int Type, bool SendClients)
q.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan
ADD_INT(q, m_aClients[i].m_Country); // client country
ADD_INT(q, !m_aClients[i].m_Score.has_value() ? -9999 : m_aClients[i].m_Score.value() == 9999 ? -10000 : -m_aClients[i].m_Score.value()); // client score
int Score;
if(m_aClients[i].m_Score.has_value())
{
Score = m_aClients[i].m_Score.value();
if(Score == 9999)
Score = -10000;
else if(Score == 0) // 0 time isn't displayed otherwise.
Score = -1;
else
Score = -Score;
}
else
{
Score = -9999;
}
ADD_INT(q, Score); // client score
ADD_INT(q, GameServer()->IsClientPlayer(i) ? 1 : 0); // is player?
if(Type == SERVERINFO_EXTENDED)
q.AddString("", 0); // extra info, reserved

View file

@ -283,7 +283,7 @@ public:
void SetClientName(int ClientID, const char *pName) override;
void SetClientClan(int ClientID, char const *pClan) override;
void SetClientCountry(int ClientID, int Country) override;
void SetClientScore(int ClientID, int Score) override;
void SetClientScore(int ClientID, std::optional<int> Score) override;
void SetClientFlags(int ClientID, int Flags) override;
void Kick(int ClientID, const char *pReason) override;

View file

@ -1135,8 +1135,9 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
}
else
{
if(CurrentClient.m_Score != -9999)
Time = absolute(CurrentClient.m_Score);
// CServerInfo::CLIENT_SCORE_KIND_POINTS
if(CurrentClient.m_Score >= 0)
Time = CurrentClient.m_Score;
}
if(Time.has_value())

View file

@ -2446,7 +2446,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
// reload scores
Score()->PlayerData(ClientID)->Reset();
m_apPlayers[ClientID]->m_Score = -9999;
m_apPlayers[ClientID]->m_Score.reset();
Score()->LoadPlayerData(ClientID);
SixupNeedsUpdate = true;

View file

@ -183,20 +183,7 @@ void CPlayer::Tick()
if(m_ChatScore > 0)
m_ChatScore--;
int Score;
if(m_Score)
{
if(*m_Score == 9999)
Score = -10000;
else
Score = *m_Score;
}
else
{
Score = -9999;
}
Server()->SetClientScore(m_ClientID, Score);
Server()->SetClientScore(m_ClientID, m_Score);
if(m_Moderating && m_Afk)
{
@ -351,15 +338,18 @@ void CPlayer::Snap(int SnappingClient)
int Latency = SnappingClient == SERVER_DEMO_CLIENT ? m_Latency.m_Min : GameServer()->m_apPlayers[SnappingClient]->m_aCurLatency[m_ClientID];
int Score;
if(m_Score)
// This is the time sent to the player while ingame (do not confuse to the one reported to the master server).
// Due to clients expecting this as a negative value, we have to make sure it's negative.
// Special numbers:
// - 9999: means no time and isn't displayed in the scoreboard.
if(m_Score.has_value())
{
// -9999 stands for no time and isn't displayed in scoreboard, so
// shift the time by a second if the player actually took 9999
// seconds to finish the map.
if(*m_Score == 9999)
if(m_Score.value() == 9999)
Score = -10000;
else
Score = -1 * absolute(*m_Score);
Score = -m_Score.value();
}
else
{
@ -912,8 +902,8 @@ void CPlayer::ProcessScoreResult(CScorePlayerResult &Result)
GameServer()->CallVote(m_ClientID, Result.m_Data.m_MapVote.m_aMap, aCmd, "/map", aChatmsg);
break;
case CScorePlayerResult::PLAYER_INFO:
if(Result.m_Data.m_Info.m_Time)
GameServer()->Score()->PlayerData(m_ClientID)->Set(*Result.m_Data.m_Info.m_Time, Result.m_Data.m_Info.m_aTimeCp);
if(Result.m_Data.m_Info.m_Time.has_value())
GameServer()->Score()->PlayerData(m_ClientID)->Set(Result.m_Data.m_Info.m_Time.value(), Result.m_Data.m_Info.m_aTimeCp);
m_Score = Result.m_Data.m_Info.m_Time;
Server()->ExpireServerInfo();
int Birthday = Result.m_Data.m_Info.m_Birthday;

View file

@ -1,5 +1,6 @@
/* (c) Shereef Marzouk. See "licence DDRace.txt" and the readme.txt in the root of the distribution for more information. */
#include "teams.h"
#include "base/system.h"
#include "entities/character.h"
#include "gamecontroller.h"
#include "player.h"
@ -817,8 +818,8 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp)
GameServer()->SendRecord(ClientID);
}
int TTime = 0 - (int)Time;
if(!Player->m_Score || -1 * absolute(*Player->m_Score) < TTime)
int TTime = (int)Time;
if(!Player->m_Score.has_value() || TTime < Player->m_Score.value())
{
Player->m_Score = TTime;
}