Files
wnmj-normal/Servers/服务器组件/比赛服务/DistributeManager.cpp
2026-03-03 13:56:44 +08:00

594 lines
15 KiB
C++

#include "StdAfx.h"
#include "DistributeManager.h"
//////////////////////////////////////////////////////////////////////////////////
//内存管理
tagDistributeNode * CDistributeNodePool::m_pHeadOfFreeList=NULL;
const int CDistributeNodePool::BLOCK_SIZE = 20;
//常量定义
#define DISTRIBUTE_WAIT_TIMESTAMP 10 //等待时间戳
//////////////////////////////////////////////////////////////////////////////////
//构造函数
CDistributeNodePool::CDistributeNodePool()
{
}
//析构函数
CDistributeNodePool::~CDistributeNodePool()
{
if(m_pHeadOfFreeList!=NULL)
{
tagDistributeNode * pDistributeNode=m_pHeadOfFreeList;
while(pDistributeNode!=NULL)
{
//安全释放
m_pHeadOfFreeList = pDistributeNode->pNextDistributeNode;
SafeDelete(pDistributeNode);
pDistributeNode=m_pHeadOfFreeList;
}
}
}
//分配结点
tagDistributeNode * CDistributeNodePool::AllocNode()
{
//获取头结点
tagDistributeNode *pDistributeNode = m_pHeadOfFreeList;
if(pDistributeNode!=NULL)
m_pHeadOfFreeList = pDistributeNode->pNextDistributeNode;
else
{
//分配大块内存
for(int nIndex=0;nIndex<BLOCK_SIZE;nIndex++)
{
tagDistributeNode * pNewBlock = new tagDistributeNode;
pNewBlock->pNextDistributeNode=m_pHeadOfFreeList;
m_pHeadOfFreeList=pNewBlock;
}
//设置结点
pDistributeNode = m_pHeadOfFreeList;
m_pHeadOfFreeList=pDistributeNode->pNextDistributeNode;
}
return pDistributeNode;
}
//释放结点
VOID CDistributeNodePool::FreeNode(void * pNode)
{
//归还结点
tagDistributeNode * pDeadNode = static_cast<tagDistributeNode*>(pNode);
pDeadNode->pNextDistributeNode = m_pHeadOfFreeList;
m_pHeadOfFreeList = pDeadNode;
pNode=NULL;
return;
}
//////////////////////////////////////////////////////////////////////////////////
//构造函数
CDistributeManager::CDistributeManager()
{
//设置变量
m_pHeadNode=NULL;
m_wNodeCount=0;
m_wAndroidCount=0;
m_wRealCount=0;
m_cbDistributeRule=0;
//设置字典
m_SameTableMap.InitHashTable(10003);
}
//析构函数
CDistributeManager::~CDistributeManager()
{
//移除节点
RemoveAll();
//释放对象
m_SameTableBuffer.Append(m_SameTableActive);
for(INT_PTR nIndex=0;nIndex<m_SameTableBuffer.GetCount();nIndex++)
{
SafeDelete(m_SameTableBuffer[nIndex]);
}
//移除元素
m_SameTableBuffer.RemoveAll();
m_SameTableActive.RemoveAll();
}
//插入结点
BOOL CDistributeManager::InsertDistributeNode(const tagDistributeInfo & DistributeInfo)
{
//查找用户
if (SearchNode(DistributeInfo.pIServerUserItem) != NULL)
{
// 日志;
#if _DEBUG
IServerUserItem* pMeServerUserItem = DistributeInfo.pIServerUserItem;
//构造提示;
TCHAR szDescribe[128] = TEXT("");
_sntprintf_s(szDescribe, CountArray(szDescribe), TEXT("player [%s] 已在分配队列, GetUserStatus:[%d]. m_wAndroidCount=%d, m_wRealCount=%d, m_wNodeCount=%d."),
pMeServerUserItem->GetNickName(), pMeServerUserItem->GetUserStatus(), m_wAndroidCount, m_wRealCount, m_wNodeCount);
CTraceService::TraceString(szDescribe, TraceLevel_Warning);
#endif
return true;
}
//头部判断
if(m_pHeadNode==NULL)
{
//分配结点
m_pHeadNode = m_DistributeNodePool.AllocNode();
ASSERT(m_pHeadNode!=NULL);
if(m_pHeadNode==NULL) return false;
//设置变量
m_pHeadNode->pNextDistributeNode=NULL;
m_pHeadNode->pPrepDistributeNode=NULL;
CopyMemory(&m_pHeadNode->DistributeInfo,&DistributeInfo,sizeof(DistributeInfo));
m_pHeadNode->DistributeInfo.pPertainNode=m_pHeadNode;
}
else
{
//分配结点
tagDistributeNode * pDistributeNode = m_DistributeNodePool.AllocNode();
ASSERT(pDistributeNode!=NULL);
if(pDistributeNode==NULL) return false;
//设置结点
pDistributeNode->pNextDistributeNode=NULL;
pDistributeNode->pPrepDistributeNode=NULL;
CopyMemory(&pDistributeNode->DistributeInfo,&DistributeInfo,sizeof(DistributeInfo));
pDistributeNode->DistributeInfo.pPertainNode=pDistributeNode;
//表头结点
if(m_pHeadNode->pNextDistributeNode!=NULL)
{
m_pHeadNode->pNextDistributeNode->pPrepDistributeNode=pDistributeNode;
pDistributeNode->pNextDistributeNode=m_pHeadNode->pNextDistributeNode;
}
pDistributeNode->pPrepDistributeNode=m_pHeadNode;
m_pHeadNode->pNextDistributeNode=pDistributeNode;
}
//更新数目
if(DistributeInfo.pIServerUserItem->IsAndroidUser())
++m_wAndroidCount;
else
++m_wRealCount;
++m_wNodeCount;
// 日志;
#if _DEBUG
IServerUserItem* pMeServerUserItem = DistributeInfo.pIServerUserItem;
//构造提示;
TCHAR szDescribe[128] = TEXT("");
_sntprintf_s(szDescribe, CountArray(szDescribe), TEXT("player [%s] InsertDistributeNode, GetUserStatus:[%d]. m_wAndroidCount=%d, m_wRealCount=%d, m_wNodeCount=%d."),
pMeServerUserItem->GetNickName(), pMeServerUserItem->GetUserStatus(), m_wAndroidCount, m_wRealCount, m_wNodeCount);
CTraceService::TraceString(szDescribe, TraceLevel_Warning);
#endif
return true;
}
//移除结点
VOID CDistributeManager::RemoveDistributeNode(const IServerUserItem * pIServerUserItem)
{
//查找结点
tagDistributeNode *pDistributeNode=SearchNode(pIServerUserItem);
if(pDistributeNode!=NULL)
RemoveDistributeNode(pDistributeNode);
return;
}
//移除结点
VOID CDistributeManager::RemoveDistributeNode(tagDistributeNode * pDistributeNode)
{
//参数校验
if(pDistributeNode==NULL) return;
//查找用户
if(SearchNode(pDistributeNode->DistributeInfo.pIServerUserItem)==NULL) return;
//变量定义
tagDistributeNode *pPrepNode=pDistributeNode->pPrepDistributeNode;
tagDistributeNode *pNextNode=pDistributeNode->pNextDistributeNode;
//删除结点
if(pPrepNode!=NULL)
{
if(pNextNode!=NULL)
{
pPrepNode->pNextDistributeNode=pNextNode;
pNextNode->pPrepDistributeNode=pPrepNode;
}
else
{
//表头链接
if(pPrepNode->pNextDistributeNode==pDistributeNode)
pPrepNode->pNextDistributeNode=NULL;
}
}
else
{
if(pNextNode!=NULL)
{
pNextNode->pPrepDistributeNode=NULL;
//重置表头
m_pHeadNode=pNextNode;
}
else
{
m_pHeadNode=NULL;
}
}
//更新数目
if(pDistributeNode->DistributeInfo.pIServerUserItem->IsAndroidUser())
--m_wAndroidCount;
else
--m_wRealCount;
--m_wNodeCount;
// 日志;
#if _DEBUG
IServerUserItem* pMeServerUserItem = pDistributeNode->DistributeInfo.pIServerUserItem;
//构造提示;
TCHAR szDescribe[128] = TEXT("");
_sntprintf_s(szDescribe, CountArray(szDescribe), TEXT("player [%s] RemoveDistributeNode, GetUserStatus:[%d]. m_wAndroidCount=%d, m_wRealCount=%d, m_wNodeCount=%d."),
pMeServerUserItem->GetNickName(), pMeServerUserItem->GetUserStatus(), m_wAndroidCount, m_wRealCount, m_wNodeCount);
CTraceService::TraceString(szDescribe, TraceLevel_Warning);
#endif
//安全释放
m_DistributeNodePool.FreeNode(pDistributeNode);
}
//移除结点
VOID CDistributeManager::RemoveAll()
{
//释放内存
while(m_pHeadNode!=NULL) RemoveDistributeNode(m_pHeadNode);
//重置变量
m_pHeadNode=NULL;
m_wNodeCount=0;
m_wAndroidCount=0;
m_wRealCount=0;
return;
}
//执行分组
WORD CDistributeManager::PerformDistribute(CDistributeInfoArray & DistributeInfoArray,WORD wNeedCount)
{
//定义变量
tagDistributeNode * pMoveNode=NULL;
tagDistributeNode * pMoveStartNode=NULL;
if(m_pHeadNode!=NULL && m_wNodeCount>1)
{
pMoveNode = m_pHeadNode;
WORD wRandNodeIndex=rand()%m_wNodeCount;
while(wRandNodeIndex-->0)
{
if(pMoveNode==NULL)
{
pMoveNode = m_pHeadNode;
break;
}
pMoveNode = pMoveNode->pNextDistributeNode;
}
//设置变量
if(pMoveNode!=NULL) pMoveStartNode = pMoveNode;
}
//
if(pMoveNode==NULL) return 0;
//获取时间戳
DWORD dwCurrentStamp = (DWORD)time(NULL);
//先让正常玩家组队;
bool bAllRealPlayer = (m_wRealCount >= wNeedCount);
WORD wNeedAndroidNum = 0;
if (!bAllRealPlayer)
{
wNeedAndroidNum = wNeedCount - m_wRealCount;
}
//找出正在玩家;
do
{
//定义变量
BOOL bFirstSuccess = TRUE;
//等待时间
if (dwCurrentStamp - pMoveNode->DistributeInfo.dwInsertStamp < DISTRIBUTE_WAIT_TIMESTAMP)
bFirstSuccess = FALSE;
//机器人过滤;
IServerUserItem * pIServerUserItem = pMoveNode->DistributeInfo.pIServerUserItem;
if (pIServerUserItem->IsAndroidUser() == true) break;
//等级过滤
if (DistributeInfoArray.GetCount() > 0 && DistributeInfoArray[0].wDistribute != pMoveNode->DistributeInfo.wDistribute)
bFirstSuccess = FALSE;
//机器过滤
if (bFirstSuccess == TRUE && DistributeInfoArray.GetCount() == wNeedCount - 1 &&
FilterRuleIsAllAndroid(DistributeInfoArray, pMoveNode->DistributeInfo.pIServerUserItem))
bFirstSuccess = FALSE;
//同IP过滤
if (bFirstSuccess == TRUE && (m_cbDistributeRule&DISTRIBUTE_SAME_ADDRESS) == 0 &&
FilterRuleExitsIPAddr(DistributeInfoArray, pMoveNode->DistributeInfo.dwClientAddr) == TRUE)
bFirstSuccess = FALSE;
//同桌过滤
if (bFirstSuccess == TRUE && (m_cbDistributeRule&DISTRIBUTE_LAST_TABLE) == 0 &&
FilterRuleIsLastSameTable(DistributeInfoArray, pMoveNode->DistributeInfo.pIServerUserItem->GetUserID()) == TRUE)
bFirstSuccess = FALSE;
//获取成功
if (bFirstSuccess == TRUE) DistributeInfoArray.Add(pMoveNode->DistributeInfo);
//向前推进
pMoveNode = pMoveNode->pNextDistributeNode;
if (pMoveNode == NULL) pMoveNode = m_pHeadNode;
//成功判断
if (DistributeInfoArray.GetCount() >= wNeedCount) break;
} while (pMoveNode && pMoveNode != pMoveStartNode);
//成功判断
if (DistributeInfoArray.GetCount() >= wNeedCount)
{
return (WORD)DistributeInfoArray.GetCount();
}
//获取用户;
do
{
//定义变量
BOOL bFirstSuccess=TRUE;
//等待时间
if(dwCurrentStamp-pMoveNode->DistributeInfo.dwInsertStamp< DISTRIBUTE_WAIT_TIMESTAMP)
bFirstSuccess=FALSE;
//等级过滤
if(DistributeInfoArray.GetCount()>0 && DistributeInfoArray[0].wDistribute!=pMoveNode->DistributeInfo.wDistribute)
bFirstSuccess=FALSE;
//机器人过滤;(先让真正的玩家匹配);
if (bFirstSuccess && bAllRealPlayer && (pMoveNode->DistributeInfo.pIServerUserItem != NULL) &&
pMoveNode->DistributeInfo.pIServerUserItem->IsAndroidUser())
bFirstSuccess = FALSE;
if (bFirstSuccess && !bAllRealPlayer && GetAndroidNum(DistributeInfoArray) >= wNeedAndroidNum )
{
bFirstSuccess = FALSE;
bAllRealPlayer = true;
wNeedAndroidNum = 0;
}
//机器过滤
if(bFirstSuccess==TRUE && DistributeInfoArray.GetCount()==wNeedCount-1 &&
FilterRuleIsAllAndroid(DistributeInfoArray,pMoveNode->DistributeInfo.pIServerUserItem))
bFirstSuccess=FALSE;
//同IP过滤
if(bFirstSuccess==TRUE && (m_cbDistributeRule&DISTRIBUTE_SAME_ADDRESS)==0 &&
FilterRuleExitsIPAddr(DistributeInfoArray,pMoveNode->DistributeInfo.dwClientAddr)==TRUE)
bFirstSuccess=FALSE;
//同桌过滤
if(bFirstSuccess==TRUE && (m_cbDistributeRule&DISTRIBUTE_LAST_TABLE)==0 &&
FilterRuleIsLastSameTable(DistributeInfoArray,pMoveNode->DistributeInfo.pIServerUserItem->GetUserID())==TRUE)
bFirstSuccess=FALSE;
//获取成功
if(bFirstSuccess==TRUE) DistributeInfoArray.Add(pMoveNode->DistributeInfo);
//向前推进
pMoveNode=pMoveNode->pNextDistributeNode;
if(pMoveNode==NULL) pMoveNode = m_pHeadNode;
//成功判断
if(DistributeInfoArray.GetCount()==wNeedCount) break;
}while(pMoveNode && pMoveNode!=pMoveStartNode);
return (WORD)DistributeInfoArray.GetCount();
}
//获取信息
tagSameTableInfo * CDistributeManager::GetUserSameTableInfo(DWORD dwUserID)
{
//变量定义
tagSameTableInfo * pSameTableInfo;
if(m_SameTableMap.Lookup(dwUserID,pSameTableInfo)==FALSE)
{
pSameTableInfo = ActiveSameTableInfo();
m_SameTableMap[dwUserID] = pSameTableInfo;
}
return pSameTableInfo;
}
//移除信息
VOID CDistributeManager::RemoveUserSameTableInfo(DWORD dwUserID)
{
//变量定义
tagSameTableInfo * pSameTableInfo;
if(m_SameTableMap.Lookup(dwUserID,pSameTableInfo)==TRUE)
{
//移除信息
m_SameTableMap.RemoveKey(dwUserID);
RemoveSameTableInfo(pSameTableInfo);
}
}
//激活对象
tagSameTableInfo * CDistributeManager::ActiveSameTableInfo()
{
//查找缓冲
if(m_SameTableBuffer.GetCount()>0)
{
tagSameTableInfo * pSameTableInfo = m_SameTableBuffer.GetAt(0);
m_SameTableBuffer.RemoveAt(0);
m_SameTableActive.Add(pSameTableInfo);
return pSameTableInfo;
}
//创建对象
try
{
//创建对象
tagSameTableInfo * pSameTableInfo = new tagSameTableInfo;
if(pSameTableInfo==NULL) throw(TEXT("内存不足,对象创建失败!"));
//设置对象
ZeroMemory(pSameTableInfo,sizeof(tagSameTableInfo));
m_SameTableActive.Add(pSameTableInfo);
return pSameTableInfo;
}
catch(...)
{
ASSERT(FALSE);
}
return NULL;
}
//移除对象
VOID CDistributeManager::RemoveSameTableInfo(tagSameTableInfo * pSameTableInfo)
{
ZeroMemory(pSameTableInfo,sizeof(tagSameTableInfo));
m_SameTableBuffer.Add(pSameTableInfo);
//查找对象
for(INT_PTR nIndex=0;nIndex<m_SameTableActive.GetCount();nIndex++)
{
if(m_SameTableActive[nIndex]==pSameTableInfo)
{
m_SameTableActive.RemoveAt(nIndex);
break;
}
}
}
//查找结点
tagDistributeNode * CDistributeManager::SearchNode(const IServerUserItem * const pIServerUserItem)
{
if(m_pHeadNode==NULL) return NULL;
//设置变量
tagDistributeNode *pMoveNode=m_pHeadNode;
//查找结点
while(pMoveNode!=NULL)
{
//接口判断
if(pMoveNode->DistributeInfo.pIServerUserItem==pIServerUserItem)
return pMoveNode;
//向前推进
pMoveNode=pMoveNode->pNextDistributeNode;
}
return NULL;
}
//IP同址
BOOL CDistributeManager::FilterRuleExitsIPAddr(const CDistributeInfoArray & DistributeInfoArray,DWORD dwClientAddr)
{
//查找同IP
for(INT_PTR nIndex=0;nIndex<DistributeInfoArray.GetCount();nIndex++)
{
if(DistributeInfoArray[nIndex].dwClientAddr==dwClientAddr)
return TRUE;
}
return FALSE;
}
//机器过滤
BOOL CDistributeManager::FilterRuleIsAllAndroid(const CDistributeInfoArray & DistributeInfoArray,IServerUserItem * const pIServerUserItem)
{
//参数校验
if(pIServerUserItem==NULL || DistributeInfoArray.GetCount()==0) return FALSE;
//变量定义
WORD wAndroidCount=0;
//统计机器
for(INT_PTR nIndex=0;nIndex<DistributeInfoArray.GetCount();nIndex++)
{
if(DistributeInfoArray[nIndex].pIServerUserItem->IsAndroidUser()==true)
++wAndroidCount;
}
return (wAndroidCount==DistributeInfoArray.GetCount()) && pIServerUserItem->IsAndroidUser();
}
//上局同桌
BOOL CDistributeManager::FilterRuleIsLastSameTable(const CDistributeInfoArray & DistributeInfoArray,DWORD dwUserID)
{
//参数校验
if(DistributeInfoArray.GetCount()==0) return FALSE;
//变量定义
tagSameTableInfo * pSameTableInfo=NULL;
for(INT_PTR nIndex=0;nIndex<DistributeInfoArray.GetCount();nIndex++)
{
pSameTableInfo = GetUserSameTableInfo(DistributeInfoArray[nIndex].pIServerUserItem->GetUserID());
if(pSameTableInfo!=NULL)
{
for(WORD i=0;i<pSameTableInfo->wPlayerCount;i++)
{
if(pSameTableInfo->wPlayerIDSet[i]==dwUserID) return TRUE;
}
}
}
return FALSE;
}
WORD CDistributeManager::GetAndroidNum(const CDistributeInfoArray & DistributeInfoArray)
{
//变量定义;
WORD wAndroidCount = 0;
INT_PTR nSize = DistributeInfoArray.GetCount();
//统计机器
for (INT_PTR nIndex = 0; nIndex < nSize; nIndex++)
{
if (DistributeInfoArray[nIndex].pIServerUserItem->IsAndroidUser() == true)
++wAndroidCount;
}
return wAndroidCount;
}
//////////////////////////////////////////////////////////////////////////////////