⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commmanager.cpp

📁 分布式坦克游戏
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
*                                                                             
*   CommManager.cpp                                                            
*                                                                             
*   Electrical Engineering Faculty - Software Lab                             
*   Spring semester 1998                                                      
*                                                                             
*   Tanks game                                                                
*                                                                             
*   Module description: The Communication Manager wraps the DPlay API, and 
*                       manages the communication setting, initializing,
*                       termination, and messages traffic to and from the app.
*                                                                             
*   Authors: Eran Yariv - 28484475                                           
*            Moshe Zur  - 24070856                                           
*                                                                            
*                                                                            
*   Date: 23/09/98                                                           
*                                                                            
******************************************************************************/
#include "stdafx.h"
#include <objbase.h>    // we need this or else initguid.h won't let us compile
#include <initguid.h>   // including the header makes DEFINE_GUID define the GUID.
#include "Tanks.h"
#include "Client.h"
#include "Host.h"
#include "EnumSession.h"

#ifdef GATHER_NETWORK_STATS

    #define SET_SESSION_START_TIME(t)           {m_dwSessionStartTime=(t);      \
                                                 m_dwLastSecTimeRecv = m_dwLastSecTimeSend = m_dwSessionStartTime;}

    #define INC_TOTAL_BYTES_SENT(cb)            m_dwTotalBytesSent+=(cb);
    #define INC_TOTAL_BYTES_RECEIVED(cb)        m_dwTotalBytesReceived+=(cb);
    #define INC_TOTAL_CLIENT_MESSAGES_SENT      m_dwTotalClientMsgsSent++;
    #define INC_TOTAL_CLIENT_MESSAGES_RECEIVED  m_dwTotalClientMsgsReceived++;
    #define INC_TOTAL_HOST_MESSAGES_SENT        m_dwTotalHostMsgsSent++;
    #define INC_TOTAL_HOST_MESSAGES_RECEIVED    m_dwTotalHostMsgsReceived++;
    
    #define UPDATE_BIGGEST_PACKET_SENT(cb)      m_dwBiggestSentPacketSize = max (m_dwBiggestSentPacketSize, (cb));
    #define UPDATE_SMALLEST_PACKET_SENT(cb)     m_dwSmallestSentPacketSize = min (m_dwSmallestSentPacketSize, (cb));
    #define UPDATE_BIGGEST_PACKET_RECEIVED(cb)  m_dwBiggestReceivedPacketSize = max (m_dwBiggestReceivedPacketSize, (cb));
    #define UPDATE_SMALLEST_PACKET_RECEIVED(cb) m_dwSmallestReceivedPacketSize = min (m_dwSmallestReceivedPacketSize,(cb));

    #define INC_CLIENT_SEND_ERRORS              m_dwClientSendErrors++;
    #define INC_HOST_SEND_ERRORS                m_dwHostSendErrors++;
    #define INC_RECEIVE_ERRORS                  m_dwReceiveErrors++;

    #define UPDATE_RECEIVE                      UpdateReceive();
    #define UPDATE_SEND                         UpdateSend();
    #define TRACE_NETWORK_STATS                 TraceNetworkStats();


#else       // !defined GATHER_NETWORK_STATS

    #define SET_SESSION_START_TIME(t)           
    #define INC_TOTAL_BYTES_SENT(cb)            
    #define INC_TOTAL_BYTES_RECEIVED(cb)        
    #define INC_TOTAL_CLIENT_MESSAGES_SENT      
    #define INC_TOTAL_CLIENT_MESSAGES_RECEIVED  
    #define INC_TOTAL_HOST_MESSAGES_SENT        
    #define INC_TOTAL_HOST_MESSAGES_RECEIVED    
    
    #define UPDATE_BIGGEST_PACKET_SENT(cb)      
    #define UPDATE_SMALLEST_PACKET_SENT(cb)     
    #define UPDATE_BIGGEST_PACKET_RECEIVED(cb)  
    #define UPDATE_SMALLEST_PACKET_RECEIVED(cb) 
    #define INC_CLIENT_SEND_ERRORS              
    #define INC_HOST_SEND_ERRORS                
    #define INC_RECEIVE_ERRORS                  
    #define UPDATE_RECEIVE                      
    #define UPDATE_SEND
    #define TRACE_NETWORK_STATS

