KBEngine奇技淫巧<二>

news/2024/7/8 6:04:27

KBEngine宏定义

  • 诡异的宏定义
    • 协议处理中的宏定义
    • DEFINE_IN_INTERFACE
    • BASEAPP
    • 协议声明宏
    • NETWORK_MESSAGE_HANDLER
    • KBEngine宏定义习惯
    • KBEngine宏的作用

诡异的宏定义

KBEngine引擎大约分为资源,脚本,网络,事件[逻辑]四个部分,在每一个部分里面都会用到大量的宏定义,理解这些宏定义还是很关键的。我们试着在读代码的时候读懂这些宏定义以达到使用这些宏和揣摩标哥的编码习惯,也为了将来改代码的时候能遵循一个编码原则。

协议处理中的宏定义

因为代码中宏定义的形式很多,这篇文章重点关注协议定义的宏定义。请看BaseApp中:
App中声明消息处理函数后开始一堆骚操作

/**
	BASEAPP所有消息接口在此定义
*/
NETWORK_INTERFACE_DECLARE_BEGIN(BaseappInterface)
	// 客户端请求导入协议。
	BASEAPP_MESSAGE_EXPOSED(importClientMessages)
	BASEAPP_MESSAGE_DECLARE_ARGS0(importClientMessages,								NETWORK_FIXED_MESSAGE)

	// 客户端entitydef导出。
	BASEAPP_MESSAGE_EXPOSED(importClientEntityDef)
	BASEAPP_MESSAGE_DECLARE_ARGS0(importClientEntityDef,							NETWORK_FIXED_MESSAGE)

	// 某app主动请求断线。
	BASEAPP_MESSAGE_DECLARE_ARGS0(reqClose,											NETWORK_FIXED_MESSAGE)

	// 某app主动请求look。
	BASEAPP_MESSAGE_DECLARE_ARGS0(lookApp,											NETWORK_FIXED_MESSAGE)

	// 某个app请求查看该app负载状态。
	BASEAPP_MESSAGE_DECLARE_ARGS0(queryLoad,										NETWORK_FIXED_MESSAGE)

	// console远程执行python语句。
	BASEAPP_MESSAGE_DECLARE_STREAM(onExecScriptCommand,								NETWORK_VARIABLE_MESSAGE)

	// 某app注册自己的接口地址到本app
	BASEAPP_MESSAGE_DECLARE_ARGS11(onRegisterNewApp,								NETWORK_VARIABLE_MESSAGE,
									int32,											uid, 
									std::string,									username,
									COMPONENT_TYPE,									componentType, 
									COMPONENT_ID,									componentID, 
									COMPONENT_ORDER,								globalorderID,
									COMPONENT_ORDER,								grouporderID,
									uint32,											intaddr, 
									uint16,											intport,
									uint32,											extaddr, 
									uint16,											extport,
									std::string,									extaddrEx)

	// dbmgr告知已经启动的其他baseapp或者cellapp的地址
	// 当前app需要主动的去与他们建立连接
	BASEAPP_MESSAGE_DECLARE_ARGS11(onGetEntityAppFromDbmgr,							NETWORK_VARIABLE_MESSAGE,
									int32,											uid, 
									std::string,									username,
									COMPONENT_TYPE,									componentType, 
									COMPONENT_ID,									componentID, 
									COMPONENT_ORDER,								globalorderID,
									COMPONENT_ORDER,								grouporderID,
									uint32,											intaddr, 
									uint16,											intport,
									uint32,											extaddr, 
									uint16,											extport,
									std::string,									extaddrEx)

	// 某app请求获取一个entityID段的回调
	BASEAPP_MESSAGE_DECLARE_ARGS2(onReqAllocEntityID,								NETWORK_FIXED_MESSAGE,
									ENTITY_ID,										startID,
									ENTITY_ID,										endID)


	// 某app请求获取一个entityID段的回调
	BASEAPP_MESSAGE_DECLARE_ARGS6(onDbmgrInitCompleted,								NETWORK_VARIABLE_MESSAGE,
									GAME_TIME,										gametime, 
									ENTITY_ID,										startID,
									ENTITY_ID,										endID,
									COMPONENT_ORDER,								startGlobalOrder,
									COMPONENT_ORDER,								startGroupOrder,
									std::string,									digest)

	// hello握手。
	BASEAPP_MESSAGE_EXPOSED(hello)
	BASEAPP_MESSAGE_DECLARE_STREAM(hello,											NETWORK_VARIABLE_MESSAGE)

	// global数据改变
	BASEAPP_MESSAGE_DECLARE_STREAM(onBroadcastGlobalDataChanged,					NETWORK_VARIABLE_MESSAGE)
	BASEAPP_MESSAGE_DECLARE_STREAM(onBroadcastBaseAppDataChanged,					NETWORK_VARIABLE_MESSAGE)

	// 某个app向本app告知处于活动状态。
	BASEAPP_MESSAGE_DECLARE_ARGS2(onAppActiveTick,									NETWORK_FIXED_MESSAGE,
									COMPONENT_TYPE,									componentType, 
									COMPONENT_ID,									componentID)

	// 某个app向本app告知处于活动状态。
	BASEAPP_MESSAGE_EXPOSED(onClientActiveTick)
	BASEAPP_MESSAGE_DECLARE_ARGS0(onClientActiveTick,								NETWORK_FIXED_MESSAGE)

	// 收到baseappmgr决定将某个baseapp要求createEntityAnywhere的请求在本baseapp上执行 
	BASEAPP_MESSAGE_DECLARE_STREAM(onCreateEntityAnywhere,							NETWORK_VARIABLE_MESSAGE)

	// createEntityAnywhere成功之后回调消息到发起层createEntityAnywhere的baseapp的entity。
	BASEAPP_MESSAGE_DECLARE_STREAM(onCreateEntityAnywhereCallback,					NETWORK_FIXED_MESSAGE)

	// createEntityRemotely成功之后回调消息到发起层createEntityRemotely的baseapp的entity。
	BASEAPP_MESSAGE_DECLARE_STREAM(onCreateEntityRemotely,							NETWORK_FIXED_MESSAGE)

	// createEntityRemotely成功之后回调消息到发起层createEntityRemotely的baseapp的entity。
	BASEAPP_MESSAGE_DECLARE_STREAM(onCreateEntityRemotelyCallback,					 NETWORK_FIXED_MESSAGE)

	// createCellEntity的cell实体创建成功回调。
	BASEAPP_MESSAGE_DECLARE_ARGS3(onEntityGetCell,									NETWORK_FIXED_MESSAGE,
									ENTITY_ID,										id,
									COMPONENT_ID,									componentID,
									SPACE_ID,										spaceID)

	// createCellEntity的cell实体创建成功回调。
	BASEAPP_MESSAGE_DECLARE_ARGS1(onCreateCellFailure,								NETWORK_FIXED_MESSAGE,
									ENTITY_ID,										entityID)

	// loginapp向自己注册一个将要登录的账号, 由baseappmgr转发。
	BASEAPP_MESSAGE_DECLARE_STREAM(registerPendingLogin,							NETWORK_VARIABLE_MESSAGE)

	// 数据库中查询的自动entity加载信息返回 
	BASEAPP_MESSAGE_DECLARE_STREAM(onEntityAutoLoadCBFromDBMgr,						NETWORK_VARIABLE_MESSAGE)

	// 前端请求登录到网关上。
	BASEAPP_MESSAGE_EXPOSED(loginBaseapp)
	BASEAPP_MESSAGE_DECLARE_ARGS2(loginBaseapp,										NETWORK_VARIABLE_MESSAGE,
									std::string,									accountName,
									std::string,									password)

	// 前端请求从网关登出。
	BASEAPP_MESSAGE_EXPOSED(logoutBaseapp)
	BASEAPP_MESSAGE_DECLARE_ARGS2(logoutBaseapp,									NETWORK_FIXED_MESSAGE,
									uint64,											key,
									ENTITY_ID,										entityID)

	// 前端请求重新登录到网关上。
	BASEAPP_MESSAGE_EXPOSED(reloginBaseapp)
	BASEAPP_MESSAGE_DECLARE_ARGS4(reloginBaseapp,									NETWORK_VARIABLE_MESSAGE,
									std::string,									accountName,
									std::string,									password,
									uint64,											key,
									ENTITY_ID,										entityID)

	// 从dbmgr获取到账号Entity信息
	BASEAPP_MESSAGE_DECLARE_STREAM(onQueryAccountCBFromDbmgr,						NETWORK_VARIABLE_MESSAGE)

	// entity收到远程call请求, 由某个app上的entitycall发起
	BASEAPP_MESSAGE_DECLARE_STREAM(onEntityCall,									NETWORK_VARIABLE_MESSAGE)
	
	// client访问entity的cell方法
	BASEAPP_MESSAGE_EXPOSED(onRemoteCallCellMethodFromClient)
	BASEAPP_MESSAGE_DECLARE_STREAM(onRemoteCallCellMethodFromClient,				NETWORK_VARIABLE_MESSAGE)

	// client更新数据
	BASEAPP_MESSAGE_EXPOSED(onUpdateDataFromClient)
	BASEAPP_MESSAGE_DECLARE_STREAM(onUpdateDataFromClient,							NETWORK_VARIABLE_MESSAGE)
	BASEAPP_MESSAGE_EXPOSED(onUpdateDataFromClientForControlledEntity)
	BASEAPP_MESSAGE_DECLARE_STREAM(onUpdateDataFromClientForControlledEntity,		NETWORK_VARIABLE_MESSAGE)

	// executeRawDatabaseCommand从dbmgr的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(onExecuteRawDatabaseCommandCB,					NETWORK_VARIABLE_MESSAGE)

	// cellapp备份entity的cell数据
	BASEAPP_MESSAGE_DECLARE_STREAM(onBackupEntityCellData,							NETWORK_VARIABLE_MESSAGE)

	// cellapp writeToDB完成
	BASEAPP_MESSAGE_DECLARE_STREAM(onCellWriteToDBCompleted,						NETWORK_VARIABLE_MESSAGE)

	// cellapp转发entity消息给client
	BASEAPP_MESSAGE_DECLARE_STREAM(forwardMessageToClientFromCellapp,				NETWORK_VARIABLE_MESSAGE)

	// cellapp转发entity消息给某个baseEntity的cellEntity
	BASEAPP_MESSAGE_DECLARE_STREAM(forwardMessageToCellappFromCellapp,				NETWORK_VARIABLE_MESSAGE)

	// 请求关闭服务器
	BASEAPP_MESSAGE_DECLARE_STREAM(reqCloseServer,									NETWORK_VARIABLE_MESSAGE)

	// 写entity到db回调。
	BASEAPP_MESSAGE_DECLARE_ARGS5(onWriteToDBCallback,								NETWORK_FIXED_MESSAGE,
									ENTITY_ID,										eid,
									DBID,											entityDBID,
									uint16,											dbInterfaceIndex,
									CALLBACK_ID,									callbackID,
									bool,											success)

	// createEntityFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(onCreateEntityFromDBIDCallback,					NETWORK_FIXED_MESSAGE)

	// createEntityAnywhereFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(onGetCreateEntityAnywhereFromDBIDBestBaseappID,	NETWORK_FIXED_MESSAGE)

	// createEntityAnywhereFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(onCreateEntityAnywhereFromDBIDCallback,			NETWORK_FIXED_MESSAGE)

	// createEntityAnywhereFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(createEntityAnywhereFromDBIDOtherBaseapp,		NETWORK_FIXED_MESSAGE)

	// createEntityAnywhereFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_ARGS5(onCreateEntityAnywhereFromDBIDOtherBaseappCallback,NETWORK_VARIABLE_MESSAGE,
									COMPONENT_ID,									createByBaseappID,
									std::string,									entityType,
									ENTITY_ID,										createdEntityID,
									CALLBACK_ID,									callbackID,
									DBID,											dbid)

	// createEntityRemotelyFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(onCreateEntityRemotelyFromDBIDCallback,			NETWORK_FIXED_MESSAGE)

	// createEntityRemotelyFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(createEntityRemotelyFromDBIDOtherBaseapp,		NETWORK_FIXED_MESSAGE)

	// createEntityRemotelyFromDBID的回调
	BASEAPP_MESSAGE_DECLARE_ARGS5(onCreateEntityRemotelyFromDBIDOtherBaseappCallback,NETWORK_VARIABLE_MESSAGE,
									COMPONENT_ID,									createByBaseappID,
									std::string,									entityType,
									ENTITY_ID,										createdEntityID,
									CALLBACK_ID,									callbackID,
									DBID,											dbid)

	// 请求查询watcher数据
	BASEAPP_MESSAGE_DECLARE_STREAM(queryWatcher,									NETWORK_VARIABLE_MESSAGE)

	// 充值回调
	BASEAPP_MESSAGE_DECLARE_STREAM(onChargeCB,										NETWORK_VARIABLE_MESSAGE)

	// 开始profile
	BASEAPP_MESSAGE_DECLARE_STREAM(startProfile,									NETWORK_VARIABLE_MESSAGE)

	// 请求从数据库删除实体
	BASEAPP_MESSAGE_DECLARE_STREAM(deleteEntityByDBIDCB,							NETWORK_VARIABLE_MESSAGE)
	
	// lookUpEntityByDBID的回调
	BASEAPP_MESSAGE_DECLARE_STREAM(lookUpEntityByDBIDCB,							NETWORK_VARIABLE_MESSAGE)

	// 某个baseapp上的space恢复了cell, 判断当前baseapp是否有相关entity需要恢复cell
	BASEAPP_MESSAGE_DECLARE_STREAM(onRestoreSpaceCellFromOtherBaseapp,				NETWORK_VARIABLE_MESSAGE)

	// 请求在其他APP灾难恢复返回结果。
	BASEAPP_MESSAGE_DECLARE_STREAM(onRequestRestoreCB,								NETWORK_VARIABLE_MESSAGE)

	// 请求绑定email
	BASEAPP_MESSAGE_EXPOSED(reqAccountBindEmail)
	BASEAPP_MESSAGE_DECLARE_ARGS3(reqAccountBindEmail,								NETWORK_VARIABLE_MESSAGE,
									ENTITY_ID,										entityID,
									std::string,									password,
									std::string,									email)

	// 请求绑定email申请的回调
	BASEAPP_MESSAGE_DECLARE_ARGS5(onReqAccountBindEmailCBFromDBMgr,					NETWORK_VARIABLE_MESSAGE,
									ENTITY_ID,										entityID,
									std::string,									accountName,
									std::string,									email,
									SERVER_ERROR_CODE,								failedcode,
									std::string,									code)

	// baseapp请求绑定email(返回时需要找到loginapp的地址)
	BASEAPP_MESSAGE_DECLARE_ARGS7(onReqAccountBindEmailCBFromBaseappmgr,			NETWORK_VARIABLE_MESSAGE,
									ENTITY_ID,										entityID,
									std::string,									accountName,
									std::string,									email,
									SERVER_ERROR_CODE,								failedcode,
									std::string,									code,
									std::string,									loginappCBHost,
									uint16,											loginappCBPort)

	// 请求修改密码
	BASEAPP_MESSAGE_EXPOSED(reqAccountNewPassword)
	BASEAPP_MESSAGE_DECLARE_ARGS3(reqAccountNewPassword,							NETWORK_VARIABLE_MESSAGE,
									ENTITY_ID,										entityID,
									std::string,									oldpassword,
									std::string,									newpassword)

	// 请求修改密码的回调
	BASEAPP_MESSAGE_DECLARE_ARGS3(onReqAccountNewPasswordCB,						NETWORK_VARIABLE_MESSAGE,
									ENTITY_ID,										entityID,
									std::string,									accountName,
									SERVER_ERROR_CODE,								failedcode)

	// 请求强制杀死当前app
	BASEAPP_MESSAGE_DECLARE_STREAM(reqKillServer,									NETWORK_VARIABLE_MESSAGE)

	//--------------------------------------------Entity----------------------------------------------------------
	// 远程呼叫entity方法
	ENTITY_MESSAGE_EXPOSED(onRemoteMethodCall)
	ENTITY_MESSAGE_DECLARE_STREAM(onRemoteMethodCall,								NETWORK_VARIABLE_MESSAGE)

	// cellapp通报该entity的cell部分销毁或者丢失
	ENTITY_MESSAGE_DECLARE_STREAM(onLoseCell,										NETWORK_VARIABLE_MESSAGE)

	// 客户端直接发送消息给cell实体
	ENTITY_MESSAGE_EXPOSED(forwardEntityMessageToCellappFromClient)
	ENTITY_MESSAGE_DECLARE_STREAM(forwardEntityMessageToCellappFromClient,			NETWORK_VARIABLE_MESSAGE)

	// 某个entity请求teleport后的回调结果
	ENTITY_MESSAGE_DECLARE_ARGS2(onTeleportCB,										NETWORK_FIXED_MESSAGE,
								SPACE_ID,											spaceID,
								bool,												fromCellTeleport)

	// 某个entity请求teleport后的回调结果
	ENTITY_MESSAGE_DECLARE_ARGS1(onGetDBID,											NETWORK_FIXED_MESSAGE,
								DBID,												dbid)

	// entity请求迁移到另一个cellapp上的space过程开始
	ENTITY_MESSAGE_DECLARE_ARGS2(onMigrationCellappStart,							NETWORK_FIXED_MESSAGE,
								COMPONENT_ID,										sourceCellAppID,
								COMPONENT_ID,										targetCellAppID)
		
	// entity请求迁移到另一个cellapp上的space过程结束
	ENTITY_MESSAGE_DECLARE_ARGS2(onMigrationCellappEnd,								NETWORK_FIXED_MESSAGE,
								COMPONENT_ID,										sourceCellAppID,
								COMPONENT_ID,										targetCellAppID)

	//--------------------------------------------Proxy---------------------------------------------------------
	/**
		远程呼叫entity方法
	*/
	//PROXY_MESSAGE_EXPOSED(onClientGetCell)
	//PROXY_MESSAGE_DECLARE_ARGS0(onClientGetCell,									NETWORK_FIXED_MESSAGE)

