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.
This commit is contained in:
ChillerDragon 2023-12-12 23:20:30 +01:00
parent bcc92fa0fb
commit 157e8b7302
5 changed files with 27 additions and 23 deletions

View file

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

View file

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

View file

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

View file

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

View file

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