Merge pull request #8221 from Zwelf/pr-teehistorian-finish

Store player names in teehistorian and Finish/TeamFinish
This commit is contained in:
Dennis Felsing 2024-04-16 01:11:16 +00:00 committed by GitHub
commit 5f45e218ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 156 additions and 17 deletions

View file

@ -356,6 +356,9 @@ public:
virtual void TeehistorianRecordPlayerJoin(int ClientId, bool Sixup) = 0; virtual void TeehistorianRecordPlayerJoin(int ClientId, bool Sixup) = 0;
virtual void TeehistorianRecordPlayerDrop(int ClientId, const char *pReason) = 0; virtual void TeehistorianRecordPlayerDrop(int ClientId, const char *pReason) = 0;
virtual void TeehistorianRecordPlayerRejoin(int ClientId) = 0; virtual void TeehistorianRecordPlayerRejoin(int ClientId) = 0;
virtual void TeehistorianRecordPlayerName(int ClientId, const char *pName) = 0;
virtual void TeehistorianRecordPlayerFinish(int ClientId, int TimeTicks) = 0;
virtual void TeehistorianRecordTeamFinish(int TeamId, int TimeTicks) = 0;
virtual void FillAntibot(CAntibotRoundData *pData) = 0; virtual void FillAntibot(CAntibotRoundData *pData) = 0;

View file

