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

📄 message.cpp

📁 分布式坦克游戏
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
*                                                                             
*   Message.cpp                                                            
*                                                                             
*   Electrical Engineering Faculty - Software Lab                             
*   Spring semester 1998                                                      
*                                                                             
*   Tanks game                                                                
*                                                                             
*   Module description: Messages are send between the game threads (in process)
*                       and over the network between the host and players.
*                       We use pool allocation techniques to make message 
*                       allocation fast and bit fields to compact the size of 
*                       messages when send over the net.
*                                                                             
*   Authors: Eran Yariv - 28484475                                           
*            Moshe Zur  - 24070856                                           
*                                                                            
*                                                                            
*   Date: 23/09/98                                                           
*                                                                            
******************************************************************************/
#include "stdafx.h"
#include "Message.h"
#include "Tanks.h"

#pragma pack (push)
#pragma pack (1)

CPool<CMessage> CMessage::m_Pool;       // The message pool. We overload the new and
                                        // delete methods to use the pools fast allocation
                                        // and deallocation methods.

#define VAR_LEN                         0xFF     // Variable message length
#define TNK_CHK_SUM_TO_TANK_ID(pb)      (BYTE(( ((PBYTE(pb))[2]) >> 2) & 0x03))
#define MSG_HEADER_SIZE                 5   // Msg type (1 Byte) + Msg time (DWORD)

static BYTE MsgSizeArr[] =              // Messages size look up table:
{
    MSG_HEADER_SIZE + sizeof (BonusParamTag),           // ADD_BONUS 
                                                        // (See BonusParamTag for description)
    MSG_HEADER_SIZE + sizeof (TankParamTag),            // ADD_TANK  
                                                        // (See TankParamTag for description)
    MSG_HEADER_SIZE + sizeof (BoardParamTag),           // ADD_BOARD 
                                                        // (See BoardParamTag for description)
    MSG_HEADER_SIZE + sizeof (BomberParamTag),          // ADD_BOMBER 
                                                        // (See BomberParamTag for description)
    MSG_HEADER_SIZE + sizeof (TankRemoveParamTag),      // REMOVE_TANK 
                                                        // (See TankRemoveParamTag for description)
    MSG_HEADER_SIZE + sizeof (ManouverSetParamTag),     // MANOUVER_SET 
                                                        // (See ManouverSetParamTag for description)
    MSG_HEADER_SIZE + sizeof (TankStatusParamTag),      // SET_TANK_STATUS 
                                                        // (See TankStatusParamTag for description)
    MSG_HEADER_SIZE + sizeof (TankPosParamTag),         // SET_TANK_POS
                                                        // (See TankPosParamTag for description)
    MSG_HEADER_SIZE + sizeof (TankZombieParamTag),      // SET_TANK_ZOMBIE
                                                        // (See TankZombieParamTag for description)
    MSG_HEADER_SIZE + sizeof (TankRequestParamTag),     // REQUEST_TANK
                                                        // (See TankRequestParamTag for description)
    VAR_LEN,                                            // CHECK_SUM
                                                        // (See SingleTankChkSumType for description)
    VAR_LEN                                             // CHAT
};

BYTE         * CMessage::m_MsgSizeArr = MsgSizeArr;
TIMER_CLASS  * CMessage::m_pTimer = NULL;


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

  Function: Constructor.

  Purpose:  Constructor for messages created internally (not from network)

  Input:    type: Type of message to be constructed.
            data: Data of message to be constructed.
            typ:  Flag to indicate if message contains our local game time
                  (internal message between threads) or the host game time
                  (external message sent over the net).

------------------------------------------------------------------------------*/
CMessage::CMessage (MessageType type, 
                    union MessageData& data, 
                    GameMessageType typ) : 
    m_Type (type), 
    m_UnionData (data)
{   
    if (NULL == m_pTimer)
        m_pTimer = &(TANKS_APP->m_gTimer);

    memcpy (&m_UnionData, &data, sizeof(union MessageData));
    if (PLAYER_MSG == typ)
    {   // Message created internally (not from network) and is directed out.
        // This only happens for clients.
        // Convert to server's time (game time)
        m_dwMsgTime = m_pTimer->GetRemoteTime ();
    }
    else 
        // Just store local time as message time:
        m_dwMsgTime = m_pTimer->GetLocalTime();
}

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

  Function: Constructor.

  Purpose:  Constructor for messages arriving from network (not created internally)

  Input:    pData: Pointer to data buffer.
            bDataSize:  Size of data buffer.
            typ: Flag indicating if message time is global (host) or local 
                 (any player).

