//IEntityServer
/消息投票sink///
struct IMessageVoteSink
{
virtual bool OnVote(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen) = NULL;
};
/消息执行sink///
struct IMessageExecuteSink
{
virtual void OnExecute(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen) = NULL;
};
//MessageSlot.h
struct IMessageVoteSink;
struct IMessageExecuteSink;
// 定义
class CMessageSlot
{
///
// 一个投票订阅sink信息
struct SVoteSinkInfo
{
// 否决sink
IMessageVoteSink * pSink;
// 订阅描述
char szDesc[32];
SVoteSinkInfo(void)
{
memset(this, 0, sizeof(SVoteSinkInfo));
}
~SVoteSinkInfo(void)
{
memset(this, 0, sizeof(SVoteSinkInfo));
}
SVoteSinkInfo(IMessageVoteSink * pVoteSink, LPCSTR pszDesc)
{
// 否决sink
pSink = pVoteSink;
// 订阅描述
lstrcpyn(szDesc, pszDesc, sizeof(szDesc));
}
void Clean(void)
{
memset(this, 0, sizeof(SVoteSinkInfo));
}
};
// 一个消息的所有投票订阅sink
typedef list< SVoteSinkInfo > TLIST_VOTESINK;
// 所有消息的所有投票订阅sink
struct SVoteSinkList
{
// 投票订阅者sink
TLIST_VOTESINK listVoteSink;
// 是否在轮询过程中,有删除节点发生
bool bRemoveFlag;
SVoteSinkList(void)
{
// 投票订阅者sink
listVoteSink.clear();
// 是否在轮询过程中,有删除节点发生
bRemoveFlag = false;
}
~SVoteSinkList(void)
{
// 投票订阅者sink
listVoteSink.clear();
// 是否在轮询过程中,有删除节点发生
bRemoveFlag = false;
}
};
typedef vector< SVoteSinkList > TVECTOR_VOTESINK;
///
// 一个执行订阅sink信息
struct SExecuteSinkInfo
{
// 执行sink
IMessageExecuteSink * pSink;
// 订阅描述
char szDesc[32];
// 不允许循环发送消息,比如发送A消息,回调还未返回,又发送A送消息
int nEndFlag;
SExecuteSinkInfo(void)
{
memset(this, 0, sizeof(SExecuteSinkInfo));
}
SExecuteSinkInfo(IMessageExecuteSink * pExecuteSink, LPCSTR pszDesc)
{
// 执行sink
pSink = pExecuteSink;
// 订阅描述
lstrcpyn(szDesc, pszDesc, sizeof(szDesc));
// 缺省为0
nEndFlag = 0;
}
~SExecuteSinkInfo(void)
{
memset(this, 0, sizeof(SExecuteSinkInfo));
}
void Clean(void)
{
memset(this, 0, sizeof(SExecuteSinkInfo));
}
};
// 所有消息的所有投票订阅sink
typedef vector< SExecuteSinkInfo > TVECTOR_EXECUTESINK;
public:
bool Subscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink, LPCSTR pszDesc);
bool UnSubscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink);
bool Subscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink, LPCSTR pszDesc);
bool UnSubscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink);
void Fire(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen);
void Init(DWORD dwInitOpenSize);
CMessageSlot(void);
virtual ~CMessageSlot(void);
private:
void ResizeVector(void);
private:
// 消息码映射表
int m_nMsgIDSinkTable[MSG_ACTION_MAXID];
// 投票订阅sink
TVECTOR_VOTESINK m_vectorVoteSink;
// 否决订阅sink
TVECTOR_EXECUTESINK m_vectorExecuteSink;
// vector最大开放
int m_nVectorOpenSize;
// 当前vector分配到何个位置了
int m_nVectorCurAllot;
};
//MessageSlot.cpp
CMessageSlot::CMessageSlot(void)
{
// 消息码映射表
memset(m_nMsgIDSinkTable, -1, sizeof(m_nMsgIDSinkTable));
// 投票订阅sink
m_vectorVoteSink.clear();
// 否决订阅sink
m_vectorExecuteSink.clear();
// vector最大开放
m_nVectorOpenSize = 0;
// 当前vector分配到何个位置了
m_nVectorCurAllot = 0;
}
CMessageSlot::~CMessageSlot(void)
{
// 投票订阅sink
m_vectorVoteSink.clear();
// 否决订阅sink
m_vectorExecuteSink.clear();
}
void CMessageSlot::Init(DWORD dwInitOpenSize)
{
// vector最大开放
m_nVectorOpenSize = dwInitOpenSize;
// 设置投票订阅sink vector大小
m_vectorVoteSink.resize(m_nVectorOpenSize);
// 设置否决订阅sink vector大小
m_vectorExecuteSink.resize(m_nVectorOpenSize);
}
bool CMessageSlot::Subscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink, LPCSTR pszDesc)
{
if(dwMsgID < 0 || dwMsgID >= MSG_ACTION_MAXID || pVoteSink == NULL || pszDesc == NULL)
{
return false;
}
int nThisLoc = m_nMsgIDSinkTable[dwMsgID];
if(nThisLoc == -1)
{
m_nVectorCurAllot++;
if(m_nVectorCurAllot >= m_nVectorOpenSize)
{
ResizeVector();
}
m_nMsgIDSinkTable[dwMsgID] = m_nVectorCurAllot;
nThisLoc = m_nVectorCurAllot;
// 压入
SVoteSinkInfo votesinkinfo(pVoteSink, pszDesc);
SVoteSinkList votesinklist;
votesinklist.listVoteSink.push_back(votesinkinfo);
m_vectorVoteSink[nThisLoc] = votesinklist;
}
else
{
// 查找是否重复订阅
SVoteSinkList * pVoteSinkList = &m_vectorVoteSink[nThisLoc];
TLIST_VOTESINK * plistVoteSink = &pVoteSinkList->listVoteSink;
if(plistVoteSink != NULL)
{
TLIST_VOTESINK::iterator itL = plistVoteSink->begin();
for( ; itL != plistVoteSink->end(); ++itL)
{
SVoteSinkInfo * pVoteSinkInfo = &(*itL);
if(pVoteSinkInfo->pSink == pVoteSink)
{
return false;
}
}
SVoteSinkInfo votesinkinfo(pVoteSink, pszDesc);
plistVoteSink->push_back(votesinkinfo);
}
}
return true;
}
bool CMessageSlot::UnSubscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink)
{
if(dwMsgID < 0 || dwMsgID >= MSG_ACTION_MAXID || pVoteSink == NULL)
{
return false;
}
int nThisLoc = m_nMsgIDSinkTable[dwMsgID];
if(nThisLoc == -1)
{
return true;
}
SVoteSinkList * pVoteSinkList = &m_vectorVoteSink[nThisLoc];
TLIST_VOTESINK * plistVoteSink = &pVoteSinkList->listVoteSink;
if(plistVoteSink != NULL)
{
TLIST_VOTESINK::iterator itL = plistVoteSink->begin();
for( ; itL != plistVoteSink->end(); ++itL)
{
SVoteSinkInfo * pVoteSinkInfo = &(*itL);
if(pVoteSinkInfo->pSink == pVoteSink)
{
pVoteSinkInfo->Clean();
pVoteSinkList->bRemoveFlag = true;
return true;
}
}
}
return true;
}
bool CMessageSlot::Subscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink, LPCSTR pszDesc)
{
if(dwMsgID < 0 || dwMsgID >= MSG_ACTION_MAXID || pExecuteSink == NULL || pszDesc == NULL)
{
return false;
}
int nThisLoc = m_nMsgIDSinkTable[dwMsgID];
if(nThisLoc == -1)
{
m_nVectorCurAllot++;
if(m_nVectorCurAllot >= m_nVectorOpenSize)
{
ResizeVector();
}
m_nMsgIDSinkTable[dwMsgID] = m_nVectorCurAllot;
nThisLoc = m_nVectorCurAllot;
// 压入
SExecuteSinkInfo executesinkinfo(pExecuteSink, pszDesc);
m_vectorExecuteSink[nThisLoc] = executesinkinfo;
}
else
{
// 查找是否重复订阅
SExecuteSinkInfo * pExecuteSinkInfo = &m_vectorExecuteSink[nThisLoc];
if(pExecuteSinkInfo->pSink == NULL)
{
// 执行sink
pExecuteSinkInfo->pSink = pExecuteSink;
// 订阅描述
lstrcpyn(pExecuteSinkInfo->szDesc, pszDesc, sizeof(pExecuteSinkInfo->szDesc/*, pszDesc*/));
return true;
}
else
{
Warning("重复订阅执行消息,消息码 = " << dwMsgID << ", 描述 = " << pszDesc << endl);
return false;
}
}
return true;
}
bool CMessageSlot::UnSubscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink)
{
if(dwMsgID < 0 || dwMsgID >= MSG_ACTION_MAXID || pExecuteSink == NULL)
{
return false;
}
int nThisLoc = m_nMsgIDSinkTable[dwMsgID];
if(nThisLoc == -1)
{
return true;
}
// 查找是否重复订阅
SExecuteSinkInfo * pExecuteSinkInfo = &m_vectorExecuteSink[nThisLoc];
if(pExecuteSinkInfo->pSink != NULL)
{
pExecuteSinkInfo->Clean();
}
return true;
}
void CMessageSlot::Fire(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen)
{
if(dwMsgID < 0 || dwMsgID >= MSG_ACTION_MAXID)
{
return;
}
// 如果没人订阅投票或者执行消息,直接返回
int nThisLoc = m_nMsgIDSinkTable[dwMsgID];
if(nThisLoc == -1)
{
return;
}
// 如果同样的消息ID还没结束,不允许再次发同样的消息
SExecuteSinkInfo * pExecuteSinkInfo = &m_vectorExecuteSink[nThisLoc];
if(pExecuteSinkInfo == NULL || pExecuteSinkInfo->nEndFlag == 1)
{
Warning("本次消息尚未轮询完毕,不能再发同样消息,消息码 = " << dwMsgID << endl);
return;
}
pExecuteSinkInfo->nEndFlag = 1;
// 先发送投票消息
SVoteSinkList * pVoteSinkList = &m_vectorVoteSink[nThisLoc];
if(pVoteSinkList != NULL)
{
// 置在轮询过程中,有删除节点发生
pVoteSinkList->bRemoveFlag = false;
// 轮询
bool bResult = true;
bool bOldTimeRemove = false; // 有一些节点并不是轮询过程删除的,而是轮询前删除的
TLIST_VOTESINK::iterator it = pVoteSinkList->listVoteSink.begin();
for( ; it != pVoteSinkList->listVoteSink.end(); ++it)
{
if((*it).pSink != NULL)
{
try
{
if(!(*it).pSink->OnVote(dwMsgID, pGameMsgHead, pszMsg, nLen))
{
bResult = false;
break;
}
}
catch (...)
{
Error("发送投票消息非法,消息码 = " << dwMsgID << ", 描述 = " << (*it).szDesc << endl);
return;
}
}
else
{
bOldTimeRemove = true;
}
}
// 如果在轮询过程中,有删节点发生
if(pVoteSinkList->bRemoveFlag || bOldTimeRemove)
{
it = pVoteSinkList->listVoteSink.begin();
for( ; it != pVoteSinkList->listVoteSink.end(); )
{
if((*it).pSink == NULL)
{
it = pVoteSinkList->listVoteSink.erase(it);
}
else
{
++it;
}
}
pVoteSinkList->bRemoveFlag = false;
}
// 如果有否决sink要截止
if(!bResult)
{
// 轮询结束
pExecuteSinkInfo->nEndFlag = 0;
return;
}
}
// 发送执行消息
if(pExecuteSinkInfo->pSink != NULL)
{
try
{
pExecuteSinkInfo->pSink->OnExecute(dwMsgID, pGameMsgHead, pszMsg, nLen);
}
catch (...)
{
Error("发送执行消息非法,消息码 = " << dwMsgID << ", 描述 = " << pExecuteSinkInfo->szDesc << endl);
return;
}
}
// 轮询结束
pExecuteSinkInfo->nEndFlag = 0;
}
void CMessageSlot::ResizeVector(void)
{
m_nVectorOpenSize += 20;
if(m_nVectorOpenSize >= MSG_ACTION_MAXID)
{
m_nVectorOpenSize = MSG_ACTION_MAXID;
}
// 设置投票订阅sink vector大小
m_vectorVoteSink.resize(m_nVectorOpenSize);
// 设置否决订阅sink vector大小
m_vectorExecuteSink.resize(m_nVectorOpenSize);
}
//CPerson.h
class CPerson
{
public:
virtual bool Subscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink, LPCSTR pszDesc);
virtual bool UnSubscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink);
virtual bool Subscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink, LPCSTR pszDesc);
virtual bool UnSubscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink);
virtual void OnMessage(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen);
private:
// 信号槽
CMessageSlot m_MessageSlot;
};
//CPerson.cpp
bool CPerson::Create(void)
{
// 信号槽
m_MessageSlot.Init(MSG_ACTION_MAXID);
}
void CPerson::OnMessage(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen)
{
// 转到消息槽中
m_MessageSlot.Fire(dwMsgID, pGameMsgHead, pszMsg, nLen);
}
bool CPerson::Subscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink, LPCSTR pszDesc)
{
return m_MessageSlot.Subscibe(dwMsgID, pVoteSink, pszDesc);
}
bool CPerson::UnSubscibe(DWORD dwMsgID, IMessageVoteSink * pVoteSink)
{
return m_MessageSlot.UnSubscibe(dwMsgID, pVoteSink);
}
bool CPerson::Subscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink, LPCSTR pszDesc)
{
return m_MessageSlot.Subscibe(dwMsgID, pExecuteSink, pszDesc);
}
bool CPerson::UnSubscibe(DWORD dwMsgID, IMessageExecuteSink * pExecuteSink)
{
return m_MessageSlot.UnSubscibe(dwMsgID, pExecuteSink);
}
//CPersonMovePart.h
class CPersonMovePart : public IMessageExecuteSink
{
public:
IMessageExecuteSink
virtual void OnExecute(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen);
};
//CPersonMovePart.cpp
bool CPersonMovePart::Create(IEntity * pMaster, LPCSTR pszData, int nLen, bool bDBImport)
{
// 订阅移动的消息
if(!m_pMaster->Subscibe(MSG_ACTION_MOVE,
static_cast<IMessageExecuteSink *>(this),
"CPersonMovePart::Create"))
{
return false;
}
return true;
}
void CPersonMovePart::OnExecute(DWORD dwMsgID, SGameMsgHead * pGameMsgHead, LPCSTR pszMsg, int nLen)
{
switch(dwMsgID)
{
case MSG_ACTION_MOVE:
{
}
break;
default:
break;
}
}
消息槽
最新推荐文章于 2022-11-26 20:05:47 发布