#endif // defined GATHER_NETWORK_STATS



char TANKS_SESSION_NAME[] = "Tanks Game";
const BYTE CCommManager::ACK = 0xFF;
const DPID CCommManager::INVALID_PLAYER_ID = MAX_DWORD;

CCommManager::CCommManager() :
    m_pIDP(NULL),
    m_fIsConnected(FALSE),
    m_fIsPlaying(FALSE),
    m_fIsHost(TRUE),
    m_IncomingMsgQ(TANKS_APP->m_gIncomingMsgQueue),
    m_OutgoingMsgQ(TANKS_APP->m_gOutgoingMsgQueue),
    m_idHost(INVALID_PLAYER_ID),
    m_idPlayer(INVALID_PLAYER_ID),
    m_pHost(NULL)

#ifdef GATHER_NETWORK_STATS
    ,
    m_dwTotalBytesSent               (0),
    m_dwTotalBytesReceived           (0),
    m_dwBiggestSentPacketSize        (0),
    m_dwLastRecvTotal                (0),
    m_dwLastSentTotal                (0),
    m_dwSmallestSentPacketSize       (MAX_DWORD),
    m_dwBiggestReceivedPacketSize    (0),
    m_dwSmallestReceivedPacketSize   (MAX_DWORD),
    m_dwMaxBytesSentInLastSecond     (0),
    m_dwMaxBytesReceivedInLastSecond (0),
    m_dwTotalClientMsgsSent          (0),
    m_dwTotalClientMsgsReceived      (0),
    m_dwClientSendErrors             (0),   
    m_dwTotalHostMsgsSent            (0),
    m_dwTotalHostMsgsReceived        (0),
    m_dwHostSendErrors               (0),
    m_dwReceiveErrors                (0)
#endif //   GATHER_NETWORK_STATS
{
    m_hRecvEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    m_hQuitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    // Create client
    m_pClient = new CClient(*this);
}

CCommManager::~CCommManager ()
{
    if (m_pIDP)
        m_pIDP->Release();

    if (m_pClient)
        delete m_pClient;

    if (m_pHost)
        delete m_pHost;

    CloseHandle (m_hRecvEvent);
    CloseHandle (m_hQuitEvent);
}


void
CCommManager::SetCommParams()
{
    CCommSettingDlg dlg;

    dlg.DoModal();

    return;
}

/*------------------------------------------------------------------------------

  Function: OnNewGame

  Purpose:  Initailizes the DPlay object, and starts the connection protocol w/
            the server. In case this is a server machine, it also starts the
            host object.

  Input:    None.

  Output:   Return TRUE if succeeded to connect to a game session.

------------------------------------------------------------------------------*/
BOOL 
CCommManager::OnNewGame()
{
    try {
        // Create DirectPlay2 interface
        CreateDPInterface();
        // Start session
        OpenSession();
        // Create player
        CreatePlayer();
    } catch (CString &strErr) {
        AfxMessageBox(strErr, MB_OK | MB_ICONEXCLAMATION);
        return FALSE;
    }
    //
    //  At last - all is well, start the message pumping:
    //
        // Empty both queues:
    TANKS_APP->m_gOutgoingMsgQueue.Empty();
    TANKS_APP->m_gOutgoingMsgQueue.Empty();

    m_bLostServerConnection = FALSE;
    TANKS_APP->SetMaxRTT(MAX_VALID_RTT);  // Init the global max RTT param from the reg.
    StartWorkerThread();

    if (! m_pClient->WaitForGameProperties()) {
        AfxMessageBox("Server timed out");
        return FALSE;
    }
    return TRUE;
}

BOOL 
CCommManager::OnStopGame()
{
    if (m_fIsPlaying) {
        // Stop the working thread:
        EndThread(TRUE);
        // Destroy the player object:
        DestroyPlayer();
        // Stop the session:
        CloseSession();
    }
    return TRUE;
}