NETWORK_INTERFACE_DECLARE_END()

太长了,都说不现实,挑拣一个流消息,比如:

	// console远程执行python语句。
	BASEAPP_MESSAGE_DECLARE_STREAM(onExecScriptCommand,								NETWORK_VARIABLE_MESSAGE)

这样子的就是说BaseApp里面的函数onExecScriptCommand怎么封装处理的问题了,协议的部分+流处理【参数】的部分

#if defined(DEFINE_IN_INTERFACE)
#if defined(BASEAPP)
#define BASEAPP_MESSAGE_HANDLER_STREAM(NAME)									\
	void NAME##BaseappMessagehandler_stream::handle(Network::Channel* pChannel,	\
													KBEngine::MemoryStream& s)	\
	{																			\
			KBEngine::Baseapp::getSingleton().NAME(pChannel, s);				\
	}																			\

#else
#define BASEAPP_MESSAGE_HANDLER_STREAM(NAME)									\
	void NAME##BaseappMessagehandler_stream::handle(Network::Channel* pChannel,	\
													KBEngine::MemoryStream& s)	\
	{																			\
	}																			\
		
#endif
#else
#define BASEAPP_MESSAGE_HANDLER_STREAM(NAME)									\
	class NAME##BaseappMessagehandler_stream : public Network::MessageHandler	\
	{																			\
	public:																		\
		virtual void handle(Network::Channel* pChannel,							\
							KBEngine::MemoryStream& s);							\
	};																			\

