诸暨麻将添加redis
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

1077 行
35 KiB

  1. #include "StdAfx.h"
  2. #include "ImmediateGroup.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. //////////////////////////////////////////////////////////////////////////
  9. //常量定义
  10. #define INVALID_VALUE 0xFFFF //无效值
  11. //静态变量
  12. WORD CImmediateGroup::m_wChairCount; //椅子数目
  13. //////////////////////////////////////////////////////////////////////////
  14. //构造函数
  15. CImmediateGroup::CImmediateGroup(DWORD dwMatchNO, tagGameMatchOption * pGameMatchOption, IImmediateGroupSink *pIImmediateGroupSink)
  16. {
  17. //指针变量
  18. m_pMatchOption = pGameMatchOption;
  19. m_pMatchSink = pIImmediateGroupSink;
  20. //状态变量
  21. m_dwMatchNO = dwMatchNO;
  22. m_enMatchStatus = MatchStatus_Signup;
  23. m_dwCurBase = m_pMatchOption->MatchType.Immediate.dwInitalBase;
  24. //设置变量
  25. ZeroMemory(&m_MatchStartTime, sizeof(m_MatchStartTime));
  26. //移除元素
  27. m_OnMatchUserMap.RemoveAll();
  28. m_FreeUserArray.RemoveAll();
  29. m_MatchTableArray.RemoveAll();
  30. //设置变量
  31. m_LoopTimer = 0;
  32. m_wAndroidUserCount = 0;
  33. }
  34. //析构函数
  35. CImmediateGroup::~CImmediateGroup()
  36. {
  37. //杀死定时器
  38. AllKillMatchTimer();
  39. //设置状态
  40. m_wAndroidUserCount = 0;
  41. m_enMatchStatus = MatchStatus_Null;
  42. //释放桌子
  43. for (int i = 0; i < m_MatchTableArray.GetCount(); i++)
  44. {
  45. SafeDelete(m_MatchTableArray[i]);
  46. }
  47. //移除元素
  48. m_MatchTableArray.RemoveAll();
  49. m_OnMatchUserMap.RemoveAll();
  50. m_FreeUserArray.RemoveAll();
  51. }
  52. //接口查询
  53. VOID* CImmediateGroup::QueryInterface(REFGUID Guid, DWORD dwQueryVer)
  54. {
  55. QUERYINTERFACE(IMatchEventSink, Guid, dwQueryVer);
  56. QUERYINTERFACE_IUNKNOWNEX(IMatchEventSink, Guid, dwQueryVer);
  57. return NULL;
  58. }
  59. //用户报名
  60. bool CImmediateGroup::OnUserSignUpMatch(IServerUserItem * pUserItem)
  61. {
  62. //用户判断
  63. ASSERT(pUserItem != NULL);
  64. if (pUserItem == NULL) return false;
  65. //查找用户
  66. IServerUserItem * pIServerUserExist = NULL;
  67. m_OnMatchUserMap.Lookup(pUserItem->GetUserID(), pIServerUserExist);
  68. //用户判断
  69. ASSERT(pIServerUserExist == NULL);
  70. if (pIServerUserExist != NULL) return false;
  71. //人数效验
  72. ASSERT(m_OnMatchUserMap.GetCount() < m_pMatchOption->MatchType.Immediate.wStartUserCount);
  73. if (m_OnMatchUserMap.GetCount() >= m_pMatchOption->MatchType.Immediate.wStartUserCount) return false;
  74. //机器判断
  75. if (pUserItem->IsAndroidUser() == true)
  76. {
  77. if (m_wAndroidUserCount >= m_pMatchOption->MatchType.Immediate.wAndroidUserCount)
  78. {
  79. return false;
  80. }
  81. m_wAndroidUserCount++;
  82. }
  83. //设置成绩
  84. tagUserInfo *pUserScore = pUserItem->GetUserInfo();
  85. pUserScore->dwWinCount = 0L;
  86. pUserScore->dwLostCount = 0L;
  87. pUserScore->dwFleeCount = 0L;
  88. pUserScore->dwDrawCount = 0L;
  89. pUserScore->lGrade = 0L;
  90. pUserScore->lScore = (SCORE)m_pMatchOption->MatchType.Immediate.dwInitalScore;
  91. //发送成绩
  92. m_pMatchSink->SendGroupUserScore(pUserItem, NULL);
  93. //设置用户
  94. m_OnMatchUserMap[pUserItem->GetUserID()] = pUserItem;
  95. //设置报名状态
  96. pUserItem->SetSignUpStatus(MS_SIGNUP);
  97. //设置报名时间
  98. pUserItem->SetSignUpTime(GetTickCount());
  99. //发送报名状态
  100. BYTE cbMatchStatus = MS_SIGNUP;
  101. m_pMatchSink->SendData(pUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbMatchStatus, sizeof(cbMatchStatus));
  102. //报名人满
  103. if (m_OnMatchUserMap.GetCount() >= m_pMatchOption->MatchType.Immediate.wStartUserCount)
  104. {
  105. //事件通知
  106. ASSERT(m_pMatchSink != NULL);
  107. if (m_pMatchSink != NULL) m_pMatchSink->SendMatchInfo(NULL);
  108. EfficacyStartMatch();
  109. }
  110. return true;
  111. }
  112. //比赛开始
  113. void CImmediateGroup::EfficacyStartMatch()
  114. {
  115. m_pMatchSink->InsertNullTable();
  116. //没有桌子的情况
  117. if (m_MatchTableArray.GetCount() < m_pMatchOption->MatchType.Immediate.wStartUserCount / m_wChairCount)
  118. {
  119. if (m_OnMatchUserMap.GetCount() < m_wChairCount)
  120. {
  121. //构造数据包
  122. CMD_CM_SystemMessage Message;
  123. Message.wType = SMT_EJECT | SMT_CHAT | SMT_CLOSE_GAME;
  124. lstrcpyn(Message.szString, TEXT("抱歉,由于某用户强行退出比赛,该场比赛提前结束。你可以继续等待比赛!"), CountArray(Message.szString));
  125. Message.wLength = CountStringBuffer(Message.szString);
  126. //发送数据
  127. WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR);
  128. m_pMatchSink->SendGroupData(MDM_CM_SYSTEM, SUB_CM_SYSTEM_MESSAGE, &Message, wSendSize, this);
  129. m_enMatchStatus = MatchStatus_Signup;
  130. return;
  131. }
  132. m_enMatchStatus = MatchStatus_Wait;
  133. //3秒后继续调用该函数直到有桌子
  134. SetMatchGameTimer(IDI_WAITTABLE_FIRST_ROUND, 3000, 1, NULL);
  135. //构造数据包
  136. CMD_CM_SystemMessage Message;
  137. Message.wType = SMT_CHAT;
  138. _sntprintf(Message.szString, CountArray(Message.szString),
  139. TEXT("抱歉,由于过多用户桌子数量不够!还差 %d 张桌子开赛,请等待。。。"), m_pMatchOption->MatchType.Immediate.wStartUserCount / m_wChairCount - m_MatchTableArray.GetCount());
  140. Message.wLength = CountStringBuffer(Message.szString);
  141. //发送数据
  142. WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR);
  143. m_pMatchSink->SendGroupData(MDM_CM_SYSTEM, SUB_CM_SYSTEM_MESSAGE, &Message, wSendSize, this);
  144. return;
  145. }
  146. //预赛安排座位
  147. DWORD dwUserID = 0L;
  148. IServerUserItem *pIServerUserItem = NULL;
  149. POSITION pos = m_OnMatchUserMap.GetStartPosition();
  150. WORD wChairID = 0;
  151. while (pos != NULL)
  152. {
  153. //获取用户
  154. m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pIServerUserItem);
  155. ASSERT(pIServerUserItem != NULL);
  156. InsertFreeGroup(pIServerUserItem);
  157. //设置用户比赛中
  158. pIServerUserItem->SetSignUpStatus(MS_MATCHING);
  159. pIServerUserItem->SetMatchData(this);
  160. }
  161. //桌子自动拉人
  162. TabelRequestUser(false);
  163. //设置状态
  164. m_enMatchStatus = MatchStatus_FirstRound;
  165. //记录时间
  166. CTime::GetCurrentTime().GetAsSystemTime(m_MatchStartTime);
  167. //开始通知
  168. if (m_pMatchSink != NULL) m_pMatchSink->OnEventMatchStart(this);
  169. //设置定时器
  170. SetMatchGameTimer(IDI_CHECK_MATCH_GROUP, 1000, TIMES_INFINITY, 0);
  171. }
  172. //用户退赛
  173. BOOL CImmediateGroup::OnUserQuitMatch(IServerUserItem *pUserItem)
  174. {
  175. //用户判断
  176. ASSERT(pUserItem != NULL);
  177. if (pUserItem == NULL) return false;
  178. //删除用户
  179. BOOL bSuccess = m_OnMatchUserMap.RemoveKey(pUserItem->GetUserID());
  180. if (bSuccess == false)return false;
  181. if (pUserItem->IsAndroidUser())
  182. {
  183. ASSERT(m_wAndroidUserCount > 0);
  184. if (m_wAndroidUserCount > 0) m_wAndroidUserCount--;
  185. }
  186. //设置状态
  187. pUserItem->SetSignUpStatus(MatchStatus_Null);
  188. BYTE cbUserStatus = MatchStatus_Null;
  189. m_pMatchSink->SendData(pUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbUserStatus, sizeof(cbUserStatus));
  190. return bSuccess;
  191. }
  192. //定时器
  193. bool CImmediateGroup::OnTimeMessage(DWORD dwTimerID, WPARAM dwBindParameter)
  194. {
  195. //状态校验
  196. if (m_enMatchStatus == MatchStatus_Null) return true;
  197. switch (dwTimerID)
  198. {
  199. case IDI_CHECK_MATCH_GROUP:
  200. {
  201. CaptureMatchTimer();
  202. return true;
  203. }
  204. case IDI_WAITTABLE_FIRST_ROUND:
  205. {
  206. if (m_enMatchStatus == MatchStatus_Wait)
  207. {
  208. EfficacyStartMatch();
  209. }
  210. return true;
  211. }
  212. case IDI_SWITCH_WAIT_TIME:
  213. {
  214. //将空闲用户自动配桌
  215. RearrangeUserSeat();
  216. TabelRequestUser();
  217. //ContinueGame((ITableFrame*)dwBindParameter);
  218. return true;
  219. }
  220. case IDI_TABLE_REQUEST_USER:
  221. {
  222. TabelRequestUser();
  223. return true;
  224. }
  225. case IDI_ENTER_NEXT_ROUND:
  226. {
  227. //if(m_enMatchStatus==MS_START_NEXT_ROUND)
  228. //{
  229. // //继续下一轮
  230. // ContinueRound();
  231. //}
  232. return true;
  233. }
  234. case IDI_ALL_DISMISS_GAME:
  235. {
  236. RearrangeUserSeat();
  237. return true;
  238. }
  239. case IDI_LASTMATCHRESULT:
  240. {
  241. //最后结束
  242. MatchOver();
  243. return true;
  244. }
  245. }
  246. return true;
  247. }
  248. WORD CImmediateGroup::SortMapUser(tagMatchScore score[])
  249. {
  250. INT_PTR nCount = m_OnMatchUserMap.GetCount();
  251. POSITION pos = m_OnMatchUserMap.GetStartPosition();
  252. nCount = 0;
  253. while (pos != NULL)
  254. {
  255. m_OnMatchUserMap.GetNextAssoc(pos, score[nCount].dwUserID, score[nCount].pUserItem);
  256. score[nCount].dwUserID = score[nCount].pUserItem->GetUserID();
  257. score[nCount].lScore = score[nCount].pUserItem->GetUserScore();
  258. nCount++;
  259. }
  260. for (INT_PTR i = 1; i < nCount; i++)
  261. {
  262. INT_PTR left = 0, right = i - 1;
  263. tagMatchScore Temp = score[i];
  264. while (left <= right)
  265. {
  266. INT_PTR mid = (left + right) / 2;
  267. if (score[i].lScore > score[mid].lScore)right = mid - 1;
  268. else left = mid + 1;
  269. }
  270. for (INT_PTR j = i - 1; j >= left; j--)
  271. score[j + 1] = score[j];
  272. score[left] = Temp;
  273. }
  274. return (WORD)nCount;
  275. }
  276. //重置桌位
  277. void CImmediateGroup::RearrangeUserSeat(bool bDismissGame)
  278. {
  279. KillMatchGameTimer(IDI_SWITCH_WAIT_TIME);
  280. for (WORD i = 0; i < m_MatchTableArray.GetCount(); i++)
  281. {
  282. tagTableFrameInfo *ptagTableFrameInfo = m_MatchTableArray[i];
  283. ASSERT(ptagTableFrameInfo != NULL);
  284. if (ptagTableFrameInfo == NULL) continue;
  285. ITableFrame* pTableFrame = ptagTableFrameInfo->pTableFrame;
  286. ASSERT(pTableFrame != NULL);
  287. if (pTableFrame == NULL) continue;
  288. if (bDismissGame == false)
  289. {
  290. ptagTableFrameInfo->cbPlayCount = 0;
  291. ptagTableFrameInfo->bRoundTableFinish = false;
  292. ptagTableFrameInfo->bSwtichTableFinish = false;
  293. ptagTableFrameInfo->bWaitForNextInnings = false;
  294. }
  295. //强制解散游戏
  296. if (pTableFrame->IsGameStarted() == true)
  297. {
  298. if (bDismissGame == true)
  299. {
  300. bool bSuccess = pTableFrame->DismissGame();
  301. if (bSuccess == false)
  302. CTraceService::TraceString(TEXT("解散游戏"), TraceLevel_Exception);
  303. }
  304. else
  305. {
  306. TCHAR szMessage[64] = TEXT("");
  307. _sntprintf(szMessage, CountArray(szMessage), TEXT("重置桌位时,第 %d 桌处于游戏状态"), pTableFrame->GetTableID());
  308. CTraceService::TraceString(szMessage, TraceLevel_Exception);
  309. }
  310. }
  311. //该桌用户全部离开
  312. AllUserExitTable(pTableFrame);
  313. }
  314. return;
  315. }
  316. //游戏开始
  317. bool CImmediateGroup::OnEventGameStart(ITableFrame *pITableFrame, WORD wChairCount)
  318. {
  319. pITableFrame->SetCellScore(m_dwCurBase);
  320. KillMatchTimer(IDI_CHECK_TABLE_START, (WPARAM)pITableFrame);
  321. tagTableFrameInfo *pTableFrameInfo = GetTableInterface(pITableFrame);
  322. pTableFrameInfo->bRoundTableFinish = false;
  323. pTableFrameInfo->bSwtichTableFinish = false;
  324. pTableFrameInfo->bWaitForNextInnings = false;
  325. //已完成局数加1
  326. pTableFrameInfo->cbPlayCount++;
  327. //发送比赛信息给桌子上的用户
  328. SendTableUserMatchInfo(pITableFrame, INVALID_CHAIR);
  329. //构造数据包
  330. CMD_CM_SystemMessage SystemMessage;
  331. ZeroMemory(&SystemMessage, sizeof(SystemMessage));
  332. TCHAR szMsg[256] = TEXT("");
  333. _sntprintf(szMsg, CountArray(szMsg), TEXT("定局排名赛第%d局开始(共%d局)。"), pTableFrameInfo->cbPlayCount, m_pMatchOption->MatchType.Immediate.cbPlayCount);
  334. lstrcpyn(SystemMessage.szString, szMsg, CountArray(SystemMessage.szString));
  335. SystemMessage.wLength = CountStringBuffer(SystemMessage.szString);
  336. SystemMessage.wType = SMT_CHAT;
  337. //发送数据
  338. WORD wSendSize = sizeof(SystemMessage)-sizeof(SystemMessage.szString) + SystemMessage.wLength*sizeof(TCHAR);
  339. pITableFrame->SendTableData(INVALID_CHAIR, SUB_GF_SYSTEM_MESSAGE, (void*)&SystemMessage, wSendSize, MDM_GF_FRAME);
  340. return true;
  341. }
  342. //游戏结束
  343. bool CImmediateGroup::OnEventGameEnd(ITableFrame *pITableFrame, WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason)
  344. {
  345. //记录本局和哪些用户玩过
  346. tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame);
  347. ASSERT(ptagTableFrameInfo);
  348. if (ptagTableFrameInfo == NULL)return false;
  349. if (m_enMatchStatus == MatchStatus_FirstRound)
  350. {
  351. FirstRoundRuleInningsGameEnd(pITableFrame);
  352. }
  353. //CheckExitMatch();
  354. //比赛结束直接返回
  355. if (m_enMatchStatus == MatchStatus_Null)return true;
  356. if (m_OnMatchUserMap.GetCount() > 0)
  357. {
  358. //分数通知
  359. tagMatchScore *pScore = new tagMatchScore[m_OnMatchUserMap.GetCount()];
  360. ZeroMemory(pScore, sizeof(tagMatchScore)*m_OnMatchUserMap.GetCount());
  361. WORD wCount = SortMapUser(pScore);
  362. for (WORD i = 0; i < wCount; i++)
  363. {
  364. m_pMatchSink->SendGroupUserScore(pScore[i].pUserItem, this);
  365. }
  366. SafeDeleteArray(pScore);
  367. }
  368. return true;
  369. }
  370. //用户坐下
  371. bool CImmediateGroup::OnActionUserSitDown(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
  372. {
  373. return true;
  374. }
  375. //用户起立
  376. bool CImmediateGroup::OnActionUserStandUp(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
  377. {
  378. return true;
  379. }
  380. //用户同意
  381. bool CImmediateGroup::OnActionUserOnReady(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, VOID * pData, WORD wDataSize)
  382. {
  383. return false;
  384. }
  385. //获取名次
  386. WORD CImmediateGroup::GetUserRank(IServerUserItem *pUserItem, ITableFrame *pITableFrame)
  387. {
  388. //参数效验
  389. ASSERT(pUserItem != NULL);
  390. if (pUserItem == NULL) return INVALID_WORD;
  391. //定义变量
  392. SCORE lUserScore = pUserItem->GetUserScore();
  393. WORD wRank = 1;
  394. DWORD dwUserID = 0;
  395. IServerUserItem *pLoopUserItem = NULL;
  396. if (pITableFrame == NULL)
  397. {
  398. //遍历容器
  399. POSITION pos = m_OnMatchUserMap.GetStartPosition();
  400. while (pos != NULL)
  401. {
  402. m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pLoopUserItem);
  403. if (pLoopUserItem != pUserItem && pLoopUserItem->GetUserScore() > lUserScore)
  404. wRank++;
  405. }
  406. }
  407. else
  408. {
  409. ASSERT(pUserItem->GetTableID() == pITableFrame->GetTableID());
  410. if (pUserItem->GetTableID() != pITableFrame->GetTableID()) return INVALID_WORD;
  411. for (WORD i = 0; i<m_wChairCount; i++)
  412. {
  413. pLoopUserItem = pITableFrame->GetTableUserItem(i);
  414. if (pLoopUserItem == NULL) continue;
  415. if (pLoopUserItem != pUserItem && pLoopUserItem->GetUserScore()>lUserScore)
  416. wRank++;
  417. }
  418. }
  419. return wRank;
  420. }
  421. //获取桌子专用接口
  422. tagTableFrameInfo* CImmediateGroup::GetTableInterface(ITableFrame* ITable)
  423. {
  424. for (int i = 0; i < m_MatchTableArray.GetCount(); i++)
  425. {
  426. if (m_MatchTableArray[i]->pTableFrame == ITable)return m_MatchTableArray[i];
  427. }
  428. return NULL;
  429. }
  430. //比赛结束
  431. void CImmediateGroup::MatchOver()
  432. {
  433. //删除定时器
  434. AllKillMatchTimer();
  435. KillMatchGameTimer(IDI_CHECK_MATCH_GROUP);
  436. KillMatchGameTimer(IDI_WAITTABLE_FIRST_ROUND);
  437. KillMatchGameTimer(IDI_WAITTABLE_RAND_TABLE);
  438. KillMatchGameTimer(IDI_SWITCH_WAIT_TIME);
  439. KillMatchGameTimer(IDI_ALL_DISMISS_GAME);
  440. KillMatchGameTimer(IDI_LASTMATCHRESULT);
  441. KillMatchGameTimer(IDI_TABLE_REQUEST_USER);
  442. //设置比赛状态
  443. ASSERT(m_enMatchStatus == MatchStatus_FirstRound);
  444. if (m_enMatchStatus == MatchStatus_FirstRound)
  445. {
  446. m_enMatchStatus = MatchStatus_Null;
  447. m_pMatchSink->OnEventMatchOver(this);
  448. }
  449. }
  450. //定局排名游戏结束
  451. void CImmediateGroup::FirstRoundRuleInningsGameEnd(ITableFrame *pITableFrame)
  452. {
  453. //获取对象
  454. tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame);
  455. ASSERT(ptagTableFrameInfo);
  456. if (ptagTableFrameInfo == NULL) return;
  457. //设置等待下局标识
  458. ptagTableFrameInfo->bWaitForNextInnings = true;
  459. TCHAR szMessage[128] = TEXT("");
  460. //该桌打完指定局数
  461. if (ptagTableFrameInfo->cbPlayCount >= m_pMatchOption->MatchType.Immediate.cbPlayCount)
  462. {
  463. _sntprintf(szMessage, CountArray(szMessage), TEXT("恭喜您,您已玩满%d局游戏,等其他桌完成后系统将进行排名,请您耐心等待!"), m_pMatchOption->MatchType.Immediate.cbPlayCount);
  464. //发送提示信息
  465. for (WORD j = 0; j < m_wChairCount; j++)
  466. {
  467. IServerUserItem *pIServerUserItem = pITableFrame->GetTableUserItem(j);
  468. if (pIServerUserItem != NULL)
  469. {
  470. m_pMatchSink->SendGameMessage(pIServerUserItem, szMessage, SMT_CHAT | SMT_TABLE_ROLL);
  471. //插入空闲列表
  472. InsertFreeGroup(pIServerUserItem);
  473. }
  474. else
  475. {
  476. ASSERT(FALSE);
  477. CTraceService::TraceString(TEXT("玩家信息为空1!"), TraceLevel_Exception);
  478. }
  479. }
  480. //设置完成标识
  481. SetRoundTableFinish(pITableFrame);
  482. SendWaitTip(pITableFrame);
  483. ptagTableFrameInfo->cbPlayCount = 0;
  484. }
  485. else
  486. {
  487. if (m_pMatchOption->MatchType.Immediate.cbSwitchTableCount > 0 && (ptagTableFrameInfo->cbPlayCount%m_pMatchOption->MatchType.Immediate.cbSwitchTableCount) == 0)
  488. _sntprintf(szMessage, CountArray(szMessage), TEXT("%s"), TEXT("本局已结束,请耐心等待其他桌完成,稍后为您配桌..."));
  489. else
  490. _sntprintf(szMessage, CountArray(szMessage), TEXT("%s"), TEXT("本局已结束,请稍候,系统配桌中..."));
  491. //发送提示信息
  492. for (WORD j = 0; j < m_wChairCount; j++)
  493. {
  494. IServerUserItem *pIServerUserItem = pITableFrame->GetTableUserItem(j);
  495. if (pIServerUserItem != NULL)
  496. {
  497. m_pMatchSink->SendGameMessage(pIServerUserItem, szMessage, SMT_CHAT | SMT_TABLE_ROLL);
  498. //插入空闲列表
  499. InsertFreeGroup(pIServerUserItem);
  500. }
  501. else
  502. {
  503. ASSERT(FALSE);
  504. CTraceService::TraceString(TEXT("玩家信息为空2!"), TraceLevel_Exception);
  505. }
  506. }
  507. }
  508. //所有桌都完成指定局数
  509. if (CheckRoundTableFinish())
  510. {
  511. SetMatchGameTimer(IDI_LASTMATCHRESULT, 5000, 1, 0);
  512. return;
  513. }
  514. else if (ptagTableFrameInfo->bRoundTableFinish == false)
  515. {
  516. //自动换桌的控制
  517. if (m_pMatchOption->MatchType.Immediate.cbSwitchTableCount > 0 && (ptagTableFrameInfo->cbPlayCount%m_pMatchOption->MatchType.Immediate.cbSwitchTableCount) == 0)
  518. {
  519. SetSwitchTableFinish(pITableFrame);
  520. SendWaitTip(pITableFrame);
  521. //检查该桌子是否可以换桌
  522. if (CheckSwitchTableFinish())
  523. {
  524. SetMatchGameTimer(IDI_SWITCH_WAIT_TIME, 5000, 1, 0);
  525. return;
  526. }
  527. }
  528. else //不换桌
  529. {
  530. //设置定时器
  531. PostMatchTimer(IDI_CONTINUE_GAME, 5, (WPARAM)pITableFrame);
  532. return;
  533. }
  534. }
  535. }
  536. //发送提示
  537. VOID CImmediateGroup::SendWaitTip(ITableFrame *pTableFrame, WORD wChairID/*=INVALID_CHAIR*/)
  538. {
  539. //状态校验
  540. if (m_enMatchStatus == MatchStatus_Null || m_enMatchStatus == MatchStatus_Signup)
  541. return;
  542. tagTableFrameInfo *pITableFameEx = GetTableInterface(pTableFrame);
  543. ASSERT(pITableFameEx != NULL);
  544. if (pITableFameEx == NULL) return;
  545. //变量定义
  546. WORD wPlayingTable = 0;
  547. for (WORD i = 0; i < m_MatchTableArray.GetCount(); i++)
  548. {
  549. if (m_MatchTableArray[i]->pTableFrame->GetGameStatus() >= GAME_STATUS_PLAY)
  550. wPlayingTable++;
  551. }
  552. //变量定义
  553. CMD_GR_Match_Wait_Tip WaitTip;
  554. ZeroMemory(&WaitTip, sizeof(WaitTip));
  555. WaitTip.wPlayingTable = wPlayingTable;
  556. WaitTip.wUserCount = (WORD)m_OnMatchUserMap.GetCount();
  557. WaitTip.wCurGameCount = pITableFameEx->cbPlayCount;
  558. WaitTip.wGameCount = m_pMatchOption->MatchType.Immediate.cbPlayCount;
  559. lstrcpyn(WaitTip.szMatchName, m_pMatchOption->szMatchName, LEN_SERVER);
  560. //发送比赛信息给本桌的玩家
  561. for (WORD i = 0; i < m_wChairCount; i++)
  562. {
  563. if (wChairID != INVALID_CHAIR && wChairID != i) continue;
  564. IServerUserItem *pTableUserItem = pTableFrame->GetTableUserItem(i);
  565. if (pTableUserItem == NULL) continue;
  566. WaitTip.wCurTableRank = GetUserRank(pTableUserItem, pTableFrame);
  567. if (WaitTip.wCurTableRank == INVALID_WORD) continue;
  568. WaitTip.wRank = GetUserRank(pTableUserItem);
  569. WaitTip.lScore = pTableUserItem->GetUserScore();
  570. m_pMatchSink->SendData(pTableUserItem, MDM_GF_FRAME, SUB_GR_MATCH_WAIT_TIP, &WaitTip, sizeof(WaitTip));
  571. }
  572. //发送比赛信息给其他桌的玩家
  573. for (WORD i = 0; i < m_MatchTableArray.GetCount(); i++)
  574. {
  575. if (pTableFrame->GetTableID() == m_MatchTableArray[i]->pTableFrame->GetTableID())continue;
  576. if (m_MatchTableArray[i]->pTableFrame->GetGameStatus() >= GAME_STATUS_PLAY) continue;
  577. for (WORD j = 0; j < m_wChairCount; j++)
  578. {
  579. IServerUserItem *pTableUserItem = m_MatchTableArray[i]->pTableFrame->GetTableUserItem(j);
  580. if (pTableUserItem == NULL) continue;
  581. WaitTip.wCurTableRank = GetUserRank(pTableUserItem, m_MatchTableArray[i]->pTableFrame);
  582. if (WaitTip.wCurTableRank == INVALID_WORD) continue;
  583. WaitTip.wRank = GetUserRank(pTableUserItem);
  584. WaitTip.lScore = pTableUserItem->GetUserScore();
  585. m_pMatchSink->SendData(pTableUserItem, MDM_GF_FRAME, SUB_GR_MATCH_WAIT_TIP, &WaitTip, sizeof(WaitTip));
  586. }
  587. }
  588. }
  589. //空闲桌子拉空闲用户
  590. void CImmediateGroup::TabelRequestUser(bool bPrecedeSit)
  591. {
  592. //参赛用户不够 椅子数量就要终止比赛
  593. if (CheckMatchUser())
  594. {
  595. return;
  596. }
  597. CTableFrameMananerArray FreeTableArray; //空比赛桌子
  598. //首先获取空桌子
  599. for (INT_PTR i = 0; i < m_MatchTableArray.GetCount(); i++)
  600. {
  601. if (m_MatchTableArray[i]->pTableFrame->IsGameStarted() == false && m_MatchTableArray[i]->bRoundTableFinish == false)
  602. {
  603. //获取数量
  604. INT_PTR cbTimer = m_MatchTimerArray.GetCount();
  605. bool cbIsInsert = false;
  606. for (int j = 0; j < cbTimer; j++)
  607. {
  608. //判断一下有没有卡赛的桌子在等待
  609. 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)
  610. {
  611. cbIsInsert = true;
  612. break;
  613. }
  614. }
  615. if (cbIsInsert == false)
  616. FreeTableArray.Add(m_MatchTableArray[i]);
  617. }
  618. }
  619. DWORD dwCurTime = (DWORD)time(NULL);
  620. bool bIsContinueCheck = false;//优化优先坐下 原本是true
  621. for (INT_PTR i = 0; i<FreeTableArray.GetCount(); i++)
  622. {
  623. DWORD nCurUserCount = (DWORD)m_FreeUserArray.GetCount();
  624. //找到一个空桌 空闲用户必须大于等于椅子
  625. if (nCurUserCount / m_wChairCount>0)
  626. {
  627. AllUserExitTable(FreeTableArray[i]->pTableFrame);
  628. for (int j = 0; j < m_wChairCount; j++)
  629. {
  630. //用户插入该桌
  631. WORD wRandID = INVALID_VALUE;
  632. if (bPrecedeSit&&bIsContinueCheck)
  633. {
  634. wRandID = GetPrecedeSitUser(dwCurTime);
  635. }
  636. if (wRandID == INVALID_VALUE)
  637. {
  638. bIsContinueCheck = false;//已经没有优先用户了
  639. wRandID = rand() % (WORD)m_FreeUserArray.GetCount();
  640. }
  641. IServerUserItem *pIServerUserItem = m_FreeUserArray[wRandID];
  642. ASSERT(pIServerUserItem != NULL);
  643. if (pIServerUserItem == NULL) continue;
  644. //先起立在坐下 让该桌的人全部起立
  645. if (pIServerUserItem->GetTableID() != INVALID_TABLE)
  646. {
  647. for (int m = 0; m < m_MatchTableArray.GetCount(); m++)
  648. {
  649. if (pIServerUserItem->GetTableID() == m_MatchTableArray[m]->wTableID)
  650. {
  651. m_MatchTableArray[m]->pTableFrame->PerformStandUpAction(pIServerUserItem);
  652. break;
  653. }
  654. }
  655. }
  656. if (FreeTableArray[i]->pTableFrame->PerformSitDownAction(j, pIServerUserItem))
  657. {
  658. m_FreeUserArray.RemoveAt(wRandID);
  659. }
  660. else
  661. {
  662. CTraceService::TraceString(TEXT("坐下失败?"), TraceLevel_Exception);
  663. }
  664. }
  665. //30秒后做一个检查 发现该桌还没有开始游戏 说明已经卡掉了
  666. PostMatchTimer(IDI_CHECK_TABLE_START, 30, (WPARAM)FreeTableArray[i]->pTableFrame);
  667. }
  668. }
  669. return;
  670. }
  671. //发送一组信息
  672. void CImmediateGroup::SendGroupBox(LPCTSTR pStrMessage)
  673. {
  674. //构造数据包
  675. CMD_CM_SystemMessage Message;
  676. Message.wType = SMT_EJECT | SMT_CHAT;
  677. lstrcpyn(Message.szString, pStrMessage, CountArray(Message.szString));
  678. Message.wLength = CountStringBuffer(Message.szString);
  679. //发送数据
  680. WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR);
  681. m_pMatchSink->SendGroupData(MDM_CM_SYSTEM, SUB_CM_SYSTEM_MESSAGE, &Message, wSendSize, this);
  682. }
  683. //设置一轮完成标记
  684. void CImmediateGroup::SetRoundTableFinish(ITableFrame *pITableFrame)
  685. {
  686. tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame);
  687. ASSERT(ptagTableFrameInfo);
  688. if (ptagTableFrameInfo)ptagTableFrameInfo->bRoundTableFinish = true;
  689. }
  690. //检查一轮是否完成
  691. bool CImmediateGroup::CheckRoundTableFinish()
  692. {
  693. for (int i = 0; i < m_MatchTableArray.GetCount(); i++)
  694. {
  695. if (m_MatchTableArray[i]->bRoundTableFinish == false)return false;
  696. }
  697. return true;
  698. }
  699. //设置换桌完成标记
  700. void CImmediateGroup::SetSwitchTableFinish(ITableFrame *pITableFrame)
  701. {
  702. tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame);
  703. ASSERT(ptagTableFrameInfo);
  704. if (ptagTableFrameInfo)ptagTableFrameInfo->bSwtichTableFinish = true;
  705. }
  706. //检查换桌是否完成
  707. bool CImmediateGroup::CheckSwitchTableFinish()
  708. {
  709. for (int i = 0; i < m_MatchTableArray.GetCount(); i++)
  710. {
  711. if (m_MatchTableArray[i]->bSwtichTableFinish == false)return false;
  712. }
  713. return true;
  714. }
  715. //设置所有用户离开
  716. void CImmediateGroup::AllUserExitTable(ITableFrame *pITableFrame)
  717. {
  718. ASSERT(pITableFrame != NULL);
  719. if (pITableFrame)
  720. {
  721. //该桌用户全部离开
  722. for (int i = 0; i < m_wChairCount; i++)
  723. {
  724. IServerUserItem* pUserItem = pITableFrame->GetTableUserItem(i);
  725. if (pUserItem&&pUserItem->GetTableID() != INVALID_TABLE)pITableFrame->PerformStandUpAction(pUserItem);
  726. }
  727. }
  728. }
  729. //本桌继续游戏
  730. void CImmediateGroup::ContinueGame(ITableFrame *pITableFrame)
  731. {
  732. if (CheckMatchUser())
  733. {
  734. return;
  735. }
  736. tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame);
  737. ASSERT(ptagTableFrameInfo);
  738. if (ptagTableFrameInfo)
  739. {
  740. AllUserExitTable(pITableFrame);
  741. for (int i = 0; i < m_wChairCount; i++)
  742. {
  743. IServerUserItem* pIServerUserItem = m_FreeUserArray[0];
  744. if (pIServerUserItem == NULL)
  745. {
  746. ASSERT(FALSE);
  747. CTraceService::TraceString(TEXT("空的用户存在于等待列表中。"), TraceLevel_Exception);
  748. return;
  749. }
  750. //先起立在坐下 让该桌的人全部起立
  751. if (pIServerUserItem->GetTableID() != INVALID_TABLE)
  752. {
  753. for (int m = 0; m < m_MatchTableArray.GetCount(); m++)
  754. {
  755. if (pIServerUserItem->GetTableID() == m_MatchTableArray[m]->wTableID)
  756. {
  757. m_MatchTableArray[m]->pTableFrame->PerformStandUpAction(pIServerUserItem);
  758. break;
  759. }
  760. }
  761. }
  762. if (pITableFrame->PerformSitDownAction(i, pIServerUserItem))
  763. {
  764. m_FreeUserArray.RemoveAt(0);
  765. }
  766. else
  767. {
  768. CTraceService::TraceString(TEXT("坐下失败?1"), TraceLevel_Exception);
  769. }
  770. }
  771. //30秒后做一个检查 发现该桌还没有开始游戏 说明已经卡掉了
  772. PostMatchTimer(IDI_CHECK_TABLE_START, 30, (WPARAM)pITableFrame);
  773. }
  774. }
  775. void CImmediateGroup::SetMatchGameTimer(DWORD dwTimerID, DWORD dwElapse, DWORD dwRepeat, WPARAM dwBindParameter)
  776. {
  777. if (m_pMatchSink)
  778. m_pMatchSink->SetGameTimer(dwTimerID + 10 * m_LoopTimer, dwElapse, dwRepeat, dwBindParameter, this);
  779. }
  780. //杀死比赛专用定时器
  781. void CImmediateGroup::KillMatchGameTimer(DWORD dwTimerID)
  782. {
  783. if (m_pMatchSink)
  784. m_pMatchSink->KillGameTimer(dwTimerID + 10 * m_LoopTimer, this);
  785. }
  786. //检测参赛人数
  787. bool CImmediateGroup::CheckMatchUser()
  788. {
  789. //参赛用户不够 椅子数量就要终止比赛
  790. DWORD nCurUserCount = (DWORD)m_OnMatchUserMap.GetCount();
  791. if (nCurUserCount < m_wChairCount)
  792. {
  793. ASSERT(FALSE);
  794. CTraceService::TraceString(TEXT("检查人数..."), TraceLevel_Exception);
  795. return false;
  796. //构造数据包
  797. CString szString;
  798. szString.Format(TEXT("抱歉,由于比赛用户强行退出比赛,人数不足 %d 人,提前结算。欢迎您继续报名参加比赛!"), m_wChairCount);
  799. SendGroupBox(szString);
  800. MatchOver();
  801. return true;
  802. }
  803. return false;
  804. }
  805. //获取优先坐下用户
  806. WORD CImmediateGroup::GetPrecedeSitUser(DWORD dwCurTime)
  807. {
  808. for (int i = 0; i<m_FreeUserArray.GetCount(); i++)
  809. {
  810. tagTimeInfo* pTimerInfo = m_FreeUserArray[i]->GetTimeInfo();
  811. if (dwCurTime - pTimerInfo->dwEndGameTimer>m_pMatchOption->MatchType.Immediate.wPrecedeTimer) return i;
  812. }
  813. return INVALID_VALUE;
  814. }
  815. //实现该函数可保证Free组唯一
  816. void CImmediateGroup::InsertFreeGroup(IServerUserItem *pUserItem)
  817. {
  818. if (pUserItem == NULL)return;
  819. for (int i = 0; i < m_FreeUserArray.GetCount(); i++)
  820. {
  821. if (m_FreeUserArray[i] != NULL && m_FreeUserArray[i]->GetUserID() == pUserItem->GetUserID())return;
  822. }
  823. m_FreeUserArray.Add(pUserItem);
  824. }
  825. //发送比赛信息
  826. void CImmediateGroup::SendTableUserMatchInfo(ITableFrame *pITableFrame, WORD wChairID)
  827. {
  828. //验证参数
  829. ASSERT(pITableFrame != NULL);
  830. if (pITableFrame == NULL) return;
  831. tagTableFrameInfo *ptagTableFrameInfo = GetTableInterface(pITableFrame);
  832. if (ptagTableFrameInfo == NULL) return;
  833. //变量定义
  834. WORD wChairCount = pITableFrame->GetChairCount();
  835. TCHAR szMsg[256] = TEXT("");
  836. if (m_enMatchStatus == MatchStatus_FirstRound)
  837. {
  838. //构造数据
  839. CMD_GR_Match_Info MatchInfo;
  840. ZeroMemory(&MatchInfo, sizeof(MatchInfo));
  841. _sntprintf(MatchInfo.szTitle[0], CountArray(MatchInfo.szTitle[0]), TEXT("积分方式:累计积分"));
  842. _sntprintf(MatchInfo.szTitle[1], CountArray(MatchInfo.szTitle[1]), TEXT("游戏基数:%d"), m_dwCurBase);
  843. _sntprintf(MatchInfo.szTitle[2], CountArray(MatchInfo.szTitle[2]), TEXT("局制名称:定局排名"));
  844. _sntprintf(MatchInfo.szTitle[3], CountArray(MatchInfo.szTitle[3]), TEXT("需要完成:%d局比赛"), m_pMatchOption->MatchType.Immediate.cbPlayCount);
  845. MatchInfo.wGameCount = ptagTableFrameInfo->cbPlayCount;
  846. //wChairID为INVALID_CHAIR发给本桌所有玩家,否则只发给指定玩家
  847. for (WORD i = 0; i < wChairCount; i++)
  848. {
  849. //获取用户
  850. if (wChairID != INVALID_CHAIR && wChairID != i) continue;
  851. IServerUserItem *pIServerUserItem = pITableFrame->GetTableUserItem(i);
  852. if (pIServerUserItem == NULL) continue;
  853. //发送数据
  854. pITableFrame->SendTableData(i, SUB_GR_MATCH_INFO, &MatchInfo, sizeof(MatchInfo), MDM_GF_FRAME);
  855. }
  856. //发送提示
  857. if ((wChairID != INVALID_CHAIR) && (ptagTableFrameInfo->bWaitForNextInnings == true))
  858. {
  859. SendWaitTip(pITableFrame, wChairID);
  860. }
  861. }
  862. return;
  863. }
  864. //捕获比赛专用定时器
  865. void CImmediateGroup::CaptureMatchTimer()
  866. {
  867. for (int i = 0; i < m_MatchTimerArray.GetCount(); i++)
  868. {
  869. if (--m_MatchTimerArray[i]->iElapse <= 0)
  870. {
  871. if (m_MatchTimerArray[i]->dwTimerID == IDI_CONTINUE_GAME)
  872. {
  873. //本桌用户继续游戏
  874. ContinueGame((ITableFrame*)m_MatchTimerArray[i]->wParam);
  875. }
  876. else if (m_MatchTimerArray[i]->dwTimerID == IDI_LEAVE_TABLE)
  877. {
  878. //离开本桌
  879. AllUserExitTable((ITableFrame*)m_MatchTimerArray[i]->wParam);
  880. }
  881. else if (m_MatchTimerArray[i]->dwTimerID == IDI_CHECK_TABLE_START)
  882. {
  883. //检查桌子是否开始游戏
  884. //CheckTableStart((ITableFrame*)m_MatchTimerArray[i]->wParam);
  885. }
  886. //删除定时器
  887. if (KillMatchTimer(i))i--;
  888. else ASSERT(false);
  889. }
  890. }
  891. }
  892. //投递比赛专用定时器
  893. void CImmediateGroup::PostMatchTimer(DWORD dwTimerID, int iElapse, WPARAM wParam, LPARAM lParam)
  894. {
  895. tagMatchTimer* pMatchTimer = new tagMatchTimer;
  896. pMatchTimer->dwTimerID = dwTimerID;
  897. pMatchTimer->iElapse = iElapse;
  898. //pMatchTimer->dwRepeat=dwRepeat;
  899. pMatchTimer->wParam = wParam;
  900. pMatchTimer->lParam = lParam;
  901. m_MatchTimerArray.Add(pMatchTimer);
  902. }
  903. //杀死比赛专用定时器
  904. bool CImmediateGroup::KillMatchTimer(DWORD dwTimerID, WPARAM wParam)
  905. {
  906. for (int i = 0; i < m_MatchTimerArray.GetCount(); i++)
  907. {
  908. if (m_MatchTimerArray[i]->dwTimerID == dwTimerID&&m_MatchTimerArray[i]->wParam == wParam)
  909. {
  910. tagMatchTimer* pMatchTimer = m_MatchTimerArray[i];
  911. m_MatchTimerArray.RemoveAt(i);
  912. SafeDelete(pMatchTimer);
  913. return true;
  914. }
  915. }
  916. return false;
  917. }
  918. //杀死比赛专用定时器
  919. bool CImmediateGroup::KillMatchTimer(INT_PTR dwIndexID)
  920. {
  921. ASSERT(dwIndexID >= 0 && dwIndexID < m_MatchTimerArray.GetCount());
  922. if (dwIndexID >= 0 && dwIndexID < m_MatchTimerArray.GetCount())
  923. {
  924. tagMatchTimer* pMatchTimer = m_MatchTimerArray[dwIndexID];
  925. m_MatchTimerArray.RemoveAt(dwIndexID);
  926. SafeDelete(pMatchTimer);
  927. return true;
  928. }
  929. return false;
  930. }
  931. //全部杀死比赛专用定时器
  932. void CImmediateGroup::AllKillMatchTimer()
  933. {
  934. for (int i = 0; i < m_MatchTimerArray.GetCount();/*i++*/)
  935. {
  936. tagMatchTimer* pMatchTimer = m_MatchTimerArray[i];
  937. m_MatchTimerArray.RemoveAt(i);
  938. SafeDelete(pMatchTimer);
  939. }
  940. }