void
CCommManager::CreateDPInterface ()
{
    LPDIRECTPLAY   lpDirectPlay1 = NULL;
    HRESULT        hr;

    //
    //  Get the GUID of the connection provider.
    //
    GUID guidCurr;
    if (! TANKS_APP->GetStoredGUID(&guidCurr)) 
    {   // Its the first run on this machine and no connection was selected.
        throw CString ("No connection was selected.\n"
            "Use Setting->Communication prefernces menu\n"
            "to select a connection and try again.");
        return;
    }

    //
    //  Release previous interface.
    //
    if (m_pIDP) 
    {    
        CloseSession();     // Just to make sure
        m_pIDP->Release();  // Release the old interface
        m_pIDP = NULL;      // Prepare for a failure
    }

    //
    //  Get a new interface.
    //

    // Retrieve a DirectPlay 1.0 interface.
    hr = DirectPlayCreate(&guidCurr, &lpDirectPlay1, NULL);
    if FAILED(hr) {
        TRACE("DirectPlayCreate failed HR=%ul\n", hr);
        throw CString("Communication failure.\n(DirectPlayCreate failed)");
        return;
    }
    
    // Query for an ANSI DirectPlay2 interface.
    hr = lpDirectPlay1->QueryInterface(IID_IDirectPlay2A, (LPVOID *) &m_pIDP);

    // Release DirectPlay 1.0 interface
    if (lpDirectPlay1)
        lpDirectPlay1->Release();

    if FAILED(hr) {
        TRACE("QueryInterface for IID_IDirectPlay2A failed HR=%ul\n", hr);
        throw CString("Communication failure.\n"
            "(QueryInterface failed)");
        return;
    }
}

void
CCommManager::OpenSession()
{
    HRESULT hr;
    DPSESSIONDESC2 SessionDesc;

    // Close any exiting session.
    if (m_fIsConnected)
        CloseSession();

    ZeroMemory(&SessionDesc, sizeof(DPSESSIONDESC2));
    SessionDesc.dwSize = sizeof(DPSESSIONDESC2);
    SessionDesc.guidApplication = TANKS_GUID;
    
    // Get user choice from registry:
    m_fIsHost = TANKS_APP->GetStoredIsHostFlag();
    //
    //  Open session:
    //
    if (m_fIsHost) 
    {    // Create a new session
        CString strName = TANKS_APP->GetStoredPlayerName();

        SessionDesc.dwFlags =   DPSESSION_KEEPALIVE         | 
                                DPSESSION_NODATAMESSAGES;
        // We add one for our Host that occupies an additional player.
        SessionDesc.dwMaxPlayers = MAX_TANKS + 1;   
        SessionDesc.lpszSessionNameA = const_cast<LPSTR>((LPCSTR)strName);
        hr = m_pIDP->Open(&SessionDesc, DPOPEN_CREATE);
        if FAILED(hr) {
            throw CString("Cannot create new session");
            return;
        }
        // Create the host object:
        m_CSHost.Lock();
        m_pHost = new CHost(*this);
        if (! m_pHost) 
        {
            m_CSHost.Unlock();
            throw CString("Cannot create new session");
            return;
        }
        m_CSHost.Unlock();
    } 
    else 
    {
        //
        // Let user select a session.
        //
        DPSESSIONDESC2 dpDesc;

        ZeroMemory(&dpDesc, sizeof(DPSESSIONDESC2));
        dpDesc.dwSize = sizeof(DPSESSIONDESC2);
        dpDesc.guidApplication = TANKS_GUID;

        // Bring the select session dialog.
        CEnumSession dlg(m_pIDP, &dpDesc.guidInstance);
        if (IDOK != dlg.DoModal())
        {   // User aborted or EnumSession failed.
            throw CString("No session selected");
            return;
        }
        // Join the session:
        hr = m_pIDP->Open(&dpDesc, DPOPEN_JOIN);
        if FAILED(hr) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -