From 157e8b7302c05927ffa2f6b0f0576b884c6f6b46 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Tue, 12 Dec 2023 23:20:30 +0100 Subject: [PATCH] Pass error message as buffer to CanJoinTeam() Now `CGameContext` no longer assumes the `IGameController` declined the team join due to slots. This enables custom gametypes to disallow joining the game if the player died, an active tournament is running or the player is not logged in yet. And then the controller can print the correct error message accordingly. --- src/game/server/gamecontext.cpp | 24 ++++++++---------------- src/game/server/gamecontroller.cpp | 20 ++++++++++++++++---- src/game/server/gamecontroller.h | 2 +- src/game/server/player.cpp | 2 +- src/game/server/player.h | 2 +- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 56b7f3e44..cf13e81ad 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2389,24 +2389,16 @@ void CGameContext::OnSetTeamNetMessage(const CNetMsg_Cl_SetTeam *pMsg, int Clien } // Switch team on given client and kill/respawn them - if(m_pController->CanJoinTeam(pMsg->m_Team, ClientID)) + char aTeamJoinError[512]; + if(m_pController->CanJoinTeam(pMsg->m_Team, ClientID, aTeamJoinError, sizeof(aTeamJoinError))) { - if(pPlayer->IsPaused()) - SendChatTarget(ClientID, "Use /pause first then you can kill"); - else - { - if(pPlayer->GetTeam() == TEAM_SPECTATORS || pMsg->m_Team == TEAM_SPECTATORS) - m_VoteUpdate = true; - m_pController->DoTeamChange(pPlayer, pMsg->m_Team); - pPlayer->m_TeamChangeTick = Server()->Tick(); - } - } - else - { - char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "Only %d active players are allowed", Server()->MaxClients() - g_Config.m_SvSpectatorSlots); - SendBroadcast(aBuf, ClientID); + if(pPlayer->GetTeam() == TEAM_SPECTATORS || pMsg->m_Team == TEAM_SPECTATORS) + m_VoteUpdate = true; + m_pController->DoTeamChange(pPlayer, pMsg->m_Team); + pPlayer->m_TeamChangeTick = Server()->Tick(); } + if(aTeamJoinError[0]) + SendBroadcast(aTeamJoinError, ClientID); } void CGameContext::OnIsDDNetLegacyNetMessage(const CNetMsg_Cl_IsDDNetLegacy *pMsg, int ClientID, CUnpacker *pUnpacker) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 270dc6a0e..138c36e18 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -710,14 +710,21 @@ int IGameController::GetAutoTeam(int NotThisID) int Team = 0; - if(CanJoinTeam(Team, NotThisID)) + if(CanJoinTeam(Team, NotThisID, nullptr, 0)) return Team; return -1; } -bool IGameController::CanJoinTeam(int Team, int NotThisID) +bool IGameController::CanJoinTeam(int Team, int NotThisID, char *pErrorReason, int ErrorReasonSize) { - if(Team == TEAM_SPECTATORS || (GameServer()->m_apPlayers[NotThisID] && GameServer()->m_apPlayers[NotThisID]->GetTeam() != TEAM_SPECTATORS)) + const CPlayer *pPlayer = GameServer()->m_apPlayers[NotThisID]; + if(pPlayer && pPlayer->IsPaused()) + { + if(pErrorReason) + str_copy(pErrorReason, "Use /pause first then you can kill", ErrorReasonSize); + return false; + } + if(Team == TEAM_SPECTATORS || (pPlayer && pPlayer->GetTeam() != TEAM_SPECTATORS)) return true; int aNumplayers[2] = {0, 0}; @@ -730,7 +737,12 @@ bool IGameController::CanJoinTeam(int Team, int NotThisID) } } - return (aNumplayers[0] + aNumplayers[1]) < Server()->MaxClients() - g_Config.m_SvSpectatorSlots; + if((aNumplayers[0] + aNumplayers[1]) < Server()->MaxClients() - g_Config.m_SvSpectatorSlots) + return true; + + if(pErrorReason) + str_format(pErrorReason, ErrorReasonSize, "Only %d active players are allowed", Server()->MaxClients() - g_Config.m_SvSpectatorSlots); + return false; } int IGameController::ClampTeam(int Team) diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 81c3fa33b..a3044d151 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -145,7 +145,7 @@ public: */ virtual const char *GetTeamName(int Team); virtual int GetAutoTeam(int NotThisID); - virtual bool CanJoinTeam(int Team, int NotThisID); + virtual bool CanJoinTeam(int Team, int NotThisID, char *pErrorReason, int ErrorReasonSize); int ClampTeam(int Team); CClientMask GetMaskForPlayerWorldEvent(int Asker, int ExceptID = -1); diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index a98192c20..11dab99af 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -832,7 +832,7 @@ int CPlayer::ForcePause(int Time) return Pause(PAUSE_SPEC, true); } -int CPlayer::IsPaused() +int CPlayer::IsPaused() const { return m_ForcePauseTime ? m_ForcePauseTime : -1 * m_Paused; } diff --git a/src/game/server/player.h b/src/game/server/player.h index 1f050cb78..4c9224c21 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -176,7 +176,7 @@ public: void ProcessPause(); int Pause(int State, bool Force); int ForcePause(int Time); - int IsPaused(); + int IsPaused() const; bool IsPlaying(); int64_t m_Last_KickVote;