#endif

#define BASEAPP_MESSAGE_DECLARE_STREAM(NAME, MSG_LENGTH)						\
	BASEAPP_MESSAGE_HANDLER_STREAM(NAME)										\
	NETWORK_MESSAGE_DECLARE_STREAM(Baseapp, NAME,								\
				NAME##BaseappMessagehandler_stream, MSG_LENGTH)					\
																				\

代码大约的意思是,定义一个处理网络流的协议,其他参数的的协议编写习惯大同小异,很好理解。
先关注两个开关宏DEFINE_IN_INTERFACE 和 BASEAPP

DEFINE_IN_INTERFACE

这个开关宏管理的事情是,如果没有定义这个开关,那么下面声明的宏就是一个类的声明,如果定义了这个开关,那么下面声明的宏就是一个类的实现。
例如没有声明 DEFINE_IN_INTERFACE 那么代码就是这个样子:

#define BASEAPP_MESSAGE_HANDLER_STREAM(NAME)									\
	class NAME##BaseappMessagehandler_stream : public Network::MessageHandler	\
	{																			\
	public:																		\
		virtual void handle(Network::Channel* pChannel,							\
							KBEngine::MemoryStream& s);							\
	};																			\

BASEAPP_MESSAGE_HANDLER_STREAM(NAME) 就是声明一个类了,
定义了DEFINE_IN_INTERFACE 就是将刚才声明的类实现了,是这个样子:

#if defined(BASEAPP)
#define BASEAPP_MESSAGE_HANDLER_STREAM(NAME)									\
	void NAME##BaseappMessagehandler_stream::handle(Network::Channel* pChannel,	\
													KBEngine::MemoryStream& s)	\
	{																			\
			KBEngine::Baseapp::getSingleton().NAME(pChannel, s);				\
	}																			\

#else
#define BASEAPP_MESSAGE_HANDLER_STREAM(NAME)									\
	void NAME##BaseappMessagehandler_stream::handle(Network::Channel* pChannel,	\
													KBEngine::MemoryStream& s)	\
	{																			\
	}																			\
		
#endif

这里面就用到了第二个开关宏:BASEAPP

BASEAPP

BASEAPP宏管的事情是:如果定义了这个宏那么就调用BaseApp对应的处理方法,这个方法就需要将来使用引擎的时候自己编写了,类内一定要有,不然会出错。如果没有定义这个宏那么类的实现就是一个空函数:
达到具体的App调用具体的类处理函数的目的。这个代码还是很好看懂的。
最后来一个总的宏:

协议声明宏

#define BASEAPP_MESSAGE_DECLARE_STREAM(NAME, MSG_LENGTH)						\
	BASEAPP_MESSAGE_HANDLER_STREAM(NAME)										\
	NETWORK_MESSAGE_DECLARE_STREAM(Baseapp, NAME,								\
				NAME##BaseappMessagehandler_stream, MSG_LENGTH)		

这块代码的意思是声明一个流处理协议的宏,可以看到第二行就是刚才说的一大堆,具体就是声明和实现一个协议处理类,那么第三行就是如何使用这个类的问题了,里面水也很深,
在Network里面有一个MessageHandlers容器,他管理着本App可以处理的所有协议。第三行就是想办法把声明的类创建一个实例放到容器里面,可以跟进这个宏看一下:
跟进这个宏第一步是这样子的:

#define NETWORK_MESSAGE_DECLARE_STREAM(DOMAIN, NAME, MSGHANDLER,	\
											MSG_LENGTH)				\
	NETWORK_MESSAGE_HANDLER(DOMAIN, NAME, MSGHANDLER, MSG_LENGTH, 	\
														_stream)	\
	MESSAGE_STREAM(NAME)											\

又遇到了两个新的宏:
NETWORK_MESSAGE_HANDLER和MESSAGE_STREAM,这个需要一步一步的读下去

NETWORK_MESSAGE_HANDLER

跟进这个宏进去会看到

#ifdef DEFINE_IN_INTERFACE
	//#undef DEFINE_IN_INTERFACE
	
	#define NETWORK_MESSAGE_HANDLER(DOMAIN, NAME, HANDLER_TYPE, MSG_LENGTH, ARG_N)						\
		HANDLER_TYPE* p##NAME = static_cast<HANDLER_TYPE*>(messageHandlers.add(#DOMAIN"::"#NAME,		\
						 new NAME##Args##ARG_N, MSG_LENGTH, new HANDLER_TYPE));							\
		const HANDLER_TYPE& NAME = *p##NAME;															\
			
	#define NETWORK_MESSAGE_EXPOSED(DOMAIN, NAME);														\
		bool p##DOMAIN##NAME##_exposed = messageHandlers.pushExposedMessage(#DOMAIN"::"#NAME);			\

#else
	#define NETWORK_MESSAGE_HANDLER(DOMAIN, NAME, HANDLER_TYPE, MSG_LENGTH, ARG_N)						\
		extern const HANDLER_TYPE& NAME;																\

	#define NETWORK_MESSAGE_EXPOSED(DOMAIN, NAME)														\
	
