From 6723910d38155a16bb05a4dbbe3e65b5c1574495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Thu, 22 Dec 2022 23:47:13 +0100 Subject: [PATCH 1/2] Fix players always being considered AFK with `sv_max_afk_time 0` The value `0` should disable the AFK feature, but players are initially considered as AFK, so their AFK state was never updated correctly. --- src/game/server/player.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index b29bcd4f8..bffc0b03a 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -686,16 +686,7 @@ void CPlayer::UpdatePlaytime() void CPlayer::AfkTimer() { - if(g_Config.m_SvMaxAfkTime == 0) - return; - - if(m_LastPlaytime < time_get() - time_freq() * g_Config.m_SvMaxAfkTime) - { - m_Afk = true; - return; - } - - m_Afk = false; + m_Afk = g_Config.m_SvMaxAfkTime != 0 && m_LastPlaytime < time_get() - time_freq() * g_Config.m_SvMaxAfkTime; } int CPlayer::GetDefaultEmote() const From 4439cbd7a1425c858d7c248a4c745c5605599477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 23 Dec 2022 00:06:29 +0100 Subject: [PATCH 2/2] Persist AFK state of players on map change Store AFK state of players in `CPersistentClientData` and restore it when a client is connected. In order for this to work, `m_LastPlaytime` must be adjusted as well to ensure that the AFK state is not reset again automatically by the `AfkTimer` function. The AFK state is encapsulated using `IsAfk` and `GetAfk`. Closes #1966. --- src/game/server/entities/character.cpp | 2 +- src/game/server/gamecontext.cpp | 10 +++++++--- src/game/server/gamecontext.h | 1 + src/game/server/player.cpp | 17 +++++++++++++++++ src/game/server/player.h | 5 ++++- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 42ffc9c1a..6cf162483 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -1028,7 +1028,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID) AmmoCount = (!m_FreezeTime) ? m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo : 0; } - if(GetPlayer()->m_Afk || GetPlayer()->IsPaused()) + if(GetPlayer()->IsAfk() || GetPlayer()->IsPaused()) { if(m_FreezeTime > 0 || m_FreezeTime == -1 || m_Core.m_DeepFrozen || m_Core.m_LiveFrozen) Emote = EMOTE_NORMAL; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index b275bd56c..100569b98 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -922,7 +922,7 @@ void CGameContext::OnTick() GetPlayerChar(m_VoteCreator)->Team() != GetPlayerChar(i)->Team()))) continue; - if(m_apPlayers[i]->m_Afk && i != m_VoteCreator) + if(m_apPlayers[i]->IsAfk() && i != m_VoteCreator) continue; // can't vote in kick and spec votes in the beginning after joining @@ -973,7 +973,7 @@ void CGameContext::OnTick() if(i != j && (!m_apPlayers[j] || str_comp(aaBuf[j], aaBuf[i]) != 0)) continue; - if(m_apPlayers[j] && !m_apPlayers[j]->m_Afk && m_apPlayers[j]->GetTeam() != TEAM_SPECTATORS && + if(m_apPlayers[j] && !m_apPlayers[j]->IsAfk() && m_apPlayers[j]->GetTeam() != TEAM_SPECTATORS && ((Server()->Tick() - m_apPlayers[j]->m_JoinTick) / (Server()->TickSpeed() * 60) > g_Config.m_SvVoteVetoTime || (m_apPlayers[j]->GetCharacter() && m_apPlayers[j]->GetCharacter()->m_DDRaceState == DDRACE_STARTED && (Server()->Tick() - m_apPlayers[j]->GetCharacter()->m_StartTime) / (Server()->TickSpeed() * 60) > g_Config.m_SvVoteVetoTime))) @@ -1488,6 +1488,7 @@ bool CGameContext::OnClientDataPersist(int ClientID, void *pData) return false; } pPersistent->m_IsSpectator = m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS; + pPersistent->m_IsAfk = m_apPlayers[ClientID]->IsAfk(); return true; } @@ -1495,9 +1496,11 @@ void CGameContext::OnClientConnected(int ClientID, void *pData) { CPersistentClientData *pPersistentData = (CPersistentClientData *)pData; bool Spec = false; + bool Afk = true; if(pPersistentData) { Spec = pPersistentData->m_IsSpectator; + Afk = pPersistentData->m_IsAfk; } { @@ -1522,6 +1525,7 @@ void CGameContext::OnClientConnected(int ClientID, void *pData) if(m_apPlayers[ClientID]) delete m_apPlayers[ClientID]; m_apPlayers[ClientID] = new(ClientID) CPlayer(this, NextUniqueClientID, ClientID, StartTeam); + m_apPlayers[ClientID]->SetAfk(Afk); NextUniqueClientID += 1; #ifdef CONF_DEBUG @@ -4361,6 +4365,6 @@ void CGameContext::OnUpdatePlayerServerInfo(char *aBuf, int BufSize, int ID) "\"afk\":%s," "\"team\":%d", aJsonSkin, - JsonBool(m_apPlayers[ID]->m_Afk), + JsonBool(m_apPlayers[ID]->IsAfk()), m_apPlayers[ID]->GetTeam()); } diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 5cf9c4451..57f6df9a3 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -127,6 +127,7 @@ class CGameContext : public IGameServer struct CPersistentClientData { bool m_IsSpectator; + bool m_IsAfk; }; public: diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index bffc0b03a..75e65dcbc 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -689,6 +689,23 @@ void CPlayer::AfkTimer() m_Afk = g_Config.m_SvMaxAfkTime != 0 && m_LastPlaytime < time_get() - time_freq() * g_Config.m_SvMaxAfkTime; } +void CPlayer::SetAfk(bool Afk) +{ + if(g_Config.m_SvMaxAfkTime == 0) + { + m_Afk = false; + return; + } + + m_Afk = Afk; + + // Ensure that the AFK state is not reset again automatically + if(Afk) + m_LastPlaytime = time_get() - time_freq() * g_Config.m_SvMaxAfkTime - 1; + else + m_LastPlaytime = time_get(); +} + int CPlayer::GetDefaultEmote() const { if(m_OverrideEmoteReset >= 0) diff --git a/src/game/server/player.h b/src/game/server/player.h index 0251ba9ab..61f31fe97 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -140,6 +140,7 @@ private: int m_Paused; int64_t m_ForcePauseTime; int64_t m_LastPause; + bool m_Afk; int m_DefEmote; int m_OverrideEmote; @@ -181,7 +182,6 @@ public: vec2 m_ShowDistance; bool m_SpecTeam; bool m_NinjaJetpack; - bool m_Afk; bool m_HasFinishScore; int m_ChatScore; @@ -190,6 +190,9 @@ public: void UpdatePlaytime(); void AfkTimer(); + void SetAfk(bool Afk); + bool IsAfk() const { return m_Afk; } + int64_t m_LastPlaytime; int64_t m_LastEyeEmote; int64_t m_LastBroadcast;