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

📄 msgdaemon.h

📁 <B>DirectX9.0 3D游戏编程</B>
💻 H
字号:
/*******************************************************************
 *         Advanced 3D Game Programming using DirectX 8.0
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *   Title: MsgDaemon.h
 *    Desc: Interface and constants for the inter-object messaging
 *          system.  This is the most important file in the game.
 * copyright (c) 2001 by Peter A Walsh and Adrian Perez
 * See license.txt for modification and distribution information
 ******************************************************************/

#ifndef _MSGDAEMON_H
#define _MSGDAEMON_H

#include "..\math3d\point3.h"
#include "..\math3d\color3.h"
#include "..\math3d\plane3.h"

#include "..\gamelib\GameTypes.h"

#include "netmsgs\NetMessages.h"

// disable the annoying 255 character limit warning
#pragma warning( disable : 4786 )

#include <map>
using std::map;

/**
 * objID
 * this is the unique identifier that each object has.
 * no two objects can have the same ID.
 *
 * Pardon my 16-bit programming jargon, but the int is
 * composed of a high-order 16-bit number (segment) and
 * a low-order 16-bit number (offset).  The segment 
 * identifies the type of object (system objects and
 * singletons have a segment of 0, gamecells have a segment
 * of 1, and so forth).  The offsets are chosen such that
 * each created object of a certain type has a 
 * different offset.
 *
 * One extremely important point: In any game, the server
 * and clients have the same ID's for each object.  That way,
 * if a client wants to modify an object with a certain ID, 
 * it just tells the server what to modify by giving it the 
 * ID.  Almost universally (with the exception of temporary
 * entities like sparks) the server decides the objID of an
 * object.  For example, look at the static constructors for
 * the player entities (cGamePlayerEnt.cpp).  The server
 * constructor generates an ID, the client takes one given to
 * it by the server.
 */
typedef uint objID;

inline objID MakeID( ushort segment, ushort offset )
{
	return (((uint)segment)<<16) | ((uint)offset);
}

inline ushort GetIDSegment( objID id )
{
	return (ushort)(id>>16);
}

inline ushort GetIDOffset( objID id )
{
	return (ushort)(id & 0xFFFF);
}


/**
 * These segments define the types of objects
 */
const ushort c_sysSegment = 0;    // System object
const ushort c_cellSegment = 1;   // Cell object
const ushort c_playerSegment = 2; // Player object
const ushort c_spawnSegment = 3;  // Spawning object
const ushort c_projSegment = 4;   // Projectile object
const ushort c_paraSegment = 5;   // Parametric object
const ushort c_tempSegment = 6;   // Temp object


/**
 * A few global constants for system objects that
 * we know we have at all times.
 */

const objID g_invalidID =	0xFFFFFFFF; // Invalid ID
const objID g_gameID =		MakeID( c_sysSegment, 1 ); // cGame object (client)
const objID g_gameWorldID = MakeID( c_sysSegment, 2 ); // cGameWorld object
const objID g_gameServer =	MakeID( c_sysSegment, 1 ); // server object



/**
 * eMsgType
 * this is the list of all the messages that can be sent to objects
 * organized by the type of object.
 */
enum eMsgType
{
	//==========--------------------------  cGameApp (client) messages
	msgPrintString, // cGameApp, print a string (passed in m_pData)
	msgPlayerCreated, // The player (id in m_i[0]) has been created.
	msgGetServerTime, // returns the current server time.
	msgSendToServerR, // unreliable message (m_pData) to server
	msgSendToServerUR, // unreliable message (m_pData) to server

	//==========--------------------------  server messages 
	// Note: server can also receive msgPrintString and msgGetServerTime
	msgSendNetMessageR, // reliable message (m_pData) to player (m_dest)
	msgSendNetMessageUR, // unreliable message (m_pData) to player (m_dest)
	msgBroadcastR, // reliable broadcast of (m_pData) to all players
	msgBroadcastRExcept, // r. broadcast of (m_pData) to all players except m_i[1]
	msgBroadcastUR, // unreliable broadcast of (m_pData) to all players
	msgAddPlayerName, // the edit box will get m_pData
	msgRemovePlayerName, // the edit box will lose m_pData
	msgKillSocket, // kill the socket with host ID m_i[0]

	//==========--------------------------  cGameWorld messages
	msgFindContainingCell, // pt is a loc, retval is a objID for the containing cell
	msgAddPlayer, // i[0] is the player (addent must be called too)
	msgRemovePlayer, // i[0] is the player (removeent must be called too)
	msgAddEnt, // i[0] is the ent
	msgRemoveEnt, // i[0] is the ent

	//==========--------------------------  cGameCell messages
	msgAddObjRef, // sent when an object enters a cell, i[0] is the object
	msgRemObjRef, // sent when an object leaves a cell, i[0] is the object

	//==========--------------------------  cGameEnt messages
	msgQueryGhost, // returns 1 if it is a ghost
	msgRebuildMatrix, // rebuild the matrix
	msgQueryInPlane, // m_plane is a plane to test against

	msgGetYaw, // returns yaw
	msgGetPitch, // returns pitch
	msgGetLoc, // returns ptr to loc
	msgGetSphere, // returns ptr to bsphere
	msgGetParent, // returns id of parent
	msgGetMatrix, // returns ptr to matrix

	msgSetYaw, // f[0] is the new yaw
	msgSetPitch, // f[0] is the new pitch
	msgSetLoc, // pt is the new loc
	msgSetParent, // i[0] is the new parent

	// m_plane is the plane the object hit. 
	// 0 if ok, -1 if the object destroyed itself
	msgNotifyPlaneCollision, 

	// m_plane is the plane the object hit. 
	// 0 if ok, -1 if the object destroyed itself
	msgNotifyObjectCollision, 