#endif

这点就是协议处理添加到容器的关键部分,还是开关宏DEFINE_IN_INTERFACE在起作用:
如果定义了开关就声明一个类的对象并且添加到容器里面:

	#define NETWORK_MESSAGE_HANDLER(DOMAIN, NAME, HANDLER_TYPE, MSG_LENGTH, ARG_N)						\
		HANDLER_TYPE* p##NAME = static_cast<HANDLER_TYPE*>(messageHandlers.add(#DOMAIN"::"#NAME,		\
						 new NAME##Args##ARG_N, MSG_LENGTH, new HANDLER_TYPE));							\
		const HANDLER_TYPE& NAME = *p##NAME;	

看见 new HANDLER_TYPE 了没,就是如此,容器的Add方法会把创建的实例返回来,然后赋值给声明的变量:

const HANDLER_TYPE& NAME = *p##NAME;

如此类有了实例,容器里面添加上了实例,以后就可以用了。然后如果没有定义开关宏就引入变量的声明:

	#define NETWORK_MESSAGE_HANDLER(DOMAIN, NAME, HANDLER_TYPE, MSG_LENGTH, ARG_N)						\
		extern const HANDLER_TYPE& NAME;	

贴一下Add方法的实现:

MessageHandler* MessageHandlers::add(std::string ihName, MessageArgs* args, 
	int32 msgLen, MessageHandler* msgHandler)
{
	if(msgID_ == 1)
	{
		//printf("\n------------------------------------------------------------------\n");
		//printf("KBEMessage_handlers begin:\n");
	}
	
	//bool isfixedMsg = false;

	FixedMessages::MSGInfo* msgInfo = FixedMessages::getSingleton().isFixed(ihName.c_str());
	if(msgInfo == NULL)
	{
		while(true)
		{
			if(FixedMessages::getSingleton().isFixed(msgID_))
			{
				msgID_++;
				//isfixedMsg = true;
			}
			else
			{
				break;
			}
		};

		msgHandler->msgID = msgID_++;
	}
	else
	{
		msgHandler->msgID = msgInfo->msgid;
	}
	
	if (g_packetAlwaysContainLength)
		msgLen = NETWORK_VARIABLE_MESSAGE;

	msgHandler->name = ihName;					
	msgHandler->pArgs = args;
	msgHandler->msgLen = msgLen;	
	msgHandler->exposed = false;
	msgHandler->pMessageHandlers = this;
	msgHandler->onInstall();

	msgHandlers_[msgHandler->msgID] = msgHandler;
	
	if(msgLen == NETWORK_VARIABLE_MESSAGE)
	{
		//printf("\tMessageHandlers::add(%d): name=%s, msgID=%d, size=Variable.\n", 
		//	(int32)msgHandlers_.size(), ihName.c_str(), msgHandler->msgID);
	}
	else
	{
		if(msgLen == 0)
		{
			msgHandler->msgLen = args->dataSize();

			if (msgHandler->pArgs)
			{ 
				std::vector<std::string>::iterator args_iter = msgHandler->pArgs->strArgsTypes.begin();
				for (; args_iter != msgHandler->pArgs->strArgsTypes.end(); ++args_iter)
				{
					if ((*args_iter) == "std::string")
					{
						DebugHelper::getSingleton().set_warningcolor();

						printf("%s::%s::dataSize: "	
							"Not NETWORK_FIXED_MESSAGE, "	
							"has changed to NETWORK_VARIABLE_MESSAGE!\n", COMPONENT_NAME_EX(g_componentType), ihName.c_str());

						DebugHelper::getSingleton().set_normalcolor();
						msgHandler->msgLen = NETWORK_VARIABLE_MESSAGE;
						break;
					}
				}
			}

			if(msgHandler->type() == NETWORK_MESSAGE_TYPE_ENTITY)
			{
				msgHandler->msgLen += sizeof(ENTITY_ID);
			}
		}
		
		//printf("\tMessageHandlers::add(%d): name=%s, msgID=%d, size=Fixed(%d).\n", 
		//		(int32)msgHandlers_.size(), ihName.c_str(), msgHandler->msgID, msgHandler->msgLen);
	}

	//if(isfixedMsg)
	//	printf("\t\t!!!message is fixed.!!!\n");

	return msgHandler;
}

