游戏服务器之事件注册
来源:互联网 发布:优化新闻源的排名 编辑:程序博客网 时间: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);//注册过哪些函数就派发到哪些函数上处理
}
}
}
拓展设想:
如果把事件压入各个模块的处理队列。到该模块的处理时间片和函数指针时才进行处理、可以较好把各个模块的处理时间更均衡的分布,然后限制时间片的长度。
- 游戏服务器之事件注册
- 游戏服务器之中心服务器
- 游戏服务器之服务器对象
- 游戏服务器之锁
- 游戏服务器之ai
- 游戏服务器之副本
- 游戏服务器之技能
- 游戏服务器之网关
- 游戏服务器之登录
- 游戏服务器之加密
- unity游戏开发之服务器与客户端或页面流转之自定义交互事件
- EventBus事件总线组件:事件通知功能之事件注册
- Unity3D学习之(游戏注册界面)
- senchatouch之container层注册事件
- javascript之BOM事件注册和案例
- #GWT#之TextBox注册onPaste事件
- 游戏服务器之文件数据库
- 游戏服务器之跨场景
- IIS日志分析辅助小工具--技术细节篇
- windows编程——简述1
- censtos6.2 DNS 服务器搭建
- 一个项目的大体架构及想法。
- HDU 1230 火星A+B
- 游戏服务器之事件注册
- 混淆的艺术-(苍井空变凤姐)Proguard源码分析(一)前言和计划
- windows编程——简述2
- Windows Server2008 禁止关闭防火强
- FFMPEG中关于ts流的时长估计的实现
- 收藏网址
- 股票EPS
- 内联定位
- 了解oracle表空间操作详解