@ -354,10 +354,11 @@ bool CServer::SetClientNameImpl(int ClientId, const char *pNameRequest, bool Set
bool Changed = str_comp(m_aClients[ClientId].m_aName, aNameTry) != 0; bool Changed = str_comp(m_aClients[ClientId].m_aName, aNameTry) != 0;
if(Set) if(Set && Changed)
{ {
// set the client name // set the client name
str_copy(m_aClients[ClientId].m_aName, aNameTry); str_copy(m_aClients[ClientId].m_aName, aNameTry);
GameServer()->TeehistorianRecordPlayerName(ClientId, m_aClients[ClientId].m_aName);
} }
return Changed; return Changed;

View file

@ -18,3 +18,6 @@ UUID(TEEHISTORIAN_TEAM_PRACTICE, "teehistorian-team-practice@ddnet.tw")
UUID(TEEHISTORIAN_PLAYER_READY, "teehistorian-player-ready@ddnet.tw") UUID(TEEHISTORIAN_PLAYER_READY, "teehistorian-player-ready@ddnet.tw")
UUID(TEEHISTORIAN_PLAYER_REJOIN, "teehistorian-rejoinver6@ddnet.org") UUID(TEEHISTORIAN_PLAYER_REJOIN, "teehistorian-rejoinver6@ddnet.org")
UUID(TEEHISTORIAN_ANTIBOT, "teehistorian-antibot@ddnet.org") UUID(TEEHISTORIAN_ANTIBOT, "teehistorian-antibot@ddnet.org")
UUID(TEEHISTORIAN_PLAYER_NAME, "teehistorian-player-name@ddnet.org")
UUID(TEEHISTORIAN_PLAYER_FINISH, "teehistorian-player-finish@ddnet.org")
UUID(TEEHISTORIAN_TEAM_FINISH, "teehistorian-team-finish@ddnet.org")

View file

@ -1767,6 +1767,30 @@ void CGameContext::TeehistorianRecordPlayerRejoin(int ClientId)
} }
} }
void CGameContext::TeehistorianRecordPlayerName(int ClientId, const char *pName)
{
if(m_TeeHistorianActive)
{
m_TeeHistorian.RecordPlayerName(ClientId, pName);
}
}
void CGameContext::TeehistorianRecordPlayerFinish(int ClientId, int TimeTicks)
{
if(m_TeeHistorianActive)
{
m_TeeHistorian.RecordPlayerFinish(ClientId, TimeTicks);
}
}
void CGameContext::TeehistorianRecordTeamFinish(int TeamId, int TimeTicks)
{
if(m_TeeHistorianActive)
{
m_TeeHistorian.RecordTeamFinish(TeamId, TimeTicks);
}
}
bool CGameContext::OnClientDDNetVersionKnown(int ClientId) bool CGameContext::OnClientDDNetVersionKnown(int ClientId)
{ {
IServer::CClientInfo Info; IServer::CClientInfo Info;

View file

@ -328,6 +328,9 @@ public:
void TeehistorianRecordPlayerJoin(int ClientId, bool Sixup) override; void TeehistorianRecordPlayerJoin(int ClientId, bool Sixup) override;
void TeehistorianRecordPlayerDrop(int ClientId, const char *pReason) override; void TeehistorianRecordPlayerDrop(int ClientId, const char *pReason) override;
void TeehistorianRecordPlayerRejoin(int ClientId) override; void TeehistorianRecordPlayerRejoin(int ClientId) override;
void TeehistorianRecordPlayerName(int ClientId, const char *pName) override;
void TeehistorianRecordPlayerFinish(int ClientId, int TimeTicks) override;
void TeehistorianRecordTeamFinish(int TeamId, int TimeTicks) override;
bool IsClientReady(int ClientId) const override; bool IsClientReady(int ClientId) const override;
bool IsClientPlayer(int ClientId) const override; bool IsClientPlayer(int ClientId) const override;

View file

@ -145,12 +145,14 @@ void CScore::MapInfo(int ClientId, const char *pMapName)
ExecPlayerThread(CScoreWorker::MapInfo, "map info", ClientId, pMapName, 0); ExecPlayerThread(CScoreWorker::MapInfo, "map info", ClientId, pMapName, 0);
} }
void CScore::SaveScore(int ClientId, float Time, const char *pTimestamp, const float aTimeCp[NUM_CHECKPOINTS], bool NotEligible) void CScore::SaveScore(int ClientId, int TimeTicks, const char *pTimestamp, const float aTimeCp[NUM_CHECKPOINTS], bool NotEligible)
{ {
CConsole *pCon = (CConsole *)GameServer()->Console(); CConsole *pCon = (CConsole *)GameServer()->Console();
if(pCon->Cheated() || NotEligible) if(pCon->Cheated() || NotEligible)
return; return;
GameServer()->TeehistorianRecordPlayerFinish(ClientId, TimeTicks);
CPlayer *pCurPlayer = GameServer()->m_apPlayers[ClientId]; CPlayer *pCurPlayer = GameServer()->m_apPlayers[ClientId];
if(pCurPlayer->m_ScoreFinishResult != nullptr) if(pCurPlayer->m_ScoreFinishResult != nullptr)
dbg_msg("sql", "WARNING: previous save score result didn't complete, overwriting it now"); dbg_msg("sql", "WARNING: previous save score result didn't complete, overwriting it now");
@ -160,7 +162,7 @@ void CScore::SaveScore(int ClientId, float Time, const char *pTimestamp, const f
FormatUuid(GameServer()->GameUuid(), Tmp->m_aGameUuid, sizeof(Tmp->m_aGameUuid)); FormatUuid(GameServer()->GameUuid(), Tmp->m_aGameUuid, sizeof(Tmp->m_aGameUuid));
Tmp->m_ClientId = ClientId; Tmp->m_ClientId = ClientId;
str_copy(Tmp->m_aName, Server()->ClientName(ClientId), sizeof(Tmp->m_aName)); str_copy(Tmp->m_aName, Server()->ClientName(ClientId), sizeof(Tmp->m_aName));
Tmp->m_Time = Time; Tmp->m_Time = (float)(TimeTicks) / (float)Server()->TickSpeed();
str_copy(Tmp->m_aTimestamp, pTimestamp, sizeof(Tmp->m_aTimestamp)); str_copy(Tmp->m_aTimestamp, pTimestamp, sizeof(Tmp->m_aTimestamp));
for(int i = 0; i < NUM_CHECKPOINTS; i++) for(int i = 0; i < NUM_CHECKPOINTS; i++)
Tmp->m_aCurrentTimeCp[i] = aTimeCp[i]; Tmp->m_aCurrentTimeCp[i] = aTimeCp[i];
@ -168,7 +170,7 @@ void CScore::SaveScore(int ClientId, float Time, const char *pTimestamp, const f
m_pPool->ExecuteWrite(CScoreWorker::SaveScore, std::move(Tmp), "save score"); m_pPool->ExecuteWrite(CScoreWorker::SaveScore, std::move(Tmp), "save score");
} }
void CScore::SaveTeamScore(int *pClientIds, unsigned int Size, float Time, const char *pTimestamp) void CScore::SaveTeamScore(int Team, int *pClientIds, unsigned int Size, int TimeTicks, const char *pTimestamp)
{ {
CConsole *pCon = (CConsole *)GameServer()->Console(); CConsole *pCon = (CConsole *)GameServer()->Console();
if(pCon->Cheated()) if(pCon->Cheated())
@ -178,11 +180,14 @@ void CScore::SaveTeamScore(int *pClientIds, unsigned int Size, float Time, const
if(GameServer()->m_apPlayers[pClientIds[i]]->m_NotEligibleForFinish) if(GameServer()->m_apPlayers[pClientIds[i]]->m_NotEligibleForFinish)
return; return;
} }
GameServer()->TeehistorianRecordTeamFinish(Team, TimeTicks);
auto Tmp = std::make_unique<CSqlTeamScoreData>(); auto Tmp = std::make_unique<CSqlTeamScoreData>();
for(unsigned int i = 0; i < Size; i++) for(unsigned int i = 0; i < Size; i++)
str_copy(Tmp->m_aaNames[i], Server()->ClientName(pClientIds[i]), sizeof(Tmp->m_aaNames[i])); str_copy(Tmp->m_aaNames[i], Server()->ClientName(pClientIds[i]), sizeof(Tmp->m_aaNames[i]));
Tmp->m_Size = Size; Tmp->m_Size = Size;
Tmp->m_Time = Time; Tmp->m_Time = (float)TimeTicks / (float)Server()->TickSpeed();
str_copy(Tmp->m_aTimestamp, pTimestamp, sizeof(Tmp->m_aTimestamp)); str_copy(Tmp->m_aTimestamp, pTimestamp, sizeof(Tmp->m_aTimestamp));
FormatUuid(GameServer()->GameUuid(), Tmp->m_aGameUuid, sizeof(Tmp->m_aGameUuid)); FormatUuid(GameServer()->GameUuid(), Tmp->m_aGameUuid, sizeof(Tmp->m_aGameUuid));
str_copy(Tmp->m_aMap, g_Config.m_SvMap, sizeof(Tmp->m_aMap)); str_copy(Tmp->m_aMap, g_Config.m_SvMap, sizeof(Tmp->m_aMap));

View file

@ -49,9 +49,9 @@ public:
void MapVote(int ClientId, const char *pMapName); void MapVote(int ClientId, const char *pMapName);
void LoadPlayerData(int ClientId, const char *pName = ""); void LoadPlayerData(int ClientId, const char *pName = "");
void LoadPlayerTimeCp(int ClientId, const char *pName = ""); void LoadPlayerTimeCp(int ClientId, const char *pName = "");
void SaveScore(int ClientId, float Time, const char *pTimestamp, const float aTimeCp[NUM_CHECKPOINTS], bool NotEligible); void SaveScore(int ClientId, int TimeTicks, const char *pTimestamp, const float aTimeCp[NUM_CHECKPOINTS], bool NotEligible);
void SaveTeamScore(int *pClientIds, unsigned int Size, float Time, const char *pTimestamp); void SaveTeamScore(int Team, int *pClientIds, unsigned int Size, int TimeTicks, const char *pTimestamp);
void ShowTop(int ClientId, int Offset = 1); void ShowTop(int ClientId, int Offset = 1);
void ShowRank(int ClientId, const char *pName); void ShowRank(int ClientId, const char *pName);

View file

@ -335,8 +335,9 @@ void CGameTeams::CheckTeamFinished(int Team)
if(PlayersCount > 0) if(PlayersCount > 0)
{ {
float Time = (float)(Server()->Tick() - GetStartTime(apTeamPlayers[0])) / ((float)Server()->TickSpeed()); int TimeTicks = Server()->Tick() - GetStartTime(apTeamPlayers[0]);
if(Time < 0.000001f) float Time = (float)TimeTicks / (float)Server()->TickSpeed();
if(TimeTicks <= 0)
{ {
return; return;
} }
@ -348,7 +349,7 @@ void CGameTeams::CheckTeamFinished(int Team)
char aBuf[256]; char aBuf[256];
str_format(aBuf, sizeof(aBuf), str_format(aBuf, sizeof(aBuf),
"Your team would've finished in: %d minute(s) %5.2f second(s). Since you had practice mode enabled your rank doesn't count.", "Your team would've finished in: %d minute(s) %5.2f second(s). Since you had practice mode enabled your rank doesn't count.",
(int)Time / 60, Time - ((int)Time / 60 * 60)); (int)Time / 50 / 60, Time - ((int)Time / 60 * 60));
GameServer()->SendChatTeam(Team, aBuf); GameServer()->SendChatTeam(Team, aBuf);
for(unsigned int i = 0; i < PlayersCount; ++i) for(unsigned int i = 0; i < PlayersCount; ++i)
@ -365,7 +366,7 @@ void CGameTeams::CheckTeamFinished(int Team)
for(unsigned int i = 0; i < PlayersCount; ++i) for(unsigned int i = 0; i < PlayersCount; ++i)
OnFinish(apTeamPlayers[i], Time, aTimestamp); OnFinish(apTeamPlayers[i], Time, aTimestamp);
ChangeTeamState(Team, TEAMSTATE_FINISHED); // TODO: Make it better ChangeTeamState(Team, TEAMSTATE_FINISHED); // TODO: Make it better
OnTeamFinish(apTeamPlayers, PlayersCount, Time, aTimestamp); OnTeamFinish(Team, apTeamPlayers, PlayersCount, TimeTicks, aTimestamp);
} }
} }
} }
@ -666,7 +667,7 @@ float *CGameTeams::GetCurrentTimeCp(CPlayer *Player)
return NULL; return NULL;
} }
void CGameTeams::OnTeamFinish(CPlayer **Players, unsigned int Size, float Time, const char *pTimestamp) void CGameTeams::OnTeamFinish(int Team, CPlayer **Players, unsigned int Size, int TimeTicks, const char *pTimestamp)
{ {
int aPlayerCids[MAX_CLIENTS]; int aPlayerCids[MAX_CLIENTS];
@ -685,13 +686,16 @@ void CGameTeams::OnTeamFinish(CPlayer **Players, unsigned int Size, float Time,
} }
if(Size >= (unsigned int)g_Config.m_SvMinTeamSize) if(Size >= (unsigned int)g_Config.m_SvMinTeamSize)
GameServer()->Score()->SaveTeamScore(aPlayerCids, Size, Time, pTimestamp); GameServer()->Score()->SaveTeamScore(Team, aPlayerCids, Size, TimeTicks, pTimestamp);
} }
void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp) void CGameTeams::OnFinish(CPlayer *Player, int TimeTicks, const char *pTimestamp)
{ {
if(!Player || !Player->IsPlaying()) if(!Player || !Player->IsPlaying())
return; return;
float Time = TimeTicks / (float)Server()->TickSpeed();
// TODO:DDRace:btd: this ugly // TODO:DDRace:btd: this ugly
const int ClientId = Player->GetCid(); const int ClientId = Player->GetCid();
CPlayerData *pData = GameServer()->Score()->PlayerData(ClientId); CPlayerData *pData = GameServer()->Score()->PlayerData(ClientId);
@ -804,7 +808,7 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp)
if(CallSaveScore) if(CallSaveScore)
if(g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(ClientId), "nameless tee")) if(g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(ClientId), "nameless tee"))
GameServer()->Score()->SaveScore(ClientId, Time, pTimestamp, GameServer()->Score()->SaveScore(ClientId, TimeTicks, pTimestamp,
GetCurrentTimeCp(Player), Player->m_NotEligibleForFinish); GetCurrentTimeCp(Player), Player->m_NotEligibleForFinish);
bool NeedToSendNewServerRecord = false; bool NeedToSendNewServerRecord = false;