传入的参数最后又返回了,标哥在编写代码的时候有个诡异的习惯:喜欢把容器重新封装一下,会就看到很多s结尾的类,没什么毛病:

KBEngine宏定义习惯

很多开关宏定义要看清楚,标哥喜欢先判断没有定义某个开关宏,然后再来定义开关宏的代码,看起来就很无语。
要在Cpp里面看怎么使用这些宏的,比如:

#include "baseapp_interface.h"
#define DEFINE_IN_INTERFACE
#define BASEAPP
#include "baseapp_interface.h"

看这个代码:一开始肯定没有定义开关宏,那么里面就对应我们说的类的声明,定义完开关宏以后再来包含头文件就成了类的定义了,达到想要的效果,有时候开关来回开关,达到惊人的效果,例如main.cpp里面会看到

#undef DEFINE_IN_INTERFACE
#include "client_lib/client_interface.h"
#define DEFINE_IN_INTERFACE
#include "client_lib/client_interface.h"

#undef DEFINE_IN_INTERFACE
#include "machine/machine_interface.h"
#define DEFINE_IN_INTERFACE
#include "machine/machine_interface.h"

#undef DEFINE_IN_INTERFACE
#include "baseappmgr/baseappmgr_interface.h"
#define DEFINE_IN_INTERFACE
#include "baseappmgr/baseappmgr_interface.h"

#undef DEFINE_IN_INTERFACE
#include "cellappmgr/cellappmgr_interface.h"
#define DEFINE_IN_INTERFACE
#include "cellappmgr/cellappmgr_interface.h"

#undef DEFINE_IN_INTERFACE
#include "baseapp/baseapp_interface.h"
#define DEFINE_IN_INTERFACE
#include "baseapp/baseapp_interface.h"

#undef DEFINE_IN_INTERFACE
#include "dbmgr/dbmgr_interface.h"
#define DEFINE_IN_INTERFACE
#include "dbmgr/dbmgr_interface.h"

