diff --git a/src/engine/server.h b/src/engine/server.h index 55c5cc7a4..850b4f11a 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -204,6 +204,7 @@ public: virtual void GetMapInfo(char *pMapName, int MapNameSize, int *pMapSize, SHA256_DIGEST *pSha256, int *pMapCrc) = 0; virtual bool WouldClientNameChange(int ClientID, const char *pNameRequest) = 0; + virtual bool WouldClientClanChange(int ClientID, const char *pClanRequest) = 0; virtual void SetClientName(int ClientID, const char *pName) = 0; virtual void SetClientClan(int ClientID, const char *pClan) = 0; virtual void SetClientCountry(int ClientID, int Country) = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 06daf4195..359363a69 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -452,11 +452,57 @@ bool CServer::SetClientNameImpl(int ClientID, const char *pNameRequest, bool Set return Changed; } +bool CServer::SetClientClanImpl(int ClientID, const char *pClanRequest, bool Set) +{ + dbg_assert(0 <= ClientID && ClientID < MAX_CLIENTS, "invalid client id"); + if(m_aClients[ClientID].m_State < CClient::STATE_READY) + return false; + + const CNameBan *pBanned = m_NameBans.IsBanned(pClanRequest); + if(pBanned) + { + if(m_aClients[ClientID].m_State == CClient::STATE_READY && Set) + { + char aBuf[256]; + if(pBanned->m_aReason[0]) + { + str_format(aBuf, sizeof(aBuf), "Kicked (your clan is banned: %s)", pBanned->m_aReason); + } + else + { + str_copy(aBuf, "Kicked (your clan is banned)"); + } + Kick(ClientID, aBuf); + } + return false; + } + + // trim the clan + char aTrimmedClan[MAX_CLAN_LENGTH]; + str_copy(aTrimmedClan, str_utf8_skip_whitespaces(pClanRequest)); + str_utf8_trim_right(aTrimmedClan); + + bool Changed = str_comp(m_aClients[ClientID].m_aClan, aTrimmedClan) != 0; + + if(Set) + { + // set the client clan + str_copy(m_aClients[ClientID].m_aClan, aTrimmedClan); + } + + return Changed; +} + bool CServer::WouldClientNameChange(int ClientID, const char *pNameRequest) { return SetClientNameImpl(ClientID, pNameRequest, false); } +bool CServer::WouldClientClanChange(int ClientID, const char *pClanRequest) +{ + return SetClientClanImpl(ClientID, pClanRequest, false); +} + void CServer::SetClientName(int ClientID, const char *pName) { SetClientNameImpl(ClientID, pName, true); @@ -464,10 +510,7 @@ void CServer::SetClientName(int ClientID, const char *pName) void CServer::SetClientClan(int ClientID, const char *pClan) { - if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY || !pClan) - return; - - str_copy(m_aClients[ClientID].m_aClan, pClan); + SetClientClanImpl(ClientID, pClan, true); } void CServer::SetClientCountry(int ClientID, int Country) diff --git a/src/engine/server/server.h b/src/engine/server/server.h index e36770edb..4c9e55922 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -296,8 +296,10 @@ public: bool IsClientNameAvailable(int ClientID, const char *pNameRequest); bool SetClientNameImpl(int ClientID, const char *pNameRequest, bool Set); + bool SetClientClanImpl(int ClientID, const char *pClanRequest, bool Set); bool WouldClientNameChange(int ClientID, const char *pNameRequest) override; + bool WouldClientClanChange(int ClientID, const char *pClanRequest) override; void SetClientName(int ClientID, const char *pName) override; void SetClientClan(int ClientID, const char *pClan) override; void SetClientCountry(int ClientID, int Country) override; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 154d12c90..2f7cf788b 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2508,9 +2508,11 @@ void CGameContext::OnChangeInfoNetMessage(const CNetMsg_Cl_ChangeInfo *pMsg, int LogEvent("Name change", ClientID); } - if(str_comp(Server()->ClientClan(ClientID), pMsg->m_pClan)) + if(Server()->WouldClientClanChange(ClientID, pMsg->m_pClan)) + { SixupNeedsUpdate = true; - Server()->SetClientClan(ClientID, pMsg->m_pClan); + Server()->SetClientClan(ClientID, pMsg->m_pClan); + } if(Server()->ClientCountry(ClientID) != pMsg->m_Country) SixupNeedsUpdate = true; @@ -2717,6 +2719,11 @@ void CGameContext::OnStartInfoNetMessage(const CNetMsg_Cl_StartInfo *pMsg, int C return; } Server()->SetClientClan(ClientID, pMsg->m_pClan); + // trying to set client clan can delete the player object, check if it still exists + if(!m_apPlayers[ClientID]) + { + return; + } Server()->SetClientCountry(ClientID, pMsg->m_Country); str_copy(pPlayer->m_TeeInfos.m_aSkinName, pMsg->m_pSkin, sizeof(pPlayer->m_TeeInfos.m_aSkinName)); pPlayer->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor;