Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: The main manager of the networking code in the game
//
// $Revision: $
// $NoKeywords: $
//===========================================================================//
#include "networkmanager.h"
#include "legion.h"
#include "networksystem/inetworkmessage.h"
#include "tier1/bitbuf.h"
#include "inetworkmessagelistener.h"
#include "tier0/icommandline.h"
#include "tier2/tier2.h"
//-----------------------------------------------------------------------------
// Singleton accessor
//-----------------------------------------------------------------------------
static CNetworkManager s_NetworkManager; extern CNetworkManager *g_pNetworkManager = &s_NetworkManager;
//-----------------------------------------------------------------------------
// Static members.
// NOTE: Do *not* set this to 0; it could cause us to lose some registered
// menus since that list is set up during construction
//-----------------------------------------------------------------------------
INetworkMessageFactory *CNetworkManager::m_pFirstFactory;
//-----------------------------------------------------------------------------
// Call to register methods to register network messages
//-----------------------------------------------------------------------------
INetworkMessageFactory *CNetworkManager::RegisterNetworkMessage( INetworkMessageFactory *pNetworkMessageFactory ) { // NOTE: This method is expected to be called during global constructor
// time, so it must not require any global constructors to be called to work
INetworkMessageFactory *pPrevFactory = m_pFirstFactory; m_pFirstFactory = pNetworkMessageFactory; return pPrevFactory; }
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CNetworkManager::Init() { m_bIsClient = m_bIsServer = false; m_pClientToServerConnection = NULL;
// Make a listener array for each message type
// Register all network messages
INetworkMessageFactory *pFactory; for ( pFactory = m_pFirstFactory; pFactory; pFactory = pFactory->GetNextFactory() ) { INetworkMessage *pNetworkMessage = pFactory->CreateNetworkMessage(); g_pNetworkSystem->RegisterMessage( pNetworkMessage ); }
return true; }
void CNetworkManager::Shutdown() { ShutdownClient(); ShutdownServer(); }
//-----------------------------------------------------------------------------
// Start a server up
//-----------------------------------------------------------------------------
bool CNetworkManager::StartServer( unsigned short nServerListenPort ) { ShutdownServer( ); if ( nServerListenPort == LEGION_DEFAULT_SERVER_PORT ) { nServerListenPort = CommandLine()->ParmValue( "-serverport", NETWORKSYSTEM_DEFAULT_SERVER_PORT ); } m_bIsServer = g_pNetworkSystem->StartServer( nServerListenPort ); return m_bIsServer; }
void CNetworkManager::ShutdownServer( ) { if ( m_bIsServer ) { g_pNetworkSystem->ShutdownServer( ); m_bIsServer = false; } }
//-----------------------------------------------------------------------------
// Start a client up
//-----------------------------------------------------------------------------
bool CNetworkManager::StartClient( unsigned short nClientListenPort ) { ShutdownClient( );
if ( nClientListenPort == LEGION_DEFAULT_CLIENT_PORT ) { nClientListenPort = CommandLine()->ParmValue( "-clientport", NETWORKSYSTEM_DEFAULT_CLIENT_PORT ); }
m_bIsClient = g_pNetworkSystem->StartClient( nClientListenPort ); return m_bIsClient; }
void CNetworkManager::ShutdownClient( ) { if ( m_bIsClient ) { DisconnectClientFromServer(); g_pNetworkSystem->ShutdownClient( ); m_bIsClient = false; } }
//-----------------------------------------------------------------------------
// Connects/disconnects the client to a server
//-----------------------------------------------------------------------------
bool CNetworkManager::ConnectClientToServer( const char *pServerName, unsigned short nServerListenPort ) { DisconnectClientFromServer(); if ( !IsClient() ) return false;
if ( nServerListenPort == LEGION_DEFAULT_SERVER_PORT ) { nServerListenPort = CommandLine()->ParmValue( "-serverport", NETWORKSYSTEM_DEFAULT_SERVER_PORT ); } m_pClientToServerConnection = g_pNetworkSystem->ConnectClientToServer( pServerName, nServerListenPort ); return ( m_pClientToServerConnection != NULL ); }
void CNetworkManager::DisconnectClientFromServer( ) { if ( m_pClientToServerConnection ) { g_pNetworkSystem->DisconnectClientFromServer( m_pClientToServerConnection ); m_pClientToServerConnection = NULL; } }
//-----------------------------------------------------------------------------
// Start up a game where the local player is playing
//-----------------------------------------------------------------------------
bool CNetworkManager::HostGame() { if ( !StartServer() ) return false;
if ( !StartClient() ) { ShutdownServer(); return false; }
if ( !ConnectClientToServer( "localhost" ) ) { ShutdownClient(); ShutdownServer(); return false; }
return true; }
void CNetworkManager::StopHostingGame() { ShutdownClient(); ShutdownServer(); }
//-----------------------------------------------------------------------------
// Are we a client?/Are we a server? (we can be both)
//-----------------------------------------------------------------------------
bool CNetworkManager::IsClient() { return m_bIsClient; }
bool CNetworkManager::IsServer() { return m_bIsServer; }
//-----------------------------------------------------------------------------
// If we are a client, are we connected to the server?
//-----------------------------------------------------------------------------
bool CNetworkManager::IsClientConnected() { return m_bIsClient && ( m_pClientToServerConnection != NULL ) && ( m_pClientToServerConnection->GetConnectionState() == CONNECTION_STATE_CONNECTED ); }
//-----------------------------------------------------------------------------
// Post a network message to the server
//-----------------------------------------------------------------------------
void CNetworkManager::PostClientToServerMessage( INetworkMessage *pMessage ) { if ( IsClientConnected() ) { m_pClientToServerConnection->AddNetMsg( pMessage ); } }
//-----------------------------------------------------------------------------
// Broadcast a network message to all clients
//-----------------------------------------------------------------------------
void CNetworkManager::BroadcastServerToClientMessage( INetworkMessage *pMessage ) { if ( IsServer() ) { int nCount = m_ServerToClientConnection.Count(); for ( int i = 0; i < nCount; ++i ) { m_ServerToClientConnection[i]->AddNetMsg( pMessage ); } } }
//-----------------------------------------------------------------------------
// Add, remove network message listeners
//-----------------------------------------------------------------------------
void CNetworkManager::AddListener( NetworkMessageRoute_t route, int nGroup, int nType, INetworkMessageListener *pListener ) { CUtlVector< CUtlVector< CUtlVector < INetworkMessageListener* > > > &listeners = m_Listeners[ route ]; if ( listeners.Count() <= nGroup ) { listeners.AddMultipleToTail( nGroup - listeners.Count() + 1 ); }
if ( listeners[nGroup].Count() <= nType ) { listeners[nGroup].AddMultipleToTail( nType - listeners[nGroup].Count() + 1 ); }
Assert( listeners[nGroup][nType].Find( pListener ) < 0 ); listeners[nGroup][nType].AddToTail( pListener ); }
void CNetworkManager::RemoveListener( NetworkMessageRoute_t route, int nGroup, int nType, INetworkMessageListener *pListener ) { CUtlVector< CUtlVector< CUtlVector < INetworkMessageListener* > > > &listeners = m_Listeners[ route ]; if ( listeners.Count() > nGroup ) { if( listeners[nGroup].Count() > nType ) { // Maintain order of listeners (not sure if it matters)
listeners[nGroup][nType].FindAndRemove( pListener ); } } }
//-----------------------------------------------------------------------------
// Notifies listeners about a network message
//-----------------------------------------------------------------------------
void CNetworkManager::NotifyListeners( NetworkMessageRoute_t route, INetworkMessage *pMessage ) { CUtlVector< CUtlVector< CUtlVector < INetworkMessageListener* > > > &listeners = m_Listeners[ route ];
// based on id, search for installed listeners
int nGroup = pMessage->GetGroup(); if ( listeners.Count() > nGroup ) { int nType = pMessage->GetType(); if ( listeners[nGroup].Count() > nType ) { CUtlVector< INetworkMessageListener* > &list = listeners[nGroup][nType]; int nCount = list.Count(); for ( int i = 0; i < nCount; ++i ) { list[i]->OnNetworkMessage( route, pMessage ); } } } }
//-----------------------------------------------------------------------------
// Process messages received by the client
//-----------------------------------------------------------------------------
void CNetworkManager::ProcessClientMessages() { NetworkEvent_t *pEvent = g_pNetworkSystem->FirstNetworkEvent(); for ( ; pEvent; pEvent = g_pNetworkSystem->NextNetworkEvent( ) ) { switch ( pEvent->m_nType ) { /*
case NETWORK_EVENT_CONNECTED: { NetworkConnectionEvent_t* pConnectEvent = static_cast<NetworkConnectionEvent_t*>( pEvent ); m_pClientToServerConnection = pConnectEvent->m_pChannel; } break;
case NETWORK_EVENT_DISCONNECTED: { NetworkDisconnectionEvent_t* pDisconnectEvent = static_cast<NetworkDisconnectionEvent_t*>( pEvent ); Assert( m_pClientToServerConnection == pDisconnectEvent->m_pChannel ); if ( m_pClientToServerConnection == pDisconnectEvent->m_pChannel ) { m_pClientToServerConnection = NULL; } } break; */
case NETWORK_EVENT_MESSAGE_RECEIVED: { NetworkMessageReceivedEvent_t* pPacketEvent = static_cast<NetworkMessageReceivedEvent_t*>( pEvent ); NotifyListeners( NETWORK_MESSAGE_SERVER_TO_CLIENT, pPacketEvent->m_pNetworkMessage ); } break; } } }
//-----------------------------------------------------------------------------
// Process messages received by the server
//-----------------------------------------------------------------------------
void CNetworkManager::ProcessServerMessages() { NetworkEvent_t *pEvent = g_pNetworkSystem->FirstNetworkEvent(); for ( ; pEvent; pEvent = g_pNetworkSystem->NextNetworkEvent( ) ) { switch ( pEvent->m_nType ) { case NETWORK_EVENT_CONNECTED: { NetworkConnectionEvent_t* pConnectEvent = static_cast<NetworkConnectionEvent_t*>( pEvent ); m_ServerToClientConnection.AddToTail( pConnectEvent->m_pChannel ); } break;
case NETWORK_EVENT_DISCONNECTED: { NetworkDisconnectionEvent_t* pDisconnectEvent = static_cast<NetworkDisconnectionEvent_t*>( pEvent ); m_ServerToClientConnection.FindAndRemove( pDisconnectEvent->m_pChannel ); } break; case NETWORK_EVENT_MESSAGE_RECEIVED: { NetworkMessageReceivedEvent_t* pPacketEvent = static_cast<NetworkMessageReceivedEvent_t*>( pEvent ); NotifyListeners( NETWORK_MESSAGE_CLIENT_TO_SERVER, pPacketEvent->m_pNetworkMessage ); } break; } } }
//-----------------------------------------------------------------------------
// Per-frame update
//-----------------------------------------------------------------------------
void CNetworkManager::Update( ) { if ( IsClient() ) { g_pNetworkSystem->ClientSendMessages(); }
if ( IsServer() ) { g_pNetworkSystem->ServerReceiveMessages(); ProcessServerMessages(); g_pNetworkSystem->ServerSendMessages(); }
if ( IsClient() ) { g_pNetworkSystem->ClientReceiveMessages(); ProcessClientMessages(); } }
|