Files
2026-03-03 13:56:44 +08:00

1072 lines
28 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "StdAfx.h"
#include "ImmediateGroup.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////////////////////////////////////////////////////
//常量定义
#define INVALID_VALUE 0xFFFF //无效值
//静态变量
WORD CImmediateGroup::m_wChairCount; //椅子数目
//////////////////////////////////////////////////////////////////////////
//构造函数
CImmediateGroup::CImmediateGroup(DWORD dwMatchNO,tagGameMatchOption * pGameMatchOption,IImmediateGroupSink *pIImmediateGroupSink)
{
//指针变量
m_pMatchOption=pGameMatchOption;
m_pMatchSink=pIImmediateGroupSink;
//状态变量
m_dwMatchNO=dwMatchNO;
m_enMatchStatus=MatchStatus_Signup;
m_dwCurBase=m_pMatchOption->MatchType.Immediate.dwInitalBase;
//设置变量
ZeroMemory(&m_MatchStartTime,sizeof(m_MatchStartTime));
//移除元素
m_OnMatchUserMap.RemoveAll();
m_FreeUserArray.RemoveAll();
m_MatchTableArray.RemoveAll();
//设置变量
m_LoopTimer=0;
m_wAndroidUserCount=0;
}
//析构函数
CImmediateGroup::~CImmediateGroup()
{
//杀死定时器
AllKillMatchTimer();
//设置状态
m_wAndroidUserCount=0;
m_enMatchStatus=MatchStatus_Null;
//释放桌子
for (int i=0; i<m_MatchTableArray.GetCount(); i++)
{
SafeDelete(m_MatchTableArray[i]);
}
//移除元素
m_MatchTableArray.RemoveAll();
m_OnMatchUserMap.RemoveAll();
m_FreeUserArray.RemoveAll();
}
//接口查询
VOID* CImmediateGroup::QueryInterface(REFGUID Guid, DWORD dwQueryVer)
{
QUERYINTERFACE(IMatchEventSink,Guid,dwQueryVer);
QUERYINTERFACE_IUNKNOWNEX(IMatchEventSink,Guid,dwQueryVer);
return NULL;
}
//用户报名
bool CImmediateGroup::OnUserSignUpMatch(IServerUserItem * pUserItem)
{
//用户判断
ASSERT(pUserItem!=NULL);
if (pUserItem==NULL) return false;
//查找用户
IServerUserItem * pIServerUserExist=NULL;
m_OnMatchUserMap.Lookup(pUserItem->GetUserID(),pIServerUserExist);
//用户判断
ASSERT(pIServerUserExist==NULL);
if (pIServerUserExist!=NULL) return false;
//人数效验
ASSERT(m_OnMatchUserMap.GetCount()<m_pMatchOption->MatchType.Immediate.wStartUserCount);
if (m_OnMatchUserMap.GetCount()>=m_pMatchOption->MatchType.Immediate.wStartUserCount) return false;
//机器判断
if (pUserItem->IsAndroidUser()==true)
{
if (m_wAndroidUserCount>=m_pMatchOption->MatchType.Immediate.wAndroidUserCount)
{
return false;
}
m_wAndroidUserCount++;
}
//设置成绩
tagUserInfo *pUserScore=pUserItem->GetUserInfo();
pUserScore->dwWinCount=0L;
pUserScore->dwLostCount=0L;
pUserScore->dwFleeCount=0L;
pUserScore->dwDrawCount=0L;
pUserScore->lGrade=0L;
pUserScore->lScore=(SCORE)m_pMatchOption->MatchType.Immediate.dwInitalScore;
//发送成绩
m_pMatchSink->SendGroupUserScore(pUserItem,NULL);
//设置用户
m_OnMatchUserMap[pUserItem->GetUserID()]=pUserItem;
//设置报名状态
pUserItem->SetUserMatchStatus(MUS_SIGNUP);
//设置报名时间
pUserItem->SetSignUpTime(GetTickCount());
//发送报名状态
BYTE cbMatchStatus = MS_WAITPLAY;
m_pMatchSink->SendData(pUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbMatchStatus, sizeof(cbMatchStatus));
//报名人满
if (m_OnMatchUserMap.GetCount()>=m_pMatchOption->MatchType.Immediate.wStartUserCount)
{
//事件通知
ASSERT(m_pMatchSink!=NULL);
if (m_pMatchSink!=NULL) m_pMatchSink->SendMatchInfo(NULL);
EfficacyStartMatch();
}
return true;
}
//比赛开始
void CImmediateGroup::EfficacyStartMatch()
{
m_pMatchSink->InsertNullTable();
//没有桌子的情况
if( m_MatchTableArray.GetCount()<m_pMatchOption->MatchType.Immediate.wStartUserCount/m_wChairCount )
{
if(m_OnMatchUserMap.GetCount()<m_wChairCount)
{
//构造数据包
CMD_CM_SystemMessage Message;
Message.wType=SMT_EJECT|SMT_CHAT|SMT_CLOSE_GAME;
lstrcpyn(Message.szString,TEXT("抱歉,由于某用户强行退出比赛,该场比赛提前结束。你可以继续等待比赛!"),CountArray(Message.szString));
Message.wLength=CountStringBuffer(Message.szString);
//发送数据
WORD wSendSize=sizeof(Message)-sizeof(Message.szString)+Message.wLength*sizeof(TCHAR);
m_pMatchSink->SendGroupData(MDM_CM_SYSTEM,SUB_CM_SYSTEM_MESSAGE,&Message,wSendSize, this);
m_enMatchStatus=MatchStatus_Signup;
return ;
}
m_enMatchStatus=MatchStatus_Wait;
//3秒后继续调用该函数直到有桌子
SetMatchGameTimer(IDI_WAITTABLE_FIRST_ROUND,3000,1,NULL);
//构造数据包
CMD_CM_SystemMessage Message;
Message.wType=SMT_CHAT;
_sntprintf_s(Message.szString,CountArray(Message.szString),
TEXT("抱歉,由于过多用户桌子数量不够!还差 %d 张桌子开赛,请等待。。。"),m_pMatchOption->MatchType.Immediate.wStartUserCount/m_wChairCount-m_MatchTableArray.GetCount());
Message.wLength=CountStringBuffer(Message.szString);
//发送数据
WORD wSendSize=sizeof(Message)-sizeof(Message.szString)+Message.wLength*sizeof(TCHAR);
m_pMatchSink->SendGroupData(MDM_CM_SYSTEM,SUB_CM_SYSTEM_MESSAGE,&Message,wSendSize, this);
return ;
}
//预赛安排座位
DWORD dwUserID=0L;
IServerUserItem *pIServerUserItem=NULL;
POSITION pos=m_OnMatchUserMap.GetStartPosition();
WORD wChairID=0;
while (pos!=NULL)
{
//获取用户
m_OnMatchUserMap.GetNextAssoc(pos,dwUserID,pIServerUserItem);
ASSERT(pIServerUserItem!=NULL);
InsertFreeGroup(pIServerUserItem);
//设置用户比赛中
pIServerUserItem->SetUserMatchStatus(MUS_MATCHING);
pIServerUserItem->SetMatchData(this);
}
//桌子自动拉人
TabelRequestUser(false);
//设置状态
m_enMatchStatus=MatchStatus_FirstRound;
//记录时间
CTime::GetCurrentTime().GetAsSystemTime(m_MatchStartTime);
//开始通知
if (m_pMatchSink!=NULL) m_pMatchSink->OnEventMatchStart(this);
//设置定时器
SetMatchGameTimer(IDI_CHECK_MATCH_GROUP,1000,TIMES_INFINITY,0);
}
//用户退赛
BOOL CImmediateGroup::OnUserQuitMatch(IServerUserItem *pUserItem)
{
//用户判断
ASSERT(pUserItem!=NULL);
if (pUserItem==NULL) return false;
//删除用户
BOOL bSuccess=m_OnMatchUserMap.RemoveKey(pUserItem->GetUserID());
if(bSuccess==false)return false;
if (pUserItem->IsAndroidUser())
{
ASSERT(m_wAndroidUserCount>0);
if (m_wAndroidUserCount>0) m_wAndroidUserCount--;
}
//设置状态
pUserItem->SetUserMatchStatus(MUS_NULL);
BYTE cbUserStatus=MatchStatus_Null;
m_pMatchSink->SendData(pUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbUserStatus, sizeof(cbUserStatus));
return bSuccess;
}
//定时器
bool CImmediateGroup::OnTimeMessage(DWORD dwTimerID, WPARAM dwBindParameter)
{
//状态校验
if(m_enMatchStatus==MatchStatus_Null) return true;
switch(dwTimerID)
{
case IDI_CHECK_MATCH_GROUP:
{
CaptureMatchTimer();
return true;
}
case IDI_WAITTABLE_FIRST_ROUND:
{
if(m_enMatchStatus==MatchStatus_Wait)
{
EfficacyStartMatch();
}
return true;
}
case IDI_SWITCH_WAIT_TIME:
{
//将空闲用户自动配桌
RearrangeUserSeat();
TabelRequestUser();
//ContinueGame((ITableFrame*)dwBindParameter);
return true;
}
case IDI_TABLE_REQUEST_USER:
{
TabelRequestUser();
return true;
}
case IDI_ENTER_NEXT_ROUND:
{
//if(m_enMatchStatus==MS_START_NEXT_ROUND)
//{
// //继续下一轮
// ContinueRound();
//}
return true;
}
case IDI_ALL_DISMISS_GAME:
{
RearrangeUserSeat();
return true;
}
case IDI_LASTMATCHRESULT:
{
//最后结束
MatchOver();
return true;
}
}
return true;
}
WORD CImmediateGroup::SortMapUser(tagMatchScore score[])
{
INT_PTR nCount=m_OnMatchUserMap.GetCount();
POSITION pos=m_OnMatchUserMap.GetStartPosition();
nCount=0;
while(pos!=NULL)
{
m_OnMatchUserMap.GetNextAssoc(pos,score[nCount].dwUserID, score[nCount].pUserItem);
score[nCount].dwUserID=score[nCount].pUserItem->GetUserID();
score[nCount].lScore = score[nCount].pUserItem->GetUserScore();
nCount++;
}
for(INT_PTR i = 1;i < nCount;i++)
{
INT_PTR left = 0,right = i - 1;
tagMatchScore Temp = score[i];
while(left <= right)
{
INT_PTR mid = (left + right)/2;
if (score[i].lScore > score[mid].lScore)right = mid - 1;
else left = mid + 1;
}
for(INT_PTR j = i - 1;j >= left;j--)
score[j+1] = score[j];
score[left] = Temp;
}
return (WORD)nCount;
}
//重置桌位
void CImmediateGroup::RearrangeUserSeat(bool bDismissGame)
{
KillMatchGameTimer(IDI_SWITCH_WAIT_TIME);
for(WORD i=0; i<m_MatchTableArray.GetCount();i++)
{
tagTableFrameInfo *ptagTableFrameInfo=m_MatchTableArray[i];
ASSERT(ptagTableFrameInfo!=NULL);
if (ptagTableFrameInfo==NULL) continue;
ITableFrame* pTableFrame=ptagTableFrameInfo->pTableFrame;
ASSERT(pTableFrame!=NULL);
if (pTableFrame==NULL) continue;
if (bDismissGame==false)
{
ptagTableFrameInfo->cbPlayCount=0;
ptagTableFrameInfo->bRoundTableFinish=false;
ptagTableFrameInfo->bSwtichTableFinish=false;
ptagTableFrameInfo->bWaitForNextInnings=false;
}
//强制解散游戏
if (pTableFrame->IsGameStarted()==true)
{
if (bDismissGame==true)
{
bool bSuccess=pTableFrame->DismissGame();
if (bSuccess==false)
CTraceService::TraceString(TEXT("解散游戏"),TraceLevel_Exception);
}
else
{
TCHAR szMessage[64]=TEXT("");
_sntprintf_s(szMessage,CountArray(szMessage),TEXT("重置桌位时,第 %d 桌处于游戏状态"),pTableFrame->GetTableID());
CTraceService::TraceString(szMessage,TraceLevel_Exception);
}
}
//该桌用户全部离开
AllUserExitTable(pTableFrame);
}
return;
}
//游戏开始
bool CImmediateGroup::OnEventGameStart(ITableFrame *pITableFrame, WORD wChairCount)
{
pITableFrame->SetCellScore(m_dwCurBase);
KillMatchTimer(IDI_CHECK_TABLE_START,(WPARAM)pITableFrame);
tagTableFrameInfo *pTableFrameInfo=GetTableInterface(pITableFrame);
pTableFrameInfo->bRoundTableFinish=false;
pTableFrameInfo->bSwtichTableFinish=false;
pTableFrameInfo->bWaitForNextInnings=false;
//已完成局数加1
pTableFrameInfo->cbPlayCount++;
//发送比赛信息给桌子上的用户
SendTableUserMatchInfo(pITableFrame, INVALID_CHAIR);
//构造数据包
CMD_CM_SystemMessage SystemMessage;
ZeroMemory(&SystemMessage,sizeof(SystemMessage));
TCHAR szMsg[256]=TEXT("");
_sntprintf_s(szMsg, CountArray(szMsg),TEXT("定局排名赛第%d局开始共%d局"),pTableFrameInfo->cbPlayCount,m_pMatchOption->MatchType.Immediate.cbPlayCount);
lstrcpyn(SystemMessage.szString,szMsg,CountArray(SystemMessage.szString));
SystemMessage.wLength=CountStringBuffer(SystemMessage.szString);
SystemMessage.wType=SMT_CHAT;
//发送数据
WORD wSendSize=sizeof(SystemMessage)-sizeof(SystemMessage.szString)+SystemMessage.wLength*sizeof(TCHAR);
pITableFrame->SendTableData(INVALID_CHAIR,SUB_GF_SYSTEM_MESSAGE, (void*)&SystemMessage,wSendSize,MDM_GF_FRAME);
return true;
}
//游戏结束
bool CImmediateGroup::OnEventGameEnd(ITableFrame *pITableFrame,WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason)
{
//记录本局和哪些用户玩过
tagTableFrameInfo * ptagTableFrameInfo=GetTableInterface(pITableFrame);
ASSERT(ptagTableFrameInfo);
if (ptagTableFrameInfo==NULL)return false;
if(m_enMatchStatus==MatchStatus_FirstRound)
{
FirstRoundRuleInningsGameEnd(pITableFrame);
}
//CheckExitMatch();
//比赛结束直接返回
if(m_enMatchStatus==MatchStatus_Null)return true;
if(m_OnMatchUserMap.GetCount()>0)
{
//分数通知
tagMatchScore *pScore = new tagMatchScore[m_OnMatchUserMap.GetCount()];
ZeroMemory(pScore,sizeof(tagMatchScore)*m_OnMatchUserMap.GetCount());
WORD wCount=SortMapUser(pScore);
for (WORD i=0;i<wCount;i++)
{
m_pMatchSink->SendGroupUserScore(pScore[i].pUserItem,this);
}
SafeDeleteArray(pScore);
}
return true;
}
//用户坐下
bool CImmediateGroup::OnActionUserSitDown(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
{
return true;
}
//用户起立
bool CImmediateGroup::OnActionUserStandUp(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
{
return true;
}
//用户同意
bool CImmediateGroup::OnActionUserOnReady(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, VOID * pData, WORD wDataSize)
{
return false;
}
//获取名次
WORD CImmediateGroup::GetUserRank(IServerUserItem *pUserItem, ITableFrame *pITableFrame)
{
//参数效验
ASSERT(pUserItem!=NULL);
if(pUserItem==NULL) return INVALID_WORD;
//定义变量
SCORE lUserScore=pUserItem->GetUserScore();
WORD wRank=1;
DWORD dwUserID=0;
IServerUserItem *pLoopUserItem=NULL;
if(pITableFrame==NULL)
{
//遍历容器
POSITION pos=m_OnMatchUserMap.GetStartPosition();
while(pos!=NULL)
{
m_OnMatchUserMap.GetNextAssoc(pos,dwUserID, pLoopUserItem);
if(pLoopUserItem!=pUserItem && pLoopUserItem->GetUserScore()>lUserScore)
wRank++;
}
}
else
{
ASSERT(pUserItem->GetTableID()==pITableFrame->GetTableID());
if(pUserItem->GetTableID()!=pITableFrame->GetTableID()) return INVALID_WORD;
for(WORD i=0; i<m_wChairCount; i++)
{
pLoopUserItem=pITableFrame->GetTableUserItem(i);
if(pLoopUserItem==NULL) continue;
if(pLoopUserItem!=pUserItem && pLoopUserItem->GetUserScore()>lUserScore)
wRank++;
}
}
return wRank;
}
//获取桌子专用接口
tagTableFrameInfo* CImmediateGroup::GetTableInterface(ITableFrame* ITable)
{
for (int i=0;i<m_MatchTableArray.GetCount();i++)
{
if (m_MatchTableArray[i]->pTableFrame==ITable)return m_MatchTableArray[i];
}
return NULL;
}
//比赛结束
void CImmediateGroup::MatchOver()
{
//删除定时器
AllKillMatchTimer();
KillMatchGameTimer(IDI_CHECK_MATCH_GROUP);
KillMatchGameTimer(IDI_WAITTABLE_FIRST_ROUND);
KillMatchGameTimer(IDI_WAITTABLE_RAND_TABLE);
KillMatchGameTimer(IDI_SWITCH_WAIT_TIME);
KillMatchGameTimer(IDI_ALL_DISMISS_GAME);
KillMatchGameTimer(IDI_LASTMATCHRESULT);
KillMatchGameTimer(IDI_TABLE_REQUEST_USER);
//设置比赛状态
ASSERT(m_enMatchStatus==MatchStatus_FirstRound);
if(m_enMatchStatus==MatchStatus_FirstRound)
{
m_enMatchStatus=MatchStatus_Null;
m_pMatchSink->OnEventMatchOver(this);
}
}
//定局排名游戏结束
void CImmediateGroup::FirstRoundRuleInningsGameEnd(ITableFrame *pITableFrame)
{
//获取对象
tagTableFrameInfo * ptagTableFrameInfo=GetTableInterface(pITableFrame);
ASSERT(ptagTableFrameInfo);
if (ptagTableFrameInfo==NULL) return;
//设置等待下局标识
ptagTableFrameInfo->bWaitForNextInnings=true;
TCHAR szMessage[128]=TEXT("");
//该桌打完指定局数
if (ptagTableFrameInfo->cbPlayCount>=m_pMatchOption->MatchType.Immediate.cbPlayCount)
{
_sntprintf_s(szMessage, CountArray(szMessage), TEXT("恭喜您,您已玩满%d局游戏,等其他桌完成后系统将进行排名,请您耐心等待!"),m_pMatchOption->MatchType.Immediate.cbPlayCount);
//发送提示信息
for (WORD j=0;j<m_wChairCount;j++)
{
IServerUserItem *pIServerUserItem=pITableFrame->GetTableUserItem(j);
if(pIServerUserItem!=NULL)
{
m_pMatchSink->SendGameMessage(pIServerUserItem,szMessage,SMT_CHAT|SMT_TABLE_ROLL);
//插入空闲列表
InsertFreeGroup(pIServerUserItem);
}
else
{
ASSERT(FALSE);
CTraceService::TraceString(TEXT("玩家信息为空1!"),TraceLevel_Exception);
}
}
//设置完成标识
SetRoundTableFinish(pITableFrame);
SendWaitTip(pITableFrame);
ptagTableFrameInfo->cbPlayCount=0;
}
else
{
if(m_pMatchOption->MatchType.Immediate.cbSwitchTableCount>0&&(ptagTableFrameInfo->cbPlayCount%m_pMatchOption->MatchType.Immediate.cbSwitchTableCount)==0)
_sntprintf_s(szMessage,CountArray(szMessage),TEXT("%s"),TEXT("本局已结束,请耐心等待其他桌完成,稍后为您配桌..."));
else
_sntprintf_s(szMessage,CountArray(szMessage),TEXT("%s"),TEXT("本局已结束,请稍候,系统配桌中..."));
//发送提示信息
for (WORD j=0;j<m_wChairCount;j++)
{
IServerUserItem *pIServerUserItem=pITableFrame->GetTableUserItem(j);
if(pIServerUserItem!=NULL)
{
m_pMatchSink->SendGameMessage(pIServerUserItem, szMessage, SMT_CHAT|SMT_TABLE_ROLL);
//插入空闲列表
InsertFreeGroup(pIServerUserItem);
}
else
{
ASSERT(FALSE);
CTraceService::TraceString(TEXT("玩家信息为空2!"),TraceLevel_Exception);
}
}
}
//所有桌都完成指定局数
if (CheckRoundTableFinish())
{
SetMatchGameTimer(IDI_LASTMATCHRESULT,5000,1,0);
return ;
}
else if(ptagTableFrameInfo->bRoundTableFinish==false)
{
//自动换桌的控制
if(m_pMatchOption->MatchType.Immediate.cbSwitchTableCount>0&&(ptagTableFrameInfo->cbPlayCount%m_pMatchOption->MatchType.Immediate.cbSwitchTableCount)==0)
{
SetSwitchTableFinish(pITableFrame);
SendWaitTip(pITableFrame);
//检查该桌子是否可以换桌
if (CheckSwitchTableFinish())
{
SetMatchGameTimer(IDI_SWITCH_WAIT_TIME,5000,1,0);
return;
}
}
else //不换桌
{
//设置定时器
PostMatchTimer(IDI_CONTINUE_GAME,5,(WPARAM)pITableFrame);
return;
}
}
}
//发送提示
VOID CImmediateGroup::SendWaitTip(ITableFrame *pTableFrame, WORD wChairID/*=INVALID_CHAIR*/)
{
//状态校验
if(m_enMatchStatus==MatchStatus_Null || m_enMatchStatus==MatchStatus_Signup )
return;
tagTableFrameInfo *pITableFameEx=GetTableInterface(pTableFrame);
ASSERT(pITableFameEx!=NULL);
if (pITableFameEx==NULL) return;
//变量定义
WORD wPlayingTable=0;
for(WORD i=0;i<m_MatchTableArray.GetCount();i++)
{
if(m_MatchTableArray[i]->pTableFrame->GetGameStatus()>=GAME_STATUS_PLAY)
wPlayingTable++;
}
//变量定义
CMD_GR_Match_Wait_Tip WaitTip;
ZeroMemory(&WaitTip,sizeof(WaitTip));
WaitTip.wPlayingTable=wPlayingTable;
WaitTip.wUserCount=(WORD)m_OnMatchUserMap.GetCount();
WaitTip.wCurGameCount=pITableFameEx->cbPlayCount;
WaitTip.wGameCount=m_pMatchOption->MatchType.Immediate.cbPlayCount;
lstrcpyn(WaitTip.szMatchName, m_pMatchOption->szMatchName,LEN_SERVER);
//发送比赛信息给本桌的玩家
for(WORD i=0;i<m_wChairCount;i++)
{
if(wChairID!=INVALID_CHAIR && wChairID!=i) continue;
IServerUserItem *pTableUserItem=pTableFrame->GetTableUserItem(i);
if(pTableUserItem==NULL) continue;
WaitTip.wCurTableRank=GetUserRank(pTableUserItem,pTableFrame);
if(WaitTip.wCurTableRank==INVALID_WORD) continue;
WaitTip.wRank=GetUserRank(pTableUserItem);
WaitTip.lScore=pTableUserItem->GetUserScore();
m_pMatchSink->SendData(pTableUserItem,MDM_GR_MATCH,SUB_GR_MATCH_WAIT_TIP,&WaitTip,sizeof(WaitTip));
}
//发送比赛信息给其他桌的玩家
for(WORD i=0;i<m_MatchTableArray.GetCount();i++)
{
if(pTableFrame->GetTableID()==m_MatchTableArray[i]->pTableFrame->GetTableID())continue;
if(m_MatchTableArray[i]->pTableFrame->GetGameStatus()>=GAME_STATUS_PLAY) continue;
for(WORD j=0;j<m_wChairCount;j++)
{
IServerUserItem *pTableUserItem=m_MatchTableArray[i]->pTableFrame->GetTableUserItem(j);
if(pTableUserItem==NULL) continue;
WaitTip.wCurTableRank=GetUserRank(pTableUserItem,m_MatchTableArray[i]->pTableFrame);
if(WaitTip.wCurTableRank==INVALID_WORD) continue;
WaitTip.wRank=GetUserRank(pTableUserItem);
WaitTip.lScore=pTableUserItem->GetUserScore();
m_pMatchSink->SendData(pTableUserItem,MDM_GR_MATCH,SUB_GR_MATCH_WAIT_TIP,&WaitTip,sizeof(WaitTip));
}
}
}
//空闲桌子拉空闲用户
void CImmediateGroup::TabelRequestUser(bool bPrecedeSit)
{
//参赛用户不够 椅子数量就要终止比赛
if (CheckMatchUser())
{
return;
}
CTableFrameMananerArray FreeTableArray; //空比赛桌子
//首先获取空桌子
for (INT_PTR i=0;i<m_MatchTableArray.GetCount();i++)
{
if(m_MatchTableArray[i]->pTableFrame->IsGameStarted()==false&&m_MatchTableArray[i]->bRoundTableFinish==false)
{
//获取数量
INT_PTR cbTimer=m_MatchTimerArray.GetCount();
bool cbIsInsert=false;
for(int j=0;j<cbTimer;j++)
{
//判断一下有没有卡赛的桌子在等待
if((m_MatchTimerArray[j]->dwTimerID==IDI_CHECK_TABLE_START||m_MatchTimerArray[j]->dwTimerID==IDI_CONTINUE_GAME)&&(ITableFrame*)(m_MatchTimerArray[j]->wParam)==m_MatchTableArray[i]->pTableFrame)
{
cbIsInsert=true;
break;
}
}
if(cbIsInsert==false)
FreeTableArray.Add(m_MatchTableArray[i]);
}
}
DWORD dwCurTime=(DWORD)time(NULL);
bool bIsContinueCheck=false;//优化优先坐下 原本是true
for (INT_PTR i=0;i<FreeTableArray.GetCount();i++)
{
DWORD nCurUserCount=(DWORD)m_FreeUserArray.GetCount();
//找到一个空桌 空闲用户必须大于等于椅子
if(nCurUserCount/m_wChairCount>0)
{
AllUserExitTable(FreeTableArray[i]->pTableFrame);
for (int j=0;j<m_wChairCount;j++)
{
//用户插入该桌
WORD wRandID=INVALID_VALUE;
if(bPrecedeSit&&bIsContinueCheck)
{
wRandID=GetPrecedeSitUser(dwCurTime);
}
if(wRandID==INVALID_VALUE)
{
bIsContinueCheck=false;//已经没有优先用户了
wRandID=rand()%(WORD)m_FreeUserArray.GetCount();
}
IServerUserItem *pIServerUserItem=m_FreeUserArray[wRandID];
ASSERT(pIServerUserItem!=NULL);
if (pIServerUserItem==NULL) continue;
//先起立在坐下 让该桌的人全部起立
if(pIServerUserItem->GetTableID()!=INVALID_TABLE)
{
for(int m=0;m<m_MatchTableArray.GetCount();m++)
{
if(pIServerUserItem->GetTableID()==m_MatchTableArray[m]->wTableID)
{
m_MatchTableArray[m]->pTableFrame->PerformStandUpAction(pIServerUserItem);
break;
}
}
}
if (FreeTableArray[i]->pTableFrame->PerformSitDownAction(j,pIServerUserItem))
{
m_FreeUserArray.RemoveAt(wRandID);
}
else
{
CTraceService::TraceString(TEXT("坐下失败?"),TraceLevel_Exception);
}
}
//30秒后做一个检查 发现该桌还没有开始游戏 说明已经卡掉了
PostMatchTimer(IDI_CHECK_TABLE_START,30,(WPARAM)FreeTableArray[i]->pTableFrame);
}
}
return ;
}
//发送一组信息
void CImmediateGroup::SendGroupBox(LPCTSTR pStrMessage)
{
//构造数据包
CMD_CM_SystemMessage Message;
Message.wType=SMT_EJECT|SMT_CHAT;
lstrcpyn(Message.szString,pStrMessage,CountArray(Message.szString));
Message.wLength=CountStringBuffer(Message.szString);
//发送数据
WORD wSendSize=sizeof(Message)-sizeof(Message.szString)+Message.wLength*sizeof(TCHAR);
m_pMatchSink->SendGroupData(MDM_CM_SYSTEM,SUB_CM_SYSTEM_MESSAGE,&Message,wSendSize, this);
}
//设置一轮完成标记
void CImmediateGroup::SetRoundTableFinish(ITableFrame *pITableFrame)
{
tagTableFrameInfo * ptagTableFrameInfo=GetTableInterface(pITableFrame);
ASSERT(ptagTableFrameInfo);
if (ptagTableFrameInfo)ptagTableFrameInfo->bRoundTableFinish=true;
}
//检查一轮是否完成
bool CImmediateGroup::CheckRoundTableFinish()
{
for (int i=0;i<m_MatchTableArray.GetCount();i++)
{
if(m_MatchTableArray[i]->bRoundTableFinish==false)return false;
}
return true;
}
//设置换桌完成标记
void CImmediateGroup::SetSwitchTableFinish(ITableFrame *pITableFrame)
{
tagTableFrameInfo * ptagTableFrameInfo=GetTableInterface(pITableFrame);
ASSERT(ptagTableFrameInfo);
if (ptagTableFrameInfo)ptagTableFrameInfo->bSwtichTableFinish=true;
}
//检查换桌是否完成
bool CImmediateGroup::CheckSwitchTableFinish()
{
for (int i=0;i<m_MatchTableArray.GetCount();i++)
{
if(m_MatchTableArray[i]->bSwtichTableFinish==false)return false;
}
return true;
}
//设置所有用户离开
void CImmediateGroup::AllUserExitTable(ITableFrame *pITableFrame)
{
ASSERT(pITableFrame!=NULL);
if(pITableFrame)
{
//该桌用户全部离开
for (int i=0;i<m_wChairCount;i++)
{
IServerUserItem* pUserItem=pITableFrame->GetTableUserItem(i);
if(pUserItem&&pUserItem->GetTableID()!=INVALID_TABLE)pITableFrame->PerformStandUpAction(pUserItem);
}
}
}
//本桌继续游戏
void CImmediateGroup::ContinueGame(ITableFrame *pITableFrame)
{
if (CheckMatchUser())
{
return;
}
tagTableFrameInfo * ptagTableFrameInfo=GetTableInterface(pITableFrame);
ASSERT(ptagTableFrameInfo);
if (ptagTableFrameInfo)
{
AllUserExitTable(pITableFrame);
for(int i=0;i<m_wChairCount;i++)
{
IServerUserItem* pIServerUserItem=m_FreeUserArray[0];
if(pIServerUserItem==NULL)
{
ASSERT(FALSE);
CTraceService::TraceString(TEXT("空的用户存在于等待列表中。"),TraceLevel_Exception);
return;
}
//先起立在坐下 让该桌的人全部起立
if(pIServerUserItem->GetTableID()!=INVALID_TABLE)
{
for(int m=0;m<m_MatchTableArray.GetCount();m++)
{
if(pIServerUserItem->GetTableID()==m_MatchTableArray[m]->wTableID)
{
m_MatchTableArray[m]->pTableFrame->PerformStandUpAction(pIServerUserItem);
break;
}
}
}
if (pITableFrame->PerformSitDownAction(i,pIServerUserItem))
{
m_FreeUserArray.RemoveAt(0);
}
else
{
CTraceService::TraceString(TEXT("坐下失败1"),TraceLevel_Exception);
}
}
//30秒后做一个检查 发现该桌还没有开始游戏 说明已经卡掉了
PostMatchTimer(IDI_CHECK_TABLE_START,30,(WPARAM)pITableFrame);
}
}
void CImmediateGroup::SetMatchGameTimer(DWORD dwTimerID, DWORD dwElapse, DWORD dwRepeat, WPARAM dwBindParameter)
{
if(m_pMatchSink)
m_pMatchSink->SetGameTimer(dwTimerID+10*m_LoopTimer,dwElapse,dwRepeat,dwBindParameter,this);
}
//杀死比赛专用定时器
void CImmediateGroup::KillMatchGameTimer(DWORD dwTimerID)
{
if(m_pMatchSink)
m_pMatchSink->KillGameTimer(dwTimerID+10*m_LoopTimer,this);
}
//检测参赛人数
bool CImmediateGroup::CheckMatchUser()
{
//参赛用户不够 椅子数量就要终止比赛
DWORD nCurUserCount=(DWORD)m_OnMatchUserMap.GetCount();
if (nCurUserCount<m_wChairCount)
{
ASSERT(FALSE);
CTraceService::TraceString(TEXT("检查人数..."),TraceLevel_Exception);
return false;
//构造数据包
CString szString;
szString.Format(TEXT("抱歉,由于比赛用户强行退出比赛,人数不足 %d 人,提前结算。欢迎您继续报名参加比赛!"),m_wChairCount);
SendGroupBox(szString);
MatchOver();
return true;
}
return false;
}
//获取优先坐下用户
WORD CImmediateGroup::GetPrecedeSitUser(DWORD dwCurTime)
{
for(int i=0;i<m_FreeUserArray.GetCount();i++)
{
tagTimeInfo* pTimerInfo=m_FreeUserArray[i]->GetTimeInfo();
if(dwCurTime-pTimerInfo->dwEndGameTimer>m_pMatchOption->MatchType.Immediate.wPrecedeTimer) return i;
}
return INVALID_VALUE;
}
//实现该函数可保证Free组唯一
void CImmediateGroup::InsertFreeGroup(IServerUserItem *pUserItem)
{
if( pUserItem == NULL )return;
for(int i=0;i<m_FreeUserArray.GetCount();i++)
{
if( m_FreeUserArray[i] != NULL && m_FreeUserArray[i]->GetUserID()==pUserItem->GetUserID())return;
}
m_FreeUserArray.Add(pUserItem);
}
//发送比赛信息
void CImmediateGroup::SendTableUserMatchInfo(ITableFrame *pITableFrame, WORD wChairID)
{
//验证参数
ASSERT(pITableFrame!=NULL);
if (pITableFrame==NULL) return;
tagTableFrameInfo *ptagTableFrameInfo=GetTableInterface(pITableFrame);
if (ptagTableFrameInfo==NULL) return;
//变量定义
WORD wChairCount=pITableFrame->GetChairCount();
TCHAR szMsg[256]=TEXT("");
if(m_enMatchStatus==MatchStatus_FirstRound)
{
//构造数据
CMD_GR_Match_Info MatchInfo;
ZeroMemory(&MatchInfo,sizeof(MatchInfo));
MatchInfo.wGameCount=ptagTableFrameInfo->cbPlayCount;
//wChairID为INVALID_CHAIR发给本桌所有玩家否则只发给指定玩家
for(WORD i=0; i<wChairCount; i++)
{
//获取用户
if(wChairID!=INVALID_CHAIR && wChairID!=i) continue;
IServerUserItem *pIServerUserItem=pITableFrame->GetTableUserItem(i);
if(pIServerUserItem==NULL) continue;
MatchInfo.wRank=GetUserRank(pIServerUserItem,pITableFrame);
//发送数据
pITableFrame->SendTableData(i, SUB_GR_MATCH_INFO, &MatchInfo, sizeof(MatchInfo), MDM_GR_MATCH);
}
//发送提示
if ((wChairID!=INVALID_CHAIR) && (ptagTableFrameInfo->bWaitForNextInnings==true))
{
SendWaitTip(pITableFrame,wChairID);
}
}
return;
}
//捕获比赛专用定时器
void CImmediateGroup::CaptureMatchTimer()
{
for(int i=0;i<m_MatchTimerArray.GetCount();i++)
{
if(--m_MatchTimerArray[i]->iElapse<=0)
{
if(m_MatchTimerArray[i]->dwTimerID==IDI_CONTINUE_GAME)
{
//本桌用户继续游戏
ContinueGame((ITableFrame*)m_MatchTimerArray[i]->wParam);
}
else if(m_MatchTimerArray[i]->dwTimerID==IDI_LEAVE_TABLE)
{
//离开本桌
AllUserExitTable((ITableFrame*)m_MatchTimerArray[i]->wParam);
}else if(m_MatchTimerArray[i]->dwTimerID==IDI_CHECK_TABLE_START)
{
//检查桌子是否开始游戏
//CheckTableStart((ITableFrame*)m_MatchTimerArray[i]->wParam);
}
//删除定时器
if(KillMatchTimer(i))i--;
else ASSERT(false);
}
}
}
//投递比赛专用定时器
void CImmediateGroup::PostMatchTimer(DWORD dwTimerID, int iElapse, WPARAM wParam, LPARAM lParam)
{
tagMatchTimer* pMatchTimer=new tagMatchTimer;
pMatchTimer->dwTimerID=dwTimerID;
pMatchTimer->iElapse=iElapse;
//pMatchTimer->dwRepeat=dwRepeat;
pMatchTimer->wParam=wParam;
pMatchTimer->lParam=lParam;
m_MatchTimerArray.Add(pMatchTimer);
}
//杀死比赛专用定时器
bool CImmediateGroup::KillMatchTimer(DWORD dwTimerID, WPARAM wParam)
{
for(int i=0;i<m_MatchTimerArray.GetCount();i++)
{
if(m_MatchTimerArray[i]->dwTimerID==dwTimerID&&m_MatchTimerArray[i]->wParam==wParam)
{
tagMatchTimer* pMatchTimer=m_MatchTimerArray[i];
m_MatchTimerArray.RemoveAt(i);
SafeDelete(pMatchTimer);
return true;
}
}
return false;
}
//杀死比赛专用定时器
bool CImmediateGroup::KillMatchTimer(INT_PTR dwIndexID)
{
ASSERT(dwIndexID >= 0 && dwIndexID < m_MatchTimerArray.GetCount());
if( dwIndexID >= 0 && dwIndexID < m_MatchTimerArray.GetCount() )
{
tagMatchTimer* pMatchTimer=m_MatchTimerArray[dwIndexID];
m_MatchTimerArray.RemoveAt(dwIndexID);
SafeDelete(pMatchTimer);
return true;
}
return false;
}
//全部杀死比赛专用定时器
void CImmediateGroup::AllKillMatchTimer()
{
for(int i=0;i<m_MatchTimerArray.GetCount();/*i++*/)
{
tagMatchTimer* pMatchTimer=m_MatchTimerArray[i];
m_MatchTimerArray.RemoveAt(i);
SafeDelete(pMatchTimer);
}
}