summaryrefslogtreecommitdiff
path: root/app/legion/networkmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'app/legion/networkmanager.cpp')
-rw-r--r--app/legion/networkmanager.cpp393
1 files changed, 393 insertions, 0 deletions
diff --git a/app/legion/networkmanager.cpp b/app/legion/networkmanager.cpp
new file mode 100644
index 0000000..062e066
--- /dev/null
+++ b/app/legion/networkmanager.cpp
@@ -0,0 +1,393 @@
+//========= 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();
+ }
+}
+
+