	//==========--------------------------  cGameSpawnEnt messages
	msgSpawnObject, // i[0] is the id to spawn

	//==========--------------------------  cGamePlayerEnt messages
	msgGetSpawnLoc, // pt is the location to spawn projectiles
	msgGetSpawnDir, // pt is the direction to spawn projectiles

	//==========--------------------------  Misc messages
	msgForceDword = 0xFFFFFFFF
};



/**
 * The message structure that gets
 * passed around.  7 DWORDS in size.
 * a few constructors are defined to
 * help inline message sending
 */
struct sMsg
{
	eMsgType	m_type;
	objID		m_dest;
	union
	{
		struct
		{
			point3 m_pt;
		};
		struct
		{
			plane3 m_plane;
		};
		struct
		{
			color3 m_col;
		};
		struct
		{
			int m_i[4];
		};
		struct
		{
			float m_f[4];
		};
		struct
		{
			void* m_pData;
		};
	};

	sMsg( eMsgType type = msgForceDword, objID dest = 0 ) 
	: m_type( type )
	, m_dest( dest )
	{
	}

	sMsg( eMsgType type, objID dest, float f )
	: m_type( type )
	, m_dest( dest )
	{
		m_f[0] = f;
	}

	sMsg( eMsgType type, objID dest, int i ) 
	: m_type( type )
	, m_dest( dest )
	{
		m_i[0] = i;
	}

	sMsg( eMsgType type, objID dest, const point3& pt ) 
	: m_type( type )
	, m_dest( dest )
	, m_pt(pt)
	{
	}

	sMsg( eMsgType type, objID dest, const plane3& plane ) 
	: m_type( type )
	, m_dest( dest )
	, m_plane(plane)
	{
	}

	sMsg( eMsgType type, objID dest, void* pData ) 
	: m_type( type )
	, m_dest( dest )
	, m_pData( pData )
	{
	}
}; 


/**
 * iGameObject
 * This is the interface that allows the game to work.
 * each class in the game that is of any concern to the
 * networking components must implement this interface.
 * It allows the network client to get and set the unique
 * ID for each object (That way, two instances of an object,
 * on two different machines, can talk to each other, by
 * sending messages.
 * Messages are sent to an object using the ProcMsg call.
 * in code this breaks down to a large switch statement,
 * with a case for every type of message the class can
 * deal with.
 */
typedef uint msgRet;

interface iGameObject
{
public:
	virtual objID GetID() = 0;
	virtual void SetID( objID id ) = 0;

	virtual msgRet ProcMsg( const sMsg& msg ) = 0;
};



/**
 * cMsgDaemon
 * This class ties together all of the objects.
 * DeliverMessage provides an abstraction so that
 * objects can communicate without requiring pointers
 * to each other.  Objects can even be modified by
 * remote software (talking through the network layer).
 * Each Game Object must Register itself with RegObject,
 * and UnReg itself whenever it deletes itself.  
 */
class cMsgDaemon  
{
	map< objID, iGameObject* > m_objectMap;

	static cMsgDaemon* m_pGlobalMsgDaemon;

public:
	cMsgDaemon();
	~cMsgDaemon();

	static cMsgDaemon* GetMsgDaemon()
	{
		// Accessor to the singleton
		if( !m_pGlobalMsgDaemon )
		{
			m_pGlobalMsgDaemon = new cMsgDaemon;
		}
		return m_pGlobalMsgDaemon;
	}

	void RegObject( objID id, iGameObject* pObj );
	void UnRegObject( objID id );

	iGameObject* Get( int id )
	{
		return m_objectMap[id];
	}

	/**
	 * Deliver this message to the destination
	 * marked in msg.m_dest.  Throws an exception
	 * if no such object exists.
	 */
	uint DeliverMessage( const sMsg& msg );
};

//==========--------------------------  Conversion functions

inline msgRet FloatToMRet( const float& in )
{
	return *((msgRet*)(&in));
}

inline float MRetToFloat( const msgRet& in )
{
	return *((float*)(&in));
}


inline msgRet PointToMRet( const point3& in )
{
	return (msgRet)(&in);
}

inline point3 MRetToPoint( const msgRet& in )
{
	return *((point3*)in);
}



inline msgRet MatrixToMRet( const matrix4& in )
{
	return (msgRet)(&in);
}

inline matrix4 MRetToMatrix( const msgRet& in )
{
	return *((matrix4*)in);
}



inline msgRet BSphereToMRet( const bSphere3& in )
{
	return (msgRet)(&in);
}

inline bSphere3 MRetToBSphere( const msgRet& in )
{
	return *((bSphere3*)in);
}

//==========--------------------------  Global-scope inline functions


// Easy way to access the singleton
inline cMsgDaemon* MsgDaemon()
{
	return cMsgDaemon::GetMsgDaemon();
}



inline uint SendMessage( const sMsg& msg )
{
	return MsgDaemon()->DeliverMessage( msg );
}



void DebPrint( char* first, ... ); // Print to the console
void LogPrint( char* first, ... ); // print to the log file


/**
 * Easy way to get access to the world object
 */
class cGameWorld;
cGameWorld* GetWorld();

//==========--------------------------  Network-associated stuff

void ReliableSendToPlayer( cNetMessage& nMsg, objID player );
void UnreliableSendToPlayer( cNetMessage& nMsg, objID player );

void UnreliableBroadcast( cNetMessage& nMsg );
void ReliableBroadcast( cNetMessage& nMsg );
void ReliableBroadcastExcept( cNetMessage& nMsg, objID exception );

bool IsClient();
objID GetClientID();

#endif // _MSGDAEMON_H

⌨️ 快捷键说明

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