诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1392 lines
58 KiB

  1. #include "StdAfx.h"
  2. #include "ImmediateMatch.h"
  3. #include "..\GameServer\DataBasePacket.h"
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static char THIS_FILE[] = __FILE__;
  8. #endif
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. #define INVALID_VALUE 0xFFFF //无效值
  11. //////////////////////////////////////////////////////////////////////////
  12. //时钟定义
  13. #define IDI_DISTRIBUTE_USER (IDI_MATCH_MODULE_START+100) //分配用户
  14. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15. //构造函数
  16. CImmediateMatch::CImmediateMatch()
  17. {
  18. //比赛配置
  19. m_pMatchOption = NULL;
  20. m_pGameServiceOption = NULL;
  21. m_pGameServiceAttrib = NULL;
  22. //设置指针
  23. m_ppITableFrame = NULL;
  24. m_pCurMatchGroup = NULL;
  25. //内核接口
  26. m_pITimerEngine = NULL;
  27. m_pIDataBaseEngine = NULL;
  28. m_pITCPNetworkEngineEvent = NULL;
  29. //服务接口
  30. m_pIGameServiceFrame = NULL;
  31. m_pIServerUserManager = NULL;
  32. m_pAndroidUserManager = NULL;
  33. m_pIServerUserItemSink = NULL;
  34. }
  35. CImmediateMatch::~CImmediateMatch(void)
  36. {
  37. SafeDeleteArray(m_ppITableFrame);
  38. m_LoopTimer.RemoveAll();
  39. SafeDelete(m_pCurMatchGroup);
  40. m_MatchGroup.Append(m_OverMatchGroup);
  41. for (int i = 0; i<m_MatchGroup.GetCount(); i++)
  42. {
  43. SafeDelete(m_MatchGroup[i]);
  44. }
  45. m_MatchGroup.RemoveAll();
  46. m_OverMatchGroup.RemoveAll();
  47. }
  48. //接口查询
  49. VOID* CImmediateMatch::QueryInterface(REFGUID Guid, DWORD dwQueryVer)
  50. {
  51. QUERYINTERFACE(IGameMatchItem, Guid, dwQueryVer);
  52. QUERYINTERFACE(IServerUserItemSink, Guid, dwQueryVer);
  53. QUERYINTERFACE_IUNKNOWNEX(IGameMatchItem, Guid, dwQueryVer);
  54. return NULL;
  55. }
  56. //启动通知
  57. void CImmediateMatch::OnStartService()
  58. {
  59. //创建分组
  60. if (m_pCurMatchGroup == NULL)
  61. {
  62. m_pCurMatchGroup = new CImmediateGroup((DWORD)time(NULL), m_pMatchOption, this);
  63. }
  64. //最多同时9组编号
  65. for (int i = 0; i<79; i++)
  66. {
  67. m_LoopTimer.Add(i);
  68. }
  69. m_pITimerEngine->SetTimer(IDI_CHECK_OVER_MATCH, 60000L, TIMES_INFINITY, 0);
  70. m_pITimerEngine->SetTimer(IDI_DELETE_OVER_MATCH, 6000, TIMES_INFINITY, 0);
  71. //#ifdef _DEBUG
  72. // m_pITimerEngine->SetTimer(IDI_ANDROID_SIGNUP,1000,TIMES_INFINITY,0);
  73. //#else
  74. // m_pITimerEngine->SetTimer(IDI_ANDROID_SIGNUP,3000,TIMES_INFINITY,0);
  75. //#endif
  76. InsertNullTable();
  77. }
  78. //绑定桌子
  79. bool CImmediateMatch::BindTableFrame(ITableFrame * pTableFrame, WORD wTableID)
  80. {
  81. if (pTableFrame == NULL || wTableID>m_pGameServiceOption->wTableCount)
  82. {
  83. ASSERT(false);
  84. return false;
  85. }
  86. //创建钩子
  87. CTableFrameHook * pTableFrameHook = new CTableFrameHook();
  88. pTableFrameHook->InitTableFrameHook(QUERY_OBJECT_PTR_INTERFACE(pTableFrame, IUnknownEx));
  89. pTableFrameHook->SetMatchEventSink(QUERY_OBJECT_PTR_INTERFACE(this, IUnknownEx));
  90. //设置接口
  91. pTableFrame->SetTableFrameHook(QUERY_OBJECT_PTR_INTERFACE(pTableFrameHook, IUnknownEx));
  92. m_ppITableFrame[wTableID] = pTableFrame;
  93. return true;
  94. }
  95. //初始化接口
  96. bool CImmediateMatch::InitMatchInterface(tagMatchManagerParameter & MatchManagerParameter)
  97. {
  98. //服务配置
  99. m_pMatchOption = MatchManagerParameter.pGameMatchOption;
  100. m_pGameServiceOption = MatchManagerParameter.pGameServiceOption;
  101. m_pGameServiceAttrib = MatchManagerParameter.pGameServiceAttrib;
  102. //内核组件
  103. m_pITimerEngine = MatchManagerParameter.pITimerEngine;
  104. m_pIDataBaseEngine = MatchManagerParameter.pICorrespondManager;
  105. m_pITCPNetworkEngineEvent = MatchManagerParameter.pTCPNetworkEngine;
  106. //服务组件
  107. m_pIGameServiceFrame = MatchManagerParameter.pIMainServiceFrame;
  108. m_pIServerUserManager = MatchManagerParameter.pIServerUserManager;
  109. m_pAndroidUserManager = MatchManagerParameter.pIAndroidUserManager;
  110. m_pIServerUserItemSink = MatchManagerParameter.pIServerUserItemSink;
  111. //创建桌子数组
  112. CImmediateGroup::m_wChairCount = m_pGameServiceAttrib->wChairCount;
  113. if (m_ppITableFrame == NULL)
  114. {
  115. m_ppITableFrame = new ITableFrame*[m_pGameServiceOption->wTableCount];
  116. }
  117. return true;
  118. }
  119. //时间事件
  120. bool CImmediateMatch::OnEventTimer(DWORD dwTimerID, WPARAM dwBindParameter)
  121. {
  122. if (dwTimerID >= IDI_GROUP_TIMER_START)
  123. {
  124. for (INT_PTR i = m_MatchGroup.GetCount() - 1; i >= 0; i--)
  125. {
  126. //查看是哪场比赛的定时器
  127. if (m_MatchGroup[i]->m_LoopTimer == ((dwTimerID - IDI_GROUP_TIMER_START) / 10))
  128. {
  129. m_MatchGroup[i]->OnTimeMessage(dwTimerID - (m_MatchGroup[i]->m_LoopTimer * 10), dwBindParameter);
  130. }
  131. }
  132. return true;
  133. }
  134. switch (dwTimerID)
  135. {
  136. case IDI_CHECK_OVER_MATCH:
  137. {
  138. //定时检测一下 那些比赛人数不够被卡的问题
  139. for (INT_PTR i = m_MatchGroup.GetCount() - 1; i >= 0; i--)
  140. {
  141. //参赛用户小于椅子数量 就要结束
  142. m_MatchGroup[i]->CheckMatchUser();
  143. }
  144. return true;
  145. }
  146. case IDI_DELETE_OVER_MATCH:
  147. {
  148. for (int i = 0; m_OverMatchGroup.GetCount(); i++)
  149. {
  150. CImmediateGroup * pOverMatch = m_OverMatchGroup[i];
  151. m_OverMatchGroup.RemoveAt(i--);
  152. SafeDelete(pOverMatch);
  153. }
  154. return true;
  155. }
  156. }
  157. return true;
  158. }
  159. //数据库事件
  160. bool CImmediateMatch::OnEventDataBase(WORD wRequestID, IServerUserItem * pIServerUserItem, VOID * pData, WORD wDataSize)
  161. {
  162. switch (wRequestID)
  163. {
  164. case DBO_GR_MATCH_SIGNUP_RESULT: //报名结果
  165. {
  166. //参数效验
  167. if (pIServerUserItem == NULL) return true;
  168. if (wDataSize>sizeof(DBO_GR_MatchSingupResult)) return false;
  169. //提取数据
  170. DBO_GR_MatchSingupResult * pMatchSignupResult = (DBO_GR_MatchSingupResult*)pData;
  171. //报名失败
  172. if (pMatchSignupResult->bResultCode == false)
  173. {
  174. m_pIGameServiceFrame->SendRoomMessage(pIServerUserItem, pMatchSignupResult->szDescribeString, SMT_EJECT);
  175. return true;
  176. }
  177. //加入比赛
  178. if (m_pCurMatchGroup->OnUserSignUpMatch(pIServerUserItem) == false)
  179. {
  180. SendRoomMessage(pIServerUserItem, TEXT("报名失败"), SMT_CHAT);
  181. return false;
  182. }
  183. //报名成功
  184. m_OnMatchUserItem.Add(pIServerUserItem);
  185. SendMatchInfo(NULL);
  186. if (m_pIGameServiceFrame != NULL)
  187. {
  188. SendRoomMessage(pIServerUserItem, TEXT("恭喜,报名成功,请等待系统为您安排座位!"), SMT_CHAT);
  189. }
  190. //金币更新
  191. if (pIServerUserItem->IsAndroidUser() == false)
  192. {
  193. //构造结构
  194. CMD_GR_MatchGoldUpdate MatchGoldUpdate;
  195. //设置变量
  196. MatchGoldUpdate.lCurrGold = pMatchSignupResult->lCurrGold;
  197. MatchGoldUpdate.lCurrIngot = pMatchSignupResult->lCurrIngot;
  198. MatchGoldUpdate.dwCurrExprience = pIServerUserItem->GetUserInfo()->dwExperience;
  199. //发送数据
  200. return SendData(pIServerUserItem, MDM_GR_MATCH, SUB_GR_MATCH_GOLDUPDATE, &MatchGoldUpdate, sizeof(MatchGoldUpdate));
  201. }
  202. break;
  203. }
  204. case DBO_GR_MATCH_UNSIGNUP_RESULT: //退赛结果
  205. {
  206. //参数效验
  207. if (pIServerUserItem == NULL) return true;
  208. if (wDataSize>sizeof(DBO_GR_MatchSingupResult)) return false;
  209. //提取数据
  210. DBO_GR_MatchSingupResult * pMatchSignupResult = (DBO_GR_MatchSingupResult*)pData;
  211. //退费失败
  212. if (pMatchSignupResult->bResultCode == false)
  213. {
  214. m_pIGameServiceFrame->SendRoomMessage(pIServerUserItem, pMatchSignupResult->szDescribeString, SMT_EJECT);
  215. return true;
  216. }
  217. //设置状态
  218. pIServerUserItem->SetSignUpStatus(MatchStatus_Null);
  219. //变量定义
  220. LPCTSTR pszMatchFeeType[] = { TEXT("游戏币"), TEXT("元宝") };
  221. if (m_pMatchOption->cbMatchFeeType<CountArray(pszMatchFeeType))
  222. {
  223. //退费通知
  224. TCHAR szDescribe[128] = TEXT("");
  225. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("退赛成功,退还报名费%I64d%s!"), m_pMatchOption->lMatchFee, pszMatchFeeType[m_pMatchOption->cbMatchFeeType]);
  226. m_pIGameServiceFrame->SendRoomMessage(pIServerUserItem, szDescribe, SMT_EJECT);
  227. }
  228. //金币更新
  229. if (pIServerUserItem->IsAndroidUser() == false)
  230. {
  231. //构造结构
  232. CMD_GR_MatchGoldUpdate MatchGoldUpdate;
  233. //设置变量
  234. MatchGoldUpdate.lCurrGold = pMatchSignupResult->lCurrGold;
  235. MatchGoldUpdate.lCurrIngot = pMatchSignupResult->lCurrIngot;
  236. MatchGoldUpdate.dwCurrExprience = pIServerUserItem->GetUserInfo()->dwExperience;
  237. //发送数据
  238. return SendData(pIServerUserItem, MDM_GR_MATCH, SUB_GR_MATCH_GOLDUPDATE, &MatchGoldUpdate, sizeof(MatchGoldUpdate));
  239. }
  240. break;
  241. }
  242. case DBO_GR_MATCH_RANK_LIST: //比赛排行
  243. {
  244. //参数校验
  245. ASSERT(wDataSize <= sizeof(DBO_GR_MatchRankList));
  246. if (wDataSize>sizeof(DBO_GR_MatchRankList)) return false;
  247. //提取数据
  248. DBO_GR_MatchRankList * pMatchRankList = (DBO_GR_MatchRankList*)pData;
  249. //变量定义
  250. IServerUserItem * pIRewardUserItem = NULL;
  251. tagMatchRankInfo * pMatchRankInfo = NULL;
  252. //发放奖励
  253. for (WORD wIndex = 0; wIndex<pMatchRankList->wUserCount; wIndex++)
  254. {
  255. //查找玩家
  256. pMatchRankInfo = &pMatchRankList->MatchRankInfo[wIndex];
  257. pIRewardUserItem = m_pIServerUserManager->SearchUserItem(pMatchRankInfo->dwUserID);
  258. if (pIRewardUserItem == NULL || pIRewardUserItem->IsAndroidUser() == true) continue;
  259. //写入奖励
  260. WriteUserAward(pIRewardUserItem, pMatchRankInfo);
  261. }
  262. //变量定义
  263. CImmediateGroup * pImmediateGroup = NULL;
  264. //查找分组
  265. for (int i = 0; i<m_MatchGroup.GetCount(); i++)
  266. {
  267. if (m_MatchGroup[i]->m_dwMatchNO == pMatchRankList->dwMatchNO)
  268. {
  269. pImmediateGroup = m_MatchGroup[i];
  270. if (pImmediateGroup != NULL)
  271. {
  272. //全部起立
  273. pImmediateGroup->RearrangeUserSeat();
  274. //发送可报名状态
  275. BYTE cbMatchStatus = MatchStatus_Null;
  276. SendGroupData(MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbMatchStatus, sizeof(cbMatchStatus), pImmediateGroup);
  277. //还原编号
  278. m_LoopTimer.Add(pImmediateGroup->m_LoopTimer);
  279. //参赛玩家退赛
  280. POSITION pos = pImmediateGroup->m_OnMatchUserMap.GetStartPosition();
  281. IServerUserItem *pITempUserItem = NULL;
  282. DWORD dwUserID = 0;
  283. WORD wQuitUserCount = 0;
  284. WORD wMatchUserCount = (WORD)pImmediateGroup->m_OnMatchUserMap.GetCount();
  285. while (pos != NULL)
  286. {
  287. pImmediateGroup->m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pITempUserItem);
  288. if (pITempUserItem != NULL)
  289. {
  290. pITempUserItem->SetSignUpStatus(MatchStatus_Null);
  291. if (true == OnEventUserQuitMatch(pITempUserItem, 0))
  292. wQuitUserCount++;
  293. //比赛结束后代打玩家未返回,则踢出房间
  294. bool bAndroidUser = pITempUserItem->IsAndroidUser();
  295. bool bTrusteeUser = pITempUserItem->IsTrusteeUser();
  296. bool bClientReady = pITempUserItem->IsClientReady();
  297. if (bAndroidUser == false && bTrusteeUser == true && bClientReady == false)
  298. {
  299. //离开桌子
  300. WORD wTableID = pITempUserItem->GetTableID();
  301. if (wTableID != INVALID_TABLE)
  302. {
  303. //状态判断
  304. ASSERT(pITempUserItem->GetUserStatus() != US_PLAYING);
  305. SendGameMessage(pITempUserItem, TEXT(""), SMT_CLOSE_GAME);
  306. //查找桌子并弹起
  307. for (int m = 0; m<pImmediateGroup->m_MatchTableArray.GetCount(); m++)
  308. {
  309. if (pITempUserItem->GetTableID() == pImmediateGroup->m_MatchTableArray[m]->wTableID)
  310. {
  311. pImmediateGroup->m_MatchTableArray[m]->pTableFrame->PerformStandUpAction(pITempUserItem);
  312. break;
  313. }
  314. }
  315. }
  316. //离开房间
  317. if (pITempUserItem->GetBindIndex() == INVALID_WORD)
  318. {
  319. pITempUserItem->SetUserStatus(US_NULL, INVALID_TABLE, INVALID_CHAIR);
  320. }
  321. }
  322. }
  323. }
  324. //校验退赛结果
  325. ASSERT(wQuitUserCount == wMatchUserCount);
  326. if (wQuitUserCount != wMatchUserCount)
  327. {
  328. CTraceService::TraceString(TEXT("比赛结束后,退赛人数异常"), TraceLevel_Exception);
  329. }
  330. //回收全部桌子
  331. for (int j = 0; pImmediateGroup->m_MatchTableArray.GetCount();)
  332. {
  333. tagTableFrameInfo* pTempTable = pImmediateGroup->m_MatchTableArray[j];
  334. pImmediateGroup->m_MatchTableArray.RemoveAt(j);
  335. SafeDelete(pTempTable);
  336. }
  337. }
  338. //移除对象
  339. m_MatchGroup.RemoveAt(i);
  340. m_OverMatchGroup.Add(pImmediateGroup);
  341. break;
  342. }
  343. }
  344. break;
  345. }
  346. case DBO_GR_MATCH_REWARD_RESULT: //奖励结果
  347. {
  348. //参数效验
  349. if (pIServerUserItem == NULL) return true;
  350. if (wDataSize>sizeof(DBR_GR_MatchRewardResult)) return false;
  351. //提取数据
  352. DBR_GR_MatchRewardResult * pMatchRewardResult = (DBR_GR_MatchRewardResult*)pData;
  353. //奖励成功
  354. if (pMatchRewardResult->bResultCode == true)
  355. {
  356. //构造结构
  357. CMD_GR_MatchGoldUpdate MatchGoldUpdate;
  358. //设置变量
  359. MatchGoldUpdate.lCurrGold = pMatchRewardResult->lCurrGold;
  360. MatchGoldUpdate.lCurrIngot = pMatchRewardResult->lCurrIngot;
  361. MatchGoldUpdate.dwCurrExprience = pMatchRewardResult->dwCurrExperience;
  362. //发送数据
  363. SendData(pIServerUserItem, MDM_GR_MATCH, SUB_GR_MATCH_GOLDUPDATE, &MatchGoldUpdate, sizeof(MatchGoldUpdate));
  364. }
  365. break;
  366. }
  367. }
  368. return true;
  369. }
  370. //命令消息
  371. bool CImmediateMatch::OnEventSocketMatch(WORD wSubCmdID, VOID * pData, WORD wDataSize, IServerUserItem * pIServerUserItem, DWORD dwSocketID)
  372. {
  373. switch (wSubCmdID)
  374. {
  375. case SUB_GR_MATCH_FEE: //比赛费用
  376. {
  377. //参数效验
  378. ASSERT(wDataSize == sizeof(SCORE));
  379. if (wDataSize != sizeof(SCORE)) return false;
  380. //提取数据
  381. SCORE lMatchFee = *(SCORE*)pData;
  382. if (lMatchFee != m_pMatchOption->lMatchFee)return false;
  383. //变量定义
  384. DBR_GR_MatchSignup MatchSignup;
  385. ZeroMemory(&MatchSignup, sizeof(MatchSignup));
  386. //构造结构
  387. MatchSignup.dwUserID = pIServerUserItem->GetUserID();
  388. MatchSignup.lMatchFee = m_pMatchOption->lMatchFee;
  389. MatchSignup.dwInoutIndex = pIServerUserItem->GetInoutIndex();
  390. MatchSignup.dwClientAddr = pIServerUserItem->GetClientAddr();
  391. MatchSignup.dwMatchID = m_pMatchOption->dwMatchID;
  392. MatchSignup.dwMatchNO = m_pCurMatchGroup->m_dwMatchNO;
  393. lstrcpyn(MatchSignup.szMachineID, pIServerUserItem->GetMachineID(), CountArray(MatchSignup.szMachineID));
  394. //投递数据
  395. m_pIDataBaseEngine->PostDataBaseRequest(MatchSignup.dwUserID, DBR_GR_MATCH_SIGNUP, dwSocketID, &MatchSignup, sizeof(MatchSignup));
  396. return true;
  397. }
  398. case SUB_GR_LEAVE_MATCH: //退出比赛
  399. {
  400. //参数效验
  401. ASSERT(pIServerUserItem != NULL);
  402. if (pIServerUserItem == NULL) return false;
  403. OnEventUserQuitMatch(pIServerUserItem, 0, 0, dwSocketID);
  404. return true;
  405. }
  406. }
  407. return true;
  408. }
  409. //用户登录
  410. bool CImmediateMatch::OnEventUserLogon(IServerUserItem * pIServerUserItem)
  411. {
  412. return SendMatchInfo(pIServerUserItem);
  413. }
  414. //用户登出
  415. bool CImmediateMatch::OnEventUserLogout(IServerUserItem * pIServerUserItem)
  416. {
  417. return true;
  418. }
  419. //进入事件
  420. bool CImmediateMatch::OnEventEnterMatch(DWORD dwSocketID, VOID* pData, DWORD dwUserIP, bool bIsMobile)
  421. {
  422. //手机用户
  423. if (bIsMobile == true)
  424. {
  425. //处理消息
  426. CMD_GR_LogonMobile * pLogonMobile = (CMD_GR_LogonMobile *)pData;
  427. pLogonMobile->szPassword[CountArray(pLogonMobile->szPassword) - 1] = 0;
  428. pLogonMobile->szMachineID[CountArray(pLogonMobile->szMachineID) - 1] = 0;
  429. //变量定义
  430. DBR_GR_LogonMobile LogonMobile;
  431. ZeroMemory(&LogonMobile, sizeof(LogonMobile));
  432. //构造数据
  433. LogonMobile.dwUserID = pLogonMobile->dwUserID;
  434. LogonMobile.dwClientAddr = dwUserIP;
  435. LogonMobile.dwMatchID = m_pMatchOption->dwMatchID;
  436. LogonMobile.dwMatchNO = m_pMatchOption->dwMatchNO;
  437. LogonMobile.cbDeviceType = pLogonMobile->cbDeviceType;
  438. LogonMobile.wBehaviorFlags = pLogonMobile->wBehaviorFlags;
  439. LogonMobile.wPageTableCount = pLogonMobile->wPageTableCount;
  440. lstrcpyn(LogonMobile.szPassword, pLogonMobile->szPassword, CountArray(LogonMobile.szPassword));
  441. lstrcpyn(LogonMobile.szMachineID, pLogonMobile->szMachineID, CountArray(LogonMobile.szMachineID));
  442. //投递请求
  443. m_pIDataBaseEngine->PostDataBaseRequest(LogonMobile.dwUserID, DBR_GR_LOGON_MOBILE, dwSocketID, &LogonMobile, sizeof(LogonMobile));
  444. }
  445. else
  446. {
  447. //处理消息
  448. CMD_GR_LogonUserID * pLogonUserID = (CMD_GR_LogonUserID *)pData;
  449. pLogonUserID->szPassword[CountArray(pLogonUserID->szPassword) - 1] = 0;
  450. pLogonUserID->szMachineID[CountArray(pLogonUserID->szMachineID) - 1] = 0;
  451. //变量定义
  452. DBR_GR_LogonUserID LogonUserID;
  453. ZeroMemory(&LogonUserID, sizeof(LogonUserID));
  454. //构造数据
  455. LogonUserID.dwClientAddr = dwUserIP;
  456. LogonUserID.dwUserID = pLogonUserID->dwUserID;
  457. LogonUserID.dwMatchID = m_pMatchOption->dwMatchID;
  458. LogonUserID.dwMatchNO = m_pMatchOption->dwMatchNO;
  459. lstrcpyn(LogonUserID.szPassword, pLogonUserID->szPassword, CountArray(LogonUserID.szPassword));
  460. lstrcpyn(LogonUserID.szMachineID, pLogonUserID->szMachineID, CountArray(LogonUserID.szMachineID));
  461. //投递请求
  462. m_pIDataBaseEngine->PostDataBaseRequest(LogonUserID.dwUserID, DBR_GR_LOGON_USERID, dwSocketID, &LogonUserID, sizeof(LogonUserID));
  463. }
  464. return true;
  465. }
  466. //用户参赛
  467. bool CImmediateMatch::OnEventUserJoinMatch(IServerUserItem * pIServerUserItem, BYTE cbReason, DWORD dwSocketID)
  468. {
  469. ASSERT(pIServerUserItem != NULL);
  470. if (pIServerUserItem == NULL)
  471. {
  472. CTraceService::TraceString(TEXT("用户指针为空!"), TraceLevel_Warning);
  473. return true;
  474. }
  475. if (CServerRule::IsForfendRoomEnter(m_pGameServiceOption->dwServerRule))
  476. {
  477. SendRoomMessage(pIServerUserItem, TEXT("抱歉,由于系统维护,该房间禁止用户报名比赛!。"), SMT_CHAT | SMT_EJECT);
  478. return true;
  479. }
  480. WORD wTableCount = GetNullTable();
  481. if (wTableCount<m_pMatchOption->MatchType.Immediate.wStartUserCount / CImmediateGroup::m_wChairCount)
  482. {
  483. CString str;
  484. str.Format(TEXT("抱歉,当前桌子不够请等待。还差 %d 张桌子可以报名"), m_pMatchOption->MatchType.Immediate.wStartUserCount / CImmediateGroup::m_wChairCount - wTableCount);
  485. SendRoomMessage(pIServerUserItem, str, SMT_CHAT);
  486. return true;
  487. }
  488. if (m_pCurMatchGroup == NULL || m_pCurMatchGroup->m_enMatchStatus == MatchStatus_Wait)
  489. {
  490. SendRoomMessage(pIServerUserItem, TEXT("抱歉,该房间参赛人数已满,请稍后再报名或者进入另一房间比赛。"), SMT_CHAT);
  491. return true;
  492. }
  493. INT_PTR dwUserCount = m_OnMatchUserItem.GetCount();
  494. for (INT_PTR i = 0; i<dwUserCount; i++)
  495. {
  496. if (m_OnMatchUserItem[i]->GetUserID() == pIServerUserItem->GetUserID())
  497. {
  498. SendRoomMessage(pIServerUserItem, TEXT("您已经成功报名,不能重复报名!"), SMT_CHAT | SMT_EJECT);
  499. return true;
  500. }
  501. }
  502. if (m_LoopTimer.GetCount() == 0)
  503. {
  504. SendRoomMessage(pIServerUserItem, TEXT("抱歉,比赛编号不够请稍等。"), SMT_CHAT);
  505. return true;
  506. }
  507. if (pIServerUserItem->GetUserStatus() != US_FREE || pIServerUserItem->GetTableID() != INVALID_TABLE)
  508. {
  509. SendRoomMessage(pIServerUserItem, TEXT("对不起,您当前的状态不允许参加比赛!"), SMT_CHAT);
  510. return true;
  511. }
  512. if (m_pMatchOption->MatchType.Immediate.dwInitalScore == 0 && pIServerUserItem->GetUserScore()<m_pMatchOption->MatchType.Immediate.dwInitalBase*m_pMatchOption->MatchType.Immediate.wMinEnterGold + m_pMatchOption->lMatchFee)
  513. {
  514. TCHAR szMsg[256] = TEXT("");
  515. _sntprintf(szMsg, CountArray(szMsg), TEXT("对不起,您当前的金币低于了%d,不能参加比赛!"),
  516. m_pMatchOption->MatchType.Immediate.dwInitalBase*m_pMatchOption->MatchType.Immediate.wMinEnterGold + m_pMatchOption->lMatchFee);
  517. SendRoomMessage(pIServerUserItem, szMsg, SMT_CHAT | SMT_EJECT);
  518. return true;
  519. }
  520. //真人扣报名费
  521. if (m_pMatchOption->lMatchFee>0 && pIServerUserItem->IsAndroidUser() == false)
  522. {
  523. ASSERT(m_pIGameServiceFrame != NULL);
  524. if (m_pIGameServiceFrame == NULL)
  525. {
  526. CTraceService::TraceString(TEXT("服务框架指针为空!"), TraceLevel_Warning);
  527. return true;
  528. }
  529. //构造结构
  530. CMD_GR_Match_Fee MatchFee;
  531. MatchFee.lMatchFee = m_pMatchOption->lMatchFee;
  532. //构造提示
  533. if (MatchFee.lMatchFee>0)
  534. {
  535. //变量定义
  536. LPCTSTR pszMatchFeeType[] = { TEXT("游戏币"), TEXT("元宝") };
  537. if (m_pMatchOption->cbMatchFeeType<CountArray(pszMatchFeeType))
  538. {
  539. _sntprintf(MatchFee.szNotifyContent, CountArray(MatchFee.szNotifyContent), TEXT("参赛将扣除报名费 %I64d %s,确认要参赛吗?"), m_pMatchOption->lMatchFee, pszMatchFeeType[m_pMatchOption->cbMatchFeeType]);
  540. }
  541. }
  542. //发送消息
  543. WORD wDataSize = sizeof(MatchFee)-sizeof(MatchFee.szNotifyContent);
  544. wDataSize += CountStringBuffer(MatchFee.szNotifyContent);
  545. m_pIGameServiceFrame->SendData(pIServerUserItem, MDM_GR_MATCH, SUB_GR_MATCH_FEE, &MatchFee, wDataSize);
  546. return true;
  547. }
  548. //机器人报名
  549. if (m_pMatchOption->lMatchFee == 0 || pIServerUserItem->IsAndroidUser() == true)
  550. {
  551. //机器数判断
  552. if (pIServerUserItem->IsAndroidUser() == true && (m_pCurMatchGroup->m_wAndroidUserCount >=
  553. m_pMatchOption->MatchType.Immediate.wAndroidUserCount))
  554. {
  555. return true;
  556. }
  557. return OnEventSocketMatch(SUB_GR_MATCH_FEE, &m_pMatchOption->lMatchFee, sizeof(SCORE), pIServerUserItem, dwSocketID);
  558. }
  559. //报名成功
  560. m_OnMatchUserItem.Add(pIServerUserItem);
  561. SendMatchInfo(NULL);
  562. if (m_pIGameServiceFrame != NULL)
  563. {
  564. SCORE lScore = SCORE(m_pMatchOption->lMatchFee)*-1;
  565. /*if(m_pMatchOption->MatchType.Immediate.dwInitalScore==0)
  566. {
  567. pIServerUserItem->GetUserInfo()->lScore+=lScore;
  568. m_pIServerUserItemSink->OnEventUserItemScore(pIServerUserItem,SCORE_REASON_MATCH_FEE);
  569. }*/
  570. SendRoomMessage(pIServerUserItem, TEXT("恭喜,报名成功,请等待系统为您安排座位!"), SMT_CHAT);
  571. }
  572. return true;
  573. }
  574. //用户退赛
  575. bool CImmediateMatch::OnEventUserQuitMatch(IServerUserItem * pIServerUserItem, BYTE cbReason, WORD *pBestRank, DWORD dwContextID)
  576. {
  577. ASSERT(pIServerUserItem != NULL);
  578. if (pIServerUserItem == NULL) return false;
  579. //正在游戏状态
  580. if (pIServerUserItem->GetUserStatus() >= US_PLAYING)
  581. {
  582. return true;
  583. }
  584. //正在比赛阶段
  585. BYTE cbUserEnlist = pIServerUserItem->GetSignUpStatus();
  586. if (cbUserEnlist == MS_MATCHING)
  587. {
  588. return true;
  589. }
  590. //否则玩家退赛
  591. if (RemoveMatchUserItem(pIServerUserItem))
  592. {
  593. //从正在比赛的组中删除该玩家
  594. INT_PTR nGroupCount = m_MatchGroup.GetCount();
  595. for (INT_PTR i = 0; i<nGroupCount; i++)
  596. {
  597. CImmediateGroup *pMatch = m_MatchGroup[i];
  598. if (pMatch->OnUserQuitMatch(pIServerUserItem))
  599. {
  600. //if(pMatch->m_enMatchStatus!=MatchStatus_Signup && pMatch->m_enMatchStatus!=MatchStatus_Wait)
  601. //{
  602. // SendRoomMessage(pIServerUserItem, TEXT("退赛成功,欢迎您继续参加其他比赛!"), SMT_CHAT|SMT_EJECT);
  603. //}
  604. if (pMatch->m_enMatchStatus != MatchStatus_Null)
  605. {
  606. SendRoomMessage(pIServerUserItem, TEXT("退赛成功,欢迎您继续参加其他比赛!"), SMT_CHAT | SMT_EJECT);
  607. }
  608. return true;
  609. }
  610. }
  611. //从正在报名的组中删除该玩家
  612. if (m_pCurMatchGroup->OnUserQuitMatch(pIServerUserItem))
  613. {
  614. //退还报名费
  615. if (m_pMatchOption->lMatchFee>0 && !pIServerUserItem->IsAndroidUser())
  616. {
  617. //变量定义
  618. DBR_GR_MatchSignup MatchSignup;
  619. MatchSignup.dwUserID = pIServerUserItem->GetUserID();
  620. //构造结构
  621. MatchSignup.lMatchFee = m_pMatchOption->lMatchFee;
  622. MatchSignup.dwInoutIndex = pIServerUserItem->GetInoutIndex();
  623. MatchSignup.dwClientAddr = pIServerUserItem->GetClientAddr();
  624. MatchSignup.dwMatchID = m_pMatchOption->dwMatchID;
  625. MatchSignup.dwMatchNO = m_pCurMatchGroup->m_dwMatchNO;
  626. lstrcpyn(MatchSignup.szMachineID, pIServerUserItem->GetMachineID(), CountArray(MatchSignup.szMachineID));
  627. //投递数据
  628. m_pIDataBaseEngine->PostDataBaseRequest(MatchSignup.dwUserID, DBR_GR_MATCH_UNSIGNUP, dwContextID, &MatchSignup, sizeof(MatchSignup));
  629. }
  630. if (m_pCurMatchGroup->m_enMatchStatus != MatchStatus_Null)
  631. {
  632. SendRoomMessage(pIServerUserItem, TEXT("退赛成功,欢迎您继续参加其他比赛!"), SMT_CHAT | SMT_EJECT);
  633. }
  634. SendMatchInfo(NULL);
  635. return true;
  636. }
  637. SendMatchInfo(NULL);
  638. }
  639. return false;
  640. }
  641. //用户积分
  642. bool CImmediateMatch::OnEventUserItemScore(IServerUserItem * pIServerUserItem, BYTE cbReason)
  643. {
  644. //效验参数
  645. ASSERT(pIServerUserItem != NULL);
  646. if (pIServerUserItem == NULL) return false;
  647. //获取对象
  648. CImmediateGroup * pImmediateGroup = static_cast<CImmediateGroup *>(pIServerUserItem->GetMatchData());
  649. if (pImmediateGroup == NULL)
  650. {
  651. return m_pIServerUserItemSink->OnEventUserItemScore(pIServerUserItem, cbReason);
  652. }
  653. //发送分数
  654. SendGroupUserScore(pIServerUserItem, pImmediateGroup);
  655. //变量定义
  656. tagUserInfo * pUserInfo = pIServerUserItem->GetUserInfo();
  657. //变量定义
  658. CMD_GR_MobileUserScore MobileUserScore;
  659. //构造数据
  660. MobileUserScore.dwUserID = pUserInfo->dwUserID;
  661. MobileUserScore.UserScore.dwWinCount = pUserInfo->dwWinCount;
  662. MobileUserScore.UserScore.dwLostCount = pUserInfo->dwLostCount;
  663. MobileUserScore.UserScore.dwDrawCount = pUserInfo->dwDrawCount;
  664. MobileUserScore.UserScore.dwFleeCount = pUserInfo->dwFleeCount;
  665. MobileUserScore.UserScore.dwExperience = pUserInfo->dwExperience;
  666. //构造积分
  667. MobileUserScore.UserScore.lScore = pUserInfo->lScore;
  668. MobileUserScore.UserScore.lScore += pIServerUserItem->GetTrusteeScore();
  669. MobileUserScore.UserScore.lScore += pIServerUserItem->GetFrozenedScore();
  670. //发送数据
  671. m_pIGameServiceFrame->SendDataBatchToMobileUser(pIServerUserItem->GetTableID(), MDM_GR_USER, SUB_GR_USER_SCORE, &MobileUserScore, sizeof(MobileUserScore));
  672. //即时写分
  673. if ((CServerRule::IsImmediateWriteScore(m_pGameServiceOption->dwServerRule) == true) && (pIServerUserItem->IsVariation() == true))
  674. {
  675. //变量定义
  676. DBR_GR_WriteGameScore WriteGameScore;
  677. ZeroMemory(&WriteGameScore, sizeof(WriteGameScore));
  678. //用户信息
  679. WriteGameScore.dwUserID = pIServerUserItem->GetUserID();
  680. WriteGameScore.dwDBQuestID = pIServerUserItem->GetDBQuestID();
  681. WriteGameScore.dwClientAddr = pIServerUserItem->GetClientAddr();
  682. WriteGameScore.dwInoutIndex = pIServerUserItem->GetInoutIndex();
  683. //提取积分
  684. pIServerUserItem->DistillVariation(WriteGameScore.VariationInfo);
  685. //比赛信息
  686. WriteGameScore.dwMatchID = m_pMatchOption->dwMatchID;
  687. WriteGameScore.dwMatchNO = pImmediateGroup->m_dwMatchNO;
  688. //投递请求
  689. m_pIDataBaseEngine->PostDataBaseRequest(WriteGameScore.dwUserID, DBR_GR_WRITE_GAME_SCORE, 0L, &WriteGameScore, sizeof(WriteGameScore), TRUE);
  690. }
  691. return true;
  692. }
  693. //用户状态
  694. bool CImmediateMatch::OnEventUserItemStatus(IServerUserItem * pIServerUserItem, WORD wOldTableID, WORD wOldChairID, bool bSendState)
  695. {
  696. //清除数据
  697. if (pIServerUserItem->GetUserStatus() == US_FREE) pIServerUserItem->SetMatchData(NULL);
  698. //回调接口
  699. if (m_pIServerUserItemSink != NULL)
  700. {
  701. return m_pIServerUserItemSink->OnEventUserItemStatus(pIServerUserItem, wOldTableID, wOldChairID);
  702. }
  703. return true;
  704. }
  705. //用户权限
  706. bool CImmediateMatch::OnEventUserItemRight(IServerUserItem *pIServerUserItem, DWORD dwAddRight, DWORD dwRemoveRight, BYTE cbRightKind)
  707. {
  708. if (m_pIServerUserItemSink != NULL)
  709. {
  710. return m_pIServerUserItemSink->OnEventUserItemRight(pIServerUserItem, dwAddRight, dwRemoveRight, cbRightKind);
  711. }
  712. return true;
  713. }
  714. //报名人满,开始比赛
  715. bool CImmediateMatch::OnEventMatchStart(CImmediateGroup *pMatch)
  716. {
  717. ASSERT(pMatch == m_pCurMatchGroup&&m_LoopTimer.GetCount()>0);
  718. //编号不够 不能报名的
  719. pMatch->m_LoopTimer = m_LoopTimer[0];
  720. m_LoopTimer.RemoveAt(0);
  721. m_MatchGroup.Add(pMatch);
  722. //准备新的一组比赛
  723. m_pCurMatchGroup = new CImmediateGroup((DWORD)time(NULL), m_pMatchOption, this);
  724. SendMatchInfo(NULL);
  725. BYTE cbMatchStatus = MS_MATCHING;
  726. SendGroupData(MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbMatchStatus, sizeof(cbMatchStatus), pMatch);
  727. return true;
  728. }
  729. //比赛结束
  730. bool CImmediateMatch::OnEventMatchOver(CImmediateGroup *pMatch)
  731. {
  732. //比赛结束
  733. if (pMatch != NULL)
  734. {
  735. DBR_GR_MatchOver MatchOver;
  736. ZeroMemory(&MatchOver, sizeof(MatchOver));
  737. //构造数据
  738. MatchOver.dwMatchID = m_pMatchOption->dwMatchID;
  739. MatchOver.dwMatchNO = pMatch->m_dwMatchNO;
  740. MatchOver.cbMatchType = MATCH_TYPE_IMMEDIATE;
  741. MatchOver.wServerID = m_pGameServiceOption->wServerID;
  742. //获取时间
  743. MatchOver.MatchStartTime = pMatch->m_MatchStartTime;
  744. CTime::GetCurrentTime().GetAsSystemTime(MatchOver.MatchEndTime);
  745. //投递请求
  746. m_pIDataBaseEngine->PostDataBaseRequest(0, DBR_GR_MATCH_OVER, 0, &MatchOver, sizeof(MatchOver));
  747. }
  748. return true;
  749. }
  750. //关闭定时器
  751. bool CImmediateMatch::KillGameTimer(DWORD dwTimerID, CImmediateGroup *pMatch)
  752. {
  753. m_pITimerEngine->KillTimer(dwTimerID);
  754. return false;
  755. }
  756. //设置定时器
  757. bool CImmediateMatch::SetGameTimer(DWORD dwTimerID, DWORD dwElapse, DWORD dwRepeat, WPARAM dwBindParameter, CImmediateGroup *pMatch)
  758. {
  759. return m_pITimerEngine->SetTimer(dwTimerID, dwElapse, dwRepeat, dwBindParameter);
  760. }
  761. //发送数据
  762. bool CImmediateMatch::SendMatchInfo(IServerUserItem * pIServerUserItem)
  763. {
  764. CMD_GR_Match_Num MatchNum;
  765. MatchNum.dwWaitting = (DWORD)m_pCurMatchGroup->m_OnMatchUserMap.GetCount();
  766. MatchNum.dwTotal = m_pMatchOption->MatchType.Immediate.wStartUserCount;
  767. if (pIServerUserItem == NULL)
  768. {
  769. m_pIGameServiceFrame->SendData(BG_ALL_CLIENT, MDM_GR_MATCH, SUB_GR_MATCH_NUM, &MatchNum, sizeof(MatchNum));
  770. return true;
  771. }
  772. m_pIGameServiceFrame->SendData(pIServerUserItem, MDM_GR_MATCH, SUB_GR_MATCH_NUM, &MatchNum, sizeof(MatchNum));
  773. m_pIGameServiceFrame->SendData(pIServerUserItem, MDM_GR_MATCH, SUB_GR_MATCH_DESC, &m_MatchDesc, sizeof(m_MatchDesc));
  774. INT_PTR dwUserCount = m_OnMatchUserItem.GetCount();
  775. for (INT_PTR i = 0; i<dwUserCount; i++)
  776. {
  777. if (m_OnMatchUserItem[i] == pIServerUserItem)
  778. {
  779. BYTE cbMatchStatus = pIServerUserItem->GetSignUpStatus();
  780. m_pIGameServiceFrame->SendData(pIServerUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbMatchStatus, sizeof(cbMatchStatus));
  781. return true;
  782. }
  783. }
  784. tagUserInfo *pUserScore = pIServerUserItem->GetUserInfo();
  785. pUserScore->dwWinCount = pUserScore->dwLostCount = pUserScore->dwFleeCount = pUserScore->dwDrawCount = pUserScore->cbGender = 0;
  786. if ((SCORE)m_pMatchOption->MatchType.Immediate.dwInitalScore != 0)
  787. {
  788. pUserScore->lScore = (LONG)m_pMatchOption->MatchType.Immediate.dwInitalScore;
  789. }
  790. return SendGroupUserScore(pIServerUserItem, NULL);
  791. }
  792. //发送信息
  793. bool CImmediateMatch::SendGroupUserMessage(LPCTSTR pStrMessage, CImmediateGroup *pMatch)
  794. {
  795. POSITION pos = pMatch->m_OnMatchUserMap.GetStartPosition();
  796. IServerUserItem *pUserItem = NULL;
  797. DWORD dwUserID = 0;
  798. while (pos != NULL)
  799. {
  800. pMatch->m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pUserItem);
  801. SendGameMessage(pUserItem, pStrMessage, SMT_CHAT | SMT_TABLE_ROLL);
  802. }
  803. return true;
  804. }
  805. //发送用户分数
  806. bool CImmediateMatch::SendGroupUserScore(IServerUserItem * pIServerUserItem, CImmediateGroup *pMatch)
  807. {
  808. //发送数据
  809. CMD_GR_UserScore UserScore;
  810. ZeroMemory(&UserScore, sizeof(UserScore));
  811. tagUserInfo * pUserInfo = pIServerUserItem->GetUserInfo();
  812. //构造数据
  813. UserScore.dwUserID = pUserInfo->dwUserID;
  814. UserScore.UserScore.dwWinCount = pUserInfo->dwWinCount;
  815. UserScore.UserScore.dwLostCount = pUserInfo->dwLostCount;
  816. UserScore.UserScore.dwDrawCount = pUserInfo->dwDrawCount;
  817. UserScore.UserScore.dwFleeCount = pUserInfo->dwFleeCount;
  818. UserScore.UserScore.dwExperience = pUserInfo->dwExperience;
  819. UserScore.UserScore.lLoveLiness = pUserInfo->lLoveLiness;
  820. //构造积分
  821. UserScore.UserScore.lIngot = 0;// pUserInfo->lIngot;
  822. UserScore.UserScore.lGrade = pUserInfo->lGrade;
  823. UserScore.UserScore.lInsure = pUserInfo->lInsure;
  824. //构造积分
  825. UserScore.UserScore.lScore = pUserInfo->lScore;
  826. if (pMatch != NULL)
  827. {
  828. POSITION pos = pMatch->m_OnMatchUserMap.GetStartPosition();
  829. IServerUserItem *pUserItem = NULL;
  830. DWORD dwUserID = 0;
  831. while (pos != NULL)
  832. {
  833. pMatch->m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pUserItem);
  834. m_pIGameServiceFrame->SendData(pUserItem, MDM_GR_USER, SUB_GR_USER_SCORE, &UserScore, sizeof(UserScore));
  835. }
  836. return true;
  837. }
  838. return m_pIGameServiceFrame->SendData(BG_COMPUTER, MDM_GR_USER, SUB_GR_USER_SCORE, &UserScore, sizeof(UserScore));
  839. }
  840. //发送状态
  841. bool CImmediateMatch::SendGroupUserStatus(IServerUserItem * pIServerUserItem, CImmediateGroup *pMatch)
  842. {
  843. //效验参数
  844. ASSERT(pIServerUserItem != NULL);
  845. ASSERT(pIServerUserItem->IsClientReady() == true);
  846. if (pIServerUserItem->IsClientReady() == false) return false;
  847. //变量定义
  848. CMD_GR_UserStatus UserStatus;
  849. ZeroMemory(&UserStatus, sizeof(UserStatus));
  850. tagUserInfo * pUserData = pIServerUserItem->GetUserInfo();
  851. //构造数据
  852. UserStatus.dwUserID = pUserData->dwUserID;
  853. UserStatus.UserStatus.wTableID = pUserData->wTableID;
  854. UserStatus.UserStatus.wChairID = pUserData->wChairID;
  855. UserStatus.UserStatus.cbUserStatus = pUserData->cbUserStatus;
  856. POSITION pos = pMatch->m_OnMatchUserMap.GetStartPosition();
  857. IServerUserItem *pUserItem = NULL;
  858. DWORD dwUserID = 0;
  859. while (pos != NULL)
  860. {
  861. pMatch->m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pUserItem);
  862. if (pUserItem->IsClientReady())
  863. m_pIGameServiceFrame->SendData(pUserItem, MDM_GR_USER, SUB_GR_USER_STATUS, &UserStatus, sizeof(UserStatus));
  864. }
  865. return true;
  866. }
  867. //发送游戏消息
  868. bool CImmediateMatch::SendGameMessage(IServerUserItem * pIServerUserItem, LPCTSTR lpszMessage, WORD wMessageType)
  869. {
  870. ASSERT(pIServerUserItem != -NULL);
  871. if (pIServerUserItem == NULL) return false;
  872. //发送数据
  873. if ((pIServerUserItem->GetBindIndex() != INVALID_WORD) && (pIServerUserItem->IsClientReady() == true) && (pIServerUserItem->IsAndroidUser() == false))
  874. {
  875. //构造数据包
  876. CMD_CM_SystemMessage Message;
  877. Message.wType = wMessageType;
  878. lstrcpyn(Message.szString, lpszMessage, CountArray(Message.szString));
  879. Message.wLength = CountStringBuffer(Message.szString);
  880. //发送数据
  881. WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR);
  882. return m_pIGameServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GF_SYSTEM_MESSAGE, &Message, wSendSize);
  883. }
  884. return true;
  885. }
  886. //发送消息
  887. bool CImmediateMatch::SendRoomMessage(IServerUserItem * pIServerUserItem, LPCTSTR lpszMessage, WORD wMessageType)
  888. {
  889. ASSERT(pIServerUserItem != -NULL);
  890. if (pIServerUserItem == NULL) return false;
  891. //发送数据
  892. if (pIServerUserItem->GetBindIndex() != INVALID_WORD && false == pIServerUserItem->IsAndroidUser())
  893. {
  894. //构造数据包
  895. CMD_CM_SystemMessage Message;
  896. Message.wType = wMessageType;
  897. lstrcpyn(Message.szString, lpszMessage, CountArray(Message.szString));
  898. Message.wLength = CountStringBuffer(Message.szString);
  899. //发送数据
  900. WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR);
  901. return m_pIGameServiceFrame->SendData(pIServerUserItem, MDM_CM_SYSTEM, SUB_CM_SYSTEM_MESSAGE, &Message, wSendSize);
  902. }
  903. return true;
  904. }
  905. //发送数据到一组用户
  906. bool CImmediateMatch::SendGroupData(WORD wMainCmdID, WORD wSubCmdID, void * pData, WORD wDataSize, CImmediateGroup *pMatch)
  907. {
  908. POSITION pos = pMatch->m_OnMatchUserMap.GetStartPosition();
  909. IServerUserItem *pUserItem = NULL;
  910. DWORD dwUserID = 0;
  911. while (pos != NULL)
  912. {
  913. pMatch->m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pUserItem);
  914. m_pIGameServiceFrame->SendData(pUserItem, wMainCmdID, wSubCmdID, pData, wDataSize);
  915. }
  916. return true;
  917. }
  918. //发送数据
  919. bool CImmediateMatch::SendData(IServerUserItem * pIServerUserItem, WORD wMainCmdID, WORD wSubCmdID, VOID * pData, WORD wDataSize)
  920. {
  921. if (pIServerUserItem != NULL)
  922. return m_pIGameServiceFrame->SendData(pIServerUserItem, wMainCmdID, wSubCmdID, pData, wDataSize);
  923. else
  924. return m_pIGameServiceFrame->SendData(BG_ALL_CLIENT, wMainCmdID, wSubCmdID, pData, wDataSize);
  925. return true;
  926. }
  927. //为首轮插入空桌子
  928. void CImmediateMatch::InsertNullTable()
  929. {
  930. for (int i = 0; i<m_pGameServiceOption->wTableCount; i++)
  931. {
  932. //超过就退出
  933. WORD nCurTableCount = (WORD)m_pCurMatchGroup->m_MatchTableArray.GetCount();
  934. if (nCurTableCount >= m_pMatchOption->MatchType.Immediate.wStartUserCount / m_pGameServiceAttrib->wChairCount)break;
  935. BOOL bIsInsert = true;
  936. for (int j = 0; j<m_MatchGroup.GetCount(); j++)
  937. {
  938. WORD wMatchGroupTableCount = (WORD)m_MatchGroup[j]->m_MatchTableArray.GetCount();
  939. for (int k = 0; k<wMatchGroupTableCount; k++)
  940. {
  941. WORD wTableID = m_MatchGroup[j]->m_MatchTableArray[k]->wTableID;
  942. if (i == wTableID){ bIsInsert = false; break; }//其他组已经分配了该桌
  943. }
  944. }
  945. //插入桌子
  946. if (bIsInsert&&m_ppITableFrame[i]->GetNullChairCount() == m_pGameServiceAttrib->wChairCount)
  947. {
  948. tagTableFrameInfo * pTableFrameInfo = new tagTableFrameInfo;
  949. ZeroMemory(pTableFrameInfo, sizeof(tagTableFrameInfo));
  950. pTableFrameInfo->wTableID = i;
  951. pTableFrameInfo->pTableFrame = m_ppITableFrame[i];
  952. pTableFrameInfo->dwBaseScore = m_pMatchOption->MatchType.Immediate.dwInitalBase;
  953. ITableFrameHook * pFrameHook = QUERY_OBJECT_PTR_INTERFACE(m_ppITableFrame[i]->GetTableFrameHook(), ITableFrameHook);
  954. pFrameHook->SetMatchEventSink(QUERY_OBJECT_PTR_INTERFACE(m_pCurMatchGroup, IUnknownEx));
  955. m_pCurMatchGroup->AddMatchTable(pTableFrameInfo);
  956. }
  957. }
  958. }
  959. //获取一个空闲的机器人
  960. IAndroidUserItem * CImmediateMatch::GetFreeAndroidUserItem()
  961. {
  962. if (m_pAndroidUserManager->GetAndroidCount() == 0) return NULL;
  963. //机器状态
  964. tagAndroidUserInfo AndroidSimulate;
  965. m_pAndroidUserManager->GetAndroidUserInfo(AndroidSimulate, ANDROID_SIMULATE | ANDROID_PASSIVITY | ANDROID_INITIATIVE);
  966. if (AndroidSimulate.wFreeUserCount == 0)
  967. return NULL;
  968. else
  969. {
  970. //避免已报名的机器人重复安排
  971. for (WORD i = 0; i<AndroidSimulate.wFreeUserCount; i++)
  972. {
  973. if (AndroidSimulate.pIAndroidUserFree[i]->GetMeUserItem()->GetSignUpStatus() == MatchStatus_Null)
  974. {
  975. ASSERT(AndroidSimulate.pIAndroidUserFree[i]->GetUserID() == AndroidSimulate.pIAndroidUserFree[i]->GetMeUserItem()->GetUserID());
  976. return AndroidSimulate.pIAndroidUserFree[i];
  977. }
  978. }
  979. }
  980. return NULL;
  981. }
  982. //用户淘汰
  983. bool CImmediateMatch::OnUserOut(IServerUserItem *pUserItem, LPCTSTR szReason, WORD wLen, WORD wRank, CImmediateGroup *pMatch)
  984. {
  985. if (pUserItem == NULL)
  986. return false;
  987. pUserItem->SetSignUpStatus(MatchStatus_Null);
  988. //清除比赛后的一些用户
  989. for (INT_PTR i = 0; i<pMatch->m_FreeUserArray.GetCount(); i++)
  990. {
  991. if (pMatch->m_FreeUserArray[i]->GetUserID() == pUserItem->GetUserID())
  992. {
  993. pMatch->m_FreeUserArray.RemoveAt(i);
  994. break;
  995. }
  996. }
  997. if (wLen>0 && szReason != NULL)
  998. {
  999. CString str(szReason, wLen);
  1000. SendGameMessage(pUserItem, str, SMT_EJECT | SMT_CHAT | SMT_CLOSE_GAME);
  1001. }
  1002. //移除参赛用户
  1003. RemoveMatchUserItem(pUserItem);
  1004. BYTE cbMatchStatus = MatchStatus_Null;
  1005. m_pIGameServiceFrame->SendData(pUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbMatchStatus, sizeof(cbMatchStatus));
  1006. if (pMatch == m_pCurMatchGroup)
  1007. {
  1008. if (pUserItem != NULL && !pUserItem->IsAndroidUser())
  1009. {
  1010. if (m_pMatchOption->lMatchFee>0)
  1011. {
  1012. //变量定义
  1013. DBR_GR_MatchSignup MatchSignup;
  1014. ZeroMemory(&MatchSignup, sizeof(MatchSignup));
  1015. //构造结构
  1016. MatchSignup.dwUserID = pUserItem->GetUserID();
  1017. MatchSignup.lMatchFee = m_pMatchOption->lMatchFee;
  1018. MatchSignup.dwInoutIndex = pUserItem->GetInoutIndex();
  1019. MatchSignup.dwClientAddr = pUserItem->GetClientAddr();
  1020. MatchSignup.dwMatchID = m_pMatchOption->dwMatchID;
  1021. MatchSignup.dwMatchNO = m_pCurMatchGroup->m_dwMatchNO;
  1022. lstrcpyn(MatchSignup.szMachineID, pUserItem->GetMachineID(), CountArray(MatchSignup.szMachineID));
  1023. //投递数据
  1024. m_pIDataBaseEngine->PostDataBaseRequest(MatchSignup.dwUserID, DBR_GR_MATCH_UNSIGNUP, 0, &MatchSignup, sizeof(MatchSignup));
  1025. //发送消息
  1026. LPCTSTR pszMatchFeeType[] = { TEXT("游戏币"), TEXT("元宝") };
  1027. if (m_pMatchOption->cbMatchFeeType<CountArray(pszMatchFeeType))
  1028. {
  1029. //构造消息
  1030. TCHAR szMessage[128] = TEXT("");
  1031. _sntprintf(szMessage, CountArray(szMessage), TEXT("该房间即将关闭,请到其他房间报名参赛。退还报名费 %I64d %s。"), m_pMatchOption->lMatchFee, pszMatchFeeType[m_pMatchOption->cbMatchFeeType]);
  1032. //发送消息
  1033. m_pIGameServiceFrame->SendRoomMessage(pUserItem, szMessage, SMT_EJECT | SMT_CHAT | SMT_CLOSE_ROOM);
  1034. }
  1035. }
  1036. }
  1037. CServerRule::SetForfendRoomEnter(static_cast<DWORD>(m_pGameServiceOption->dwServerRule), true);
  1038. }
  1039. else if (m_pIDataBaseEngine != NULL)
  1040. {
  1041. /*DBR_GR_MatchReward MatchReward;
  1042. ZeroMemory(&MatchReward,sizeof(MatchReward));
  1043. MatchReward.dwMatchID=m_pMatchOption->dwMatchID;
  1044. MatchReward.dwUserID=pUserItem->GetUserID();
  1045. MatchReward.dwMatchNO=pMatch->m_dwMatchNO;
  1046. MatchReward.wRank=wRank;
  1047. MatchReward.lMatchScore=pUserItem->GetUserScore();
  1048. MatchReward.dwClientAddr=pUserItem->GetClientAddr();
  1049. m_pIDataBaseEngine->PostDataBaseRequest(MatchReward.dwUserID,DBR_GR_MATCH_REWARD, 0, &MatchReward, sizeof(MatchReward));*/
  1050. }
  1051. return true;
  1052. }
  1053. //写入奖励
  1054. bool CImmediateMatch::WriteUserAward(IServerUserItem *pIServerUserItem, tagMatchRankInfo * pMatchRankInfo)
  1055. {
  1056. //参数效验
  1057. ASSERT(pIServerUserItem != NULL && pMatchRankInfo != NULL);
  1058. if (pIServerUserItem == NULL || pMatchRankInfo == NULL) return false;
  1059. //写入判断
  1060. bool bWriteReward = (pMatchRankInfo->lRewardGold + pMatchRankInfo->dwRewardIngot + pMatchRankInfo->dwRewardExperience)>0;
  1061. //写入奖励
  1062. if (bWriteReward == true)
  1063. {
  1064. //变量定义
  1065. CMD_GR_MatchResult MatchResult;
  1066. ZeroMemory(&MatchResult, sizeof(MatchResult));
  1067. //比赛奖励
  1068. MatchResult.lGold += pMatchRankInfo->lRewardGold;
  1069. MatchResult.dwIngot += pMatchRankInfo->dwRewardIngot;
  1070. MatchResult.dwExperience += pMatchRankInfo->dwRewardExperience;
  1071. //获奖提示
  1072. _sntprintf(MatchResult.szDescribe, CountArray(MatchResult.szDescribe), TEXT("%s, 恭喜您在%s中获得第%d名,奖励如下:"),
  1073. pIServerUserItem->GetNickName(), m_pMatchOption->szMatchName, pMatchRankInfo->wRankID);
  1074. //更新用户信息
  1075. tagUserInfo * pUserInfo = pIServerUserItem->GetUserInfo();
  1076. //pUserInfo->lIngot = 0;//+= pMatchRankInfo->dwRewardIngot;
  1077. pUserInfo->dwExperience += pMatchRankInfo->dwRewardExperience;
  1078. SendGroupUserScore(pIServerUserItem, NULL);
  1079. //发送数据
  1080. if (pIServerUserItem->IsAndroidUser() == false)
  1081. {
  1082. m_pIGameServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GR_MATCH_RESULT, &MatchResult, sizeof(MatchResult));
  1083. }
  1084. }
  1085. else
  1086. {
  1087. TCHAR szMessage[256] = TEXT("");
  1088. _sntprintf(szMessage, CountArray(szMessage), TEXT("比赛已结束,恭喜您获得第%d名,欢迎您参加其他场次的比赛!"), pMatchRankInfo->wRankID);
  1089. SendGameMessage(pIServerUserItem, szMessage, SMT_CLOSE_GAME);
  1090. SendRoomMessage(pIServerUserItem, szMessage, SMT_CHAT | SMT_EJECT);
  1091. return true;
  1092. }
  1093. //写入记录
  1094. if (m_pIDataBaseEngine != NULL)
  1095. {
  1096. //变量定义
  1097. DBR_GR_MatchReward MatchReward;
  1098. ZeroMemory(&MatchReward, sizeof(MatchReward));
  1099. //构造结构
  1100. MatchReward.dwUserID = pIServerUserItem->GetUserID();
  1101. MatchReward.lRewardGold = pMatchRankInfo->lRewardGold;
  1102. MatchReward.dwRewardIngot = pMatchRankInfo->dwRewardIngot;
  1103. MatchReward.dwRewardExperience = pMatchRankInfo->dwRewardExperience;
  1104. MatchReward.dwClientAddr = pIServerUserItem->GetClientAddr();
  1105. //投递数据
  1106. m_pIDataBaseEngine->PostDataBaseRequest(MatchReward.dwUserID, DBR_GR_MATCH_REWARD, 0, &MatchReward, sizeof(MatchReward));
  1107. }
  1108. return true;
  1109. }
  1110. //获取空桌子
  1111. WORD CImmediateMatch::GetNullTable()
  1112. {
  1113. WORD wTableCount = 0;
  1114. for (int i = 0; i<m_pGameServiceOption->wTableCount; i++)
  1115. {
  1116. BOOL bIsInsert = true;
  1117. for (int j = 0; j<m_MatchGroup.GetCount(); j++)
  1118. {
  1119. WORD wMatchGroupTableCount = (WORD)m_MatchGroup[j]->m_MatchTableArray.GetCount();
  1120. for (int k = 0; k<wMatchGroupTableCount; k++)
  1121. {
  1122. WORD wTableID = m_MatchGroup[j]->m_MatchTableArray[k]->wTableID;
  1123. if (i == wTableID){ bIsInsert = false; break; }//其他组已经分配了该桌
  1124. }
  1125. }
  1126. //插入桌子
  1127. if (bIsInsert&&m_ppITableFrame[i]->GetNullChairCount() == m_pGameServiceAttrib->wChairCount)
  1128. {
  1129. wTableCount++;
  1130. }
  1131. }
  1132. return wTableCount;
  1133. }
  1134. //删除用户
  1135. bool CImmediateMatch::DeleteUserItem(DWORD dwUserIndex)
  1136. {
  1137. try
  1138. {
  1139. if (m_pITCPNetworkEngineEvent == NULL)
  1140. {
  1141. throw 0;
  1142. }
  1143. m_pITCPNetworkEngineEvent->OnEventTCPNetworkShut(dwUserIndex, 0, 0L);
  1144. }
  1145. catch (...)
  1146. {
  1147. //错误断言
  1148. ASSERT(FALSE);
  1149. return false;
  1150. }
  1151. return true;
  1152. }
  1153. //移除参赛用户
  1154. bool CImmediateMatch::RemoveMatchUserItem(IServerUserItem *pIServerUserItem)
  1155. {
  1156. for (INT_PTR i = 0; i<m_OnMatchUserItem.GetCount(); i++)
  1157. {
  1158. //获取用户
  1159. IServerUserItem * pOnLineUserItem = m_OnMatchUserItem[i];
  1160. //用户判断
  1161. if (pOnLineUserItem == pIServerUserItem)
  1162. {
  1163. ASSERT(pOnLineUserItem->GetUserID() == pIServerUserItem->GetUserID());
  1164. m_OnMatchUserItem.RemoveAt(i);
  1165. return true;
  1166. }
  1167. }
  1168. return false;
  1169. }
  1170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////