View file

@ -47,8 +47,8 @@ class CGameTeams
*/ */
void KillTeam(int Team, int NewStrongId, int ExceptId = -1); void KillTeam(int Team, int NewStrongId, int ExceptId = -1);
bool TeamFinished(int Team); bool TeamFinished(int Team);
void OnTeamFinish(CPlayer **Players, unsigned int Size, float Time, const char *pTimestamp); void OnTeamFinish(int Team, CPlayer **Players, unsigned int Size, int TimeTicks, const char *pTimestamp);
void OnFinish(CPlayer *Player, float Time, const char *pTimestamp); void OnFinish(CPlayer *Player, int TimeTicks, const char *pTimestamp);
public: public:
enum enum

View file

@ -573,6 +573,23 @@ void CTeeHistorian::RecordPlayerDrop(int ClientId, const char *pReason)
Write(Buffer.Data(), Buffer.Size()); Write(Buffer.Data(), Buffer.Size());
} }
void CTeeHistorian::RecordPlayerName(int ClientId, const char *pName)
{
EnsureTickWritten();
CPacker Buffer;
Buffer.Reset();
Buffer.AddInt(ClientId);
Buffer.AddString(pName, 0);
if(m_Debug)
{
dbg_msg("teehistorian", "drop cid=%d reason='%s'", ClientId, pName);
}
WriteExtra(UUID_TEEHISTORIAN_PLAYER_NAME, Buffer.Data(), Buffer.Size());
}
void CTeeHistorian::RecordConsoleCommand(int ClientId, int FlagMask, const char *pCmd, IConsole::IResult *pResult) void CTeeHistorian::RecordConsoleCommand(int ClientId, int FlagMask, const char *pCmd, IConsole::IResult *pResult)
{ {
EnsureTickWritten(); EnsureTickWritten();
@ -794,6 +811,34 @@ void CTeeHistorian::RecordAntibot(const void *pData, int DataSize)
WriteExtra(UUID_TEEHISTORIAN_ANTIBOT, pData, DataSize); WriteExtra(UUID_TEEHISTORIAN_ANTIBOT, pData, DataSize);
} }
void CTeeHistorian::RecordPlayerFinish(int ClientId, int TimeTicks)
{
CPacker Buffer;
Buffer.Reset();
Buffer.AddInt(ClientId);
Buffer.AddInt(TimeTicks);
if(m_Debug)
{
dbg_msg("teehistorian", "player_finish cid=%d Time=%d", ClientId, TimeTicks);
}
WriteExtra(UUID_TEEHISTORIAN_PLAYER_FINISH, Buffer.Data(), Buffer.Size());
}
void CTeeHistorian::RecordTeamFinish(int TeamId, int TimeTicks)
{
CPacker Buffer;
Buffer.Reset();
Buffer.AddInt(TeamId);
Buffer.AddInt(TimeTicks);
if(m_Debug)
{
dbg_msg("teehistorian", "player_finish cid=%d Time=%d", TeamId, TimeTicks);
}
WriteExtra(UUID_TEEHISTORIAN_TEAM_FINISH, Buffer.Data(), Buffer.Size());
}
void CTeeHistorian::Finish() void CTeeHistorian::Finish()
{ {
dbg_assert(m_State == STATE_START || m_State == STATE_INPUTS || m_State == STATE_BEFORE_ENDTICK || m_State == STATE_BEFORE_TICK, "invalid teehistorian state"); dbg_assert(m_State == STATE_START || m_State == STATE_INPUTS || m_State == STATE_BEFORE_ENDTICK || m_State == STATE_BEFORE_TICK, "invalid teehistorian state");

View file

@ -70,6 +70,7 @@ public:
void RecordPlayerRejoin(int ClientId); void RecordPlayerRejoin(int ClientId);
void RecordPlayerReady(int ClientId); void RecordPlayerReady(int ClientId);
void RecordPlayerDrop(int ClientId, const char *pReason); void RecordPlayerDrop(int ClientId, const char *pReason);
void RecordPlayerName(int ClientId, const char *pName);
void RecordConsoleCommand(int ClientId, int FlagMask, const char *pCmd, IConsole::IResult *pResult); void RecordConsoleCommand(int ClientId, int FlagMask, const char *pCmd, IConsole::IResult *pResult);
void RecordTestExtra(); void RecordTestExtra();
void RecordPlayerSwap(int ClientId1, int ClientId2); void RecordPlayerSwap(int ClientId1, int ClientId2);
@ -90,6 +91,9 @@ public:
void RecordAntibot(const void *pData, int DataSize); void RecordAntibot(const void *pData, int DataSize);
void RecordPlayerFinish(int ClientId, int TimeTicks);
void RecordTeamFinish(int TeamId, int TimeTicks);
int m_Debug; // Possible values: 0, 1, 2. int m_Debug; // Possible values: 0, 1, 2.
private: private:

View file

@ -838,6 +838,53 @@ TEST_F(TeeHistorian, AntibotEmptyMessage)
Expect(EXPECTED, sizeof(EXPECTED)); Expect(EXPECTED, sizeof(EXPECTED));
} }
TEST_F(TeeHistorian, PlayerName)
{
const unsigned char EXPECTED[] = {
// EX uuid=d016f9b9-4151-3b87-87e5-3a6087eb5f26 datalen=4
0x4a,
0xd0, 0x16, 0xf9, 0xb9, 0x41, 0x51, 0x3b, 0x87,
0x87, 0xe5, 0x3a, 0x60, 0x87, 0xeb, 0x5f, 0x26,
0x0e,
// (PLAYER_NAME) id=21 name="nameless tee"
0x15,
0x6e, 0x61, 0x6d, 0x65, 0x6c, 0x65, 0x73, 0x73,
0x20, 0x74, 0x65, 0x65, 0x00};
m_TH.RecordPlayerName(21, "nameless tee");
Expect(EXPECTED, sizeof(EXPECTED));
}
TEST_F(TeeHistorian, PlayerFinish)
{
const unsigned char EXPECTED[] = {
// EX uuid=68943c01-2348-3e01-9490-3f27f8269d94 datalen=4
0x4a,
0x68, 0x94, 0x3c, 0x01, 0x23, 0x48, 0x3e, 0x01,
0x94, 0x90, 0x3f, 0x27, 0xf8, 0x26, 0x9d, 0x94,
0x04,
// (PLAYER_FINISH) id=1 time=1000000
0x01, 0x80, 0x89, 0x7a};
m_TH.RecordPlayerFinish(1, 1000000);
Expect(EXPECTED, sizeof(EXPECTED));
}
TEST_F(TeeHistorian, TeamFinish)
{
const unsigned char EXPECTED[] = {
// EX uuid=9588b9af-3fdc-3760-8043-82deeee317a5 datalen=4
0x4a,
0x95, 0x88, 0xb9, 0xaf, 0x3f, 0xdc, 0x37, 0x60,
0x80, 0x43, 0x82, 0xde, 0xee, 0xe3, 0x17, 0xa5,
0x03,
// (TEAM_FINISH) team=63 Time=5000
0x3f, 0xa8, 0x0f};
m_TH.RecordTeamFinish(63, 1000);
Expect(EXPECTED, sizeof(EXPECTED));
}
TEST_F(TeeHistorian, PrevGameUuid) TEST_F(TeeHistorian, PrevGameUuid)
{ {
m_GameInfo.m_HavePrevGameUuid = true; m_GameInfo.m_HavePrevGameUuid = true;