游戏服务器之事件注册

来源:互联网 发布:优化新闻源的排名 编辑:程序博客网 时间:2024/05/19 14:01

线程内的模块间通信为的是让各个模块之间容易以事件触发的形式来进行通信。


就是以注册和派送事件的方式来实现。


逻辑引擎里含有逻辑事件分派器

CLogicEventDispatcher m_EventDispatcher;//逻辑事件分派器


注册消息事件调用(在逻辑引擎构造时)

m_EventDispatcher.addEventListener(leAddItem, &CPlayerQuest::addItem);

注册消息事件实现

void CLogicEventDispatcher::addEventListener(const int EventId, LogicEventHandler lpEventHandler)
{
EventHandlerStruct handler;
handler.lpEventHandler = lpEventHandler;

if (EventId >=(int) m_EventTypeList.size())
{
int Count = (EventId + 1024) & (~1023);
m_EventTypeList.insert(m_EventTypeList.size(), Count - m_EventTypeList.size(), true);
}


EventHandlerList *pHandlerList = m_EventTypeList.start[EventId];
if (!pHandlerList)
{
m_EventTypeList.start[EventId] = pHandlerList = new EventHandlerList();
}
pHandlerList->add(handler);//把事件处理函数添加到指定的事件id索引的列表后面
}

注销消息事件调用(在逻辑引擎初析构时)

m_EventDispatcher.removeEventListener(leAddItem, &CPlayerQuest::addItem);

注销消息事件实现

void CLogicEventDispatcher::removeEventListener(const int EventId, LogicEventHandler lpEventHandler)
{
if (EventId >=(int) m_EventTypeList.size())
return ;
EventHandlerList *pHandlerList = m_EventTypeList.start[EventId];
if (pHandlerList)
{
for (int i=(int)pHandlerList->size()-1; i>-1; --i)
{
if (pHandlerList->start[i].lpEventHandler == lpEventHandler)
{
pHandlerList->remove(i, 1);
}
}
}
}
 

事件派发(触发)如下:

获得一个物品

LogicEvent event(leAddItem, m_pPlayer);
 event.n1 = wItemId;
 event.n2 = nRemCount;
 g_LogicEngine->dispatchLogicEvent(event);


事件派发的实现:

void CLogicEventDispatcher::dispatchEvent(LogicEvent &event)
{
if (event.eventId >= (int)m_EventTypeList.size())
return ;
EventHandlerList *pHandlerList = m_EventTypeList[event.eventId];
if (pHandlerList)
{
EventHandlerStruct *handlers = pHandlerList->start;
for (int i=(int)pHandlerList->size()-1; i>-1; --i)
{
handlers[i].lpEventHandler(&event);//以之前以事件id(索引)注册的事件列表里的所有的事件处理函数来处理
}
}
}


事件处理函数如下:

这里写的只有任务处理,但其他的跟获得物品有关的都可以在这里处理。

void CPlayerQuest::addItem(LogicEvent* event)
{//获得道具
CDoer* pActor = (CDoer*)event->sender;
if (pActor->m_btType == ePlayer)
{
CPlayer* pPlayer = (CPlayer*)pActor;
pPlayer->m_Quest.questNormalHandler(int(event->n1), int(event->n2), QuestConfig::EQUEST_TARGET_GET_ITEM);
}
}
以上是一些代码分析,下面是整体的代码:


头文件的代码:
 事件处理定义函数指针
typedef void (*LogicEventHandler)(LogicEvent*);
逻辑事件派发器实现

class CLogicEventDispatcher
{
public:
struct EventHandlerStruct
{
LogicEventHandler lpEventHandler;
};
typedef MemoryBlock<EventHandlerStruct, 8> EventHandlerList;//事件句柄列表
typedef MemoryBlock<EventHandlerList*, 2048> EventTypeList;//所有的事件的列表

public:
CLogicEventDispatcher();
virtual ~CLogicEventDispatcher();

void addEventListener(const int EventId, LogicEventHandler lpEventHandler);
void removeEventListener(const int EventId, LogicEventHandler lpEventHandler);
void dispatchEvent(LogicEvent &event);
private:
EventTypeList m_EventTypeList;
};


源文件的代码:

CLogicEventDispatcher::CLogicEventDispatcher()
{
}

CLogicEventDispatcher::~CLogicEventDispatcher()
{
int i;
for (i = (int)m_EventTypeList.size() - 1;i > -1;i--)
{
SafeDelete(m_EventTypeList.start[i]);
}
m_EventTypeList.clear();
}


void CLogicEventDispatcher::addEventListener(const int EventId, LogicEventHandler lpEventHandler)
{
EventHandlerStruct handler;
handler.lpEventHandler = lpEventHandler;


if (EventId >=(int) m_EventTypeList.size())
{
int Count = (EventId + 1024) & (~1023);//为了让事件列表的大小以1024为单位向上取整
m_EventTypeList.insert(m_EventTypeList.size(), Count - m_EventTypeList.size(), true);
}


EventHandlerList *pHandlerList = m_EventTypeList.start[EventId];
if (!pHandlerList)
{
m_EventTypeList.start[EventId] = pHandlerList = new EventHandlerList();
}
pHandlerList->add(handler);
}


void CLogicEventDispatcher::removeEventListener(const int EventId, LogicEventHandler lpEventHandler)
{
if (EventId >=(int) m_EventTypeList.size())
return ;
EventHandlerList *pHandlerList = m_EventTypeList.start[EventId];
if (pHandlerList)
{
for (int i=(int)pHandlerList->size()-1; i>-1; --i)
{
if (pHandlerList->start[i].lpEventHandler == lpEventHandler)
{
pHandlerList->remove(i, 1);
}
}
}
}


void CLogicEventDispatcher::dispatchEvent(LogicEvent &event)
{
if (event.eventId >= (int)m_EventTypeList.size())
return ;
EventHandlerList *pHandlerList = m_EventTypeList[event.eventId];
if (pHandlerList)
{
EventHandlerStruct *handlers = pHandlerList->start;
for (int i=(int)pHandlerList->size()-1; i>-1; --i)
{
handlers[i].lpEventHandler(&event);//注册过哪些函数就派发到哪些函数上处理
}
}
}
拓展设想:

如果把事件压入各个模块的处理队列。到该模块的处理时间片和函数指针时才进行处理、可以较好把各个模块的处理时间更均衡的分布,然后限制时间片的长度。
 

0 0
原创粉丝点击