------------------------------------------------------------------------------*/
CMessage::CMessage (PBYTE pData, BYTE bDataSize, GameMessageType typ)
{
    if (NULL == m_pTimer)
        m_pTimer = &(TANKS_APP->m_gTimer);

        // Get message ID
    BYTE bType = BYTE((pData[0]) & 0x000F);
        // Make sure the message has a valid type
    ASSERT (bType < sizeof (MsgSizeArr) / sizeof(MsgSizeArr[0]));
        // Make sure the data fits the size according to its type
    ASSERT ((VAR_LEN == m_MsgSizeArr[bType]) ||     // Variable length or (ignored)
            (bDataSize == m_MsgSizeArr[bType]));    // exact length
        // Message type ok - store it.
    m_Type = MessageType(bType);

    pData++;
        // Read time from message
    PDWORD pTime = PDWORD(pData);
    if (PLAYER_MSG == typ)
    { // Requested by player (coming from server), convert to local time
        m_dwMsgTime = m_pTimer->GetLocalTime (*pTime);
    }
    else
    { // Requested by server (coming from a client to server), already in server's time
        m_dwMsgTime = *pTime;
    }

    pData += sizeof(DWORD);
        // Handle decoding of incoming message according to type
    switch (m_Type)
    {   
        case ADD_BONUS:                 // Server => Client
            DecodeAddBonus (pData);     
            break;
        case ADD_TANK:                  // Server => Client
            DecodeAddTank (pData);
            break;
        case ADD_BOARD:                 // Server => Client
            DecodeAddBoard (pData);
            break;
        case ADD_BOMBER:                // Server => Client
            DecodeAddBomber (pData);
            break;
        case REMOVE_TANK:               // Server => Client
            DecodeRemoveTank (pData);
            break;
        case MANOUVER_SET:              // Server <=> Client
            DecodeManouverSet (pData);
            break;
        case REQUEST_TANK:              // Client => Server
            DecodeRequestTank (pData);
            break;
        case CHECK_SUM:                 // Client => Server;
            DecodeCheckSum (pData);
            break;
        case SET_TANK_STATUS:            // Server => Client
            DecodeSetTankStatus (pData);
            break;
        case SET_TANK_POS:              // Server => Client
            DecodeSetTankPos (pData);
            break;
        case SET_TANK_ZOMBIE:              // Server => Client
            DecodeSetTankZombie (pData);
            break;
        case CHAT:
            DecodeChat(pData);
            break;
        default:
            ASSERT (FALSE);
            break;
    }
    UNREFERENCED_PARAMETER(bDataSize);
}


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

  Function: GetBuffer

  Purpose:  Spools the message contents to buffer, minimizing buffer size by 
            using bit fields to store the message contents.

  Input:    pRes: Pointer to buffer.

  Output:   Return the buffer length.

  Remarks:  Each type of message has an encoding method to convert data to
            compact structure w/o loosing information.

------------------------------------------------------------------------------*/
DWORD        
CMessage::GetBuffer (PBYTE pRes)
{
        // Store the type
    pRes[0] = BYTE(m_Type);
    pRes++;
        // Store the remote time
    *((PDWORD)pRes) = m_dwMsgTime;
    pRes += sizeof (DWORD);
        // Handle encoding of message according to type
    switch (m_Type)
    {   
        case REQUEST_TANK:          // Client => Server
            return EncodeRequestTank (pRes);
        case ADD_BONUS:             // Server => Client
            return EncodeAddBonus (pRes);
        case ADD_TANK:              // Server => Client
            return EncodeAddTank (pRes);
        case ADD_BOARD:             // Server => Client
            return EncodeAddBoard (pRes);
        case ADD_BOMBER:            // Server => Client
            return EncodeAddBomber (pRes);
        case REMOVE_TANK:           // Server => Client
            return EncodeRemoveTank (pRes);
        case MANOUVER_SET:          // Server <=> Client
            return EncodeManouverSet (pRes);
        case CHECK_SUM:             // Client => Server
            return EncodeCheckSum (pRes);
        case SET_TANK_STATUS:        // Server => Client
            return EncodeSetTankStatus (pRes);
        case SET_TANK_POS:          // Server => Client
            return EncodeSetTankPos (pRes);
        case SET_TANK_ZOMBIE:       // Server => Client
            return EncodeSetTankZombie (pRes);
        case CHAT:
            return EncodeChat(pRes);
        default:
            ASSERT (FALSE);
            return 0;
    }
}


// Encoding & decoding functions:
// ------------------------------

DWORD            
CMessage::EncodeAddBomber (PBYTE pData) 
{
    // Validate data to encode
    ASSERT (m_UnionData.BomberParam.Direction < 24);
    *((BomberParamTag *)pData) = m_UnionData.BomberParam;
    return m_MsgSizeArr[ADD_BOMBER];
}

void            
CMessage::DecodeAddBomber (PBYTE pData)
{
    m_UnionData.BomberParam = *((BomberParamTag *)pData);
    ASSERT (m_UnionData.BomberParam.Direction < 24);
}

DWORD            
CMessage::EncodeRequestTank (PBYTE pData) const
{
    // Validate data to encode
    ASSERT (m_UnionData.TankRequestParam.bID < 4);
    *pData = m_UnionData.TankRequestParam.bID;
    return m_MsgSizeArr[REQUEST_TANK];
}

void            
CMessage::DecodeRequestTank (PBYTE pData)
{
    m_UnionData.TankRequestParam.bID = *pData;
    ASSERT (m_UnionData.TankRequestParam.bID < 4);
}


DWORD            
CMessage::EncodeManouverSet (PBYTE pData) const
{
    // Validate data to encode
    ASSERT (m_UnionData.ManouverSetParam.Direction < 24);
    *((ManouverSetParamTag *)pData) = m_UnionData.ManouverSetParam;
    return m_MsgSizeArr[MANOUVER_SET];
}

void            
CMessage::DecodeManouverSet (PBYTE pData)
{
    m_UnionData.ManouverSetParam = *((ManouverSetParamTag *)pData);
    ASSERT (m_UnionData.ManouverSetParam.Direction < 24);
}

DWORD            
CMessage::EncodeAddBonus (PBYTE pData) const
{
    ASSERT (m_UnionData.BonusParam.XPos < 512);
    ASSERT (m_UnionData.BonusParam.YPos < 512);
    ASSERT (BonusType(m_UnionData.BonusParam.Type) < NUM_BONUSES);

    *((BonusParamTag *)pData) = m_UnionData.BonusParam;

⌨️ 快捷键说明

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