#undef DEFINE_IN_INTERFACE
#include "loginapp/loginapp_interface.h"
#define DEFINE_IN_INTERFACE
#include "loginapp/loginapp_interface.h"

#undef DEFINE_IN_INTERFACE
#include "tools/logger/logger_interface.h"
#define DEFINE_IN_INTERFACE
#include "tools/logger/logger_interface.h"

#undef DEFINE_IN_INTERFACE
#include "tools/bots/bots_interface.h"
#define DEFINE_IN_INTERFACE
#include "tools/bots/bots_interface.h"

#undef DEFINE_IN_INTERFACE
#include "tools/interfaces/interfaces_interface.h"
#define DEFINE_IN_INTERFACE
#include "tools/interfaces/interfaces_interface.h"

一会开,一会儿关,真是无所不用其极.

KBEngine宏的作用

标哥代码写的让人惊叹,达到了艺术化的效果。因为是多进程编程,大量的重复代码,利用宏可以有效减少代码的编写量,不过就是需要对项目思考的非常深,不费二两脑细胞写不出来的,而且看的时候也是需要考究如何这样编写和有什么作用,是非常牛叉的。

最后我这篇文章只说了协议定义这么小小的一块宏定义,而且还是不全的,可以说是比较关键的一部分吧,至少是协议处理,至于脚本宏定义和资源配置宏定义我们可以留到以后再扯,体会标哥的编写习惯和思路看的时候会顺畅一些~~


http://www.niftyadmin.cn/n/3921979.html

相关文章

C++98宏实现std::tuple

原文&#xff1a;http://geek.csdn.net/news/detail/61260 最近准备重构一下我的kapok库&#xff0c;让meta函数可以返回元素为kv的tuple&#xff0c;例如&#xff1a; struct person {std::string name;int age;META(name, age) //定义一个支持变参的meta函数 }; int main() {…

KBEngine奇技淫巧<三>

KBEngine奇技淫巧之操作处理各种Handler运行机制框架组织处理任务逻辑InitProgressHandlerBaseMessagesForwardClientHandler自成系统的handler总结各种Handler 研读KBEngine源码的时候&#xff0c;你经常会看到各种Handler结尾的类&#xff0c;搞懂这些类是很有必要的。我们以…

[UE4]AI中使用Tick()函数的性能问题

Tick()函数一般是debug时用的&#xff0c;正规的逻辑中&#xff0c;如果要用Tick函数&#xff0c;可以考虑用UE4提供的事件代理(Event Delegate&#xff1a;http://aigo.iteye.com/blog/2301010)。 参考&#xff1a;Using Tick() within AI? https://answers.unrealengine.com…

[UE4]不使用角色蓝图、动画蓝图、状态机,用“24K纯C++”实现动画播放

原文作者&#xff1a;玄冬Wong 不好意思&#xff0c;我稍稍标题党了&#xff0c;目前还不清楚如何用C代码来实现BlendSpace和Montage的逻辑&#xff0c;如果这两个文件也不我们创建了&#xff0c;那么以下内容就是真正意义上的纯C实现角色蓝图和动画蓝图。 逻辑用C&#xff0c…

KBEngine奇技淫巧<四>

KBEngine定时器定时器介绍EventDispatcherTimer 时间 定时器container_timeQueue_TimerTTimeprocessadd总结一下定时器介绍 是时候放出灵魂框架图了&#xff0c;KBEngine最重要的几个类 是的&#xff0c;这个图就说明了KBEngine引擎最重要的几个类。从程序来看&#xff0c;最…

[C++]为什么模板函数的声明与实现都放在.h头文件中

原文&#xff1a;http://www.360doc.com/content/13/0722/14/10072361_301717293.shtml 当你不使用这个模版函数或模版类,编译器并不实例化它 ,当你使用时&#xff0c;编译器需要实例化它&#xff0c; 因为编译器是一次只能处理一个编译单元, 也就是一次处理一个cpp文件,所以…

KBEngine奇技淫巧<五>

KBEngine网络网络模块的组织EventPoller结构图对象组织InputNotificationHandler如何创建各种HandlerLIstener初始化Receiver创建Channel各种协议Handler的调用NetworkInterfaceChannel 就是socket连接NetworkInerface的结构总结一下网络模块的组织 KBEngine最核心的三个模块我…

[UE4]APlayerController::PlayerTick()注意事项

官方文档&#xff1a; APlayerController::PlayerTick() https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/APlayerController/PlayerTick/index.html PlayerController用PlayerTick&#xff0c;Character中有Tick函数&#xff0c;什么时候用Player…