diff --git a/src/engine/server.h b/src/engine/server.h index 2bb5a0b99..4e8b280f4 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -85,7 +85,7 @@ public: virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) = 0; - virtual void OnClientConnected(int ClientID) = 0; + virtual void OnClientConnected(int ClientID, bool AsSpec) = 0; virtual void OnClientEnter(int ClientID) = 0; virtual void OnClientDrop(int ClientID, const char *pReason) = 0; virtual void OnClientDirectInput(int ClientID, void *pInput) = 0; @@ -93,6 +93,7 @@ public: virtual bool IsClientReady(int ClientID) const = 0; virtual bool IsClientPlayer(int ClientID) const = 0; + virtual bool IsClientSpectator(int ClientID) const = 0; virtual const char *GameType() const = 0; virtual const char *Version() const = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 613dc6b99..fc0d636ab 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -892,7 +892,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else if(Msg == NETMSG_READY) { - if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_State == CClient::STATE_CONNECTING) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && (m_aClients[ClientID].m_State == CClient::STATE_CONNECTING || m_aClients[ClientID].m_State == CClient::STATE_CONNECTING_AS_SPEC)) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); @@ -900,8 +900,10 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); + + bool ConnectAsSpec = m_aClients[ClientID].m_State == CClient::STATE_CONNECTING_AS_SPEC; m_aClients[ClientID].m_State = CClient::STATE_READY; - GameServer()->OnClientConnected(ClientID); + GameServer()->OnClientConnected(ClientID, ConnectAsSpec); SendConnectionReady(ClientID); } } @@ -1359,6 +1361,10 @@ int CServer::Run() if(LoadMap(g_Config.m_SvMap)) { // new map loaded + bool aSpecs[MAX_CLIENTS]; + for(int c = 0; c < MAX_CLIENTS; c++) + aSpecs[c] = GameServer()->IsClientSpectator(c); + GameServer()->OnShutdown(); for(int c = 0; c < MAX_CLIENTS; c++) @@ -1368,7 +1374,7 @@ int CServer::Run() SendMap(c); m_aClients[c].Reset(); - m_aClients[c].m_State = CClient::STATE_CONNECTING; + m_aClients[c].m_State = aSpecs[c] ? CClient::STATE_CONNECTING_AS_SPEC : CClient::STATE_CONNECTING; } m_GameStartTime = time_get(); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 9ff0d2c6c..0b5b8b160 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -92,6 +92,7 @@ public: STATE_EMPTY = 0, STATE_AUTH, STATE_CONNECTING, + STATE_CONNECTING_AS_SPEC, STATE_READY, STATE_INGAME, diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 05a49cef5..6fb0f6b8e 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -656,9 +656,9 @@ void CGameContext::OnClientEnter(int ClientID) } } -void CGameContext::OnClientConnected(int ClientID, bool Dummy) +void CGameContext::OnClientConnected(int ClientID, bool Dummy, bool AsSpec) { - m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, Dummy); + m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, Dummy, AsSpec); if(Dummy) return; @@ -1531,7 +1531,12 @@ bool CGameContext::IsClientReady(int ClientID) const bool CGameContext::IsClientPlayer(int ClientID) const { - return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS ? false : true; + return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() != TEAM_SPECTATORS; +} + +bool CGameContext::IsClientSpectator(int ClientID) const +{ + return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS; } const char *CGameContext::GameType() const { return m_pController && m_pController->GetGameType() ? m_pController->GetGameType() : ""; } diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index e22ddedda..3b299621c 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -163,8 +163,8 @@ public: virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID); - virtual void OnClientConnected(int ClientID) { OnClientConnected(ClientID, false); } - void OnClientConnected(int ClientID, bool Dummy); + virtual void OnClientConnected(int ClientID, bool AsSpec) { OnClientConnected(ClientID, false, AsSpec); } + void OnClientConnected(int ClientID, bool Dummy, bool AsSpec); void OnClientTeamChange(int ClientID); virtual void OnClientEnter(int ClientID); virtual void OnClientDrop(int ClientID, const char *pReason); @@ -173,6 +173,7 @@ public: virtual bool IsClientReady(int ClientID) const; virtual bool IsClientPlayer(int ClientID) const; + virtual bool IsClientSpectator(int ClientID) const; virtual const char *GameType() const; virtual const char *Version() const; diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index ba68be5da..ebf31c159 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -12,7 +12,7 @@ MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS) IServer *CPlayer::Server() const { return m_pGameServer->Server(); } -CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy) +CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy, bool AsSpec) { m_pGameServer = pGameServer; m_RespawnTick = Server()->Tick(); @@ -20,7 +20,7 @@ CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy) m_ScoreStartTick = Server()->Tick(); m_pCharacter = 0; m_ClientID = ClientID; - m_Team = GameServer()->m_pController->GetStartTeam(); + m_Team = AsSpec ? TEAM_SPECTATORS : GameServer()->m_pController->GetStartTeam(); m_SpecMode = SPEC_FREEVIEW; m_SpectatorID = -1; m_pSpecFlag = 0; diff --git a/src/game/server/player.h b/src/game/server/player.h index dd57d450d..568c7befa 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -19,7 +19,7 @@ class CPlayer MACRO_ALLOC_POOL_ID() public: - CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy); + CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy, bool AsSpec = false); ~CPlayer(); void Init(int CID);