诸暨麻将添加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.
 
 
 
 
 
 

5472 lines
167 KiB

  1. #include "StdAfx.h"
  2. #include "TableFrame.h"
  3. #include "DataBasePacket.h"
  4. #include "AttemperEngineSink.h"
  5. #include "..\..\..\Games\Normal\松滋晃晃血流\消息定义\CMD_Sparrow.h"
  6. #include "BaiDuMap.h"
  7. #include "../../MessageDef/Pb_UserInfo.pb.h"
  8. #include "../../MessageDef/Pb_GameInfo.pb.h"
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. //////////////////////////////////////////////////////////////////////////////////
  15. //断线定义
  16. #define IDI_OFF_LINE (TIME_TABLE_SINK_RANGE+1) //断线标识
  17. #define MAX_OFF_LINE 3 //断线次数
  18. #define TIME_OFF_LINE 60000L //断线时间
  19. #define TIME_CREATE_OUT 60000 * 30L //15分钟后检测牌桌状态
  20. #define TIME_OFF_STARTED 60000 * 120 //2个小时后检测牌桌状态
  21. //开始超时
  22. #define IDI_START_OVERTIME (TIME_TABLE_SINK_RANGE+2) //开始超时
  23. #define IDI_START_OVERTIME_END (TIME_TABLE_SINK_RANGE+22) //开始超时
  24. #define IDI_START_DISMISS_PRIVATE (TIME_TABLE_SINK_RANGE+50) //解散桌子消息
  25. #define IDI_START_TIME (TIME_TABLE_SINK_RANGE+150) //牌桌开始计时
  26. #define IDI_STARTED_TIME (TIME_TABLE_SINK_RANGE+161) //牌桌开始计时,开始后的计时
  27. #define IDI_TABLE_TIME 200 //牌桌模块计时
  28. #ifndef _DEBUG
  29. #define TIME_OVERTIME 15000L
  30. #define TIME_DISMISS_PRIVATE 2 * 60 * 1000L //超时时间 1分钟
  31. #else
  32. #define TIME_OVERTIME 15000L
  33. #define TIME_DISMISS_PRIVATE 60000 * 2L //超时时间 1分钟
  34. #endif
  35. //////////////////////////////////////////////////////////////////////////////////
  36. //游戏记录
  37. CGameScoreRecordArray CTableFrame::m_GameScoreRecordBuffer;
  38. //////////////////////////////////////////////////////////////////////////////////
  39. //构造函数
  40. CTableFrame::CTableFrame()
  41. {
  42. w_SendChairID = 65535;
  43. //固有属性
  44. m_wTableID = 0;
  45. m_wChairCount = 0;
  46. m_cbStartMode = START_MODE_ALL_READY;
  47. m_wUserCount = 0;
  48. m_wStartCount = 0;
  49. m_bJieSan = false;
  50. //标志变量
  51. m_iLastDismissVoteTime = 0;
  52. m_bDismissVoteStarted = false;
  53. m_bGameStarted = false;
  54. m_bDrawStarted = false;
  55. m_bTableStarted = false;
  56. m_bTableInitFinish = false;
  57. ZeroMemory(&m_bAllowLookon, sizeof(m_bAllowLookon));
  58. ZeroMemory(&m_lFrozenedScore, sizeof(m_lFrozenedScore));
  59. ZeroMemory(&m_jgrUserLockData, sizeof(m_jgrUserLockData));
  60. ZeroMemory(m_GameRead, sizeof(bool) * MAX_CHAIR);
  61. //游戏变量
  62. m_lCellScore = 0L;
  63. m_cbGameStatus = GAME_STATUS_FREE;
  64. m_wDrawCount = 0;
  65. //时间变量
  66. m_dwDrawStartTime = 0L;
  67. ZeroMemory(&m_SystemTimeStart, sizeof(m_SystemTimeStart));
  68. //回放记录
  69. m_ReplayRecordData = NULL;
  70. m_ReplayRecordDataSize = 0;
  71. //动态属性
  72. m_dwTableOwnerID = 0L;
  73. m_wPrivateTableOwnerID = 0L;
  74. ZeroMemory(m_szEnterPassword, sizeof(m_szEnterPassword));
  75. //断线变量
  76. ZeroMemory(m_wOffLineCount, sizeof(m_wOffLineCount));
  77. ZeroMemory(m_dwOffLineTime, sizeof(m_dwOffLineTime));
  78. //配置信息
  79. m_pGameParameter = NULL;
  80. m_pGameServiceAttrib = NULL;
  81. m_pGameServiceOption = NULL;
  82. ZeroMemory(&mGameConfig, sizeof(mGameConfig));
  83. //组件接口
  84. m_pITimerEngine = NULL;
  85. m_pITableFrameSink = NULL;
  86. m_pIMainServiceFrame = NULL;
  87. m_pIAndroidUserManager = NULL;
  88. //扩张接口
  89. m_pITableUserAction = NULL;
  90. m_pITableUserRequest = NULL;
  91. m_pIMatchTableAction = NULL;
  92. //数据接口
  93. m_pIKernelDataBaseEngine = NULL;
  94. m_pIRecordDataBaseEngine = NULL;
  95. //比赛接口
  96. m_pITableFrameHook = NULL;
  97. //用户数组
  98. ZeroMemory(m_TableUserItemArray, sizeof(m_TableUserItemArray));
  99. m_wPrivateTablParentNodeID = 0;
  100. m_dwClubID = 0;
  101. m_wTableKind = 0;
  102. wXianZhi = 0;
  103. ZeroMemory(m_GameShuffleRead, sizeof(bool) * MAX_CHAIR);
  104. return;
  105. }
  106. //析构函数
  107. CTableFrame::~CTableFrame()
  108. {
  109. //释放对象
  110. SafeRelease(m_pITableFrameSink);
  111. SafeRelease(m_pITableFrameHook);
  112. return;
  113. }
  114. //接口查询
  115. VOID * CTableFrame::QueryInterface(REFGUID Guid, DWORD dwQueryVer)
  116. {
  117. QUERYINTERFACE(ITableFrame, Guid, dwQueryVer);
  118. QUERYINTERFACE(ICompilationSink, Guid, dwQueryVer);
  119. QUERYINTERFACE_IUNKNOWNEX(ITableFrame, Guid, dwQueryVer);
  120. return NULL;
  121. }
  122. USHORT CTableFrame::GetNeedPayCxz()
  123. {
  124. USHORT uRet = 0;
  125. CString juShuCfg;
  126. CString payCoinCfg;
  127. juShuCfg = m_pGameParameter->msParameter[2].juShuCfg;
  128. payCoinCfg = m_pGameParameter->msParameter[2].payCoinCfg;
  129. CList<int> list1;
  130. CList<int> list2;
  131. int pos = juShuCfg.Find(_T('#'));
  132. int i = 0;
  133. while (pos != -1)
  134. {
  135. CString field = juShuCfg.Left(pos);
  136. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  137. list1.AddTail(iRet);
  138. juShuCfg.ReleaseBuffer();
  139. i++;
  140. juShuCfg = juShuCfg.Right(juShuCfg.GetLength() - pos - 1);
  141. pos = juShuCfg.Find(_T('#'));
  142. }
  143. if (juShuCfg.GetLength() > 0)
  144. {
  145. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  146. list1.AddTail(iRet);
  147. juShuCfg.ReleaseBuffer();
  148. }
  149. pos = payCoinCfg.Find(_T('#'));
  150. i = 0;
  151. while (pos != -1)
  152. {
  153. CString field = payCoinCfg.Left(pos);
  154. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  155. list2.AddTail(iRet);
  156. payCoinCfg.ReleaseBuffer();
  157. i++;
  158. payCoinCfg = payCoinCfg.Right(payCoinCfg.GetLength() - pos - 1);
  159. pos = payCoinCfg.Find(_T('#'));
  160. }
  161. if (payCoinCfg.GetLength() > 0)
  162. {
  163. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  164. list2.AddTail(iRet);
  165. payCoinCfg.ReleaseBuffer();
  166. }
  167. bool bFind = false;
  168. int iNum = 0;
  169. int iCount = list1.GetCount();
  170. for (int var = 0; var < iCount; var++)
  171. {
  172. int iRet = list1.GetAt(list1.FindIndex(var));
  173. if (iRet == mGameConfig.wPlayCountRule)
  174. {
  175. bFind = true;
  176. iNum = var;
  177. break;
  178. }
  179. }
  180. if (!bFind)
  181. {
  182. return 0XFF;
  183. }
  184. if (NULL == list2.FindIndex(iNum))
  185. {
  186. return 0XFF;
  187. }
  188. int iBao = list2.GetAt(list2.FindIndex(iNum));
  189. return iBao;
  190. }
  191. //此局总共需要多少元宝
  192. USHORT CTableFrame::GetNeedPay()
  193. {
  194. USHORT uRet = 0;
  195. CString juShuCfg;
  196. CString payCoinCfg;
  197. juShuCfg = m_pGameParameter->msParameter[0].juShuCfg;
  198. payCoinCfg = m_pGameParameter->msParameter[0].payCoinCfg;
  199. CList<int> list1;
  200. CList<int> list2;
  201. int pos = juShuCfg.Find(_T('#'));
  202. int i = 0;
  203. while (pos != -1)
  204. {
  205. CString field = juShuCfg.Left(pos);
  206. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  207. list1.AddTail(iRet);
  208. juShuCfg.ReleaseBuffer();
  209. i++;
  210. juShuCfg = juShuCfg.Right(juShuCfg.GetLength() - pos - 1);
  211. pos = juShuCfg.Find(_T('#'));
  212. }
  213. if (juShuCfg.GetLength() > 0)
  214. {
  215. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  216. list1.AddTail(iRet);
  217. juShuCfg.ReleaseBuffer();
  218. }
  219. pos = payCoinCfg.Find(_T('#'));
  220. i = 0;
  221. while (pos != -1)
  222. {
  223. CString field = payCoinCfg.Left(pos);
  224. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  225. list2.AddTail(iRet);
  226. payCoinCfg.ReleaseBuffer();
  227. i++;
  228. payCoinCfg = payCoinCfg.Right(payCoinCfg.GetLength() - pos - 1);
  229. pos = payCoinCfg.Find(_T('#'));
  230. }
  231. if (payCoinCfg.GetLength() > 0)
  232. {
  233. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  234. list2.AddTail(iRet);
  235. payCoinCfg.ReleaseBuffer();
  236. }
  237. bool bFind = false;
  238. int iNum = 0;
  239. int iCount = list1.GetCount();
  240. for (int var = 0; var < iCount; var++)
  241. {
  242. int iRet = list1.GetAt(list1.FindIndex(var));
  243. if (iRet == mGameConfig.wPlayCountRule)
  244. {
  245. bFind = true;
  246. iNum = var;
  247. break;
  248. }
  249. }
  250. if (!bFind)
  251. {
  252. return 0XFF;
  253. }
  254. if (NULL == list2.FindIndex(iNum))
  255. {
  256. return 0XFF;
  257. }
  258. int iBao = list2.GetAt(list2.FindIndex(iNum));
  259. return iBao;
  260. }
  261. //此局总共需要多少元宝
  262. USHORT CTableFrame::GetNeedPayZhiPai()
  263. {
  264. USHORT uRet = 0;
  265. CString juShuCfg;
  266. CString payCoinCfg;
  267. juShuCfg = m_pGameParameter->msParameter[3].juShuCfg;
  268. payCoinCfg = m_pGameParameter->msParameter[3].payCoinCfg;
  269. CList<int> list1;
  270. CList<int> list2;
  271. int pos = juShuCfg.Find(_T('#'));
  272. int i = 0;
  273. while (pos != -1)
  274. {
  275. CString field = juShuCfg.Left(pos);
  276. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  277. list1.AddTail(iRet);
  278. juShuCfg.ReleaseBuffer();
  279. i++;
  280. juShuCfg = juShuCfg.Right(juShuCfg.GetLength() - pos - 1);
  281. pos = juShuCfg.Find(_T('#'));
  282. }
  283. if (juShuCfg.GetLength() > 0)
  284. {
  285. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  286. list1.AddTail(iRet);
  287. juShuCfg.ReleaseBuffer();
  288. }
  289. pos = payCoinCfg.Find(_T('#'));
  290. i = 0;
  291. while (pos != -1)
  292. {
  293. CString field = payCoinCfg.Left(pos);
  294. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  295. list2.AddTail(iRet);
  296. payCoinCfg.ReleaseBuffer();
  297. i++;
  298. payCoinCfg = payCoinCfg.Right(payCoinCfg.GetLength() - pos - 1);
  299. pos = payCoinCfg.Find(_T('#'));
  300. }
  301. if (payCoinCfg.GetLength() > 0)
  302. {
  303. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  304. list2.AddTail(iRet);
  305. payCoinCfg.ReleaseBuffer();
  306. }
  307. bool bFind = false;
  308. int iNum = 0;
  309. int iCount = list1.GetCount();
  310. for (int var = 0; var < iCount; var++)
  311. {
  312. int iRet = list1.GetAt(list1.FindIndex(var));
  313. if (iRet == mGameConfig.wPlayCountRule)
  314. {
  315. bFind = true;
  316. iNum = var;
  317. break;
  318. }
  319. }
  320. if (!bFind)
  321. {
  322. return 0XFF;
  323. }
  324. if (NULL == list2.FindIndex(iNum))
  325. {
  326. return 0XFF;
  327. }
  328. int iBao = list2.GetAt(list2.FindIndex(iNum));
  329. return iBao;
  330. }
  331. //此局总共需要多少元宝
  332. USHORT CTableFrame::GetNeedPayEx()
  333. {
  334. USHORT uRet = 0;
  335. CString juShuCfg;
  336. CString payCoinCfg;
  337. juShuCfg = m_pGameParameter->msParameter[1].juShuCfg;
  338. payCoinCfg = m_pGameParameter->msParameter[1].payCoinCfg;
  339. CList<int> list1;
  340. CList<int> list2;
  341. int pos = juShuCfg.Find(_T('#'));
  342. int i = 0;
  343. while (pos != -1)
  344. {
  345. CString field = juShuCfg.Left(pos);
  346. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  347. list1.AddTail(iRet);
  348. juShuCfg.ReleaseBuffer();
  349. i++;
  350. juShuCfg = juShuCfg.Right(juShuCfg.GetLength() - pos - 1);
  351. pos = juShuCfg.Find(_T('#'));
  352. }
  353. if (juShuCfg.GetLength() > 0)
  354. {
  355. int iRet = _wtoi(juShuCfg.GetBuffer(0));
  356. list1.AddTail(iRet);
  357. juShuCfg.ReleaseBuffer();
  358. }
  359. pos = payCoinCfg.Find(_T('#'));
  360. i = 0;
  361. while (pos != -1)
  362. {
  363. CString field = payCoinCfg.Left(pos);
  364. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  365. list2.AddTail(iRet);
  366. payCoinCfg.ReleaseBuffer();
  367. i++;
  368. payCoinCfg = payCoinCfg.Right(payCoinCfg.GetLength() - pos - 1);
  369. pos = payCoinCfg.Find(_T('#'));
  370. }
  371. if (payCoinCfg.GetLength() > 0)
  372. {
  373. int iRet = _wtoi(payCoinCfg.GetBuffer(0));
  374. list2.AddTail(iRet);
  375. payCoinCfg.ReleaseBuffer();
  376. }
  377. bool bFind = false;
  378. int iNum = 0;
  379. int iCount = list1.GetCount();
  380. for (int var = 0; var < iCount; var++)
  381. {
  382. int iRet = list1.GetAt(list1.FindIndex(var));
  383. if (iRet == mGameConfig.wPlayCountRule)
  384. {
  385. bFind = true;
  386. iNum = var;
  387. break;
  388. }
  389. }
  390. if (!bFind)
  391. {
  392. return 0XFF;
  393. }
  394. if (NULL == list2.FindIndex(iNum))
  395. {
  396. return 0XFF;
  397. }
  398. int iBao = list2.GetAt(list2.FindIndex(iNum));
  399. return iBao;
  400. }
  401. //开始游戏
  402. bool CTableFrame::StartGame()
  403. {
  404. //游戏状态
  405. ASSERT(m_bDrawStarted == false);
  406. if (m_bDrawStarted == true) return false;
  407. //保存变量
  408. bool bGameStarted = m_bGameStarted;
  409. bool bTableStarted = m_bTableStarted;
  410. //设置状态
  411. m_bGameStarted = true;
  412. m_bDrawStarted = true;
  413. m_bTableStarted = true;
  414. //自增游戏开始次数
  415. m_wStartCount++;
  416. KillGameTimer(IDI_START_TIME);//关闭创建超时定时器。
  417. //开始时间
  418. GetLocalTime(&m_SystemTimeStart);
  419. m_dwDrawStartTime = (DWORD)time(NULL);
  420. /*if (nullptr !=m_ReplayRecordData)
  421. {
  422. delete [] m_ReplayRecordData;
  423. m_ReplayRecordData = nullptr;
  424. }*/
  425. if (!m_sPrivateTableID.empty() && 1 == m_wStartCount)
  426. {
  427. SetGameTimer(IDI_STARTED_TIME, TIME_OFF_STARTED, 1, 0);
  428. //私有房间,需要记录一个总数据
  429. tagScoreInfo* ScoreInfoArray = new tagScoreInfo[m_wChairCount];
  430. ZeroMemory(ScoreInfoArray, sizeof(tagScoreInfo)*m_wChairCount);
  431. //初始时生成一个父节点房间记录。
  432. for (int i = 0; i < m_wChairCount; ++i)
  433. ScoreInfoArray[i].cbType = SCORE_TYPE_START;
  434. WriteTableScore(ScoreInfoArray, m_wChairCount);
  435. RecordGameScore(m_bDrawStarted);
  436. if (ScoreInfoArray != NULL)
  437. {
  438. //内存泄露
  439. delete[] ScoreInfoArray;
  440. ScoreInfoArray = NULL;
  441. }
  442. }
  443. //开始设置
  444. if (bGameStarted == false)
  445. {
  446. //状态变量
  447. ZeroMemory(m_wOffLineCount, sizeof(m_wOffLineCount));
  448. ZeroMemory(m_dwOffLineTime, sizeof(m_dwOffLineTime));
  449. //设置用户
  450. for (WORD i = 0; i<m_wChairCount; i++)
  451. {
  452. //获取用户
  453. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  454. //设置用户
  455. if (pIServerUserItem != NULL)
  456. {
  457. //锁定游戏币
  458. if (m_pGameServiceOption->lServiceScore>0L)
  459. {
  460. m_lFrozenedScore[i] = m_pGameServiceOption->lServiceScore;
  461. pIServerUserItem->FrozenedUserScore(m_pGameServiceOption->lServiceScore);
  462. }
  463. //设置状态
  464. BYTE cbUserStatus = pIServerUserItem->GetUserStatus();
  465. if ((cbUserStatus != US_OFFLINE) && (cbUserStatus != US_PLAYING)) pIServerUserItem->SetUserStatus(US_PLAYING, m_wTableID, i);
  466. }
  467. }
  468. //发送状态
  469. if (bTableStarted != m_bTableStarted) SendTableStatus();
  470. }
  471. //比赛通知
  472. bool bStart = true;
  473. if (m_pITableFrameHook != NULL) bStart = m_pITableFrameHook->OnEventGameStart(this, m_wChairCount);
  474. //通知事件
  475. ASSERT(m_pITableFrameSink != NULL);
  476. if (m_pITableFrameSink != NULL) m_pITableFrameSink->OnEventGameStart();
  477. //通知调度引擎
  478. CAttemperEngineSink * pAttemperEngineSink = (CAttemperEngineSink *)m_pIMainServiceFrame;
  479. pAttemperEngineSink->UpdataTableJushu(_ttol(this->GetPrivateTableID().c_str()), this->m_wStartCount);
  480. return true;
  481. }
  482. //解散游戏
  483. bool CTableFrame::DismissGame()
  484. {
  485. //状态判断
  486. /*ASSERT(m_bTableStarted == true);
  487. if (m_bTableStarted == false) return false;*/
  488. //结束游戏
  489. m_bJieSan = true;
  490. return DeletePrivateResult(2, TEXT("此房间已经被群主解散!"));
  491. }
  492. //结束游戏
  493. bool CTableFrame::ConcludeGame(BYTE cbGameStatus, bool bSendState)
  494. {
  495. CAttemperEngineSink * pAttemperEngineSink = (CAttemperEngineSink *)m_pIMainServiceFrame;
  496. //效验状态
  497. if (cbGameStatus == GAME_STATUS_DELETE)
  498. {
  499. //if (m_wTableKind == 1)
  500. //{
  501. // WriteXianLiaoTableRecord();//推送闲聊机器人数据
  502. //}
  503. //删除桌子
  504. if (m_wPrivateTablParentNodeID > 0) {
  505. RecordGameScore(true, INVALID_TABLE, true);
  506. }
  507. //变量定义
  508. WORD wEnumIndex = 0;
  509. IServerUserItem * pIServerUserItem = NULL;
  510. for (WORD i = 0; i < m_wChairCount; i++)
  511. {
  512. //IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  513. pIServerUserItem = GetTableUserItem(i);
  514. if (pIServerUserItem == NULL) continue;
  515. //添加校验
  516. if (pIServerUserItem->GetTableID() != this->GetTableID())
  517. {
  518. TCHAR szString[512] = { 0 };
  519. _sntprintf(szString, CountArray(szString), TEXT("发现异常:ConcludeGame:玩家桌子ID和桌子ID不匹配[ UserTableID=%ld,TableID= %ld, PrivateTableId= %ld ]"), pIServerUserItem->GetTableID(), this->GetTableID(), _ttol(this->GetPrivateTableID().c_str()));
  520. CTraceService::TraceString(szString, TraceLevel_Warning);
  521. continue;
  522. }
  523. PerformStandUpAction(pIServerUserItem, false, bSendState);
  524. //pAttemperEngineSink->SetUserServerID(pIServerUserItem, 0);
  525. }
  526. //旁观用户 起立动作,将其用户状态更新
  527. do
  528. {
  529. pIServerUserItem = EnumLookonUserItem(0);
  530. if (pIServerUserItem == NULL) break;
  531. //添加校验
  532. if (pIServerUserItem->GetTableID() != this->GetTableID())
  533. {
  534. TCHAR szString[512] = { 0 };
  535. _sntprintf(szString, CountArray(szString), TEXT("发现异常:ConcludeGame:玩家桌子ID和桌子ID不匹配[ UserTableID=%ld,TableID= %ld, PrivateTableId= %ld ]"), pIServerUserItem->GetTableID(), this->GetTableID(), _ttol(this->GetPrivateTableID().c_str()));
  536. CTraceService::TraceString(szString, TraceLevel_Warning);
  537. continue;
  538. }
  539. PerformStandUpAction(pIServerUserItem, false, bSendState);
  540. } while (pIServerUserItem != NULL);
  541. return true;
  542. }
  543. if (m_bGameStarted == false) return false;
  544. //保存变量
  545. bool bDrawStarted = m_bDrawStarted;
  546. //设置状态
  547. m_bDrawStarted = false;
  548. m_cbGameStatus = cbGameStatus;
  549. m_bGameStarted = (cbGameStatus >= GAME_STATUS_PLAY) ? true : false;
  550. m_wDrawCount++;
  551. ZeroMemory(m_GameRead, sizeof(bool) * MAX_CHAIR); //游戏中准备取消
  552. ZeroMemory(m_GameShuffleRead, sizeof(bool) * MAX_CHAIR);
  553. if (m_wStartCount == 1 && m_bJieSan)
  554. {
  555. //解散的方式结束
  556. }
  557. else if (m_wStartCount == 1 && !m_bJieSan)
  558. {
  559. //扣费 把锁定费用扣出
  560. bool bFind = false;
  561. for (int i = 0; i < m_wChairCount; i++)
  562. {
  563. if (m_TableUserItemArray[i] != NULL && m_TableUserItemArray[i]->GetUserID() == m_wPrivateTableOwnerID)
  564. {
  565. bFind = true;
  566. break;
  567. }
  568. }
  569. //如果是均摊扣费的情况
  570. if (mGameConfig.wMaxFanRule == 1)
  571. {
  572. if (bFind)
  573. {
  574. //房间创建人参与打牌的情况 全部扣费
  575. for (int i = 0; i < 6; i++)
  576. {
  577. this->ReduceBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  578. }
  579. for (int i = 0; i < m_wChairCount; i++)
  580. {
  581. if (m_TableUserItemArray[i] != NULL && m_TableUserItemArray[i]->GetUserID() != m_wPrivateTableOwnerID)
  582. {
  583. if (mGameConfig.wSubGameID >= 10 && mGameConfig.wSubGameID < 13)
  584. {
  585. int iNeed = 1;
  586. iNeed = GetNeedPayEx();
  587. if (iNeed == 255)
  588. {
  589. iNeed = 8;
  590. ASSERT(false);
  591. }
  592. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), iNeed / 4);
  593. }
  594. else if (mGameConfig.wSubGameID >= 14 && mGameConfig.wSubGameID < 17)
  595. {
  596. int iNeed = 1;
  597. iNeed = GetNeedPayZhiPai();
  598. if (iNeed == 255)
  599. {
  600. iNeed = 8;
  601. ASSERT(false);
  602. }
  603. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), iNeed / 3);
  604. }
  605. else if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  606. {
  607. int iNeed = 1;
  608. iNeed = GetNeedPayCxz();
  609. if (iNeed == 255)
  610. {
  611. iNeed = 6;
  612. ASSERT(false);
  613. }
  614. //戳瞎子
  615. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), iNeed / 3);
  616. }
  617. else
  618. {
  619. int iNeed = 1;
  620. iNeed = GetNeedPay();
  621. if (iNeed == 255)
  622. {
  623. iNeed = 8;
  624. ASSERT(false);
  625. }
  626. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), iNeed / 4);
  627. }
  628. }
  629. }
  630. }
  631. else
  632. {
  633. // 返还房主冻结金额 冻结在桌上玩的四人
  634. for (int i = 0; i < 6; i++)
  635. {
  636. if (m_jgrUserLockData[i].User == m_wPrivateTableOwnerID)
  637. {
  638. this->UnLockBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  639. }
  640. }
  641. for (int i = 0; i < m_wChairCount; i++)
  642. {
  643. if (m_TableUserItemArray[i] != NULL && m_TableUserItemArray[i]->GetUserID() != m_wPrivateTableOwnerID)
  644. {
  645. if (mGameConfig.wSubGameID >= 10 && mGameConfig.wSubGameID < 13)
  646. {
  647. int iNeed = 1;
  648. iNeed = GetNeedPayEx();
  649. if (iNeed == 255)
  650. {
  651. iNeed = 8;
  652. ASSERT(false);
  653. }
  654. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), iNeed / 4);
  655. }
  656. else if (mGameConfig.wSubGameID >= 14 && mGameConfig.wSubGameID < 17)
  657. {
  658. int iNeed = 1;
  659. iNeed = GetNeedPayZhiPai();
  660. if (iNeed == 255)
  661. {
  662. iNeed = 6;
  663. ASSERT(false);
  664. }
  665. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), iNeed / 3);
  666. }
  667. else if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  668. {
  669. int iNeed = 1;
  670. iNeed = GetNeedPayCxz();
  671. if (iNeed == 255)
  672. {
  673. iNeed = 6;
  674. ASSERT(false);
  675. }
  676. //戳瞎子
  677. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), (iNeed / 3));
  678. }
  679. else
  680. {
  681. int iNeed = 1;
  682. iNeed = GetNeedPay();
  683. if (iNeed == 255)
  684. {
  685. iNeed = 8;
  686. ASSERT(false);
  687. }
  688. NowReduceBeans(m_TableUserItemArray[i]->GetUserID(), iNeed / 4);
  689. }
  690. }
  691. }
  692. }
  693. }
  694. else
  695. {
  696. //房主支付
  697. for (int i = 0; i < 6; i++)
  698. {
  699. if (m_jgrUserLockData[i].User != 0)
  700. {
  701. this->ReduceBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  702. }
  703. }
  704. }
  705. //俱乐部游戏记录
  706. WriteClubTableRecord();
  707. }
  708. //游戏积分记录
  709. RecordGameScore(bDrawStarted);
  710. //结束设置
  711. if (m_bGameStarted == false)
  712. {
  713. //变量定义
  714. bool bOffLineWait = false;
  715. //设置用户
  716. for (WORD i = 0; i < m_wChairCount; i++)
  717. {
  718. //获取用户
  719. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  720. //用户处理
  721. if (pIServerUserItem != NULL)
  722. {
  723. tagTimeInfo* TimeInfo = pIServerUserItem->GetTimeInfo();
  724. //游戏时间
  725. DWORD dwCurrentTime = (DWORD)time(NULL);
  726. TimeInfo->dwEndGameTimer = dwCurrentTime;
  727. //解锁游戏币
  728. if (m_lFrozenedScore[i] != 0L)
  729. {
  730. pIServerUserItem->UnFrozenedUserScore(m_lFrozenedScore[i]);
  731. m_lFrozenedScore[i] = 0L;
  732. }
  733. //设置状态
  734. if (pIServerUserItem->GetUserStatus() == US_OFFLINE)
  735. {
  736. //断线处理
  737. /*bOffLineWait = true;
  738. if (m_pGameServiceOption->wServerType != GAME_GENRE_MATCH)
  739. {
  740. PerformStandUpAction(pIServerUserItem);
  741. }
  742. else
  743. {*/ // 修改 BY JN 如果是断线,牌局打完了,则把他的状态设置为游戏中等待。
  744. pIServerUserItem->SetClientReady(false);
  745. pIServerUserItem->SetUserStatus(US_PLAYINGWAIT, m_wTableID, i);
  746. /*}*/
  747. }
  748. else
  749. {
  750. //设置状态
  751. pIServerUserItem->SetUserStatus(US_PLAYINGWAIT, m_wTableID, i);
  752. }
  753. }
  754. }
  755. //删除时间
  756. if (bOffLineWait == true) KillGameTimer(IDI_OFF_LINE);
  757. }
  758. //通知比赛
  759. if (m_pITableFrameHook != NULL) m_pITableFrameHook->OnEventGameEnd(this, 0, NULL, cbGameStatus);
  760. //重置桌子
  761. ASSERT(m_pITableFrameSink != NULL);
  762. if (m_pITableFrameSink != NULL) m_pITableFrameSink->RepositionSink();
  763. //踢出检测
  764. if (m_bGameStarted == false)
  765. {
  766. for (WORD i = 0; i < m_wChairCount; i++)
  767. {
  768. //获取用户
  769. if (m_TableUserItemArray[i] == NULL) continue;
  770. IServerUserItem * pIServerUserItem = m_TableUserItemArray[i];
  771. //积分限制
  772. if ((m_pGameServiceOption->lMinTableScore != 0L) && (pIServerUserItem->GetUserScore() < m_pGameServiceOption->lMinTableScore))
  773. {
  774. //构造提示
  775. TCHAR szDescribe[128] = TEXT("");
  776. if (m_pGameServiceOption->wServerType&GAME_GENRE_GOLD)
  777. {
  778. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("您的游戏币少于 ") SCORE_STRING TEXT(",不能继续游戏!"), m_pGameServiceOption->lMinTableScore);
  779. }
  780. else
  781. {
  782. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("您的游戏积分少于 ") SCORE_STRING TEXT(",不能继续游戏!"), m_pGameServiceOption->lMinTableScore);
  783. }
  784. //发送消息
  785. //if (pIServerUserItem->IsAndroidUser() == true)
  786. //SendGameMessage(pIServerUserItem, szDescribe, SMT_CHAT | SMT_CLOSE_GAME | SMT_CLOSE_ROOM | SMT_EJECT);
  787. //else
  788. //SendGameMessage(pIServerUserItem, szDescribe, SMT_CHAT | SMT_CLOSE_GAME | SMT_EJECT);
  789. //用户起立
  790. PerformStandUpAction(pIServerUserItem);
  791. continue;
  792. }
  793. //关闭判断
  794. if ((CServerRule::IsForfendGameEnter(m_pGameServiceOption->dwServerRule) == true) && (pIServerUserItem->GetMasterOrder() == 0))
  795. {
  796. //发送消息
  797. LPCTSTR pszMessage = TEXT("由于系统维护,当前游戏桌子禁止用户继续游戏!");
  798. SendGameMessage(pIServerUserItem, pszMessage, SMT_TABLE_EXIT);
  799. //用户起立
  800. PerformStandUpAction(pIServerUserItem,false, true);
  801. continue;
  802. }
  803. //机器起立
  804. if (pIServerUserItem->GetUserStatus() != US_OFFLINE && (m_pGameServiceOption->wServerType&GAME_GENRE_MATCH) == 0)
  805. {
  806. //机器处理
  807. if (pIServerUserItem->IsAndroidUser() == true)
  808. {
  809. //绑定信息
  810. CAttemperEngineSink * pAttemperEngineSink = (CAttemperEngineSink *)m_pIMainServiceFrame;
  811. tagBindParameter * pBindParameter = pAttemperEngineSink->GetBindParameter(pIServerUserItem->GetBindIndex());
  812. //查找机器
  813. IAndroidUserItem * pIAndroidUserItem = m_pIAndroidUserManager->SearchAndroidUserItem(pIServerUserItem->GetUserID(), pBindParameter->dwSocketID);
  814. if (pIAndroidUserItem == NULL) continue;
  815. //离开判断
  816. if (pIAndroidUserItem->JudgeAndroidActionAndRemove(ANDROID_WAITLEAVE))
  817. {
  818. //起立处理
  819. PerformStandUpAction(pIServerUserItem);
  820. continue;
  821. }
  822. //起立判断
  823. if (pIAndroidUserItem->JudgeAndroidActionAndRemove(ANDROID_WAITSTANDUP))
  824. {
  825. //起立处理
  826. PerformStandUpAction(pIServerUserItem);
  827. continue;
  828. }
  829. }
  830. }
  831. if (m_sPrivateTableID.empty())
  832. {//公共房间开启准备超时定时器。
  833. if (IsGameStarted() == false && pIServerUserItem->IsMobileUser() && m_pGameServiceAttrib->wChairCount < MAX_CHAIR)
  834. SetGameTimer(IDI_START_OVERTIME + i, TIME_OVERTIME, 1, i);
  835. }
  836. }
  837. }
  838. //结束桌子
  839. ConcludeTable();
  840. //发送状态
  841. //SendTableStatus();
  842. return true;
  843. }
  844. //房主在未开始游戏前,请求解散牌桌
  845. bool CTableFrame::SetTableFree()
  846. {
  847. if (GetStartCount() > 0)
  848. {
  849. //SendGameMessage(SearchUserItem(m_wPrivateTableOwnerID), TEXT("游戏已经开始,无法解散!"), SMT_EJECT);
  850. return false;
  851. }
  852. //分别请桌上的用户离开
  853. for (int i = 0; i < m_wChairCount; i++)
  854. {
  855. if (m_TableUserItemArray[i] != NULL && m_TableUserItemArray[i]->GetUserID() != m_wPrivateTableOwnerID)
  856. {
  857. //发送消息
  858. SendGameMessage(m_TableUserItemArray[i], TEXT("此房间已经被房主解散了!"), SMT_TABLE_EXIT);
  859. //先请其他人离开
  860. //如果发现该玩家的桌子索引和本桌子索引不一致
  861. if (m_TableUserItemArray[i]->GetTableID() != this->GetTableID())
  862. {
  863. TCHAR szString[512] = { 0 };
  864. _sntprintf(szString, CountArray(szString), TEXT("发现异常:SetTableFree1:用户ID不匹配[ userTableID=%ld,TableID=%ld,PrivateTableID = %ld ]"), m_TableUserItemArray[i]->GetUserInfo()->wTableID, this->GetTableID(), _ttol(this->GetPrivateTableID().c_str()));
  865. CTraceService::TraceString(szString, TraceLevel_Warning);
  866. }
  867. PerformStandUpAction(m_TableUserItemArray[i], false, true);
  868. }
  869. }
  870. //分别请桌上旁观用户离开
  871. for (INT_PTR i = 0; i < m_LookonUserItemArray.GetCount(); i++)
  872. {
  873. if (m_LookonUserItemArray[i] != NULL && m_LookonUserItemArray[i]->GetUserID() != m_wPrivateTableOwnerID)
  874. {
  875. //发送消息
  876. SendGameMessage(m_LookonUserItemArray[i], TEXT("此房间已经被房主解散了!"), SMT_TABLE_EXIT);
  877. //请旁观的人离开
  878. if (m_LookonUserItemArray[i]->GetTableID() != this->GetTableID())
  879. {
  880. TCHAR szString[512] = { 0 };
  881. _sntprintf(szString, CountArray(szString), TEXT("发现异常:SetTableFree2:用户ID不匹配[ userTableID=%ld,TableID=%ld,PrivateTableID = %ld ]"), m_LookonUserItemArray[i]->GetUserInfo()->wTableID, this->GetTableID(), _ttol(this->GetPrivateTableID().c_str()));
  882. CTraceService::TraceString(szString, TraceLevel_Warning);
  883. }
  884. PerformStandUpAction(m_LookonUserItemArray[i], false, true);
  885. }
  886. }
  887. //返还房主冻结元宝
  888. UnAdminLockBeans();
  889. IServerUserItem * pIServerUserItem = SearchUserItem(m_wPrivateTableOwnerID);
  890. if (pIServerUserItem != NULL)
  891. {
  892. //请房主离开
  893. SendGameMessage(pIServerUserItem, TEXT("此房间已经解散了!"), SMT_TABLE_EXIT);
  894. if (pIServerUserItem->GetTableID() != this->GetTableID())
  895. {
  896. TCHAR szString[512] = { 0 };
  897. _sntprintf(szString, CountArray(szString), TEXT("发现异常:SetTableFree3:用户ID不匹配[ userTableID=%ld,TableID=%ld,PrivateTableID = %ld ]"), pIServerUserItem->GetUserInfo()->wTableID, this->GetTableID(), _ttol(this->GetPrivateTableID().c_str()));
  898. CTraceService::TraceString(szString, TraceLevel_Warning);
  899. }
  900. //请旁观的人离开
  901. PerformStandUpAction(pIServerUserItem, false, true);
  902. }
  903. KillGameTimer(IDI_START_TIME);
  904. //删除房间
  905. return DeletePrivateTableNow();
  906. }
  907. //++交换座位
  908. bool CTableFrame::SwapChair()
  909. {
  910. IServerUserItem * pISrcUserItem[4] = { NULL };
  911. for (int i = 0; i < 4; i++)
  912. {
  913. if (m_TableUserItemArray[i])
  914. {
  915. pISrcUserItem[i] = m_TableUserItemArray[i];
  916. }
  917. }
  918. for (int i = 0; i < 4; i++)
  919. {
  920. if (pISrcUserItem[i])
  921. {
  922. m_TableUserItemArray[pISrcUserItem[i]->GetChairID()] = pISrcUserItem[i];
  923. }
  924. }
  925. return true;
  926. }
  927. //私有桌子号码
  928. bool CTableFrame::GetPrivateTableID(TCHAR *pTableID, DWORD dLen)
  929. {
  930. int iLen = m_sPrivateTableID.length();
  931. if (dLen>iLen)
  932. {
  933. StringCchCopy(pTableID, dLen, m_sPrivateTableID.c_str());
  934. }
  935. return true;
  936. }
  937. //结束桌子
  938. bool CTableFrame::ConcludeTable()
  939. {
  940. //结束桌子
  941. if ((m_bGameStarted == false) && (m_bTableStarted == true))
  942. {
  943. //人数判断
  944. WORD wTableUserCount = GetSitUserCount();
  945. if (wTableUserCount == 0) m_bTableStarted = false;
  946. if (m_pGameServiceAttrib->wChairCount == MAX_CHAIR) m_bTableStarted = false;
  947. //模式判断
  948. if (m_cbStartMode == START_MODE_FULL_READY) m_bTableStarted = false;
  949. if (m_cbStartMode == START_MODE_PAIR_READY) m_bTableStarted = false;
  950. if (m_cbStartMode == START_MODE_ALL_READY) m_bTableStarted = false;
  951. }
  952. return true;
  953. }
  954. bool CTableFrame::DeletePrivateTableReq(IServerUserItem * pIUserItem, CMD_GR_DELETE_PRIVATE_ROOM_REQ req)
  955. {
  956. if (m_bDismissVoteStarted) return true;
  957. auto now = time(0);
  958. /*
  959. #ifdef DEBUG
  960. if (now - m_iLastDismissVoteTime < 10)
  961. #else
  962. if (now - m_iLastDismissVoteTime < 30)
  963. #endif
  964. {
  965. LPCTSTR pszMessage = TEXT("申请解散私有桌子,最少间隔30秒!请稍后再试。");
  966. SendRequestFailure(pIUserItem, pszMessage, 0);
  967. return false;
  968. }*/
  969. w_SendChairID = pIUserItem->GetChairID();
  970. m_iLastDismissVoteTime = now;
  971. m_bDismissVoteStarted = true;
  972. req.leftTime = TIME_DISMISS_PRIVATE /1000;
  973. m_AgreeDeletePriTableUsers[pIUserItem->GetUserID()] = 1;
  974. //在房间中广播 申请消息
  975. for (WORD i = 0; i < m_wChairCount; i++)
  976. {
  977. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  978. if (pIServerUserItem == NULL)
  979. continue;
  980. UserInfo::PB_CS_C_DELETE_PRIVATE_ROOM_REQ RoomReq;
  981. RoomReq.set_wtableid(req.wTableID);
  982. RoomReq.set_wchairid(req.wChairID);
  983. RoomReq.set_lefttime(req.leftTime);
  984. //发送数据
  985. std::string pbdata = RoomReq.SerializePartialAsString();
  986. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_REQ, (void*)pbdata.c_str(), pbdata.length());
  987. }
  988. WORD wEnumIndex = 0;
  989. IServerUserItem * pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  990. while (pIServerUserItem)
  991. {
  992. UserInfo::PB_CS_C_DELETE_PRIVATE_ROOM_REQ RoomReq;
  993. RoomReq.set_wtableid(req.wTableID);
  994. RoomReq.set_wchairid(req.wChairID);
  995. RoomReq.set_lefttime(req.leftTime);
  996. //发送数据
  997. std::string pbdata = RoomReq.SerializePartialAsString();
  998. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_REQ, (void*)pbdata.c_str(), pbdata.length());
  999. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  1000. }
  1001. //默认此用户同意
  1002. SetGameTimer(IDI_START_DISMISS_PRIVATE, TIME_DISMISS_PRIVATE, 1, m_wTableID);
  1003. if (m_pIMainServiceFrame->IsJC(8888))
  1004. {
  1005. //输出信息
  1006. TCHAR szBuffer[128] = TEXT("");
  1007. TCHAR szTemp[32] = { 0 };
  1008. this->GetPrivateTableID(szTemp, 32);
  1009. _sntprintf(szBuffer, CountArray(szBuffer), TEXT("定时器开启 ID [ %d ], 桌号 [ %d ], 好友房标识 [ %d ]."), IDI_START_DISMISS_PRIVATE, m_wTableID, szTemp);
  1010. //输出信息
  1011. CTraceService::TraceString(szBuffer, TraceLevel_Normal);
  1012. }
  1013. return true;
  1014. }
  1015. //设置冻结金额
  1016. bool CTableFrame::SetUserLockData(DWORD dwUserID, DWORD dwNum)
  1017. {
  1018. int iFirst = 0;
  1019. int i = 0;
  1020. for ( i = 0; i < 5; i++)
  1021. {
  1022. DWORD dwTemp = m_jgrUserLockData[i].User;
  1023. //ASSERT(dwTemp != dwUserID);
  1024. if (dwTemp == dwUserID)
  1025. {
  1026. m_jgrUserLockData[i].dwLockNum = dwNum;
  1027. m_jgrUserLockData[i].User = dwUserID;
  1028. return true;
  1029. }
  1030. if (dwTemp == 0)
  1031. {
  1032. iFirst = i;
  1033. break;
  1034. }
  1035. }
  1036. if (iFirst<=4)
  1037. {
  1038. m_jgrUserLockData[iFirst].dwLockNum = dwNum;
  1039. m_jgrUserLockData[iFirst].User = dwUserID;
  1040. return true;
  1041. }
  1042. return false;
  1043. }
  1044. //获取冻结金额
  1045. DWORD CTableFrame::GetUserLockData(DWORD dwUserID)
  1046. {
  1047. DWORD dwRet = 0;
  1048. for (int i = 0; i < 5; i++)
  1049. {
  1050. DWORD dwTemp = m_jgrUserLockData[i].User;
  1051. if (dwTemp == dwUserID)
  1052. {
  1053. dwRet = m_jgrUserLockData[i].dwLockNum;
  1054. break;
  1055. }
  1056. }
  1057. return dwRet;
  1058. }
  1059. //踢出所有玩家,并删除桌子
  1060. bool CTableFrame::DeletePrivateTableResp(IServerUserItem * pIUserItem, BYTE bAgree, bool bSendMe)
  1061. {
  1062. if (m_sPrivateTableID.empty())
  1063. return false;
  1064. if (!m_bDismissVoteStarted)
  1065. return true;
  1066. if (m_bJieSan) return true;
  1067. auto dwUserID = pIUserItem->GetUserID();
  1068. auto iter = m_AgreeDeletePriTableUsers.find(dwUserID);
  1069. if (iter!=m_AgreeDeletePriTableUsers.end())
  1070. return true;
  1071. int RealPlayerCount = 0;
  1072. if (bAgree == 1) //同意
  1073. {
  1074. m_AgreeDeletePriTableUsers[dwUserID] = 1;
  1075. }
  1076. else if (bAgree == 2) //拒绝
  1077. {
  1078. m_AgreeDeletePriTableUsers[dwUserID] = 2;
  1079. }
  1080. CMD_GR_DELETE_PRIVATE_ROOM_RESP req;
  1081. req.wTableID = m_wTableID;
  1082. req.wChairID = pIUserItem->GetChairID();
  1083. req.bAgree = bAgree;
  1084. for (WORD i = 0; i < m_wChairCount; i++)
  1085. {
  1086. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  1087. if (pIServerUserItem == NULL) continue;
  1088. RealPlayerCount++;
  1089. if (bSendMe) continue;
  1090. UserInfo::PB_CS_C_DELETE_PRIVATE_ROOM_RESP RoomResp;
  1091. RoomResp.set_wtableid(req.wTableID);
  1092. RoomResp.set_wchairid(req.wChairID);
  1093. RoomResp.set_bagree(req.bAgree);
  1094. //发送数据
  1095. std::string pbdata = RoomResp.SerializePartialAsString();
  1096. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_RESP, (void*)pbdata.c_str(), pbdata.length());
  1097. }
  1098. WORD wEnumIndex = 0;
  1099. IServerUserItem * pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  1100. while (pIServerUserItem)
  1101. {
  1102. UserInfo::PB_CS_C_DELETE_PRIVATE_ROOM_RESP RoomResp;
  1103. RoomResp.set_wtableid(req.wTableID);
  1104. RoomResp.set_wchairid(req.wChairID);
  1105. RoomResp.set_bagree(req.bAgree);
  1106. //发送数据
  1107. std::string pbdata = RoomResp.SerializePartialAsString();
  1108. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_RESP, (void*)pbdata.c_str(), pbdata.length());
  1109. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  1110. }
  1111. std::unordered_map<DWORD, int>::iterator iter_ = m_AgreeDeletePriTableUsers.begin();
  1112. int iNum = 0; int iNone = 0;
  1113. for (int i = 0; i < m_AgreeDeletePriTableUsers.size(); i++)
  1114. {
  1115. if (iter_->second == 1) iNum++; //同意解散
  1116. else if (iter_->second == 2) iNone++;//拒绝解散
  1117. iter_++;
  1118. }
  1119. //if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  1120. //{
  1121. // //戳瞎子
  1122. // if (iNone >= 1)
  1123. // {
  1124. // DeletePrivateResult(0, TEXT("有玩家反对,不能解散房间."));
  1125. // return true;
  1126. // }
  1127. // else
  1128. // {
  1129. // if (iNum == 3)
  1130. // {
  1131. // m_bJieSan = true;
  1132. // return DeletePrivateResult(1, TEXT("所有玩家同意,房间已成功解散!"));
  1133. // }
  1134. // }
  1135. //}
  1136. //else
  1137. {
  1138. //if (iNone >= 2)
  1139. if (iNone >= 1)
  1140. {
  1141. DeletePrivateResult(0, TEXT("根据少数服从多数的原则,不能解散房间."));
  1142. return true;
  1143. }
  1144. else
  1145. {
  1146. //if (iNum > m_wChairCount - 2)
  1147. if (iNum > m_wChairCount - 1)
  1148. {
  1149. m_bJieSan = true;
  1150. return DeletePrivateResult(1, TEXT("根据少数服从多数的原则,房间已成功解散!"));
  1151. }
  1152. if (iNum == RealPlayerCount)
  1153. {
  1154. m_bJieSan = true;
  1155. return DeletePrivateResult(1, TEXT("全部玩家同意解散,房间已成功解散!"));
  1156. }
  1157. }
  1158. }
  1159. return true;
  1160. }
  1161. bool CTableFrame::DeletePrivateTableNow()
  1162. {
  1163. if (m_sPrivateTableID.empty())
  1164. return false;
  1165. KillGameTimer(IDI_STARTED_TIME);
  1166. return m_pIMainServiceFrame->DeletePrivateTable(this);
  1167. }
  1168. bool CTableFrame::DeletePrivateResult(USHORT uState, LPCTSTR szDescription)
  1169. {
  1170. CMD_GR_DELETE_PRIVATE_ROOM_RESULT result;
  1171. result.bState = uState;
  1172. lstrcpy(result.szDescription, szDescription);
  1173. for (WORD i = 0; i < m_wChairCount; i++)
  1174. {
  1175. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  1176. if (pIServerUserItem == NULL) continue;
  1177. UserInfo::PB_CS_S_DELETE_PRIVATE_ROOM_RESULT RoomResult;
  1178. RoomResult.set_wtableid(result.wTableID);
  1179. RoomResult.set_bstate(result.bState);
  1180. std::string szDescription = CW2AEX<1024>(result.szDescription, CP_UTF8).m_psz;
  1181. RoomResult.set_szdescription(szDescription);
  1182. //发送数据
  1183. std::string pbdata = RoomResult.SerializePartialAsString();
  1184. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_RESULT, (void*)pbdata.c_str(), pbdata.length());
  1185. //发送消息
  1186. if (result.bState == 2)
  1187. SendGameMessage(m_TableUserItemArray[i], TEXT("此房间已经被群主解散了!"), SMT_TABLE_EXIT);
  1188. }
  1189. WORD wEnumIndex = 0;
  1190. IServerUserItem * pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  1191. while (pIServerUserItem)
  1192. {
  1193. UserInfo::PB_CS_S_DELETE_PRIVATE_ROOM_RESULT RoomResult;
  1194. RoomResult.set_wtableid(result.wTableID);
  1195. RoomResult.set_bstate(result.bState);
  1196. std::string szDescription = CW2AEX<1024>(result.szDescription, CP_UTF8).m_psz;
  1197. RoomResult.set_szdescription(szDescription);
  1198. //发送数据
  1199. std::string pbdata = RoomResult.SerializePartialAsString();
  1200. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_RESULT, (void*)pbdata.c_str(), pbdata.length());
  1201. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  1202. }
  1203. KillGameTimer(IDI_START_DISMISS_PRIVATE);
  1204. KillGameTimer(IDI_STARTED_TIME);//申请解散时,把定时器去掉
  1205. m_AgreeDeletePriTableUsers.clear();
  1206. m_bDismissVoteStarted = false;
  1207. if (1 == uState || 2 == uState)
  1208. {
  1209. //如果第一局没结束,则退钱给房主
  1210. if (m_wDrawCount == 0 && m_cbGameStatus == 101)
  1211. {
  1212. UnAdminLockBeans();
  1213. }
  1214. if (2 == uState) //异常结束。
  1215. {
  1216. m_pITableFrameSink->OnEventGameConclude(INVALID_CHAIR, NULL, GER_DELETE_PRIVATE, true);
  1217. }
  1218. else //调用游戏内结算,发送当前游戏结算。
  1219. {
  1220. m_pITableFrameSink->OnEventGameConclude(INVALID_CHAIR, NULL, GER_DISMISS, true);
  1221. }
  1222. //CTraceService::TraceString(TEXT("定时解散成功!"), TraceLevel_Normal);
  1223. return false;
  1224. }
  1225. return true;
  1226. }
  1227. bool CTableFrame::DeletePrivateStarted(USHORT uState, LPCTSTR szDescription)
  1228. {
  1229. CMD_GR_DELETE_PRIVATE_ROOM_RESULT result;
  1230. result.bState = uState;
  1231. lstrcpy(result.szDescription, szDescription);
  1232. for (WORD i = 0; i < m_wChairCount; i++)
  1233. {
  1234. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  1235. if (pIServerUserItem == NULL) continue;
  1236. UserInfo::PB_CS_S_DELETE_PRIVATE_ROOM_RESULT RoomResult;
  1237. RoomResult.set_wtableid(result.wTableID);
  1238. RoomResult.set_bstate(result.bState);
  1239. std::string szDescription = CW2AEX<1024>(result.szDescription, CP_UTF8).m_psz;
  1240. RoomResult.set_szdescription(szDescription);
  1241. //发送数据
  1242. std::string pbdata = RoomResult.SerializePartialAsString();
  1243. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_RESULT, (void*)pbdata.c_str(), pbdata.length());
  1244. }
  1245. WORD wEnumIndex = 0;
  1246. IServerUserItem * pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  1247. while (pIServerUserItem)
  1248. {
  1249. UserInfo::PB_CS_S_DELETE_PRIVATE_ROOM_RESULT RoomResult;
  1250. RoomResult.set_wtableid(result.wTableID);
  1251. RoomResult.set_bstate(result.bState);
  1252. std::string szDescription = CW2AEX<1024>(result.szDescription, CP_UTF8).m_psz;
  1253. RoomResult.set_szdescription(szDescription);
  1254. //发送数据
  1255. std::string pbdata = RoomResult.SerializePartialAsString();
  1256. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_DELETE_PRIVATE_TABLE_RESULT, (void*)pbdata.c_str(), pbdata.length());
  1257. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  1258. }
  1259. KillGameTimer(IDI_STARTED_TIME);
  1260. if (1 == uState)
  1261. {
  1262. //如果第一局没结束,则退钱给房主
  1263. if (m_wDrawCount == 0 && m_cbGameStatus == 101)
  1264. {
  1265. UnAdminLockBeans();
  1266. }
  1267. //调用游戏内结算,发送当前游戏结算。
  1268. m_pITableFrameSink->OnEventGameConclude(INVALID_CHAIR, NULL, GER_DELETE_PRIVATE, true);
  1269. //CTraceService::TraceString(TEXT("定时解散成功!"), TraceLevel_Normal);
  1270. return false;
  1271. }
  1272. return true;
  1273. }
  1274. //写入积分
  1275. bool CTableFrame::WriteUserScore(WORD wChairID, tagScoreInfo & ScoreInfo, DWORD dwGameMemal, DWORD dwPlayGameTime)
  1276. {
  1277. //效验参数
  1278. if ((wChairID >= m_wChairCount) && (ScoreInfo.cbType == SCORE_TYPE_NULL)) return false;
  1279. //if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  1280. //{
  1281. // //戳瞎子
  1282. // if (wChairID == 3)
  1283. // {
  1284. // return false;
  1285. // }
  1286. //}
  1287. //获取用户
  1288. ASSERT(GetTableUserItem(wChairID) != NULL);
  1289. IServerUserItem * pIServerUserItem = GetTableUserItem(wChairID);
  1290. TCHAR szMessage[128] = TEXT("");
  1291. //写入积分
  1292. //二人麻将异常修改
  1293. if (pIServerUserItem == NULL)
  1294. {
  1295. return true;
  1296. //离开用户
  1297. //CTraceService::TraceString(TEXT("系统暂时未支持离开用户的补分操作处理!"), TraceLevel_Exception);
  1298. //return false;
  1299. }
  1300. //游戏时间
  1301. DWORD dwCurrentTime = (DWORD)time(NULL);
  1302. DWORD dwPlayTimeCount = ((m_bDrawStarted == true) ? (dwCurrentTime - m_dwDrawStartTime) : 0L);
  1303. if (dwPlayGameTime != INVALID_DWORD) dwPlayTimeCount = dwPlayGameTime;
  1304. //变量定义
  1305. DWORD dwUserMemal = 0L;
  1306. //查询是否使用临时积分(临时积分:输赢都不计入用户积分)
  1307. bool bUseTemporaryScore = m_pITableFrameSink->QueryUseTemporaryScore();
  1308. if (!bUseTemporaryScore)
  1309. {
  1310. //使用积分
  1311. SCORE lRevenueScore = __min(m_lFrozenedScore[wChairID], m_pGameServiceOption->lServiceScore);
  1312. //扣服务费
  1313. if (m_pGameServiceOption->lServiceScore > 0L
  1314. && m_pGameServiceOption->wServerType == GAME_GENRE_GOLD
  1315. && m_pITableFrameSink->QueryBuckleServiceCharge(wChairID))
  1316. {
  1317. //扣服务费
  1318. ScoreInfo.lScore -= lRevenueScore;
  1319. ScoreInfo.lRevenue += lRevenueScore;
  1320. //解锁游戏币
  1321. pIServerUserItem->UnFrozenedUserScore(m_lFrozenedScore[wChairID]);
  1322. m_lFrozenedScore[wChairID] = 0L;
  1323. }
  1324. //奖牌计算
  1325. if (dwGameMemal != INVALID_DWORD)
  1326. {
  1327. dwUserMemal = dwGameMemal;
  1328. }
  1329. else if (ScoreInfo.lRevenue > 0L)
  1330. {
  1331. WORD wMedalRate = m_pGameParameter->wMedalRate;
  1332. dwUserMemal = (DWORD)(ScoreInfo.lRevenue*wMedalRate / 1000L);
  1333. }
  1334. //变量定义
  1335. tagUserProperty * pUserProperty = pIServerUserItem->GetUserProperty();
  1336. //道具判断
  1337. if (m_pGameServiceOption->wServerType == GAME_GENRE_SCORE)
  1338. {
  1339. if (ScoreInfo.lScore > 0L)
  1340. {
  1341. //四倍积分
  1342. if ((pUserProperty->wPropertyUseMark&PT_USE_MARK_FOURE_SCORE) != 0)
  1343. {
  1344. //变量定义
  1345. DWORD dwValidTime = pUserProperty->PropertyInfo[1].wPropertyCount*pUserProperty->PropertyInfo[1].dwValidNum;
  1346. if (pUserProperty->PropertyInfo[1].dwEffectTime + dwValidTime > dwCurrentTime)
  1347. {
  1348. //积分翻倍
  1349. ScoreInfo.lScore *= 4;
  1350. _sntprintf(szMessage, CountArray(szMessage), TEXT("[ %s ] 使用了[ 四倍积分卡 ],得分翻四倍!)"), pIServerUserItem->GetNickName());
  1351. }
  1352. else
  1353. {
  1354. pUserProperty->wPropertyUseMark &= ~PT_USE_MARK_FOURE_SCORE;
  1355. }
  1356. } //双倍积分
  1357. else if ((pUserProperty->wPropertyUseMark&PT_USE_MARK_DOUBLE_SCORE) != 0)
  1358. {
  1359. //变量定义
  1360. DWORD dwValidTime = pUserProperty->PropertyInfo[0].wPropertyCount*pUserProperty->PropertyInfo[0].dwValidNum;
  1361. if (pUserProperty->PropertyInfo[0].dwEffectTime + dwValidTime > dwCurrentTime)
  1362. {
  1363. //积分翻倍
  1364. ScoreInfo.lScore *= 2L;
  1365. _sntprintf(szMessage, CountArray(szMessage), TEXT("[ %s ] 使用了[ 双倍积分卡 ],得分翻倍!"), pIServerUserItem->GetNickName());
  1366. }
  1367. else
  1368. {
  1369. pUserProperty->wPropertyUseMark &= ~PT_USE_MARK_DOUBLE_SCORE;
  1370. }
  1371. }
  1372. }
  1373. else
  1374. {
  1375. //附身符
  1376. if ((pUserProperty->wPropertyUseMark&PT_USE_MARK_POSSESS) != 0)
  1377. {
  1378. //变量定义
  1379. DWORD dwValidTime = pUserProperty->PropertyInfo[3].wPropertyCount*pUserProperty->PropertyInfo[3].dwValidNum;
  1380. if (pUserProperty->PropertyInfo[3].dwEffectTime + dwValidTime > dwCurrentTime)
  1381. {
  1382. //积分翻倍
  1383. ScoreInfo.lScore = 0;
  1384. _sntprintf(szMessage, CountArray(szMessage), TEXT("[ %s ] 使用了[ 护身符卡 ],积分不变!"), pIServerUserItem->GetNickName());
  1385. }
  1386. else
  1387. {
  1388. pUserProperty->wPropertyUseMark &= ~PT_USE_MARK_POSSESS;
  1389. }
  1390. }
  1391. }
  1392. }
  1393. //写入积分
  1394. DWORD dwWinExperience = ScoreInfo.cbType == SCORE_TYPE_WIN ? m_pGameParameter->dwWinExperience : 0;
  1395. pIServerUserItem->WriteUserScore(ScoreInfo.lScore, ScoreInfo.lGrade, ScoreInfo.lRevenue, dwUserMemal, ScoreInfo.cbType, dwPlayTimeCount, dwWinExperience);
  1396. }
  1397. else
  1398. {
  1399. //写入积分
  1400. DWORD dwWinExperience = ScoreInfo.cbType == SCORE_TYPE_WIN ? m_pGameParameter->dwWinExperience : 0;
  1401. pIServerUserItem->WriteUserScore(ScoreInfo.lScore, ScoreInfo.lGrade, ScoreInfo.lRevenue, dwUserMemal, ScoreInfo.cbType, dwPlayTimeCount, dwWinExperience);
  1402. //使用临时积分
  1403. DBR_GR_WriteGameTemporaryScore req;
  1404. ZeroMemory(&req, sizeof(req));
  1405. req.dwUserID = pIServerUserItem->GetUserID();
  1406. req.dwClientAddr = pIServerUserItem->GetClientAddr();
  1407. req.lScore = ScoreInfo.lScore;
  1408. if (ScoreInfo.lScore < 0)
  1409. {
  1410. req.lScore = 0; //换算成 不含倍数的得分
  1411. }
  1412. if (m_wDrawCount < 1)
  1413. {
  1414. req.lScore = 0; //换算成 不含倍数的得分
  1415. }
  1416. if (req.lScore>0)
  1417. {
  1418. //req.lScore = req.lScore / mGameConfig.wPlayRule;
  1419. //底分为0的时候会崩溃
  1420. req.lScore = 0;
  1421. }
  1422. req.dwPlayTimeCount = dwPlayTimeCount;
  1423. /*if (SCORE_TYPE_END == ScoreInfo.cbType)
  1424. {
  1425. return true;
  1426. }*/
  1427. //修改胜负
  1428. switch (ScoreInfo.cbType)
  1429. {
  1430. case SCORE_TYPE_WIN: //胜局
  1431. case SCORE_TYPE_LOSE: //输局
  1432. case SCORE_TYPE_DRAW: //平局
  1433. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_WRITE_GAME_TEMPORARY_SCORE, 0, &req, sizeof(req)); break;
  1434. default:
  1435. break;
  1436. //case SCORE_TYPE_WIN: //胜局
  1437. //{
  1438. // req.dwWinCount++;
  1439. //}break;
  1440. //case SCORE_TYPE_LOSE: //输局
  1441. //{
  1442. // req.dwLostCount++;
  1443. //}break;
  1444. //case SCORE_TYPE_DRAW:
  1445. //{
  1446. // req.dwPingCount++;
  1447. // break;
  1448. //}
  1449. }
  1450. }
  1451. //游戏记录
  1452. if (pIServerUserItem->IsAndroidUser() == false && CServerRule::IsRecordGameScore(m_pGameServiceOption->dwServerRule) == true)
  1453. {
  1454. //变量定义
  1455. tagGameScoreRecord * pGameScoreRecord = NULL;
  1456. //查询库存
  1457. if (m_GameScoreRecordBuffer.GetCount() > 0L)
  1458. {
  1459. //获取对象
  1460. INT_PTR nCount = m_GameScoreRecordBuffer.GetCount();
  1461. pGameScoreRecord = m_GameScoreRecordBuffer[nCount - 1];
  1462. //删除对象
  1463. m_GameScoreRecordBuffer.RemoveAt(nCount - 1);
  1464. }
  1465. //创建对象
  1466. if (pGameScoreRecord == NULL)
  1467. {
  1468. try
  1469. {
  1470. //创建对象
  1471. pGameScoreRecord = new tagGameScoreRecord;
  1472. if (pGameScoreRecord == NULL) throw TEXT("游戏记录对象创建失败");
  1473. }
  1474. catch (...)
  1475. {
  1476. ASSERT(FALSE);
  1477. }
  1478. }
  1479. //记录数据
  1480. if (pGameScoreRecord != NULL)
  1481. {
  1482. //用户信息
  1483. pGameScoreRecord->wChairID = wChairID;
  1484. pGameScoreRecord->dwUserID = pIServerUserItem->GetUserID();
  1485. lstrcpy(pGameScoreRecord->szUserName , pIServerUserItem->GetNickName());
  1486. lstrcpy(pGameScoreRecord->szHeadImg, pIServerUserItem->GetUserInfo()->szHeadUrl);
  1487. pGameScoreRecord->cbAndroid = (pIServerUserItem->IsAndroidUser() ? TRUE : FALSE);
  1488. //用户信息
  1489. pGameScoreRecord->dwDBQuestID = pIServerUserItem->GetDBQuestID();
  1490. pGameScoreRecord->dwInoutIndex = pIServerUserItem->GetInoutIndex();
  1491. //成绩信息
  1492. pGameScoreRecord->lScore = ScoreInfo.lScore;
  1493. pGameScoreRecord->lGrade = ScoreInfo.lGrade;
  1494. pGameScoreRecord->lRevenue = ScoreInfo.lRevenue;
  1495. //附加信息
  1496. pGameScoreRecord->dwUserMemal = dwUserMemal;
  1497. pGameScoreRecord->dwPlayTimeCount = dwPlayTimeCount;
  1498. //机器人免税
  1499. if (pIServerUserItem->IsAndroidUser())
  1500. {
  1501. pGameScoreRecord->lScore += pGameScoreRecord->lRevenue;
  1502. pGameScoreRecord->lRevenue = 0L;
  1503. }
  1504. //插入数据
  1505. m_GameScoreRecordActive.Add(pGameScoreRecord);
  1506. }
  1507. }
  1508. //游戏记录
  1509. if (dwGameMemal != INVALID_DWORD || dwPlayGameTime != INVALID_DWORD)
  1510. {
  1511. DWORD dwStartGameTime = INVALID_DWORD;
  1512. if (dwPlayGameTime != INVALID_DWORD)
  1513. {
  1514. dwStartGameTime = (dwCurrentTime - dwPlayGameTime);
  1515. }
  1516. RecordGameScore(true, dwStartGameTime);
  1517. }
  1518. //广播消息
  1519. if (szMessage[0] != 0)
  1520. {
  1521. //变量定义
  1522. IServerUserItem * pISendUserItem = NULL;
  1523. WORD wEnumIndex = 0;
  1524. //游戏玩家
  1525. for (WORD i = 0; i < m_wChairCount; i++)
  1526. {
  1527. //获取用户
  1528. pISendUserItem = GetTableUserItem(i);
  1529. if (pISendUserItem == NULL) continue;
  1530. SendRequestFailure(pIServerUserItem, szMessage, 0);
  1531. //发送消息
  1532. //SendGameMessage(pISendUserItem, szMessage, SMT_CHAT);
  1533. }
  1534. //旁观用户
  1535. do
  1536. {
  1537. pISendUserItem = EnumLookonUserItem(wEnumIndex++);
  1538. if (pISendUserItem != NULL)
  1539. {
  1540. SendRequestFailure(pIServerUserItem, szMessage, 0);
  1541. //发送消息
  1542. //SendGameMessage(pISendUserItem, szMessage, SMT_CHAT);
  1543. }
  1544. } while (pISendUserItem != NULL);
  1545. }
  1546. return true;
  1547. }
  1548. //锁定元宝
  1549. bool CTableFrame::LockBeans(DWORD dwUserID, UINT32 dwConsumeCurrency)
  1550. {
  1551. if (dwUserID == 0 || dwConsumeCurrency == 0) return true;
  1552. DWORD dwSocketID = 0;
  1553. auto pIUserItem = m_pIMainServiceFrame->SearchUserItem(dwUserID);
  1554. if (pIUserItem)
  1555. {
  1556. auto bindParam = m_pIMainServiceFrame->GetBindParameter(pIUserItem->GetBindIndex());
  1557. if (bindParam)
  1558. dwSocketID = bindParam->dwSocketID;
  1559. }
  1560. DBR_GR_UserReduceBeans req;
  1561. ZeroMemory(&req, sizeof(DBR_GR_UserReduceBeans));
  1562. req.ConsumeCurrency = dwConsumeCurrency;
  1563. req.dwUserID = dwUserID;
  1564. req.dwTableID = this->GetTableID();
  1565. if (pIUserItem) req.dwClientAddr = pIUserItem->GetClientAddr();
  1566. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_USER_LUCK_BEANS, dwSocketID, &req, sizeof(DBR_GR_UserReduceBeans));
  1567. return true;
  1568. }
  1569. //在桌子解散的情况下,按照约定处理房间创建者需要解锁的元宝
  1570. void CTableFrame::UnAdminLockBeans()
  1571. {
  1572. //先处理创建者的元宝,查看创建者是否参与游戏中。
  1573. IServerUserItem * pIServerUserItem = NULL;
  1574. for (WORD i = 0; i < m_wChairCount; i++)
  1575. {
  1576. IServerUserItem * p = GetTableUserItem(i);
  1577. if ((p != NULL) && (p->GetUserID() == this->GetPrivateTableOwnerID()))
  1578. {
  1579. pIServerUserItem = p;
  1580. break;
  1581. }
  1582. }
  1583. if (pIServerUserItem != NULL)
  1584. {
  1585. //创建者参与或者群主支付
  1586. if (mGameConfig.wMaxFanRule == 0)
  1587. {
  1588. //创建者支付
  1589. if (m_wDrawCount >= 1)
  1590. {
  1591. //游戏已经打过一局的情况。扣款
  1592. for (int i = 0; i < 6; i++)
  1593. {
  1594. if (m_jgrUserLockData[i].User == this->GetPrivateTableOwnerID())
  1595. {
  1596. //是创建者
  1597. if (m_jgrUserLockData[i].dwLockNum > 0)
  1598. {
  1599. ReduceBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1600. m_jgrUserLockData[i].dwLockNum = 0;
  1601. break;
  1602. }
  1603. }
  1604. }
  1605. }
  1606. else
  1607. {
  1608. //游戏没打,就解散了。退款
  1609. for (int i = 0; i < 6; i++)
  1610. {
  1611. if (m_jgrUserLockData[i].User == this->GetPrivateTableOwnerID())
  1612. {
  1613. //是创建者
  1614. if (m_jgrUserLockData[i].dwLockNum > 0)
  1615. {
  1616. UnLockBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1617. m_jgrUserLockData[i].dwLockNum = 0;
  1618. }
  1619. }
  1620. }
  1621. }
  1622. }
  1623. else if (mGameConfig.wMaxFanRule >= 10)
  1624. {
  1625. //创建者支付
  1626. if (m_wDrawCount >= 1)
  1627. {
  1628. //游戏已经打过一局的情况。扣款
  1629. for (int i = 0; i < 6; i++)
  1630. {
  1631. if (m_jgrUserLockData[i].User != 0)
  1632. {
  1633. //是创建者
  1634. if (m_jgrUserLockData[i].dwLockNum > 0)
  1635. {
  1636. ReduceBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1637. m_jgrUserLockData[i].dwLockNum = 0;
  1638. break;
  1639. }
  1640. }
  1641. }
  1642. }
  1643. else
  1644. {
  1645. //游戏没打,就解散了。退款
  1646. for (int i = 0; i < 6; i++)
  1647. {
  1648. if (m_jgrUserLockData[i].User != 0)
  1649. {
  1650. //是创建者
  1651. if (m_jgrUserLockData[i].dwLockNum > 0)
  1652. {
  1653. UnLockBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1654. m_jgrUserLockData[i].dwLockNum = 0;
  1655. break;
  1656. }
  1657. }
  1658. }
  1659. }
  1660. }
  1661. else
  1662. {
  1663. //平摊
  1664. if (m_wDrawCount >= 1)
  1665. {
  1666. //游戏已经打过一局的情况。扣款
  1667. for (int i = 0; i < 6; i++)
  1668. {
  1669. if (m_jgrUserLockData[i].User != 0)
  1670. {
  1671. if (m_jgrUserLockData[i].dwLockNum > 0)
  1672. {
  1673. int a = m_jgrUserLockData[i].dwLockNum;
  1674. m_jgrUserLockData[i].dwLockNum = 0;
  1675. ReduceBeans(m_jgrUserLockData[i].User, a);
  1676. }
  1677. }
  1678. }
  1679. }
  1680. else
  1681. {
  1682. //游戏没打,就解散了。退款
  1683. for (int i = 0; i < 6; i++)
  1684. {
  1685. if (m_jgrUserLockData[i].User != 0)
  1686. {
  1687. if (m_jgrUserLockData[i].dwLockNum > 0)
  1688. {
  1689. int a = m_jgrUserLockData[i].dwLockNum;
  1690. m_jgrUserLockData[i].dwLockNum = 0;
  1691. UnLockBeans(m_jgrUserLockData[i].User, a);
  1692. }
  1693. }
  1694. }
  1695. }
  1696. }
  1697. }
  1698. else
  1699. {
  1700. //创建者不参与
  1701. if (mGameConfig.wMaxFanRule == 0)
  1702. {
  1703. //创建者支付
  1704. if (m_wDrawCount >= 1)
  1705. {
  1706. //游戏已经打过一局的情况。扣款
  1707. for (int i = 0; i < 6; i++)
  1708. {
  1709. if (m_jgrUserLockData[i].User == this->GetPrivateTableOwnerID())
  1710. {
  1711. //是创建者
  1712. if (m_jgrUserLockData[i].dwLockNum > 0)
  1713. {
  1714. ReduceBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1715. m_jgrUserLockData[i].dwLockNum = 0;
  1716. break;
  1717. }
  1718. }
  1719. }
  1720. }
  1721. else
  1722. {
  1723. //游戏没打,就解散了。退款
  1724. for (int i = 0; i < 6; i++)
  1725. {
  1726. if (m_jgrUserLockData[i].User == this->GetPrivateTableOwnerID())
  1727. {
  1728. //是创建者
  1729. if (m_jgrUserLockData[i].dwLockNum > 0)
  1730. {
  1731. UnLockBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1732. m_jgrUserLockData[i].dwLockNum = 0;
  1733. break;
  1734. }
  1735. }
  1736. }
  1737. }
  1738. }
  1739. else if (mGameConfig.wMaxFanRule >= 10)
  1740. {
  1741. //创建者支付
  1742. if (m_wDrawCount >= 1)
  1743. {
  1744. //游戏已经打过一局的情况。扣款
  1745. for (int i = 0; i < 6; i++)
  1746. {
  1747. if (m_jgrUserLockData[i].User != 0)
  1748. {
  1749. //是创建者
  1750. if (m_jgrUserLockData[i].dwLockNum > 0)
  1751. {
  1752. ReduceBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1753. m_jgrUserLockData[i].dwLockNum = 0;
  1754. break;
  1755. }
  1756. }
  1757. }
  1758. }
  1759. else
  1760. {
  1761. //游戏没打,就解散了。退款
  1762. for (int i = 0; i < 6; i++)
  1763. {
  1764. if (m_jgrUserLockData[i].User != 0)
  1765. {
  1766. //是创建者
  1767. if (m_jgrUserLockData[i].dwLockNum > 0)
  1768. {
  1769. UnLockBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1770. m_jgrUserLockData[i].dwLockNum = 0;
  1771. break;
  1772. }
  1773. }
  1774. }
  1775. }
  1776. }
  1777. else
  1778. {
  1779. //平摊
  1780. if (m_wDrawCount >= 1)
  1781. {
  1782. for (int i = 0; i < 6; i++)
  1783. {
  1784. if (m_jgrUserLockData[i].User != 0)
  1785. {
  1786. //是创建者
  1787. if (m_jgrUserLockData[i].dwLockNum > 0)
  1788. {
  1789. if (m_jgrUserLockData[i].User == this->GetPrivateTableOwnerID())
  1790. {
  1791. UnLockBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1792. }
  1793. else
  1794. {
  1795. ReduceBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1796. }
  1797. m_jgrUserLockData[i].dwLockNum = 0;
  1798. }
  1799. }
  1800. }
  1801. }
  1802. else
  1803. {
  1804. for (int i = 0; i < 6; i++)
  1805. {
  1806. if (m_jgrUserLockData[i].User != 0)
  1807. {
  1808. if (m_jgrUserLockData[i].dwLockNum > 0)
  1809. {
  1810. UnLockBeans(m_jgrUserLockData[i].User, m_jgrUserLockData[i].dwLockNum);
  1811. m_jgrUserLockData[i].dwLockNum = 0;
  1812. }
  1813. }
  1814. }
  1815. }
  1816. }
  1817. }
  1818. }
  1819. //解锁元宝
  1820. bool CTableFrame::UnLockBeans(DWORD dwUserID, UINT32 dwConsumeCurrency)
  1821. {
  1822. if (dwUserID == 0 || dwConsumeCurrency == 0) return true;
  1823. DWORD dwSocketID = 0;
  1824. auto pIUserItem = m_pIMainServiceFrame->SearchUserItem(dwUserID);
  1825. if (pIUserItem)
  1826. {
  1827. auto bindParam = m_pIMainServiceFrame->GetBindParameter(pIUserItem->GetBindIndex());
  1828. if (bindParam)
  1829. dwSocketID = bindParam->dwSocketID;
  1830. }
  1831. DBR_GR_UserReduceBeans req;
  1832. ZeroMemory(&req, sizeof(DBR_GR_UserReduceBeans));
  1833. req.ConsumeCurrency = dwConsumeCurrency;
  1834. req.dwUserID = dwUserID;
  1835. req.dwTableID = this->GetTableID();
  1836. if (pIUserItem) req.dwClientAddr = pIUserItem->GetClientAddr();
  1837. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_USER_UNLUCK_BEANS, dwSocketID, &req, sizeof(DBR_GR_UserReduceBeans));
  1838. return true;
  1839. }
  1840. //消耗房卡
  1841. bool CTableFrame::ReduceBeans(DWORD dwUserID,UINT32 dwConsumeCurrency)
  1842. {
  1843. if (dwUserID == 0 || dwConsumeCurrency == 0) return true;
  1844. DWORD dwSocketID = 0;
  1845. auto pIUserItem = m_pIMainServiceFrame->SearchUserItem(dwUserID);
  1846. if (pIUserItem)
  1847. {
  1848. auto bindParam = m_pIMainServiceFrame->GetBindParameter(pIUserItem->GetBindIndex());
  1849. if (bindParam)
  1850. dwSocketID = bindParam->dwSocketID;
  1851. }
  1852. DBR_GR_UserReduceBeans req;
  1853. ZeroMemory(&req, sizeof(DBR_GR_UserReduceBeans));
  1854. req.ConsumeCurrency = dwConsumeCurrency;
  1855. req.dwUserID = dwUserID;
  1856. req.dwTableID = this->GetTableID();
  1857. if (pIUserItem) req.dwClientAddr = pIUserItem->GetClientAddr();
  1858. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_USER_REDUCE_BEANS, dwSocketID, &req, sizeof(DBR_GR_UserReduceBeans));
  1859. return true;
  1860. }
  1861. //直接扣除房卡
  1862. bool CTableFrame::NowReduceBeans(DWORD dwUserID, UINT32 dwConsumeCurrency)
  1863. {
  1864. if (dwUserID == 0 || dwConsumeCurrency == 0) return true;
  1865. DWORD dwSocketID = 0;
  1866. auto pIUserItem = m_pIMainServiceFrame->SearchUserItem(dwUserID);
  1867. if (pIUserItem)
  1868. {
  1869. auto bindParam = m_pIMainServiceFrame->GetBindParameter(pIUserItem->GetBindIndex());
  1870. if (bindParam)
  1871. dwSocketID = bindParam->dwSocketID;
  1872. }
  1873. DBR_GR_UserReduceBeans req;
  1874. ZeroMemory(&req, sizeof(DBR_GR_UserReduceBeans));
  1875. req.ConsumeCurrency = dwConsumeCurrency;
  1876. req.dwUserID = dwUserID;
  1877. req.dwTableID = this->GetTableID();
  1878. if(pIUserItem) req.dwClientAddr = pIUserItem->GetClientAddr();
  1879. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_USER_CHECK_BEANS, dwSocketID, &req, sizeof(DBR_GR_UserReduceBeans));
  1880. return true;
  1881. }
  1882. //写入积分
  1883. bool CTableFrame::WriteTableScore(tagScoreInfo ScoreInfoArray[], WORD wScoreCount)
  1884. {
  1885. //写入分数
  1886. for (WORD i = 0; i < m_wChairCount; i++)
  1887. {
  1888. if (ScoreInfoArray[i].cbType != SCORE_TYPE_NULL && !(1 == i && GetStartMode() == START_MODE_ALL_READY))
  1889. {
  1890. WriteUserScore(i, ScoreInfoArray[i]);
  1891. }
  1892. }
  1893. return true;
  1894. }
  1895. //推送闲聊机器人
  1896. //void CTableFrame::WriteXianLiaoTableRecord()
  1897. //{
  1898. // IServerUserItem * pIServerUserItem = NULL;
  1899. // DBR_GR_ClubRecordXianLiao FenXiangXianLiao = { 0 };
  1900. // FenXiangXianLiao.WanFa = this->GetGameConfig().wSubGameID;
  1901. // FenXiangXianLiao.dwClubID = m_dwClubID;
  1902. // FenXiangXianLiao.dwTableID = stoi(m_sPrivateTableID);//桌子号
  1903. // FenXiangXianLiao.dwUserCount = m_wChairCount;
  1904. // if (m_wChairCount == 3 && this->GetStartMode() == START_MODE_ALL_READY)
  1905. // {
  1906. // FenXiangXianLiao.dwUserCount = 2;
  1907. // }
  1908. // FenXiangXianLiao.Jushu = m_wStartCount;
  1909. // FenXiangXianLiao.DiFen = this->GetGameConfig().wPlayRule;
  1910. // BYTE TempCount = 0;
  1911. // for (BYTE i = 0; i < m_wChairCount; i++)
  1912. // {
  1913. // pIServerUserItem = GetTableUserItem(i);
  1914. // if (pIServerUserItem == NULL) continue;
  1915. // FenXiangXianLiao.Player[TempCount].userID = pIServerUserItem->GetUserID();
  1916. // CopyMemory(&FenXiangXianLiao.Player[TempCount].szName, pIServerUserItem->GetUserInfo()->szNickName, sizeof(FenXiangXianLiao.Player[i].szName));
  1917. // CopyMemory(&FenXiangXianLiao.Player[TempCount].szImgHead, pIServerUserItem->GetUserInfo()->szHeadUrl, sizeof(FenXiangXianLiao.Player[i].szImgHead));
  1918. // FenXiangXianLiao.Player[TempCount].gScore = m_pITableFrameSink->QueryTatolScore(i);
  1919. // TempCount++;
  1920. // }
  1921. // //投递数据
  1922. // m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_CLUB_XIANLIAO_RECORD, 0, &FenXiangXianLiao, sizeof(FenXiangXianLiao));
  1923. //}
  1924. //写入俱乐部记录
  1925. void CTableFrame::WriteClubTableRecord()
  1926. {
  1927. if (this->m_wTableKind == 1)
  1928. {
  1929. //变量定义
  1930. DBR_GR_ClubRecordWrite ClubRecordWrite;
  1931. ZeroMemory(&ClubRecordWrite, sizeof(ClubRecordWrite));
  1932. //设置变量
  1933. ClubRecordWrite.dwClubID = m_dwClubID;
  1934. ClubRecordWrite.SystemTimeStart = m_SystemTimeStart;
  1935. ClubRecordWrite.dwUserID = this->GetPrivateTableOwnerID();
  1936. ClubRecordWrite.dwTableID = _wtoi(this->GetPrivateTableID().c_str());
  1937. ClubRecordWrite.PayWay = this->GetGameConfig().wMaxFanRule;
  1938. ClubRecordWrite.Jushu = this->GetGameConfig().wPlayCountRule;
  1939. ClubRecordWrite.dwUserCount = m_wChairCount;
  1940. if (this->GetStartMode() == START_MODE_ALL_READY && m_wChairCount == 3)
  1941. {
  1942. ClubRecordWrite.dwUserCount = 2;
  1943. }
  1944. for (int i = 0; i < m_wChairCount; i++)
  1945. {
  1946. if (GetTableUserItem(i))
  1947. {
  1948. ClubRecordWrite.Player[i] = GetTableUserItem(i)->GetUserInfo()->dwUserID;
  1949. }
  1950. }
  1951. //投递数据
  1952. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_CLUB_WRITE_RECORD, 0, &ClubRecordWrite, sizeof(ClubRecordWrite));
  1953. }
  1954. }
  1955. //回放
  1956. bool CTableFrame::SaveReplayRecord(void* pData, WORD wDataSize)
  1957. {
  1958. if (nullptr != m_ReplayRecordData)
  1959. {
  1960. delete [] m_ReplayRecordData;
  1961. m_ReplayRecordData = nullptr;
  1962. }
  1963. m_ReplayRecordData = new char[wDataSize];
  1964. ZeroMemory(m_ReplayRecordData, sizeof(char) * wDataSize);
  1965. CopyMemory(m_ReplayRecordData, pData, sizeof(char) * wDataSize);
  1966. //m_ReplayRecordData = pData;
  1967. m_ReplayRecordDataSize = wDataSize;
  1968. return true;
  1969. }
  1970. //计算税收
  1971. SCORE CTableFrame::CalculateRevenue(WORD wChairID, SCORE lScore)
  1972. {
  1973. //效验参数
  1974. ASSERT(wChairID<m_wChairCount);
  1975. if (wChairID >= m_wChairCount) return 0L;
  1976. //计算税收
  1977. if ((m_pGameServiceOption->wRevenueRatio>0) && (lScore >= REVENUE_BENCHMARK))
  1978. {
  1979. //获取用户
  1980. ASSERT(GetTableUserItem(wChairID) != NULL);
  1981. IServerUserItem * pIServerUserItem = GetTableUserItem(wChairID);
  1982. //计算税收
  1983. SCORE lRevenue = lScore*m_pGameServiceOption->wRevenueRatio / REVENUE_DENOMINATOR;
  1984. return lRevenue;
  1985. }
  1986. return 0L;
  1987. }
  1988. //消费限额
  1989. SCORE CTableFrame::QueryConsumeQuota(IServerUserItem * pIServerUserItem)
  1990. {
  1991. //用户效验
  1992. ASSERT(pIServerUserItem->GetTableID() == m_wTableID);
  1993. if (pIServerUserItem->GetTableID() != m_wTableID) return 0L;
  1994. //查询额度
  1995. SCORE lTrusteeScore = pIServerUserItem->GetTrusteeScore();
  1996. SCORE lMinEnterScore = m_pGameServiceOption->lMinTableScore;
  1997. SCORE lUserConsumeQuota = m_pITableFrameSink->QueryConsumeQuota(pIServerUserItem);
  1998. //效验额度
  1999. ASSERT((lUserConsumeQuota >= 0L) && (lUserConsumeQuota <= pIServerUserItem->GetUserScore() - lMinEnterScore));
  2000. if ((lUserConsumeQuota<0L) || (lUserConsumeQuota>pIServerUserItem->GetUserScore() - lMinEnterScore)) return 0L;
  2001. return lUserConsumeQuota + lTrusteeScore;
  2002. }
  2003. //寻找用户
  2004. IServerUserItem * CTableFrame::SearchUserItem(DWORD dwUserID)
  2005. {
  2006. //变量定义
  2007. WORD wEnumIndex = 0;
  2008. IServerUserItem * pIServerUserItem = NULL;
  2009. //桌子用户
  2010. for (WORD i = 0; i < m_wChairCount; i++)
  2011. {
  2012. pIServerUserItem = GetTableUserItem(i);
  2013. if ((pIServerUserItem != NULL) && (pIServerUserItem->GetUserID() == dwUserID)) return pIServerUserItem;
  2014. }
  2015. //旁观用户
  2016. do
  2017. {
  2018. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  2019. if ((pIServerUserItem != NULL) && (pIServerUserItem->GetUserID() == dwUserID)) return pIServerUserItem;
  2020. } while (pIServerUserItem != NULL);
  2021. return NULL;
  2022. }
  2023. //游戏用户
  2024. IServerUserItem * CTableFrame::GetTableUserItem(WORD wChairID)
  2025. {
  2026. //效验参数
  2027. //ASSERT(wChairID < m_wChairCount);
  2028. if (wChairID >= m_wChairCount) return NULL;
  2029. //获取用户
  2030. return m_TableUserItemArray[wChairID];
  2031. }
  2032. //旁观用户
  2033. IServerUserItem * CTableFrame::EnumLookonUserItem(WORD wEnumIndex)
  2034. {
  2035. if (wEnumIndex >= m_LookonUserItemArray.GetCount()) return NULL;
  2036. return m_LookonUserItemArray[wEnumIndex];
  2037. }
  2038. //设置时间
  2039. bool CTableFrame::SetGameTimer(DWORD dwTimerID, DWORD dwElapse, DWORD dwRepeat, WPARAM dwBindParameter)
  2040. {
  2041. //效验参数
  2042. ASSERT((dwTimerID > 0) && (dwTimerID < TIME_TABLE_MODULE_RANGE));
  2043. if ((dwTimerID <= 0) || (dwTimerID >= TIME_TABLE_MODULE_RANGE)) return false;
  2044. //设置时间
  2045. DWORD dwEngineTimerID = IDI_TABLE_MODULE_START + m_wTableID*TIME_TABLE_MODULE_RANGE;
  2046. if (m_pITimerEngine != NULL) m_pITimerEngine->SetTimer(dwEngineTimerID + dwTimerID, dwElapse, dwRepeat, dwBindParameter);
  2047. return true;
  2048. }
  2049. //删除时间
  2050. bool CTableFrame::KillGameTimer(DWORD dwTimerID)
  2051. {
  2052. //效验参数
  2053. ASSERT((dwTimerID > 0) && (dwTimerID <= TIME_TABLE_MODULE_RANGE));
  2054. if ((dwTimerID <= 0) || (dwTimerID > TIME_TABLE_MODULE_RANGE)) return false;
  2055. //删除时间
  2056. DWORD dwEngineTimerID = IDI_TABLE_MODULE_START + m_wTableID*TIME_TABLE_MODULE_RANGE;
  2057. if (m_pITimerEngine != NULL) m_pITimerEngine->KillTimer(dwEngineTimerID + dwTimerID);
  2058. return true;
  2059. }
  2060. //发送数据
  2061. bool CTableFrame::SendUserItemData(IServerUserItem * pIServerUserItem, WORD wSubCmdID)
  2062. {
  2063. //状态效验
  2064. ASSERT((pIServerUserItem != NULL) && (pIServerUserItem->IsClientReady() == true));
  2065. if ((pIServerUserItem == NULL) && (pIServerUserItem->IsClientReady() == false)) return false;
  2066. //发送数据
  2067. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_GAME, wSubCmdID, NULL, 0);
  2068. return true;
  2069. }
  2070. //发送数据
  2071. bool CTableFrame::SendUserItemData(IServerUserItem * pIServerUserItem, WORD wSubCmdID, VOID * pData, WORD wDataSize)
  2072. {
  2073. //状态效验
  2074. ASSERT((pIServerUserItem != NULL) && (pIServerUserItem->IsClientReady() == true));
  2075. if ((pIServerUserItem == NULL) && (pIServerUserItem->IsClientReady() == false)) return false;
  2076. //发送数据
  2077. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_GAME, wSubCmdID, pData, wDataSize);
  2078. return true;
  2079. }
  2080. //发送数据
  2081. bool CTableFrame::SendTableData(WORD wChairID, WORD wSubCmdID)
  2082. {
  2083. //用户群发
  2084. if (wChairID == INVALID_CHAIR)
  2085. {
  2086. for (WORD i = 0; i < m_wChairCount; i++)
  2087. {
  2088. //获取用户
  2089. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  2090. if (pIServerUserItem == NULL) continue;
  2091. //效验状态
  2092. ASSERT(pIServerUserItem->IsClientReady() == true);
  2093. if (pIServerUserItem->IsClientReady() == false) continue;
  2094. //发送数据
  2095. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_GAME, wSubCmdID, NULL, 0);
  2096. }
  2097. return true;
  2098. }
  2099. else
  2100. {
  2101. //获取用户
  2102. IServerUserItem * pIServerUserItem = GetTableUserItem(wChairID);
  2103. if (pIServerUserItem == NULL) return false;
  2104. //效验状态
  2105. ASSERT(pIServerUserItem->IsClientReady() == true);
  2106. if (pIServerUserItem->IsClientReady() == false) return false;
  2107. //发送数据
  2108. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_GAME, wSubCmdID, NULL, 0);
  2109. return true;
  2110. }
  2111. return false;
  2112. }
  2113. //发送数据
  2114. bool CTableFrame::SendTableData(WORD wChairID, WORD wSubCmdID, VOID * pData, WORD wDataSize, WORD wMainCmdID)
  2115. {
  2116. //用户群发
  2117. if (wChairID == INVALID_CHAIR)
  2118. {
  2119. for (WORD i = 0; i < m_wChairCount; i++)
  2120. {
  2121. //获取用户
  2122. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  2123. if ((pIServerUserItem == NULL) || (pIServerUserItem->IsClientReady() == false)) continue;
  2124. //发送数据
  2125. m_pIMainServiceFrame->SendData(pIServerUserItem, wMainCmdID, wSubCmdID, pData, wDataSize);
  2126. }
  2127. return true;
  2128. }
  2129. else
  2130. {
  2131. //获取用户
  2132. IServerUserItem * pIServerUserItem = GetTableUserItem(wChairID);
  2133. if ((pIServerUserItem == NULL) || (pIServerUserItem->IsClientReady() == false)) return false;
  2134. //发送数据
  2135. m_pIMainServiceFrame->SendData(pIServerUserItem, wMainCmdID, wSubCmdID, pData, wDataSize);
  2136. return true;
  2137. }
  2138. return false;
  2139. }
  2140. //发送数据
  2141. bool CTableFrame::SendLookonData(WORD wChairID, WORD wSubCmdID)
  2142. {
  2143. //变量定义
  2144. WORD wEnumIndex = 0;
  2145. IServerUserItem * pIServerUserItem = NULL;
  2146. //枚举用户
  2147. do
  2148. {
  2149. //获取用户
  2150. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  2151. if (pIServerUserItem == NULL) break;
  2152. //效验状态
  2153. ASSERT(pIServerUserItem->IsClientReady() == true);
  2154. if (pIServerUserItem->IsClientReady() == false) return false;
  2155. //发送数据
  2156. if ((wChairID == INVALID_CHAIR) || (pIServerUserItem->GetChairID() == wChairID))
  2157. {
  2158. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_GAME, wSubCmdID, NULL, 0);
  2159. }
  2160. } while (true);
  2161. return true;
  2162. }
  2163. //发送数据 ///---发送旁观数据
  2164. bool CTableFrame::SendLookonData(WORD wChairID, WORD wSubCmdID, VOID * pData, WORD wDataSize)
  2165. {
  2166. //变量定义
  2167. WORD wEnumIndex = 0;
  2168. IServerUserItem * pIServerUserItem = NULL;
  2169. //枚举用户
  2170. do
  2171. {
  2172. //获取用户
  2173. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  2174. if (pIServerUserItem == NULL) break;
  2175. //效验状态
  2176. //ASSERT(pIServerUserItem->IsClientReady()==true);
  2177. if (pIServerUserItem->IsClientReady() == false) return false;
  2178. //发送数据
  2179. //if ((wChairID == INVALID_CHAIR) || (pIServerUserItem->GetChairID() == wChairID))
  2180. //{
  2181. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_GAME, wSubCmdID, pData, wDataSize);
  2182. //}
  2183. } while (true);
  2184. return true;
  2185. }
  2186. //发送消息
  2187. bool CTableFrame::SendGameMessage(LPCTSTR lpszMessage, WORD wType)
  2188. {
  2189. //变量定义
  2190. WORD wEnumIndex = 0;
  2191. //发送消息
  2192. for (WORD i = 0; i < m_wChairCount; i++)
  2193. {
  2194. //获取用户
  2195. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  2196. if ((pIServerUserItem == NULL) || (pIServerUserItem->IsClientReady() == false)) continue;
  2197. //发送消息
  2198. m_pIMainServiceFrame->SendGameMessage(pIServerUserItem, lpszMessage, wType);
  2199. }
  2200. //枚举用户
  2201. do
  2202. {
  2203. //获取用户
  2204. IServerUserItem * pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  2205. if (pIServerUserItem == NULL) break;
  2206. //效验状态
  2207. //ASSERT(pIServerUserItem->IsClientReady() == true);
  2208. //if (pIServerUserItem->IsClientReady() == false) return false;
  2209. //发送消息
  2210. m_pIMainServiceFrame->SendGameMessage(pIServerUserItem, lpszMessage, wType);
  2211. } while (true);
  2212. return true;
  2213. }
  2214. //房间消息
  2215. bool CTableFrame::SendRoomMessage(IServerUserItem * pIServerUserItem, LPCTSTR lpszMessage, WORD wType)
  2216. {
  2217. //用户效验
  2218. ASSERT(pIServerUserItem != NULL);
  2219. if (pIServerUserItem == NULL) return false;
  2220. //发送消息
  2221. m_pIMainServiceFrame->SendRoomMessage(pIServerUserItem, lpszMessage, wType);
  2222. return true;
  2223. }
  2224. //游戏消息
  2225. bool CTableFrame::SendGameMessage(IServerUserItem * pIServerUserItem, LPCTSTR lpszMessage, WORD wType)
  2226. {
  2227. //用户效验
  2228. ASSERT(pIServerUserItem != NULL);
  2229. if (pIServerUserItem == NULL) return false;
  2230. //发送消息
  2231. return m_pIMainServiceFrame->SendGameMessage(pIServerUserItem, lpszMessage, wType);
  2232. }
  2233. //发送场景
  2234. bool CTableFrame::SendGameScene(IServerUserItem * pIServerUserItem, VOID * pData, WORD wDataSize)
  2235. {
  2236. //用户效验
  2237. ASSERT(pIServerUserItem != NULL);
  2238. if (pIServerUserItem == NULL) return false;
  2239. if (m_cbGameStatus == 0)
  2240. {
  2241. CMD_S_StatusFree* pStat = (CMD_S_StatusFree*)pData;
  2242. if (m_bDismissVoteStarted)
  2243. {
  2244. auto now = time(0);
  2245. int aa = now - m_iLastDismissVoteTime;
  2246. aa = TIME_DISMISS_PRIVATE / 1000 - aa;
  2247. if (aa < 0)
  2248. {
  2249. aa = 0;
  2250. }
  2251. //投票过程中
  2252. pStat->leftTime = aa;
  2253. pStat->wchairId = w_SendChairID;
  2254. std::unordered_map<DWORD, int>::iterator iter_ = m_AgreeDeletePriTableUsers.begin();
  2255. int iNum = 0; int iNone = 0;
  2256. for (int i = 0; i < m_AgreeDeletePriTableUsers.size(); i++)
  2257. {
  2258. if (iter_->second == 1)
  2259. {
  2260. //同意解散
  2261. DWORD UserID = iter_->first;
  2262. IServerUserItem* pUser = SearchUserItem(UserID);
  2263. if (pUser)
  2264. {
  2265. WORD wChair = pUser->GetChairID();
  2266. ASSERT(wChair < GAME_PLAYER);
  2267. if (wChair <= GAME_PLAYER) pStat->options[wChair] = 1;
  2268. }
  2269. }
  2270. else if (iter_->second == 2)
  2271. {
  2272. //拒绝解散
  2273. DWORD UserID = iter_->first;
  2274. IServerUserItem* pUser = SearchUserItem(UserID);
  2275. if (pUser)
  2276. {
  2277. WORD wChair = pUser->GetChairID();
  2278. ASSERT(wChair < GAME_PLAYER);
  2279. if (wChair <= GAME_PLAYER) pStat->options[wChair] = 2;
  2280. }
  2281. }
  2282. iter_++;
  2283. }
  2284. }
  2285. else
  2286. {
  2287. //非投票时间
  2288. pStat->leftTime = 255;
  2289. }
  2290. //发送场景
  2291. ASSERT(m_pIMainServiceFrame != NULL);
  2292. GameInfo::PB_CS_S_StatusFree Status;
  2293. for (int i = 0; i < 4; i++)
  2294. {
  2295. Status.add_lusertmpscore(pStat->lUserTmpScore[i]);
  2296. }
  2297. Status.set_lefttime(pStat->leftTime);
  2298. Status.set_wchairid(pStat->wchairId);
  2299. for (int i = 0; i < 4; i++)
  2300. {
  2301. Status.add_options(pStat->options[i]);
  2302. }
  2303. Status.set_userstat(pStat->UserStat);
  2304. Status.mutable_gameconfig()->set_wsubgameid(pStat->gameConfig.wSubGameID);
  2305. Status.mutable_gameconfig()->set_wplayrule(pStat->gameConfig.wDiScore);
  2306. Status.mutable_gameconfig()->set_wmaxfanrule(pStat->gameConfig.wFanFei);
  2307. Status.mutable_gameconfig()->set_wmaxscore(pStat->gameConfig.wIpLimit);
  2308. Status.mutable_gameconfig()->set_wplaycountrule(pStat->gameConfig.wPlayCountRule);
  2309. Status.mutable_gameconfig()->set_whadplaycount(pStat->gameConfig.wHadPlayCount);
  2310. Status.mutable_gameconfig()->set_zmextrarule(pStat->gameConfig.IsOwner);
  2311. Status.mutable_gameconfig()->set_dghrule(pStat->gameConfig.RoomId);
  2312. std::string sPrivateTableID = CW2AEX<1024>(pStat->gameConfig.sPrivateTableID, CP_UTF8).m_psz;
  2313. Status.mutable_gameconfig()->set_sprivatetableid(sPrivateTableID);
  2314. Status.mutable_gameconfig()->set_bduolai(pStat->gameConfig.GameScoreType);
  2315. Status.mutable_gameconfig()->set_wfengding(pStat->gameConfig.tmp2);
  2316. Status.mutable_gameconfig()->set_tmp1(pStat->gameConfig.temp3);
  2317. //发送数据
  2318. std::string pbdata = Status.SerializePartialAsString();
  2319. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME,SUB_GF_GAME_SCENE, (void*)pbdata.c_str(), pbdata.length());
  2320. }
  2321. else
  2322. {
  2323. CMD_S_StatusPlay_ZhuJi* pStat = (CMD_S_StatusPlay_ZhuJi*)pData;
  2324. if (m_bDismissVoteStarted)
  2325. {
  2326. auto now = time(0);
  2327. int aa = now - m_iLastDismissVoteTime;
  2328. aa = TIME_DISMISS_PRIVATE / 1000 - aa;
  2329. if (aa < 0)
  2330. {
  2331. aa = 0;
  2332. }
  2333. //投票过程中
  2334. pStat->leftTime = aa;
  2335. pStat->wchairId = w_SendChairID;
  2336. std::unordered_map<DWORD, int>::iterator iter_ = m_AgreeDeletePriTableUsers.begin();
  2337. int iNum = 0; int iNone = 0;
  2338. for (int i = 0; i < m_AgreeDeletePriTableUsers.size(); i++)
  2339. {
  2340. if (iter_->second == 1)
  2341. {
  2342. //同意解散
  2343. DWORD UserID = iter_->first;
  2344. IServerUserItem* pUser = SearchUserItem(UserID);
  2345. if (pUser)
  2346. {
  2347. WORD wChair = pUser->GetChairID();
  2348. ASSERT(wChair < GAME_PLAYER);
  2349. if (wChair <= GAME_PLAYER) pStat->options[wChair] = 1;
  2350. }
  2351. }
  2352. else if (iter_->second == 2)
  2353. {
  2354. //拒绝解散
  2355. DWORD UserID = iter_->first;
  2356. IServerUserItem* pUser = SearchUserItem(UserID);
  2357. if (pUser)
  2358. {
  2359. WORD wChair = pUser->GetChairID();
  2360. ASSERT(wChair < GAME_PLAYER);
  2361. if (wChair <= GAME_PLAYER) pStat->options[wChair] = 2;
  2362. }
  2363. }
  2364. iter_++;
  2365. }
  2366. }
  2367. else
  2368. {
  2369. //非投票时间
  2370. pStat->leftTime = 255;
  2371. }
  2372. //发送场景
  2373. ASSERT(m_pIMainServiceFrame != NULL);
  2374. GameInfo::PB_CS_S_StatusPlay Status;
  2375. Status.mutable_gameconfig()->set_wsubgameid(pStat->gameConfig.wSubGameID);
  2376. Status.mutable_gameconfig()->set_wplayrule(pStat->gameConfig.wDiScore);
  2377. Status.mutable_gameconfig()->set_wmaxfanrule(pStat->gameConfig.wFanFei);
  2378. Status.mutable_gameconfig()->set_wmaxscore(pStat->gameConfig.wIpLimit);
  2379. Status.mutable_gameconfig()->set_wplaycountrule(pStat->gameConfig.wPlayCountRule);
  2380. Status.mutable_gameconfig()->set_whadplaycount(pStat->gameConfig.wHadPlayCount);
  2381. Status.mutable_gameconfig()->set_zmextrarule(pStat->gameConfig.IsOwner);
  2382. Status.mutable_gameconfig()->set_dghrule(pStat->gameConfig.RoomId);
  2383. std::string sPrivateTableID = CW2AEX<1024>(pStat->gameConfig.sPrivateTableID, CP_UTF8).m_psz;
  2384. Status.mutable_gameconfig()->set_sprivatetableid(sPrivateTableID);
  2385. Status.mutable_gameconfig()->set_bduolai(pStat->gameConfig.GameScoreType);
  2386. Status.mutable_gameconfig()->set_wfengding(pStat->gameConfig.tmp2);
  2387. Status.mutable_gameconfig()->set_tmp1(pStat->gameConfig.temp3);
  2388. for (int i = 0; i < 4; i++)
  2389. {
  2390. Status.add_lusertmpscore(pStat->lUserTmpScore[i]);
  2391. }
  2392. Status.set_lefttime(pStat->leftTime);
  2393. Status.set_wchairid(pStat->wchairId);
  2394. for (int i = 0; i < 4; i++)
  2395. {
  2396. Status.add_options(pStat->options[i]);
  2397. }
  2398. for (BYTE j = 0; j < GAME_PLAYER; j++)
  2399. {
  2400. Status.add_bputcarddata(pStat->bPutCardData[j]);
  2401. Status.add_cbcardcount(pStat->cbCardCount[j]);
  2402. Status.add_cbweavecount(pStat->cbWeaveCount[j]);
  2403. Status.add_cbdiscardcount(pStat->cbDiscardCount[j]);
  2404. GameInfo::pb_cbDiscardCard* DiscardCard = Status.add_cbdiscardcard();
  2405. for (BYTE i = 0; i < pStat->cbDiscardCount[j]; i++)
  2406. {
  2407. DiscardCard->add_cbdiscardcard(pStat->cbDiscardCard[j][i]);
  2408. }
  2409. //Status.add_cbdiscardcard(DiscardCard);
  2410. GameInfo::pb_WeaveItemArray* WeaveItemArray = Status.add_weaveitemarray();
  2411. for (BYTE i = 0; i < pStat->cbWeaveCount[j]; i++)
  2412. {
  2413. GameInfo::pb_WeaveItem* WeaveItem = WeaveItemArray->add_weaveitem();
  2414. WeaveItem->set_cbcentercard(pStat->WeaveItemArray[j][i].cbCenterCard);
  2415. WeaveItem->set_cbpubliccard(pStat->WeaveItemArray[j][i].cbPublicCard);
  2416. WeaveItem->set_cbweavekind(pStat->WeaveItemArray[j][i].cbWeaveKind);
  2417. WeaveItem->set_wprovideuser(pStat->WeaveItemArray[j][i].wProvideUser);
  2418. for (BYTE k = 0; k < 4; k++)
  2419. {
  2420. WeaveItem->add_cbmargicoffset(pStat->WeaveItemArray[j][i].cbMargicOffset[k]);
  2421. }
  2422. }
  2423. }
  2424. Status.set_cbtotalcardcount(pStat->cbTotalCardCount);
  2425. Status.set_cbleftcardcount(pStat->cbLeftCardCount);
  2426. Status.set_wbankeruser(pStat->wBankerUser);
  2427. for (BYTE j = 0; j < 4; j++)
  2428. {
  2429. Status.add_lsizi(pStat->lSiZi[j]);
  2430. }
  2431. for (BYTE j = 0; j < 14; j++)
  2432. {
  2433. Status.add_cbcarddata(pStat->cbCardData[j]);
  2434. }
  2435. Status.set_dwownerid(pStat->dwOwnerID);
  2436. Status.set_wcurrentuser(pStat->wCurrentUser);
  2437. Status.set_totalopttime(pStat->totalOptTime);
  2438. Status.set_leftopttime(pStat->leftOptTime);
  2439. Status.set_cbactionmask(pStat->cbActionMask);
  2440. for (BYTE j = 0; j < 6; j++)
  2441. {
  2442. Status.add_gangcards(pStat->gangCards[j]);
  2443. }
  2444. //发送数据
  2445. std::string pbdata = Status.SerializePartialAsString();
  2446. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME,SUB_GF_GAME_SCENEING, (void*)pbdata.c_str(), pbdata.length());
  2447. }
  2448. //开始判断
  2449. if ((pIServerUserItem->GetUserInfo()->cbUserStatus == US_READY) && (EfficacyStartGame(pIServerUserItem->GetUserInfo()->wChairID) == true))
  2450. {
  2451. StartGame();
  2452. }
  2453. return true;
  2454. }
  2455. //设置接口
  2456. bool CTableFrame::SetTableFrameHook(IUnknownEx * pIUnknownEx)
  2457. {
  2458. ASSERT(pIUnknownEx != NULL);
  2459. if (pIUnknownEx == NULL) return false;
  2460. //类型判断
  2461. if ((m_pGameServiceOption->wServerType&GAME_GENRE_MATCH) == 0) return false;
  2462. //查询接口
  2463. m_pITableFrameHook = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, ITableFrameHook);
  2464. m_pIMatchTableAction = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, ITableUserAction);
  2465. return true;
  2466. }
  2467. //上线事件
  2468. bool CTableFrame::OnEventUserOnLine(IServerUserItem * pIServerUserItem)
  2469. {
  2470. //modify by picker,2016-8-29,增加玩家掉线重连机制
  2471. WORD wChairID = pIServerUserItem->GetChairID();
  2472. if (wChairID > m_wChairCount) return false;
  2473. //添加校验
  2474. auto pIOldServerUserItem = GetTableUserItem(wChairID);
  2475. if (pIOldServerUserItem == NULL)return false;
  2476. if (pIOldServerUserItem->GetUserID() != pIServerUserItem->GetUserID())
  2477. {
  2478. TCHAR szString[512] = { 0 };
  2479. _sntprintf(szString, CountArray(szString), TEXT("断线重连失败:OnEventUserOnLine1:用户ID不匹配[ newUserID=%ld,oldUserID=%ld, tableID = %ld]"), pIServerUserItem->GetUserID(), pIOldServerUserItem->GetUserID(), _ttol(this->GetPrivateTableID().c_str()));
  2480. CTraceService::TraceString(szString, TraceLevel_Warning);
  2481. return false;
  2482. }
  2483. if (pIServerUserItem->GetTableID() != this->GetTableID())
  2484. {
  2485. TCHAR szString[512] = { 0 };
  2486. _sntprintf(szString, CountArray(szString), TEXT("断线重连校验:OnEventUserOnLine2:用户桌子ID不匹配[ pIServerUserItem=%ld,talbe=%ld, tableID = %ld]"), pIServerUserItem->GetTableID(), this->GetTableID(), _ttol(this->GetPrivateTableID().c_str()));
  2487. CTraceService::TraceString(szString, TraceLevel_Warning);
  2488. }
  2489. m_TableUserItemArray[wChairID] = pIServerUserItem;
  2490. if (IsGameStarted())
  2491. {
  2492. //设置状态
  2493. pIServerUserItem->SetUserStatus(US_PLAYING, m_wTableID, wChairID);
  2494. }
  2495. else
  2496. {
  2497. if (m_wDrawCount >= 1)
  2498. {
  2499. pIServerUserItem->SetUserStatus(US_PLAYINGWAIT, m_wTableID, wChairID);
  2500. }
  2501. else
  2502. {
  2503. pIServerUserItem->SetUserStatus(US_READY, m_wTableID, wChairID);
  2504. }
  2505. }
  2506. //发送桌子上所有用户信息
  2507. for (int j = 0; j < GetChairCount(); j++)
  2508. {
  2509. if (pIServerUserItem->GetChairID() == j) continue;
  2510. IServerUserItem * pUser = GetTableUserItem(j);
  2511. if (!pUser) continue;
  2512. //检验添加提示
  2513. if (pUser->GetUserInfo()->wTableID != this->GetTableID())
  2514. {
  2515. TCHAR szString[512] = { 0 };
  2516. _sntprintf(szString, CountArray(szString), TEXT("发现异常:OnEventUserOnLine3:用户ID不匹配[ userTableID=%ld,TableID=%ld,重连UserID=%ld,问题UserID=%ld,wChaird=%d,j=%d, PrivateTableID = %ld ]"), pUser->GetUserInfo()->wTableID, this->GetTableID(), pIServerUserItem->GetUserID(), pUser->GetUserID(), wChairID, j, _ttol(this->GetPrivateTableID().c_str()));
  2517. CTraceService::TraceString(szString, TraceLevel_Warning);
  2518. DismissGame();
  2519. return false;
  2520. }
  2521. //变量定义
  2522. tagMobileUserInfoHead pUserInfoHead;
  2523. tagUserInfo *pUserInfo = pUser->GetUserInfo();
  2524. //用户属性
  2525. pUserInfoHead.wFaceID = pUserInfo->wFaceID;
  2526. pUserInfoHead.dwGameID = pUserInfo->dwGameID;
  2527. pUserInfoHead.dwUserID = pUserInfo->dwUserID;
  2528. pUserInfoHead.dwCustomID = pUserInfo->dwCustomID;
  2529. //用户属性
  2530. pUserInfoHead.cbGender = pUserInfo->cbGender;
  2531. pUserInfoHead.cbMemberOrder = pUserInfo->cbMemberOrder;
  2532. //用户状态
  2533. pUserInfoHead.wTableID = pUserInfo->wTableID;
  2534. pUserInfoHead.wChairID = pUserInfo->wChairID;
  2535. pUserInfoHead.cbUserStatus = pUserInfo->cbUserStatus;
  2536. //用户局数
  2537. pUserInfoHead.dwWinCount = pUserInfo->dwWinCount;
  2538. pUserInfoHead.dwLostCount = pUserInfo->dwLostCount;
  2539. pUserInfoHead.dwDrawCount = pUserInfo->dwDrawCount;
  2540. pUserInfoHead.dwFleeCount = pUserInfo->dwFleeCount;
  2541. pUserInfoHead.dwExperience = pUserInfo->dwExperience;
  2542. //用户成绩
  2543. pUserInfoHead.lScore = pUserInfo->lScore;
  2544. pUserInfoHead.lScore += pUser->GetTrusteeScore();
  2545. pUserInfoHead.lScore += pUser->GetFrozenedScore();
  2546. pUserInfoHead.llDingWeiX = pUserInfo->dDingWeiX;
  2547. pUserInfoHead.llDingWeiY = pUserInfo->dDingWeiY;
  2548. pUserInfoHead.iJiePing = pUserInfo->llJiePing;
  2549. pUserInfoHead.iXinYong = pUserInfo->iXinYong;
  2550. lstrcpyn(pUserInfoHead.szNickname, pUserInfo->szNickName, CountArray(pUserInfo->szNickName));
  2551. //用户头像地址
  2552. lstrcpyn(pUserInfoHead.szHeadUrl, pUserInfo->szHeadUrl, CountArray(pUserInfo->szHeadUrl));
  2553. //IP地址
  2554. pUserInfoHead.dwClientAddr = pUser->GetClientAddr();
  2555. lstrcpyn(pUserInfoHead.RetTime, pUserInfo->RegisterDate, CountArray(pUserInfo->RegisterDate));
  2556. lstrcpyn(pUserInfoHead.ChengShi, pUserInfo->szChengShi, CountArray(pUserInfo->szChengShi));
  2557. UserInfo::PB_CS_S_tagMobileUserInfoHead UserInfoHead;
  2558. UserInfoHead.set_wfaceid(pUserInfoHead.wFaceID);
  2559. UserInfoHead.set_dwgameid(pUserInfoHead.dwGameID);
  2560. UserInfoHead.set_dwuserid(pUserInfoHead.dwUserID);
  2561. UserInfoHead.set_dwcustomid(pUserInfoHead.dwCustomID);
  2562. UserInfoHead.set_cbgender(pUserInfoHead.cbGender);
  2563. UserInfoHead.set_cbmemberorder(pUserInfoHead.cbMemberOrder);
  2564. UserInfoHead.set_wtableid(pUserInfoHead.wTableID);
  2565. UserInfoHead.set_wchairid(pUserInfoHead.wChairID);
  2566. UserInfoHead.set_cbuserstatus(pUserInfoHead.cbUserStatus);
  2567. UserInfoHead.set_lscore(pUserInfoHead.lScore);
  2568. UserInfoHead.set_dwwincount(pUserInfoHead.dwWinCount);
  2569. UserInfoHead.set_dwlostcount(pUserInfoHead.dwLostCount);
  2570. UserInfoHead.set_dwdrawcount(pUserInfoHead.dwDrawCount);
  2571. UserInfoHead.set_dwfleecount(pUserInfoHead.dwFleeCount);
  2572. UserInfoHead.set_dwexperience(pUserInfoHead.dwExperience);
  2573. std::string szNickname = CW2AEX<1024>(pUserInfoHead.szNickname, CP_UTF8).m_psz;
  2574. std::string szHeadUrl = CW2AEX<1024>(pUserInfoHead.szHeadUrl, CP_UTF8).m_psz;
  2575. std::string RetTime = CW2AEX<1024>(pUserInfoHead.RetTime, CP_UTF8).m_psz;
  2576. std::string ChengShi = CW2AEX<1024>(pUserInfoHead.ChengShi, CP_UTF8).m_psz;
  2577. UserInfoHead.set_sznickname(szNickname);
  2578. UserInfoHead.set_szheadurl(szHeadUrl);
  2579. UserInfoHead.set_dwclientaddr(pUserInfoHead.dwClientAddr);
  2580. UserInfoHead.set_ixinyong(pUserInfoHead.iXinYong);
  2581. UserInfoHead.set_rettime(RetTime);
  2582. UserInfoHead.set_chengshi(ChengShi);
  2583. UserInfoHead.set_lldingweix(pUserInfoHead.llDingWeiX);
  2584. UserInfoHead.set_lldingweiy(pUserInfoHead.llDingWeiY);
  2585. UserInfoHead.set_ijieping(pUserInfoHead.iJiePing);
  2586. //发送数据
  2587. std::string pbdata = UserInfoHead.SerializePartialAsString();
  2588. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_USER_ENTER, (void*)pbdata.c_str(), pbdata.length());
  2589. }
  2590. //发送场景
  2591. bool bRet1 = m_pITableFrameSink->OnEventSendGameScene(pIServerUserItem->GetChairID(), pIServerUserItem, m_cbGameStatus, true);
  2592. pIServerUserItem->SetClientReady(true);
  2593. //重入
  2594. bool bRet2 = m_pITableUserAction->OnActionUserConnect(pIServerUserItem->GetChairID(), pIServerUserItem);
  2595. return bRet1 && bRet2;
  2596. }
  2597. //断线事件
  2598. bool CTableFrame::OnEventUserOffLine(IServerUserItem * pIServerUserItem)
  2599. {
  2600. //参数效验
  2601. ASSERT(pIServerUserItem != NULL);
  2602. if (pIServerUserItem == NULL) return false;
  2603. //用户变量
  2604. tagUserInfo * pUserInfo = pIServerUserItem->GetUserInfo();
  2605. IServerUserItem * pITableUserItem = m_TableUserItemArray[pUserInfo->wChairID];
  2606. //用户属性
  2607. WORD wChairID = pIServerUserItem->GetChairID();
  2608. BYTE cbUserStatus = pIServerUserItem->GetUserStatus();
  2609. //游戏用户
  2610. if (cbUserStatus != US_LOOKON)
  2611. {
  2612. //效验用户
  2613. ASSERT(pIServerUserItem == GetTableUserItem(wChairID));
  2614. if (pIServerUserItem != GetTableUserItem(wChairID)) return false;
  2615. //断线处理
  2616. if (!m_sPrivateTableID.empty()
  2617. || ((cbUserStatus == US_PLAYING) && (m_wOffLineCount[wChairID] < MAX_OFF_LINE)))
  2618. {
  2619. //用户设置
  2620. pIServerUserItem->SetClientReady(false);
  2621. pIServerUserItem->SetUserStatus(US_OFFLINE, m_wTableID, wChairID);
  2622. //比赛类型
  2623. if (m_pGameServiceOption->wServerType == GAME_GENRE_MATCH)
  2624. {
  2625. if (pIServerUserItem->IsTrusteeUser() == false)
  2626. {
  2627. //设置托管
  2628. pIServerUserItem->SetTrusteeUser(true);
  2629. //掉线通知
  2630. if (m_pITableUserAction != NULL) m_pITableUserAction->OnActionUserOffLine(wChairID, pIServerUserItem);
  2631. }
  2632. return true;
  2633. }
  2634. //掉线通知
  2635. if (m_pITableUserAction != NULL) m_pITableUserAction->OnActionUserOffLine(wChairID, pIServerUserItem);
  2636. //断线处理
  2637. if (m_dwOffLineTime[wChairID] == 0L && m_sPrivateTableID.empty())
  2638. {
  2639. //设置变量
  2640. m_wOffLineCount[wChairID]++;
  2641. m_dwOffLineTime[wChairID] = (DWORD)time(NULL);
  2642. //时间设置
  2643. WORD wOffLineCount = GetOffLineUserCount();
  2644. if (wOffLineCount == 1)
  2645. SetGameTimer(IDI_OFF_LINE, TIME_OFF_LINE, 1, wChairID);
  2646. }
  2647. return true;
  2648. }
  2649. }
  2650. PerformStandUpAction(pIServerUserItem, true);
  2651. if (m_pGameServiceOption->wServerType == GAME_GENRE_MATCH)
  2652. {
  2653. if (pIServerUserItem->IsTrusteeUser() == true)
  2654. return true;
  2655. }
  2656. //删除用户
  2657. ASSERT(pIServerUserItem->GetUserStatus() == US_FREE);
  2658. pIServerUserItem->SetUserStatus(US_NULL, INVALID_TABLE, INVALID_CHAIR);
  2659. return true;
  2660. }
  2661. //积分事件
  2662. bool CTableFrame::OnUserScroeNotify(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason)
  2663. {
  2664. //通知游戏
  2665. return m_pITableFrameSink->OnUserScroeNotify(wChairID, pIServerUserItem, cbReason);
  2666. }
  2667. //时间事件
  2668. bool CTableFrame::OnEventTimer(DWORD dwTimerID, WPARAM dwBindParameter)
  2669. {
  2670. //回调事件
  2671. if ((dwTimerID >= 0) && (dwTimerID < TIME_TABLE_SINK_RANGE))
  2672. {
  2673. ASSERT(m_pITableFrameSink != NULL);
  2674. return m_pITableFrameSink->OnTimerMessage(dwTimerID, dwBindParameter);
  2675. }
  2676. //事件处理
  2677. switch (dwTimerID)
  2678. {
  2679. case IDI_START_DISMISS_PRIVATE://申请解散私有房间超时
  2680. {
  2681. int iNum = 0; int iNone = 0;
  2682. for (std::unordered_map<DWORD, int>::iterator iter = m_AgreeDeletePriTableUsers.begin(); iter != m_AgreeDeletePriTableUsers.end(); iter++)
  2683. {
  2684. if (iter->second == 1) iNum++; //同意解散
  2685. else if (iter->second == 2) iNone++;//拒绝解散
  2686. }
  2687. iNum = iNum + (m_wChairCount - iNum - iNone);
  2688. //if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5) ///---modify by yd 2017-12-26 产品变更解散规则
  2689. {
  2690. //戳瞎子
  2691. if (iNone >= 1)
  2692. {
  2693. DeletePrivateResult(0, TEXT("有玩家反对,不能解散房间."));
  2694. if (m_pIMainServiceFrame->IsJC(8888))
  2695. {
  2696. //输出信息
  2697. TCHAR szBuffer[128] = TEXT("");
  2698. TCHAR szTemp[32] = { 0 };
  2699. this->GetPrivateTableID(szTemp, 32);
  2700. _sntprintf(szBuffer, CountArray(szBuffer), TEXT("有玩家反对,不能解散房间. 同意[ %d ], 拒绝 [ %d ], 好友房标识 [ %d ]."), iNum, iNone, szTemp);
  2701. //输出信息
  2702. CTraceService::TraceString(szBuffer, TraceLevel_Normal);
  2703. }
  2704. return true;
  2705. }
  2706. else
  2707. {
  2708. m_bJieSan = true;
  2709. if (m_pIMainServiceFrame->IsJC(8888))
  2710. {
  2711. //输出信息
  2712. TCHAR szBuffer[128] = TEXT("");
  2713. TCHAR szTemp[32] = { 0 };
  2714. this->GetPrivateTableID(szTemp, 32);
  2715. _sntprintf(szBuffer, CountArray(szBuffer), TEXT("根据少数服从多数的原则,房间已成功解散! 同意[ %d ], 拒绝 [ %d ], 好友房标识 [ %d ]."), iNum, iNone, szTemp);
  2716. //输出信息
  2717. CTraceService::TraceString(szBuffer, TraceLevel_Normal);
  2718. }
  2719. return DeletePrivateResult(1, TEXT("全数玩家同意,房间已成功解散!"));
  2720. }
  2721. }
  2722. //else
  2723. //{
  2724. // if (iNone >= 2)
  2725. // {
  2726. // DeletePrivateResult(0, TEXT("根据少数服从多数的原则,不能解散房间."));
  2727. // if (m_pIMainServiceFrame->IsJC(8888))
  2728. // {
  2729. // //输出信息
  2730. // TCHAR szBuffer[128] = TEXT("");
  2731. // TCHAR szTemp[32] = { 0 };
  2732. // this->GetPrivateTableID(szTemp, 32);
  2733. // _sntprintf(szBuffer, CountArray(szBuffer), TEXT("根据少数服从多数的原则,不能解散房间. 同意[ %d ], 拒绝 [ %d ], 好友房标识 [ %d ]."), iNum, iNone, szTemp);
  2734. // //输出信息
  2735. // CTraceService::TraceString(szBuffer, TraceLevel_Normal);
  2736. // }
  2737. // return true;
  2738. // }
  2739. // else
  2740. // {
  2741. // m_bJieSan = true;
  2742. // if (m_pIMainServiceFrame->IsJC(8888))
  2743. // {
  2744. // //输出信息
  2745. // TCHAR szBuffer[128] = TEXT("");
  2746. // TCHAR szTemp[32] = { 0 };
  2747. // this->GetPrivateTableID(szTemp, 32);
  2748. // _sntprintf(szBuffer, CountArray(szBuffer), TEXT("根据少数服从多数的原则,房间已成功解散! 同意[ %d ], 拒绝 [ %d ], 好友房标识 [ %d ]."), iNum, iNone, szTemp);
  2749. // //输出信息
  2750. // CTraceService::TraceString(szBuffer, TraceLevel_Normal);
  2751. // }
  2752. // return DeletePrivateResult(1, TEXT("根据少数服从多数的原则,房间已成功解散!"));
  2753. // }
  2754. //}
  2755. return true;
  2756. }break;
  2757. case IDI_START_TIME://创建私有房间,超时未开始检测。
  2758. {
  2759. KillGameTimer(IDI_START_TIME);
  2760. //检查游戏状态是否开始。
  2761. if (this->GetStartCount() == 0)
  2762. {
  2763. //返还房主冻结元宝
  2764. UnAdminLockBeans();
  2765. //让所有人返回大厅,解散。
  2766. for (WORD i = 0; i < m_wChairCount; i++)
  2767. {
  2768. //获取用户
  2769. if (m_TableUserItemArray[i] == NULL) continue;
  2770. IServerUserItem * pIServerUserItem = m_TableUserItemArray[i];
  2771. SendGameMessage(pIServerUserItem, TEXT("此游戏桌已经超时解散了!"), SMT_TABLE_EXIT);
  2772. //用户起立
  2773. PerformStandUpAction(pIServerUserItem, false, true);
  2774. }
  2775. //发送消息
  2776. for (INT_PTR i = 0; i < m_LookonUserItemArray.GetCount(); i++)
  2777. {
  2778. //获取用户
  2779. IServerUserItem * pILookonUserItem = m_LookonUserItemArray[i];
  2780. if (pILookonUserItem == NULL) continue;
  2781. //发送消息
  2782. SendGameMessage(pILookonUserItem, TEXT("此游戏桌已经超时解散了!"), SMT_TABLE_EXIT);
  2783. //用户离开
  2784. PerformStandUpAction(pILookonUserItem, false, true);
  2785. }
  2786. DeletePrivateTableNow();
  2787. return true;
  2788. }
  2789. }
  2790. break;
  2791. case IDI_STARTED_TIME:
  2792. {
  2793. KillGameTimer(IDI_STARTED_TIME);
  2794. return DeletePrivateStarted(1, TEXT("房间超时,房间已成功解散!"));
  2795. }
  2796. break;
  2797. case IDI_OFF_LINE: //断线事件
  2798. {
  2799. //效验状态
  2800. ASSERT(m_bGameStarted == true);
  2801. if (m_bGameStarted == false) return false;
  2802. //变量定义
  2803. DWORD dwOffLineTime = 0L;
  2804. WORD wOffLineChair = INVALID_CHAIR;
  2805. //寻找用户
  2806. for (WORD i = 0; i < m_wChairCount; i++)
  2807. {
  2808. if ((m_dwOffLineTime[i] != 0L) && ((m_dwOffLineTime[i] < dwOffLineTime) || (wOffLineChair == INVALID_CHAIR)))
  2809. {
  2810. wOffLineChair = i;
  2811. dwOffLineTime = m_dwOffLineTime[i];
  2812. }
  2813. }
  2814. //位置判断
  2815. ASSERT(wOffLineChair != INVALID_CHAIR);
  2816. if (wOffLineChair == INVALID_CHAIR) return false;
  2817. //用户判断
  2818. ASSERT(dwBindParameter < m_wChairCount);
  2819. if (wOffLineChair != (WORD)dwBindParameter)
  2820. {
  2821. //时间计算
  2822. DWORD dwCurrentTime = (DWORD)time(NULL);
  2823. DWORD dwLapseTime = dwCurrentTime - m_dwOffLineTime[wOffLineChair];
  2824. //设置时间
  2825. dwLapseTime = __min(dwLapseTime, TIME_OFF_LINE - 2000L);
  2826. SetGameTimer(IDI_OFF_LINE, TIME_OFF_LINE - dwLapseTime, 1, wOffLineChair);
  2827. return true;
  2828. }
  2829. //获取用户
  2830. ASSERT(GetTableUserItem(wOffLineChair) != NULL);
  2831. IServerUserItem * pIServerUserItem = GetTableUserItem(wOffLineChair);
  2832. //结束游戏
  2833. if (pIServerUserItem != NULL)
  2834. {
  2835. //设置变量
  2836. m_dwOffLineTime[wOffLineChair] = 0L;
  2837. //用户起立
  2838. PerformStandUpAction(pIServerUserItem);
  2839. }
  2840. //继续时间
  2841. if (m_bGameStarted == true)
  2842. {
  2843. //变量定义
  2844. DWORD dwOffLineTime = 0L;
  2845. WORD wOffLineChair = INVALID_CHAIR;
  2846. //寻找用户
  2847. for (WORD i = 0; i < m_wChairCount; i++)
  2848. {
  2849. if ((m_dwOffLineTime[i] != 0L) && ((m_dwOffLineTime[i] < dwOffLineTime) || (wOffLineChair == INVALID_CHAIR)))
  2850. {
  2851. wOffLineChair = i;
  2852. dwOffLineTime = m_dwOffLineTime[i];
  2853. }
  2854. }
  2855. //设置时间
  2856. if (wOffLineChair != INVALID_CHAIR)
  2857. {
  2858. //时间计算
  2859. DWORD dwCurrentTime = (DWORD)time(NULL);
  2860. DWORD dwLapseTime = dwCurrentTime - m_dwOffLineTime[wOffLineChair];
  2861. //设置时间
  2862. dwLapseTime = __min(dwLapseTime, TIME_OFF_LINE - 2000L);
  2863. SetGameTimer(IDI_OFF_LINE, TIME_OFF_LINE - dwLapseTime, 1, wOffLineChair);
  2864. }
  2865. }
  2866. return true;
  2867. }
  2868. }
  2869. //未开始超时
  2870. if (dwTimerID >= IDI_START_OVERTIME && dwTimerID <= IDI_START_OVERTIME_END)
  2871. {
  2872. //变量定义
  2873. WORD wChair = (WORD)dwBindParameter;
  2874. //
  2875. if (wChair != (WORD)(dwTimerID - IDI_START_OVERTIME)) return false;
  2876. //获取用户
  2877. IServerUserItem * pIServerUserItem = GetTableUserItem(wChair);
  2878. //超时处理
  2879. if (pIServerUserItem && pIServerUserItem->GetUserStatus() == US_SIT)
  2880. {
  2881. //用户起立
  2882. PerformStandUpAction(pIServerUserItem);
  2883. }
  2884. return false;
  2885. }
  2886. //错误断言
  2887. ASSERT(FALSE);
  2888. return false;
  2889. }
  2890. //游戏事件
  2891. bool CTableFrame::OnEventSocketGame(WORD wSubCmdID, VOID * pData, WORD wDataSize, IServerUserItem * pIServerUserItem)
  2892. {
  2893. //效验参数
  2894. ASSERT(pIServerUserItem != NULL);
  2895. ASSERT(m_pITableFrameSink != NULL);
  2896. //消息处理
  2897. return m_pITableFrameSink->OnGameMessage(wSubCmdID, pData, wDataSize, pIServerUserItem);
  2898. }
  2899. //设置游戏配置
  2900. void CTableFrame::OnEventSetGameConfig(VOID * pData, WORD wDataSize, std::wstring sPrivateRoomId)
  2901. {
  2902. //效验参数
  2903. ASSERT(m_pITableFrameSink != NULL);
  2904. this->GetChairCount();
  2905. //消息处理
  2906. return this->m_pITableFrameSink->SetGameConfig(pData, wDataSize, sPrivateRoomId);
  2907. }
  2908. //框架事件
  2909. bool CTableFrame::OnEventSocketFrame(WORD wSubCmdID, VOID * pData, WORD wDataSize, IServerUserItem * pIServerUserItem)
  2910. {
  2911. //游戏处理
  2912. if (m_pITableFrameSink->OnFrameMessage(wSubCmdID, pData, wDataSize, pIServerUserItem) == true) return true;
  2913. //默认处理
  2914. switch (wSubCmdID)
  2915. {
  2916. case SUB_GF_GAME_OPTION: //游戏配置
  2917. {
  2918. return false;
  2919. //效验参数
  2920. //ASSERT(wDataSize == sizeof(CMD_GF_GameOption));
  2921. //if (wDataSize != sizeof(CMD_GF_GameOption)) return false;
  2922. //变量定义
  2923. //CMD_GF_GameOption * pGameOption = (CMD_GF_GameOption *)pData;
  2924. //获取属性
  2925. WORD wChairID = pIServerUserItem->GetChairID();
  2926. BYTE cbUserStatus = pIServerUserItem->GetUserStatus();
  2927. //断线清理
  2928. if ((cbUserStatus != US_LOOKON) && ((m_dwOffLineTime[wChairID] != 0L)))
  2929. {
  2930. //设置变量
  2931. m_dwOffLineTime[wChairID] = 0L;
  2932. //删除时间
  2933. WORD wOffLineCount = GetOffLineUserCount();
  2934. if (wOffLineCount == 0) KillGameTimer(IDI_OFF_LINE);
  2935. }
  2936. //设置状态
  2937. pIServerUserItem->SetClientReady(true);
  2938. //if (cbUserStatus != US_LOOKON) m_bAllowLookon[wChairID] = pGameOption->cbAllowLookon ? true : false;
  2939. //发送状态
  2940. //CMD_GF_GameStatus GameStatus;
  2941. //GameStatus.cbGameStatus = m_cbGameStatus;
  2942. //GameStatus.cbAllowLookon = m_bAllowLookon[wChairID] ? TRUE : FALSE;
  2943. //m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GF_GAME_STATUS, &GameStatus, sizeof(GameStatus));
  2944. //发送消息
  2945. //TCHAR szMessage[128] = TEXT("");
  2946. //_sntprintf(szMessage, CountArray(szMessage), TEXT("欢迎您进入“%s”游戏,祝您游戏愉快!"), m_pGameServiceAttrib->szGameName);
  2947. //m_pIMainServiceFrame->SendGameMessage(pIServerUserItem, szMessage, SMT_CHAT);
  2948. //发送场景
  2949. bool bSendSecret = ((cbUserStatus != US_LOOKON) || (m_bAllowLookon[wChairID] == true));
  2950. m_pITableFrameSink->OnEventSendGameScene(wChairID, pIServerUserItem, m_cbGameStatus, bSendSecret);
  2951. //取消托管
  2952. if (m_pGameServiceOption->wServerType == GAME_GENRE_MATCH)
  2953. {
  2954. if (pIServerUserItem->IsTrusteeUser() == true)
  2955. {
  2956. //设置托管
  2957. pIServerUserItem->SetTrusteeUser(false);
  2958. }
  2959. //回归通知
  2960. //if(m_pITableFrameHook) m_pITableFrameHook->OnUserBackMatch(this,pIServerUserItem);
  2961. }
  2962. //开始判断
  2963. if ((cbUserStatus == US_READY) && (EfficacyStartGame(wChairID) == true))
  2964. {
  2965. StartGame();
  2966. }
  2967. return true;
  2968. }
  2969. case SUB_GF_USER_READY: //用户准备
  2970. {
  2971. //获取属性
  2972. WORD wChairID = pIServerUserItem->GetChairID();
  2973. BYTE cbUserStatus = pIServerUserItem->GetUserStatus();
  2974. //效验状态
  2975. ASSERT(GetTableUserItem(wChairID) == pIServerUserItem);
  2976. if (GetTableUserItem(wChairID) != pIServerUserItem) return false;
  2977. //效验状态
  2978. //ASSERT(cbUserStatus==US_SIT);
  2979. if (cbUserStatus != US_SIT
  2980. && cbUserStatus != US_PLAYINGWAIT) return true;
  2981. //防作弊分组判断
  2982. if ((CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule) && (m_pGameServiceAttrib->wChairCount < MAX_CHAIR))
  2983. && (m_wDrawCount >= m_pGameServiceOption->wDistributeDrawCount || CheckDistribute()))
  2984. {
  2985. //发送消息
  2986. LPCTSTR pszMessage = TEXT("系统重新分配桌子,请稍后!");
  2987. SendRequestFailure(pIServerUserItem, pszMessage, 0);
  2988. //发送消息
  2989. m_pIMainServiceFrame->InsertDistribute(pIServerUserItem);
  2990. ////用户起立
  2991. //PerformStandUpAction(pIServerUserItem);
  2992. return true;
  2993. }
  2994. //事件通知
  2995. if (m_pIMatchTableAction != NULL && !m_pIMatchTableAction->OnActionUserOnReady(wChairID, pIServerUserItem, pData, wDataSize))
  2996. {
  2997. return true;
  2998. }
  2999. //事件通知
  3000. if (m_pITableUserAction != NULL)
  3001. {
  3002. m_pITableUserAction->OnActionUserOnReady(wChairID, pIServerUserItem, pData, wDataSize);
  3003. }
  3004. if (m_sPrivateTableID.empty())
  3005. {
  3006. //删除定时
  3007. if (m_pGameServiceAttrib->wChairCount < MAX_CHAIR) KillGameTimer(IDI_START_OVERTIME + wChairID);
  3008. }
  3009. pIServerUserItem->SetClientReady(true);
  3010. //设置状态
  3011. pIServerUserItem->SetUserStatus(US_READY, m_wTableID, wChairID);
  3012. if (m_wStartCount > 0)
  3013. {
  3014. m_GameRead[wChairID] = true;
  3015. }
  3016. //开始判断
  3017. if (EfficacyStartGame(wChairID))
  3018. {
  3019. USER_SHUFFLE_ALL_ACK ss;
  3020. ZeroMemory(&ss, sizeof(ss));
  3021. DWORD dwUserID = INVALID_DWORD, nIndex = 0;
  3022. for (WORD i = 0; i < m_wChairCount; i++)
  3023. {
  3024. if (!m_GameShuffleRead[i])continue;
  3025. lstrcpyn(ss.dwUserName[nIndex], m_TableUserItemArray[i]->GetNickName(), CountArray(ss.dwUserName[nIndex]));
  3026. dwUserID = m_TableUserItemArray[i]->GetUserID();
  3027. DeductWLZuanshi(dwUserID);//开始洗牌 准备扣钻
  3028. nIndex++;
  3029. }
  3030. ss.cbCount = nIndex;
  3031. GameInfo::PB_CS_S_SHUFFLE_ALL_ACK Shuffle;
  3032. Shuffle.set_cbcount(ss.cbCount);
  3033. for (WORD i = 0; i < m_wChairCount; i++)
  3034. {
  3035. GameInfo::pb_dwUserName* UserName = Shuffle.add_dwusername();
  3036. std::string dwUserName = CW2AEX<1024>(ss.dwUserName[i], CP_UTF8).m_psz;
  3037. UserName->set_dwusername(dwUserName);
  3038. }
  3039. //发送数据
  3040. std::string pbdata = Shuffle.SerializePartialAsString();
  3041. //发送消息
  3042. if (0 < nIndex) SendTableData(INVALID_CHAIR, SUB_GF_USER_SHUFFLE_ALL_ACK, (void*)pbdata.c_str(), pbdata.length());
  3043. StartGame();
  3044. }
  3045. return true;
  3046. }
  3047. case SUB_GF_USER_SHUFFLE: //洗牌准备
  3048. {
  3049. //获取属性
  3050. WORD wChairID = pIServerUserItem->GetChairID();
  3051. BYTE cbUserStatus = pIServerUserItem->GetUserStatus();
  3052. //效验状态
  3053. ASSERT(GetTableUserItem(wChairID) == pIServerUserItem);
  3054. if (GetTableUserItem(wChairID) != pIServerUserItem) return false;
  3055. //效验状态
  3056. //ASSERT(cbUserStatus==US_SIT);
  3057. if (cbUserStatus != US_SIT
  3058. && cbUserStatus != US_PLAYINGWAIT) return true;
  3059. if (m_sPrivateTableID.empty())
  3060. {
  3061. //删除定时
  3062. if (m_pGameServiceAttrib->wChairCount < MAX_CHAIR) KillGameTimer(IDI_START_OVERTIME + wChairID);
  3063. }
  3064. pIServerUserItem->SetClientReady(true);
  3065. //设置状态
  3066. pIServerUserItem->SetUserStatus(US_READY, m_wTableID, wChairID);
  3067. if (m_wStartCount > 0)
  3068. {
  3069. m_GameRead[wChairID] = true;
  3070. m_GameShuffleRead[wChairID] = true;
  3071. }
  3072. //开始判断
  3073. if (EfficacyStartGame(wChairID))
  3074. {
  3075. USER_SHUFFLE_ALL_ACK ss;
  3076. ZeroMemory(&ss, sizeof(ss));
  3077. DWORD dwUserID = INVALID_DWORD, nIndex = 0;
  3078. for (WORD i = 0; i < m_wChairCount; i++)
  3079. {
  3080. if (!m_GameShuffleRead[i])continue;
  3081. lstrcpyn(ss.dwUserName[nIndex], m_TableUserItemArray[i]->GetNickName(), CountArray(ss.dwUserName[nIndex]));
  3082. dwUserID = m_TableUserItemArray[i]->GetUserID();
  3083. DeductWLZuanshi(dwUserID);//开始洗牌 准备扣钻
  3084. nIndex++;
  3085. }
  3086. ss.cbCount = nIndex;
  3087. GameInfo::PB_CS_S_SHUFFLE_ALL_ACK Shuffle;
  3088. Shuffle.set_cbcount(ss.cbCount);
  3089. for (WORD i = 0; i < m_wChairCount; i++)
  3090. {
  3091. GameInfo::pb_dwUserName* UserName = Shuffle.add_dwusername();
  3092. std::string dwUserName = CW2AEX<1024>(ss.dwUserName[i], CP_UTF8).m_psz;
  3093. UserName->set_dwusername(dwUserName);
  3094. }
  3095. //发送数据
  3096. std::string pbdata = Shuffle.SerializePartialAsString();
  3097. //发送消息
  3098. if (0 < nIndex) SendTableData(INVALID_CHAIR, SUB_GF_USER_SHUFFLE_ALL_ACK, (void*)pbdata.c_str(), pbdata.length());
  3099. StartGame();
  3100. }
  3101. return true;
  3102. }
  3103. case SUB_GF_GAME_USER_DISTANCE: //玩家距离 @yuanjing
  3104. {
  3105. //获取属性
  3106. WORD wChairID = pIServerUserItem->GetChairID();
  3107. BYTE cbUserStatus = pIServerUserItem->GetUserStatus();
  3108. //效验状态
  3109. ASSERT(GetTableUserItem(wChairID) == pIServerUserItem);
  3110. if (GetTableUserItem(wChairID) != pIServerUserItem) return false;
  3111. //效验状态
  3112. //if (cbUserStatus != US_SIT) return false;
  3113. //构造消息
  3114. CMD_GF_UserDistance UserDistance;
  3115. ZeroMemory(&UserDistance, sizeof(UserDistance));
  3116. //游戏用户
  3117. WORD count = 0;
  3118. for (WORD i = 0; i < GAME_PLAYER; i++)
  3119. {
  3120. //获取用户
  3121. IServerUserItem * pIServerUserItem1 = GetTableUserItem(i);
  3122. //位置没有用户
  3123. if (pIServerUserItem1 == NULL)
  3124. {
  3125. //该位置没用户则与其他位置距离为0;
  3126. for (WORD k = i + 1; k < GAME_PLAYER; k++)
  3127. {
  3128. UserDistance.dwUserDistance[count++] = 0;
  3129. }
  3130. //所以当前位置定位也没有开启(未开启=0,开启=1)
  3131. UserDistance.cbOperLocation[i] = 0;
  3132. continue;
  3133. }
  3134. //位置不为空则获取当前位置用户的坐标
  3135. BaiDuMap aa;
  3136. LONGLONG llx1 = pIServerUserItem1->GetUserInfo()->dDingWeiX;
  3137. LONGLONG lly1 = pIServerUserItem1->GetUserInfo()->dDingWeiY;
  3138. double dX1 = (double)llx1 / (double)1000000;
  3139. double dY1 = (double)lly1 / (double)1000000;
  3140. //判断当前位置用户是否开启定位
  3141. if ((int)dX1 != 0 && (int)dY1 != 0)
  3142. {
  3143. UserDistance.cbOperLocation[i] = 1;
  3144. }
  3145. else
  3146. {
  3147. UserDistance.cbOperLocation[i] = 0;
  3148. }
  3149. for (WORD j = i + 1; j < GAME_PLAYER; j++)
  3150. {
  3151. //获取用户
  3152. IServerUserItem * pIServerUserItem2 = GetTableUserItem(j);
  3153. //该位置没有用户
  3154. if (pIServerUserItem2 == NULL)
  3155. {
  3156. //该位置没有用户则距离设置为0
  3157. UserDistance.dwUserDistance[count++] = 0;
  3158. continue;
  3159. }
  3160. //该位置有用户
  3161. LONGLONG llx2 = pIServerUserItem2->GetUserInfo()->dDingWeiX;
  3162. LONGLONG lly2 = pIServerUserItem2->GetUserInfo()->dDingWeiY;
  3163. double dX2 = (double)llx2 / (double)1000000;
  3164. double dY2 = (double)lly2 / (double)1000000;
  3165. if ((int)dX1 != 0 && (int)dY1 != 0 && (int)dX2 != 0 && (int)dY2 != 0)
  3166. {
  3167. double dRet = aa.GetShortDistance(dX1, dY1, dX2, dY2);
  3168. if (dRet >= 2000)
  3169. {
  3170. dRet = 2000;
  3171. }
  3172. UserDistance.dwUserDistance[count++] = (int)dRet;
  3173. }
  3174. else
  3175. {
  3176. UserDistance.dwUserDistance[count++] = 0;
  3177. }
  3178. }
  3179. }
  3180. GameInfo::PB_CS_S_UserDistance Distance;
  3181. for (WORD i = 0; i < 4; i++)
  3182. {
  3183. Distance.add_cboperlocation(UserDistance.cbOperLocation[i]);
  3184. }
  3185. for (WORD i = 0; i < 6; i++)
  3186. {
  3187. Distance.add_dwuserdistance(UserDistance.dwUserDistance[i]);
  3188. }
  3189. //发送数据
  3190. std::string pbdata = Distance.SerializePartialAsString();
  3191. //只发送个当前用户
  3192. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GF_GAME_USER_DISTANCE, (void*)pbdata.c_str(), pbdata.length());
  3193. return true;
  3194. }
  3195. case SUB_GF_USER_CHAT: //用户聊天
  3196. {
  3197. //效验参数
  3198. GameInfo::PB_CS_UserChat UserChats;
  3199. UserChats.ParseFromArray(pData, wDataSize);
  3200. //处理消息
  3201. CMD_GF_C_UserChat pUserChat;
  3202. ZeroMemory(&pUserChat, sizeof(pUserChat));
  3203. pUserChat.wChatLength = UserChats.wchatlength();
  3204. pUserChat.dwChatColor = UserChats.dwchatcolor();
  3205. pUserChat.dwTargetUserID = UserChats.dwtargetuserid();
  3206. CString szchatstring = (CA2CTEX<2048>(UserChats.szchatstring().c_str(), CP_UTF8)).m_szBuffer;
  3207. CopyMemory(pUserChat.szChatString, szchatstring, sizeof(pUserChat.szChatString));
  3208. //目标用户
  3209. if ((pUserChat.dwTargetUserID != 0) && (SearchUserItem(pUserChat.dwTargetUserID) == NULL))
  3210. {
  3211. ASSERT(FALSE);
  3212. return true;
  3213. }
  3214. //状态判断
  3215. if ((CServerRule::IsForfendGameChat(m_pGameServiceOption->dwServerRule) == true) && (pIServerUserItem->GetMasterOrder() == 0L))
  3216. {
  3217. SendRequestFailure(pIServerUserItem, TEXT("抱歉,当前游戏房间禁止游戏聊天!"), 0);
  3218. return true;
  3219. }
  3220. //权限判断
  3221. if (CUserRight::CanRoomChat(pIServerUserItem->GetUserRight()) == false)
  3222. {
  3223. SendRequestFailure(pIServerUserItem, TEXT("抱歉,您没有游戏聊天的权限,若需要帮助,请联系游戏客服咨询!"), 0);
  3224. //SendGameMessage(pIServerUserItem, TEXT("抱歉,您没有游戏聊天的权限,若需要帮助,请联系游戏客服咨询!"), SMT_EJECT | SMT_CHAT);
  3225. return true;
  3226. }
  3227. //构造消息
  3228. CMD_GF_S_UserChat UserChat;
  3229. ZeroMemory(&UserChat, sizeof(UserChat));
  3230. StringCchCat(UserChat.szChatString, LEN_USER_CHAT, pUserChat.szChatString);
  3231. //字符过滤
  3232. //m_pIMainServiceFrame->SensitiveWordFilter(pUserChat->szChatString, UserChat.szChatString, CountArray(UserChat.szChatString));
  3233. //构造数据
  3234. UserChat.dwChatColor = pUserChat.dwChatColor;
  3235. UserChat.wChatLength = pUserChat.wChatLength;
  3236. UserChat.dwTargetUserID = pUserChat.dwTargetUserID;
  3237. UserChat.dwSendUserID = pIServerUserItem->GetUserID();
  3238. //UserChat.wChatLength = CountStringBuffer(UserChat.szChatString);
  3239. //发送数据
  3240. WORD wHeadSize = sizeof(UserChat) - sizeof(UserChat.szChatString);
  3241. WORD wSendSize = wHeadSize + UserChat.wChatLength * sizeof(UserChat.szChatString[0]);
  3242. //游戏用户
  3243. for (WORD i = 0; i < m_wChairCount; i++)
  3244. {
  3245. //获取用户
  3246. IServerUserItem* pIServerUserItem = GetTableUserItem(i);
  3247. if ((pIServerUserItem == NULL) || (pIServerUserItem->IsClientReady() == false)) continue;
  3248. GameInfo::PB_CS_UserChat Chat;
  3249. Chat.set_dwchatcolor(UserChat.dwChatColor);
  3250. Chat.set_wchatlength(UserChat.wChatLength);
  3251. Chat.set_dwtargetuserid(UserChat.dwTargetUserID);
  3252. Chat.set_dwsenduserid(UserChat.dwSendUserID);
  3253. std::string szChatString = CW2AEX<1024>(UserChat.szChatString, CP_UTF8).m_psz;
  3254. Chat.set_szchatstring(szChatString);
  3255. //发送数据
  3256. std::string pbdata = Chat.SerializePartialAsString();
  3257. //发送消息
  3258. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GF_USER_CHAT, (void*)pbdata.c_str(), pbdata.length());
  3259. }
  3260. //旁观用户
  3261. WORD wEnumIndex = 0;
  3262. IServerUserItem* pIServerUserItem = NULL;
  3263. //枚举用户
  3264. do
  3265. {
  3266. //获取用户
  3267. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  3268. if (pIServerUserItem == NULL) break;
  3269. //发送数据
  3270. if (pIServerUserItem->IsClientReady() == true)
  3271. {
  3272. GameInfo::PB_CS_UserChat Chat;
  3273. Chat.set_dwchatcolor(UserChat.dwChatColor);
  3274. Chat.set_wchatlength(UserChat.wChatLength);
  3275. Chat.set_dwtargetuserid(UserChat.dwTargetUserID);
  3276. Chat.set_dwsenduserid(UserChat.dwSendUserID);
  3277. std::string szChatString = CW2AEX<1024>(UserChat.szChatString, CP_UTF8).m_psz;
  3278. Chat.set_szchatstring(szChatString);
  3279. //发送数据
  3280. std::string pbdata = Chat.SerializePartialAsString();
  3281. //发送消息
  3282. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GF_USER_CHAT, (void*)pbdata.c_str(), pbdata.length());
  3283. }
  3284. } while (true);
  3285. return true;
  3286. }
  3287. case SUB_GF_USER_EXPRESSION: //用户表情
  3288. {
  3289. //效验参数
  3290. GameInfo::PB_CS_UserExpression Expression;
  3291. Expression.ParseFromArray(pData, wDataSize);
  3292. //处理消息
  3293. CMD_GF_C_UserExpression pUserExpression;
  3294. ZeroMemory(&pUserExpression, sizeof(pUserExpression));
  3295. pUserExpression.wItemIndex = Expression.witemindex();
  3296. pUserExpression.dwTargetUserID = Expression.dwtargetuserid();
  3297. //目标用户
  3298. if ((pUserExpression.dwTargetUserID != 0) && (SearchUserItem(pUserExpression.dwTargetUserID) == NULL))
  3299. {
  3300. ASSERT(FALSE);
  3301. return true;
  3302. }
  3303. //状态判断
  3304. if ((CServerRule::IsForfendGameChat(m_pGameServiceOption->dwServerRule) == true) && (pIServerUserItem->GetMasterOrder() == 0L))
  3305. {
  3306. SendRequestFailure(pIServerUserItem, TEXT("抱歉,当前游戏房间禁止游戏聊天!"), 0);
  3307. //SendGameMessage(pIServerUserItem, TEXT("抱歉,当前游戏房间禁止游戏聊天!"), SMT_CHAT);
  3308. return true;
  3309. }
  3310. //权限判断
  3311. if (CUserRight::CanRoomChat(pIServerUserItem->GetUserRight()) == false)
  3312. {
  3313. SendRequestFailure(pIServerUserItem, TEXT("抱歉,您没有游戏聊天的权限,若需要帮助,请联系游戏客服咨询!"), 0);
  3314. //SendGameMessage(pIServerUserItem, TEXT("抱歉,您没有游戏聊天的权限,若需要帮助,请联系游戏客服咨询!"), SMT_EJECT | SMT_CHAT);
  3315. return true;
  3316. }
  3317. //构造消息
  3318. CMD_GR_S_UserExpression UserExpression;
  3319. ZeroMemory(&UserExpression, sizeof(UserExpression));
  3320. //构造数据
  3321. UserExpression.wItemIndex = pUserExpression.wItemIndex;
  3322. UserExpression.dwSendUserID = pIServerUserItem->GetUserID();
  3323. UserExpression.dwTargetUserID = pUserExpression.dwTargetUserID;
  3324. //游戏用户
  3325. for (WORD i = 0; i < m_wChairCount; i++)
  3326. {
  3327. //获取用户
  3328. IServerUserItem* pIServerUserItem = GetTableUserItem(i);
  3329. if ((pIServerUserItem == NULL) || (pIServerUserItem->IsClientReady() == false)) continue;
  3330. //发送数据
  3331. if (pIServerUserItem->IsClientReady() == true)
  3332. {
  3333. GameInfo::PB_CS_UserExpression Expressions;
  3334. Expressions.set_witemindex(UserExpression.wItemIndex);
  3335. Expressions.set_dwsenduserid(UserExpression.dwSendUserID);
  3336. Expressions.set_dwtargetuserid(UserExpression.dwTargetUserID);
  3337. //发送数据
  3338. std::string pbdata = Expressions.SerializePartialAsString();
  3339. //发送消息
  3340. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GF_USER_EXPRESSION, (void*)pbdata.c_str(), pbdata.length());
  3341. }
  3342. }
  3343. //旁观用户
  3344. WORD wEnumIndex = 0;
  3345. IServerUserItem* pIServerUserItem = NULL;
  3346. //枚举用户
  3347. do
  3348. {
  3349. //获取用户
  3350. pIServerUserItem = EnumLookonUserItem(wEnumIndex++);
  3351. if (pIServerUserItem == NULL) break;
  3352. //发送数据
  3353. if (pIServerUserItem->IsClientReady() == true)
  3354. {
  3355. GameInfo::PB_CS_UserExpression Expressions;
  3356. Expressions.set_witemindex(UserExpression.wItemIndex);
  3357. Expressions.set_dwsenduserid(UserExpression.dwSendUserID);
  3358. Expressions.set_dwtargetuserid(UserExpression.dwTargetUserID);
  3359. //发送数据
  3360. std::string pbdata = Expressions.SerializePartialAsString();
  3361. //发送消息
  3362. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GF_FRAME, SUB_GF_USER_EXPRESSION, (void*)pbdata.c_str(), pbdata.length());
  3363. }
  3364. } while (true);
  3365. return true;
  3366. }
  3367. case SUB_GF_LOOKON_CONFIG: //旁观配置
  3368. {
  3369. //效验参数
  3370. /*ASSERT(wDataSize == sizeof(CMD_GF_LookonConfig));
  3371. if (wDataSize < sizeof(CMD_GF_LookonConfig)) return false;
  3372. //变量定义
  3373. CMD_GF_LookonConfig * pLookonConfig = (CMD_GF_LookonConfig *)pData;
  3374. //目标用户
  3375. if ((pLookonConfig->dwUserID != 0) && (SearchUserItem(pLookonConfig->dwUserID) == NULL))
  3376. {
  3377. ASSERT(FALSE);
  3378. return true;
  3379. }
  3380. //用户效验
  3381. ASSERT(pIServerUserItem->GetUserStatus() != US_LOOKON);
  3382. if (pIServerUserItem->GetUserStatus() == US_LOOKON) return false;
  3383. //旁观处理
  3384. if (pLookonConfig->dwUserID != 0L)
  3385. {
  3386. for (INT_PTR i = 0; i < m_LookonUserItemArray.GetCount(); i++)
  3387. {
  3388. //获取用户
  3389. IServerUserItem * pILookonUserItem = m_LookonUserItemArray[i];
  3390. if (pILookonUserItem->GetUserID() != pLookonConfig->dwUserID) continue;
  3391. //if (pILookonUserItem->GetChairID() != pIServerUserItem->GetChairID()) continue;
  3392. //构造消息
  3393. CMD_GF_LookonStatus LookonStatus;
  3394. LookonStatus.cbAllowLookon = pLookonConfig->cbAllowLookon;
  3395. //发送消息
  3396. ASSERT(m_pIMainServiceFrame != NULL);
  3397. m_pIMainServiceFrame->SendData(pILookonUserItem, MDM_GF_FRAME, SUB_GF_LOOKON_STATUS, &LookonStatus, sizeof(LookonStatus));
  3398. break;
  3399. }
  3400. }
  3401. else
  3402. {
  3403. //设置判断
  3404. bool bAllowLookon = (pLookonConfig->cbAllowLookon == TRUE) ? true : false;
  3405. if (bAllowLookon == m_bAllowLookon[pIServerUserItem->GetChairID()]) return true;
  3406. //设置变量
  3407. m_bAllowLookon[pIServerUserItem->GetChairID()] = bAllowLookon;
  3408. //构造消息
  3409. CMD_GF_LookonStatus LookonStatus;
  3410. LookonStatus.cbAllowLookon = pLookonConfig->cbAllowLookon;
  3411. //发送消息
  3412. for (INT_PTR i = 0; i < m_LookonUserItemArray.GetCount(); i++)
  3413. {
  3414. //获取用户
  3415. IServerUserItem * pILookonUserItem = m_LookonUserItemArray[i];
  3416. if (pILookonUserItem->GetChairID() != pIServerUserItem->GetChairID()) continue;
  3417. //发送消息
  3418. ASSERT(m_pIMainServiceFrame != NULL);
  3419. m_pIMainServiceFrame->SendData(pILookonUserItem, MDM_GF_FRAME, SUB_GF_LOOKON_STATUS, &LookonStatus, sizeof(LookonStatus));
  3420. }
  3421. }
  3422. return true;*/
  3423. }
  3424. }
  3425. return false;
  3426. }
  3427. //游戏局数
  3428. WORD CTableFrame::GetDrawCount()
  3429. {
  3430. return m_wDrawCount;
  3431. }
  3432. //获取空位
  3433. WORD CTableFrame::GetNullChairIDWithoutHost()
  3434. {
  3435. //椅子搜索
  3436. for (WORD i = 1; i < m_wChairCount; i++)
  3437. {
  3438. if (m_TableUserItemArray[i] == NULL)
  3439. {
  3440. return i;
  3441. }
  3442. }
  3443. return INVALID_CHAIR;
  3444. }
  3445. //获取空位
  3446. WORD CTableFrame::GetNullChairID()
  3447. {
  3448. //椅子搜索
  3449. for (WORD i = 0; i < m_wChairCount; i++)
  3450. {
  3451. if (m_TableUserItemArray[i] == NULL)
  3452. {
  3453. return i;
  3454. }
  3455. }
  3456. return INVALID_CHAIR;
  3457. }
  3458. //随机空位
  3459. WORD CTableFrame::GetRandNullChairID()
  3460. {
  3461. //椅子搜索
  3462. WORD wIndex = rand() % m_wChairCount;
  3463. for (WORD i = wIndex; i < m_wChairCount + wIndex; i++)
  3464. {
  3465. if (m_TableUserItemArray[i%m_wChairCount] == NULL)
  3466. {
  3467. return i%m_wChairCount;
  3468. }
  3469. }
  3470. return INVALID_CHAIR;
  3471. }
  3472. //用户数目
  3473. WORD CTableFrame::GetSitUserCount()
  3474. {
  3475. //变量定义
  3476. WORD wUserCount = 0;
  3477. //数目统计
  3478. for (WORD i = 0; i < m_wChairCount; i++)
  3479. {
  3480. if (GetTableUserItem(i) != NULL)
  3481. {
  3482. wUserCount++;
  3483. }
  3484. }
  3485. return wUserCount;
  3486. }
  3487. //旁观数目
  3488. WORD CTableFrame::GetLookonUserCount()
  3489. {
  3490. //获取数目
  3491. INT_PTR nLookonCount = m_LookonUserItemArray.GetCount();
  3492. return (WORD)(nLookonCount);
  3493. }
  3494. //断线数目
  3495. WORD CTableFrame::GetOffLineUserCount()
  3496. {
  3497. //变量定义
  3498. WORD wOffLineCount = 0;
  3499. //断线人数
  3500. for (WORD i = 0; i < m_wChairCount; i++)
  3501. {
  3502. if (m_dwOffLineTime[i] != 0L)
  3503. {
  3504. wOffLineCount++;
  3505. }
  3506. }
  3507. return wOffLineCount;
  3508. }
  3509. //桌子状况
  3510. WORD CTableFrame::GetTableUserInfo(tagTableUserInfo & TableUserInfo)
  3511. {
  3512. //设置变量
  3513. ZeroMemory(&TableUserInfo, sizeof(TableUserInfo));
  3514. //用户分析
  3515. for (WORD i = 0; i < m_pGameServiceAttrib->wChairCount; i++)
  3516. {
  3517. //获取用户
  3518. IServerUserItem * pIServerUserItem = GetTableUserItem(i);
  3519. if (pIServerUserItem == NULL) continue;
  3520. //用户类型
  3521. if (pIServerUserItem->IsAndroidUser() == false)
  3522. {
  3523. TableUserInfo.wTableUserCount++;
  3524. }
  3525. else
  3526. {
  3527. TableUserInfo.wTableAndroidCount++;
  3528. }
  3529. //准备判断
  3530. if (pIServerUserItem->GetUserStatus() == US_READY)
  3531. {
  3532. TableUserInfo.wTableReadyCount++;
  3533. }
  3534. }
  3535. //最少数目
  3536. switch (m_cbStartMode)
  3537. {
  3538. case START_MODE_ALL_READY: //所有准备
  3539. {
  3540. TableUserInfo.wMinUserCount = 2;
  3541. break;
  3542. }
  3543. case START_MODE_PAIR_READY: //配对开始
  3544. {
  3545. TableUserInfo.wMinUserCount = 2;
  3546. break;
  3547. }
  3548. case START_MODE_TIME_CONTROL: //时间控制
  3549. {
  3550. TableUserInfo.wMinUserCount = 1;
  3551. break;
  3552. }
  3553. default: //默认模式
  3554. {
  3555. TableUserInfo.wMinUserCount = m_pGameServiceAttrib->wChairCount;
  3556. break;
  3557. }
  3558. }
  3559. return TableUserInfo.wTableAndroidCount + TableUserInfo.wTableUserCount;
  3560. }
  3561. //配置桌子
  3562. bool CTableFrame::InitializationFrame(WORD wTableID, tagTableFrameParameter & TableFrameParameter, WORD wGameType)
  3563. {
  3564. //设置变量
  3565. m_wTableID = wTableID;
  3566. m_wChairCount = TableFrameParameter.pGameServiceAttrib->wChairCount;
  3567. //配置参数
  3568. m_pGameParameter = TableFrameParameter.pGameParameter;
  3569. m_pGameServiceAttrib = TableFrameParameter.pGameServiceAttrib;
  3570. m_pGameServiceOption = TableFrameParameter.pGameServiceOption;
  3571. //组件接口
  3572. m_pITimerEngine = TableFrameParameter.pITimerEngine;
  3573. m_pIMainServiceFrame = TableFrameParameter.pIMainServiceFrame;
  3574. m_pIAndroidUserManager = TableFrameParameter.pIAndroidUserManager;
  3575. m_pIKernelDataBaseEngine = TableFrameParameter.pIKernelDataBaseEngine;
  3576. m_pIRecordDataBaseEngine = TableFrameParameter.pIRecordDataBaseEngine;
  3577. //创建桌子
  3578. IGameServiceManager * pIGameServiceManager = TableFrameParameter.pIGameServiceManager;
  3579. if (wGameType < 3)
  3580. {
  3581. m_pITableFrameSink = (ITableFrameSink *)pIGameServiceManager->CreateTableFrameSink(IID_ITableFrameSink, VER_ITableFrameSink);
  3582. }
  3583. else if (wGameType >= 3 && wGameType <= 5)
  3584. {
  3585. m_pITableFrameSink = (ITableFrameSink *)pIGameServiceManager->CreateTableFrameSink(IID_ITableFrameSink, VER_ITableFrameSinkCxz);
  3586. }
  3587. else if (wGameType >= 10 && wGameType < 14)
  3588. {
  3589. m_pITableFrameSink = (ITableFrameSink *)pIGameServiceManager->CreateTableFrameSink(IID_ITableFrameSink, VER_ITableFrameSinkOther);
  3590. }
  3591. else if (wGameType >= 14 && wGameType <= 16)
  3592. {
  3593. m_pITableFrameSink = (ITableFrameSink *)pIGameServiceManager->CreateTableFrameSink(IID_ITableFrameSink, VER_ITableFrameSinkZhiPai);
  3594. }
  3595. else
  3596. {
  3597. m_pITableFrameSink = (ITableFrameSink *)pIGameServiceManager->CreateTableFrameSink(IID_ITableFrameSink, VER_ITableFrameSink);
  3598. }
  3599. //错误判断
  3600. if (m_pITableFrameSink == NULL)
  3601. {
  3602. //ASSERT(FALSE);
  3603. return false;
  3604. }
  3605. //设置变量
  3606. m_lCellScore = m_pGameServiceOption->lCellScore;
  3607. //设置桌子
  3608. IUnknownEx * pITableFrame = QUERY_ME_INTERFACE(IUnknownEx);
  3609. if (m_pITableFrameSink->Initialization(pITableFrame) == false) return false;
  3610. //设置标识
  3611. m_bTableInitFinish = true;
  3612. //扩展接口
  3613. m_pITableUserAction = QUERY_OBJECT_PTR_INTERFACE(m_pITableFrameSink, ITableUserAction);
  3614. m_pITableUserRequest = QUERY_OBJECT_PTR_INTERFACE(m_pITableFrameSink, ITableUserRequest);
  3615. return true;
  3616. }
  3617. //用户创建私有房间
  3618. bool CTableFrame::OnTCPNetworkSubUserCreateRoom(IServerUserItem * pIServerUserItem)
  3619. {
  3620. //建立定时器
  3621. SetGameTimer(IDI_START_TIME, TIME_CREATE_OUT, 1, 0);
  3622. return true;
  3623. }
  3624. //起立动作
  3625. bool CTableFrame::PerformStandUpAction(IServerUserItem * pIServerUserItem, bool bInitiative/*=false*/, bool bSendState)
  3626. {
  3627. //效验参数
  3628. ASSERT(pIServerUserItem != NULL);
  3629. ASSERT(pIServerUserItem->GetTableID() == m_wTableID);
  3630. //如果是旁观的状态。则让此人离开。
  3631. bool currUserLookOn = false;
  3632. for (INT_PTR i = 0; i < m_LookonUserItemArray.GetCount(); i++)
  3633. {
  3634. if (pIServerUserItem == m_LookonUserItemArray[i])
  3635. {
  3636. //删除子项
  3637. currUserLookOn = true;
  3638. m_LookonUserItemArray.RemoveAt(i);
  3639. break;
  3640. }
  3641. }
  3642. if (pIServerUserItem->GetUserStatus() == US_LOOKON)
  3643. {
  3644. if (currUserLookOn)
  3645. {
  3646. //用户状态
  3647. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR, bSendState);
  3648. return true;
  3649. }
  3650. return true;
  3651. }
  3652. ASSERT(pIServerUserItem->GetChairID() <= m_wChairCount);
  3653. //用户属性
  3654. WORD wChairID = pIServerUserItem->GetChairID();
  3655. BYTE cbUserStatus = pIServerUserItem->GetUserStatus();
  3656. IServerUserItem * pITableUserItem = GetTableUserItem(wChairID);
  3657. //游戏用户
  3658. if ((m_bGameStarted == true) && ((cbUserStatus == US_PLAYING) || (cbUserStatus == US_PLAYINGWAIT) || (cbUserStatus == US_OFFLINE)))
  3659. {
  3660. //比赛类型
  3661. if (m_pGameServiceOption->wServerType == GAME_GENRE_MATCH)
  3662. {
  3663. //设置托管
  3664. pIServerUserItem->SetTrusteeUser(true);
  3665. //掉线通知
  3666. if (m_pITableUserAction != NULL) m_pITableUserAction->OnActionUserOffLine(wChairID, pIServerUserItem);
  3667. return true;
  3668. }
  3669. //结束游戏
  3670. BYTE cbConcludeReason = (cbUserStatus == US_OFFLINE) ? GER_NETWORK_ERROR : GER_USER_LEAVE;
  3671. m_pITableFrameSink->OnEventGameConclude(wChairID, pIServerUserItem, cbConcludeReason); //告诉游戏模块 断线了 或是有人强退了
  3672. //离开判断
  3673. if (m_TableUserItemArray[wChairID] != pIServerUserItem) return true;
  3674. }
  3675. else
  3676. {
  3677. CAttemperEngineSink * pAttemperEngineSink = (CAttemperEngineSink *)m_pIMainServiceFrame;
  3678. pAttemperEngineSink->SetUserServerID(pIServerUserItem, 0, 0);//通知协调服务器 这个用户已经离开了桌子。
  3679. }
  3680. if ((m_pGameServiceOption->wServerType == GAME_GENRE_MATCH) && (bInitiative == true))
  3681. {
  3682. if (pIServerUserItem->IsTrusteeUser() == false)
  3683. {
  3684. pIServerUserItem->SetTrusteeUser(true);
  3685. //掉线通知
  3686. if (m_pITableUserAction != NULL) m_pITableUserAction->OnActionUserOffLine(wChairID, pIServerUserItem);
  3687. }
  3688. return true;
  3689. }
  3690. //设置变量
  3691. if (pIServerUserItem == pITableUserItem)
  3692. {
  3693. if (m_sPrivateTableID.empty())
  3694. {
  3695. //公共房间开启准备超时定时器。
  3696. //删除定时
  3697. if (m_pGameServiceAttrib->wChairCount < MAX_CHAIR) KillGameTimer(IDI_START_OVERTIME + wChairID);
  3698. }
  3699. //设置变量
  3700. m_TableUserItemArray[wChairID] = NULL;
  3701. //解锁游戏币
  3702. if (m_lFrozenedScore[wChairID] != 0L)
  3703. {
  3704. pIServerUserItem->UnFrozenedUserScore(m_lFrozenedScore[wChairID]);
  3705. m_lFrozenedScore[wChairID] = 0L;
  3706. }
  3707. //事件通知
  3708. if (m_pITableUserAction != NULL)
  3709. {
  3710. m_pITableUserAction->OnActionUserStandUp(wChairID, pIServerUserItem, false);
  3711. }
  3712. //事件通知
  3713. if (m_pIMatchTableAction != NULL) m_pIMatchTableAction->OnActionUserStandUp(wChairID, pIServerUserItem, false);
  3714. //用户状态
  3715. //pIServerUserItem->SetClientReady(false);
  3716. pIServerUserItem->SetUserStatus((cbUserStatus == US_OFFLINE) ? US_NULL : US_FREE, INVALID_TABLE, INVALID_CHAIR, bSendState);
  3717. //变量定义
  3718. bool bTableLocked = IsTableLocked();
  3719. bool bTableStarted = IsTableStarted();
  3720. WORD wTableUserCount = GetSitUserCount();
  3721. //设置变量
  3722. m_wUserCount = wTableUserCount;
  3723. //桌子信息
  3724. if (wTableUserCount == 0)
  3725. {
  3726. m_dwTableOwnerID = 0L;
  3727. m_szEnterPassword[0] = 0;
  3728. }
  3729. //结束桌子
  3730. ConcludeTable();
  3731. //发送状态
  3732. if ((bTableLocked != IsTableLocked()) || (bTableStarted != IsTableStarted()))
  3733. {
  3734. SendTableStatus();
  3735. }
  3736. //防作弊分组判断
  3737. if (CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule) && (m_pGameServiceAttrib->wChairCount < MAX_CHAIR))
  3738. {
  3739. //防作弊分组判断
  3740. if (IsTableStarted() == false && CheckDistribute())
  3741. {
  3742. for (int i = 0; i < m_wChairCount; i++)
  3743. {
  3744. if (m_TableUserItemArray[i] != NULL && m_TableUserItemArray[i]->GetUserStatus() == US_READY)
  3745. {
  3746. //发送消息
  3747. LPCTSTR pszMessage = TEXT("由玩家离开,系统重新分配桌子,请稍后!");
  3748. SendRequestFailure(m_TableUserItemArray[i], pszMessage, 0);
  3749. //发送消息
  3750. m_pIMainServiceFrame->InsertDistribute(m_TableUserItemArray[i]);
  3751. ////用户起立
  3752. //PerformStandUpAction(m_TableUserItemArray[i]);
  3753. }
  3754. }
  3755. }
  3756. }
  3757. return true;
  3758. }
  3759. else
  3760. {
  3761. if (currUserLookOn)
  3762. {
  3763. //事件通知
  3764. if (m_pITableUserAction != NULL)
  3765. {
  3766. m_pITableUserAction->OnActionUserStandUp(wChairID, pIServerUserItem, true);
  3767. }
  3768. //事件通知
  3769. if (m_pIMatchTableAction != NULL) m_pIMatchTableAction->OnActionUserStandUp(wChairID, pIServerUserItem, true);
  3770. //用户状态
  3771. //pIServerUserItem->SetClientReady(false);
  3772. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR, bSendState);
  3773. return true;
  3774. }
  3775. }
  3776. return true;
  3777. }
  3778. //比对客户端版本
  3779. bool CTableFrame::CheckClient(TCHAR *pNow, LPCTSTR pOld)
  3780. {
  3781. for (int i = 0; i < (LEN_MACHINE_ID - 5); i++)
  3782. {
  3783. if (pNow[i] > pOld[i])
  3784. {
  3785. //CString str;
  3786. //str.Format(TEXT("当前版本没有旁观功能"));
  3787. //CTraceService::TraceString(str, TraceLevel_Normal);
  3788. return false;
  3789. }
  3790. }
  3791. return true;
  3792. }
  3793. //游戏中途旁观进入
  3794. bool CTableFrame::PerformLookonLogin(IServerUserItem * pIServerUserItem)
  3795. {
  3796. //判断客户端版本
  3797. /*TCHAR szBanBen[LEN_MACHINE_ID];
  3798. LPCTSTR csBanBen = pIServerUserItem->GetMachineID();
  3799. ZeroMemory(szBanBen, sizeof(TCHAR) * LEN_MACHINE_ID);
  3800. StringCchCat(szBanBen, LEN_MACHINE_ID, _T("1.1.6")); //比对版本 此版本以前不允许进入旁观
  3801. //比较版本
  3802. if (!CheckClient(szBanBen, csBanBen)) return false;*/
  3803. /*if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  3804. {
  3805. //判断客户端版本
  3806. TCHAR szBanBen[LEN_MACHINE_ID];
  3807. ZeroMemory(szBanBen, sizeof(TCHAR) * LEN_MACHINE_ID);
  3808. StringCchCat(szBanBen, LEN_MACHINE_ID, _T("2.0.0")); //比对版本 此版本以前不允许进入旁观
  3809. //比较版本
  3810. if (!CheckClient(szBanBen, pIServerUserItem->GetMachineID()))
  3811. {
  3812. //发送消息
  3813. SendGameMessage(pIServerUserItem, TEXT("您的游戏版本不支持戳虾子游戏,请更新版本哟!"), SMT_TABLE_EXIT);
  3814. //请旁观的人离开
  3815. return false;
  3816. }
  3817. }*/
  3818. bool bRet = false;
  3819. if (m_wStartCount == 0)
  3820. {
  3821. return false;
  3822. }
  3823. if (m_pITableUserAction == NULL)
  3824. {
  3825. //CString str;
  3826. //str.Format(TEXT("游戏中途旁观进入失败:%d"), pIServerUserItem->GetUserID());
  3827. //CTraceService::TraceString(str, TraceLevel_Normal);
  3828. return false;
  3829. }
  3830. //游戏未开始,不算中途
  3831. if (m_pITableUserAction != NULL)
  3832. {
  3833. bRet = m_pITableUserAction->PerformLookonLogin(pIServerUserItem);
  3834. }
  3835. if (bRet)
  3836. {
  3837. //CString str;
  3838. //str.Format(TEXT("游戏中途旁观进入场景发送成功:%d"), pIServerUserItem->GetUserID());
  3839. //CTraceService::TraceString(str, TraceLevel_Normal);
  3840. }
  3841. return true;
  3842. }
  3843. //旁观动作
  3844. bool CTableFrame::PerformLookonAction(IServerUserItem * pIServerUserItem)
  3845. {
  3846. //效验参数
  3847. ASSERT((pIServerUserItem != NULL));
  3848. ASSERT((pIServerUserItem->GetTableID() == INVALID_TABLE) && (pIServerUserItem->GetChairID() == INVALID_CHAIR));
  3849. //变量定义
  3850. tagUserInfo * pUserInfo = pIServerUserItem->GetUserInfo();
  3851. tagUserRule * pUserRule = pIServerUserItem->GetUserRule();
  3852. //模拟处理
  3853. if (m_pGameServiceAttrib->wChairCount < MAX_CHAIR && pIServerUserItem->IsAndroidUser() == false)
  3854. {
  3855. //定义变量
  3856. CAttemperEngineSink * pAttemperEngineSink = (CAttemperEngineSink *)m_pIMainServiceFrame;
  3857. //查找机器
  3858. for (WORD i = 0; i < m_pGameServiceAttrib->wChairCount; i++)
  3859. {
  3860. //获取用户
  3861. IServerUserItem *pIUserItem = m_TableUserItemArray[i];
  3862. if (pIUserItem == NULL) continue;
  3863. if (pIUserItem->IsAndroidUser() == false)break;
  3864. //获取参数
  3865. tagBindParameter * pBindParameter = pAttemperEngineSink->GetBindParameter(pIUserItem->GetBindIndex());
  3866. IAndroidUserItem * pIAndroidUserItem = m_pIAndroidUserManager->SearchAndroidUserItem(pIUserItem->GetUserID(), pBindParameter->dwSocketID);
  3867. tagAndroidParameter * pAndroidParameter = pIAndroidUserItem->GetAndroidParameter();
  3868. //模拟判断
  3869. if ((pAndroidParameter->dwServiceMode&ANDROID_SIMULATE) != 0
  3870. && (pAndroidParameter->dwServiceMode&ANDROID_PASSIVITY) == 0
  3871. && (pAndroidParameter->dwServiceMode&ANDROID_INITIATIVE) == 0)
  3872. {
  3873. //SendRequestFailure(pIServerUserItem, TEXT("抱歉,当前游戏桌子禁止用户旁观!"), REQUEST_FAILURE_NORMAL);
  3874. CMD_GR_UserSitDownAck req;
  3875. req.cbRet = 1;
  3876. req.szText;
  3877. StringCchCopy(req.szText, _countof(req.szText), _T("抱歉,当前游戏桌子禁止用户旁观!"));
  3878. UserInfo::PB_CS_S_UserSitDownAck SitDownAck;
  3879. SitDownAck.set_cbret(req.cbRet);
  3880. std::string szText = CW2AEX<1024>(req.szText, CP_UTF8).m_psz;
  3881. SitDownAck.set_sztext(szText);
  3882. //发送数据
  3883. std::string pbdata = SitDownAck.SerializePartialAsString();
  3884. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_USER_ADDCREATE_TABLE_ID, (void*)pbdata.c_str(), pbdata.length());
  3885. return false;
  3886. }
  3887. break;
  3888. }
  3889. }
  3890. //状态判断
  3891. if ((CServerRule::IsForfendGameLookon(m_pGameServiceOption->dwServerRule) == true) && (pIServerUserItem->GetMasterOrder() == 0))
  3892. {
  3893. //SendRequestFailure(pIServerUserItem, TEXT("抱歉,当前游戏房间禁止用户旁观!"), REQUEST_FAILURE_NORMAL);
  3894. CMD_GR_UserSitDownAck req;
  3895. req.cbRet = 1;
  3896. req.szText;
  3897. StringCchCopy(req.szText, _countof(req.szText), _T("抱歉,当前游戏房间禁止用户旁观!"));
  3898. UserInfo::PB_CS_S_UserSitDownAck SitDownAck;
  3899. SitDownAck.set_cbret(req.cbRet);
  3900. std::string szText = CW2AEX<1024>(req.szText, CP_UTF8).m_psz;
  3901. SitDownAck.set_sztext(szText);
  3902. //发送数据
  3903. std::string pbdata = SitDownAck.SerializePartialAsString();
  3904. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_USER_ADDCREATE_TABLE_ID, (void*)pbdata.c_str(), pbdata.length());
  3905. return false;
  3906. }
  3907. if (pUserInfo->cbUserStatus > US_FREE)
  3908. {
  3909. CString csTest;
  3910. csTest.Format(_T("旁观玩家%d状态:%d "), pUserInfo->dwUserID, pUserInfo->cbUserStatus);
  3911. //提示消息
  3912. CTraceService::TraceString(csTest, TraceLevel_Warning);
  3913. return false;
  3914. }
  3915. //密码效验
  3916. if ((IsTableLocked() == true) && (pIServerUserItem->GetMasterOrder() == 0L) && (lstrcmp(pUserRule->szPassword, m_szEnterPassword) != 0))
  3917. {
  3918. //SendRequestFailure(pIServerUserItem, TEXT("游戏桌进入密码不正确,不能旁观游戏!"), REQUEST_FAILURE_PASSWORD);
  3919. CMD_GR_UserSitDownAck req;
  3920. req.cbRet = 1;
  3921. req.szText;
  3922. StringCchCopy(req.szText, _countof(req.szText), _T("游戏桌进入密码不正确,不能旁观游戏!"));
  3923. UserInfo::PB_CS_S_UserSitDownAck SitDownAck;
  3924. SitDownAck.set_cbret(req.cbRet);
  3925. std::string szText = CW2AEX<1024>(req.szText, CP_UTF8).m_psz;
  3926. SitDownAck.set_sztext(szText);
  3927. //发送数据
  3928. std::string pbdata = SitDownAck.SerializePartialAsString();
  3929. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_USER_ADDCREATE_TABLE_ID, (void*)pbdata.c_str(), pbdata.length());
  3930. return false;
  3931. }
  3932. /*if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  3933. {
  3934. //判断客户端版本
  3935. TCHAR szBanBen[LEN_MACHINE_ID];
  3936. ZeroMemory(szBanBen, sizeof(TCHAR) * LEN_MACHINE_ID);
  3937. StringCchCat(szBanBen, LEN_MACHINE_ID, _T("2.0.0")); //比对版本 此版本以前不允许进入旁观
  3938. //比较版本
  3939. if (!CheckClient(szBanBen, pIServerUserItem->GetMachineID()))
  3940. {
  3941. //发送消息
  3942. SendGameMessage(pIServerUserItem, TEXT("您的游戏版本不支持戳虾子游戏,请更新版本哟!"), SMT_TABLE_EXIT);
  3943. //请旁观的人离开
  3944. return false;
  3945. }
  3946. }*/
  3947. if (m_wStartCount > 0)
  3948. {
  3949. //设置用户
  3950. m_LookonUserItemArray.Add(pIServerUserItem);
  3951. }
  3952. else
  3953. {
  3954. //设置用户
  3955. m_LookonUserItemArray.Add(pIServerUserItem);
  3956. }
  3957. return true;
  3958. }
  3959. //发送在坐用户状态
  3960. bool CTableFrame::SendUserInfoStat(IServerUserItem * pIServerUserItem)
  3961. {
  3962. //变量定义
  3963. tagUserInfo * pUserInfo = pIServerUserItem->GetUserInfo();
  3964. for (int i = 0; i < m_wChairCount; i++)
  3965. {
  3966. if (m_TableUserItemArray[i] != NULL)
  3967. {
  3968. IServerUserItem *p = m_TableUserItemArray[i];
  3969. if (p == pIServerUserItem) continue;
  3970. //变量定义
  3971. CMD_GR_UserStatus UserStatus;
  3972. ZeroMemory(&UserStatus, sizeof(UserStatus));
  3973. //构造数据
  3974. UserStatus.dwUserID = p->GetUserID();
  3975. UserStatus.UserStatus.wTableID = p->GetTableID();
  3976. UserStatus.UserStatus.wChairID = p->GetChairID();
  3977. UserStatus.UserStatus.cbUserStatus = p->GetUserStatus();
  3978. UserInfo::PB_CS_S_UserStatus Status;
  3979. Status.set_dwuserid(UserStatus.dwUserID);
  3980. Status.mutable_userstatus()->set_cbuserstatus(UserStatus.UserStatus.cbUserStatus);
  3981. Status.mutable_userstatus()->set_wchairid(UserStatus.UserStatus.wChairID);
  3982. Status.mutable_userstatus()->set_wtableid(UserStatus.UserStatus.wTableID);
  3983. //发送数据
  3984. std::string pbdata = Status.SerializePartialAsString();
  3985. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_USER_STATUS, (void*)pbdata.c_str(), pbdata.length());
  3986. }
  3987. }
  3988. return true;
  3989. }
  3990. //坐下动作
  3991. bool CTableFrame::PerformSitDownAction(WORD wChairID, IServerUserItem * pIServerUserItem, LPCTSTR lpszPassword)
  3992. {
  3993. //效验参数
  3994. ASSERT((pIServerUserItem != NULL) && (wChairID < m_wChairCount));
  3995. ASSERT((pIServerUserItem->GetChairID() == INVALID_CHAIR));
  3996. //变量定义
  3997. tagUserInfo * pUserInfo = pIServerUserItem->GetUserInfo();
  3998. tagUserRule * pUserRule = pIServerUserItem->GetUserRule();
  3999. IServerUserItem * pITableUserItem = GetTableUserItem(wChairID);
  4000. //积分变量
  4001. SCORE lUserScore = pIServerUserItem->GetUserScore();
  4002. SCORE lMinTableScore = m_pGameServiceOption->lMinTableScore;
  4003. SCORE lLessEnterScore = m_pITableFrameSink->QueryLessEnterScore(wChairID, pIServerUserItem);
  4004. //清楚旁观的我的数据
  4005. for (INT_PTR i = 0; i < m_LookonUserItemArray.GetCount(); i++)
  4006. {
  4007. if (pIServerUserItem == m_LookonUserItemArray[i])
  4008. {
  4009. //删除子项
  4010. m_LookonUserItemArray.RemoveAt(i);
  4011. }
  4012. }
  4013. //状态判断
  4014. if ((CServerRule::IsForfendGameEnter(m_pGameServiceOption->dwServerRule) == true) && (pIServerUserItem->GetMasterOrder() == 0))
  4015. {
  4016. SendRequestFailure(pIServerUserItem, TEXT("抱歉,当前游戏桌子禁止用户进入!"), REQUEST_FAILURE_NORMAL);
  4017. return false;
  4018. }
  4019. //动态加入
  4020. bool bDynamicJoin = true;
  4021. if (m_pGameServiceAttrib->cbDynamicJoin == FALSE) bDynamicJoin = false;
  4022. if (CServerRule::IsAllowDynamicJoin(m_pGameServiceOption->dwServerRule) == false) bDynamicJoin = false;
  4023. //游戏状态
  4024. if ((m_bGameStarted == true) && (bDynamicJoin == false))
  4025. {
  4026. //用户状态
  4027. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4028. SendRequestFailure(pIServerUserItem, TEXT("游戏已经开始了!"), REQUEST_FAILURE_NORMAL);
  4029. return false;
  4030. }
  4031. //椅子判断
  4032. if (pITableUserItem != NULL)
  4033. {
  4034. //防作弊
  4035. if (CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule)) return false;
  4036. //构造信息
  4037. TCHAR szDescribe[128] = TEXT("");
  4038. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("椅子已经被 [ %s ] 捷足先登了,下次动作要快点了!"), pITableUserItem->GetNickName());
  4039. //用户状态
  4040. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4041. //发送信息
  4042. SendRequestFailure(pIServerUserItem, szDescribe, REQUEST_FAILURE_NORMAL);
  4043. return false;
  4044. }
  4045. //密码效验
  4046. if (m_wChairCount <= MAX_CHAIR_GENERAL)
  4047. {
  4048. //防作弊
  4049. if (CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule) == false)
  4050. {
  4051. if ((m_pGameServiceOption->wServerType&GAME_GENRE_MATCH) == 0 && ((IsTableLocked() == true) && (pIServerUserItem->GetMasterOrder() == 0L))
  4052. && ((lpszPassword == NULL) || (lstrcmp(lpszPassword, m_szEnterPassword) != 0)))
  4053. {
  4054. SendRequestFailure(pIServerUserItem, TEXT("游戏桌进入密码不正确,不能加入游戏!"), REQUEST_FAILURE_PASSWORD);
  4055. return false;
  4056. }
  4057. }
  4058. }
  4059. //规则效验
  4060. if ((m_pGameServiceOption->wServerType&GAME_GENRE_MATCH) == 0 && EfficacyEnterTableScoreRule(wChairID, pIServerUserItem) == false) return false;
  4061. if (mGameConfig.wMaxScore == 0 && EfficacyIPAddress(pIServerUserItem) == false)
  4062. {
  4063. //用户状态
  4064. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4065. return false;
  4066. }
  4067. if (mGameConfig.wMaxScore == 2 && EfficacyIPAddress(pIServerUserItem) == false)
  4068. {
  4069. //用户状态
  4070. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4071. return false;
  4072. }
  4073. //校验准入
  4074. if (wXianZhi > 0)
  4075. {
  4076. if (pIServerUserItem->GetUserInfo()->dwBean < wXianZhi)
  4077. {
  4078. CString csTest;
  4079. csTest.Format(_T("抱歉,当前房间准入标准为%d个钻石,您目前不符合条件,无法入座."), wXianZhi);
  4080. //小于准入标准
  4081. //用户状态
  4082. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4083. SendRequestFailure(pIServerUserItem, csTest, REQUEST_FAILURE_NORMAL);
  4084. return false;
  4085. }
  4086. }
  4087. if (mGameConfig.wMaxScore == 2 )
  4088. {
  4089. //校验当前玩家的位置信息(主要是校验第一个玩家入座的时候)
  4090. LONGLONG llx3 = pIServerUserItem->GetUserInfo()->dDingWeiX;
  4091. LONGLONG lly3 = pIServerUserItem->GetUserInfo()->dDingWeiY;
  4092. double dX3 = (double)llx3 / (double)1000000;
  4093. double dY3 = (double)lly3 / (double)1000000;
  4094. if (dX3 == 0.0f && dY3 == 0.0f)
  4095. {
  4096. //用户状态
  4097. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4098. //定位信息不完整
  4099. SendRequestFailure(pIServerUserItem, TEXT("抱歉,未获取到您的位置信息,当前为反作弊专场,请选择其他房间!"), REQUEST_FAILURE_NORMAL);
  4100. return false;
  4101. }
  4102. //校验地理位置
  4103. for (int i = 0; i < GAME_PLAYER; i++)
  4104. {
  4105. IServerUserItem * pCheckUserItem = GetTableUserItem(i);
  4106. if (pCheckUserItem)
  4107. {
  4108. BaiDuMap aa;
  4109. LONGLONG llx1 = pCheckUserItem->GetUserInfo()->dDingWeiX;
  4110. LONGLONG lly1 = pCheckUserItem->GetUserInfo()->dDingWeiY;
  4111. double dX1 = (double)llx1 / (double)1000000;
  4112. double dY1 = (double)lly1 / (double)1000000;
  4113. LONGLONG llx2 = pIServerUserItem->GetUserInfo()->dDingWeiX;
  4114. LONGLONG lly2 = pIServerUserItem->GetUserInfo()->dDingWeiY;
  4115. double dX2 = (double)llx2 / (double)1000000;
  4116. double dY2 = (double)lly2 / (double)1000000;
  4117. if (dX1 != 0.0f && dY1 != 0.0f&& dX2 != 0.0f&& dY2 != 0.0f)
  4118. {
  4119. double dRet = aa.GetShortDistance(dX1, dY1, dX2, dY2);
  4120. CString csTest;
  4121. csTest.Format(L"\r\n%d->%d距离信息:%f", pCheckUserItem->GetUserInfo()->dwUserID, pIServerUserItem->GetUserInfo()->dwUserID, dRet);
  4122. OutputDebugString(csTest);
  4123. //if (dRet < 350)
  4124. //{
  4125. // //用户状态
  4126. // pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4127. // //小于350 则拒绝进入
  4128. // SendRequestFailure(pIServerUserItem, TEXT("抱歉,当前在座玩家与您的距离过近,当前为反作弊专场,请选择其他房间!"), REQUEST_FAILURE_NORMAL);
  4129. // return false;
  4130. //}
  4131. }
  4132. else
  4133. {
  4134. //用户状态
  4135. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4136. //定位信息不完整
  4137. SendRequestFailure(pIServerUserItem, TEXT("抱歉,未获取到您的位置信息,当前为反作弊专场,请选择其他房间!"), REQUEST_FAILURE_NORMAL);
  4138. return false;
  4139. }
  4140. }
  4141. }
  4142. }
  4143. if ((m_pGameServiceOption->wServerType&GAME_GENRE_MATCH) == 0 && EfficacyScoreRule(pIServerUserItem) == false) return false;
  4144. //扩展效验
  4145. if ((m_pGameServiceOption->wServerType&GAME_GENRE_MATCH) == 0 && m_pITableUserRequest != NULL)
  4146. {
  4147. //变量定义
  4148. tagRequestResult RequestResult;
  4149. ZeroMemory(&RequestResult, sizeof(RequestResult));
  4150. //坐下效验
  4151. if (m_pITableUserRequest->OnUserRequestSitDown(wChairID, pIServerUserItem, RequestResult) == false)
  4152. {
  4153. //发送信息
  4154. SendRequestFailure(pIServerUserItem, RequestResult.szFailureReason, RequestResult.cbFailureCode);
  4155. return false;
  4156. }
  4157. }
  4158. //还需要多少元宝
  4159. UINT wReduceBeans = 0;
  4160. UINT wBean = 0;
  4161. if (mGameConfig.wSubGameID >= 10 && mGameConfig.wSubGameID <20)
  4162. {
  4163. //新版本 血流
  4164. wBean = GetNeedPayEx();
  4165. }
  4166. else if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  4167. {
  4168. //新版本
  4169. wBean = GetNeedPayCxz();
  4170. }
  4171. else
  4172. {
  4173. //检验房间参数
  4174. wBean = GetNeedPay();
  4175. }
  4176. if (wBean == 0xff)
  4177. {
  4178. return false;
  4179. }
  4180. //检验元宝
  4181. if (m_wPrivateTableOwnerID == pIServerUserItem->GetUserID())
  4182. {
  4183. //是创建者 已经扣完元宝了
  4184. wReduceBeans = 0;
  4185. }
  4186. else
  4187. {
  4188. if (mGameConfig.wMaxFanRule == 0)
  4189. {
  4190. //房主支付
  4191. wReduceBeans = 0;
  4192. }
  4193. else if (mGameConfig.wMaxFanRule >= 10)
  4194. {
  4195. //群主支付
  4196. wReduceBeans = 0;
  4197. }
  4198. else
  4199. {
  4200. if (mGameConfig.wSubGameID >= 3 && mGameConfig.wSubGameID <= 5)
  4201. {
  4202. //戳瞎子
  4203. wReduceBeans = wBean / 3;
  4204. }
  4205. else
  4206. {
  4207. //正常版本
  4208. wReduceBeans = wBean / MAX_CHAIR;
  4209. }
  4210. }
  4211. }
  4212. auto UserInfo = pIServerUserItem->GetUserInfo();
  4213. if (UserInfo->dwBean < wReduceBeans && pIServerUserItem->GetUserID() != m_wPrivateTableOwnerID)
  4214. {
  4215. //用户状态
  4216. pIServerUserItem->SetUserStatus(US_FREE, INVALID_TABLE, INVALID_CHAIR);
  4217. SendRequestFailure(pIServerUserItem, TEXT("钻石不足,不能进行选座."), 0); ///---元宝改钻石 2017-8-3
  4218. return false;
  4219. }
  4220. //设置变量
  4221. m_TableUserItemArray[wChairID] = pIServerUserItem;
  4222. m_wDrawCount = 0;
  4223. //用户状态
  4224. if ((IsGameStarted() == false) || (m_cbStartMode != START_MODE_TIME_CONTROL))
  4225. {
  4226. if (CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule) == false && (m_pGameServiceOption->wServerType&GAME_GENRE_MATCH) == 0)
  4227. {
  4228. pIServerUserItem->SetClientReady(true);
  4229. pIServerUserItem->SetUserStatus(US_SIT, m_wTableID, wChairID);
  4230. }
  4231. else
  4232. {
  4233. if (m_pGameServiceOption->wServerType == GAME_GENRE_MATCH)
  4234. {
  4235. pIServerUserItem->SetClientReady(pIServerUserItem->IsTrusteeUser());
  4236. pIServerUserItem->SetUserStatus(US_READY, m_wTableID, wChairID);
  4237. }
  4238. else
  4239. {
  4240. pIServerUserItem->SetClientReady(true);
  4241. pIServerUserItem->SetUserStatus(US_SIT, m_wTableID, wChairID);
  4242. }
  4243. }
  4244. }
  4245. else
  4246. {
  4247. //设置变量
  4248. m_wOffLineCount[wChairID] = 0L;
  4249. m_dwOffLineTime[wChairID] = 0L;
  4250. //设置状态
  4251. pIServerUserItem->SetClientReady(true);
  4252. pIServerUserItem->SetUserStatus(US_SIT, m_wTableID, wChairID);
  4253. }
  4254. //设置变量
  4255. m_wUserCount = GetSitUserCount();
  4256. if (m_sPrivateTableID.empty())
  4257. {//公共房间开启准备超时定时器。
  4258. //启动定时
  4259. if (IsGameStarted() == false && pIServerUserItem->IsMobileUser() && m_pGameServiceAttrib->wChairCount < MAX_CHAIR)
  4260. SetGameTimer(IDI_START_OVERTIME + wChairID, TIME_OVERTIME, 1, wChairID);
  4261. }
  4262. //事件通知
  4263. if (m_pITableUserAction != NULL)
  4264. {
  4265. m_pITableUserAction->OnActionUserSitDown(wChairID, pIServerUserItem, false);
  4266. }
  4267. //事件通知
  4268. if (m_pIMatchTableAction != NULL) m_pIMatchTableAction->OnActionUserSitDown(wChairID, pIServerUserItem, false);
  4269. if (m_pGameServiceOption->wServerType == GAME_GENRE_MATCH)
  4270. {
  4271. //开始判断
  4272. if (EfficacyStartGame(INVALID_CHAIR) == true)
  4273. {
  4274. StartGame();
  4275. }
  4276. }
  4277. CAttemperEngineSink * pAttemperEngineSink = (CAttemperEngineSink *)m_pIMainServiceFrame;
  4278. pAttemperEngineSink->SetUserServerID(pIServerUserItem, 1, 0);//通知协调服务器 这个用户已经进入桌子了。
  4279. return true;
  4280. }
  4281. //单元积分
  4282. VOID CTableFrame::SetCellScore(LONG lCellScore)
  4283. {
  4284. m_lCellScore = lCellScore;
  4285. if (m_bTableInitFinish == true)
  4286. {
  4287. SendTableStatus();
  4288. m_pITableFrameSink->SetGameBaseScore(lCellScore);
  4289. }
  4290. }
  4291. //桌子状态
  4292. bool CTableFrame::SendTableStatus()
  4293. {
  4294. return true;
  4295. //变量定义
  4296. CMD_GR_TableStatus TableStatus;
  4297. ZeroMemory(&TableStatus, sizeof(TableStatus));
  4298. //构造数据
  4299. TableStatus.wTableID = m_wTableID;
  4300. TableStatus.TableStatus.lCellScore = m_lCellScore;
  4301. TableStatus.TableStatus.cbTableLock = IsTableLocked() ? TRUE : FALSE;
  4302. TableStatus.TableStatus.cbPlayStatus = IsTableStarted() ? TRUE : FALSE;
  4303. //电脑数据
  4304. //m_pIMainServiceFrame->SendData(BG_COMPUTER, MDM_GR_STATUS, SUB_GR_TABLE_STATUS, &TableStatus, sizeof(TableStatus));
  4305. //手机数据
  4306. }
  4307. //请求失败
  4308. bool CTableFrame::SendRequestFailure(IServerUserItem * pIServerUserItem, LPCTSTR pszDescribe, LONG lErrorCode)
  4309. {
  4310. //变量定义
  4311. CMD_GR_RequestFailure RequestFailure;
  4312. ZeroMemory(&RequestFailure, sizeof(RequestFailure));
  4313. //构造数据
  4314. RequestFailure.lErrorCode = lErrorCode;
  4315. lstrcpyn(RequestFailure.szDescribeString, pszDescribe, CountArray(RequestFailure.szDescribeString));
  4316. UserInfo::PB_CS_S_RequestFailure Failure;
  4317. Failure.set_lerrorcode(RequestFailure.lErrorCode);
  4318. std::string szDescribeString = CW2AEX<1024>(RequestFailure.szDescribeString, CP_UTF8).m_psz;
  4319. Failure.set_szdescribestring(szDescribeString);
  4320. //发送数据
  4321. std::string pbdata = Failure.SerializePartialAsString();
  4322. m_pIMainServiceFrame->SendData(pIServerUserItem, MDM_GR_USER, SUB_GR_REQUEST_FAILURE, (void*)pbdata.c_str(), pbdata.length());
  4323. return true;
  4324. }
  4325. //开始效验
  4326. bool CTableFrame::EfficacyStartGame(WORD wReadyChairID)
  4327. {
  4328. //状态判断
  4329. if (m_bGameStarted == true) return false;
  4330. //模式过滤
  4331. if (m_cbStartMode == START_MODE_TIME_CONTROL) return false;
  4332. if (m_cbStartMode == START_MODE_MASTER_CONTROL) return false;
  4333. //准备人数
  4334. WORD wReadyUserCount = 0;
  4335. for (WORD i = 0; i < m_wChairCount; i++)
  4336. {
  4337. //获取用户
  4338. IServerUserItem * pITableUserItem = GetTableUserItem(i);
  4339. if (pITableUserItem == NULL) continue;
  4340. //用户统计
  4341. if (pITableUserItem != NULL)
  4342. {
  4343. //状态判断
  4344. //if (pITableUserItem->IsClientReady() == false) return false;
  4345. if (!m_bGameStarted)
  4346. {
  4347. if (pITableUserItem->GetUserStatus() == US_READY
  4348. || pITableUserItem->GetUserStatus() == US_OFFLINE
  4349. || US_PLAYING == pITableUserItem->GetUserStatus())
  4350. {
  4351. //用户计数
  4352. wReadyUserCount++;
  4353. }
  4354. }
  4355. else
  4356. {
  4357. //游戏开始以后 看是否在游戏中已经点了准备
  4358. if (m_GameRead[i] == true)
  4359. {
  4360. //用户计数
  4361. wReadyUserCount++;
  4362. }
  4363. }
  4364. }
  4365. }
  4366. //开始处理
  4367. switch (m_cbStartMode)
  4368. {
  4369. case START_MODE_ALL_READY: //所有准备
  4370. {
  4371. //数目判断
  4372. if (wReadyUserCount >= 2L) return true;
  4373. return false;
  4374. }
  4375. case START_MODE_FULL_READY: //满人开始
  4376. {
  4377. //人数判断
  4378. if (wReadyUserCount == m_wChairCount) return true;
  4379. return false;
  4380. }
  4381. case START_MODE_PAIR_READY: //配对开始
  4382. {
  4383. //数目判断
  4384. if (wReadyUserCount == m_wChairCount) return true;
  4385. if ((wReadyUserCount < 2L) || (wReadyUserCount % 2) != 0) return false;
  4386. //位置判断
  4387. for (WORD i = 0; i < m_wChairCount / 2; i++)
  4388. {
  4389. //获取用户
  4390. IServerUserItem * pICurrentUserItem = GetTableUserItem(i);
  4391. IServerUserItem * pITowardsUserItem = GetTableUserItem(i + m_wChairCount / 2);
  4392. //位置过滤
  4393. if ((pICurrentUserItem == NULL) && (pITowardsUserItem != NULL)) return false;
  4394. if ((pICurrentUserItem != NULL) && (pITowardsUserItem == NULL)) return false;
  4395. }
  4396. return true;
  4397. }
  4398. default:
  4399. {
  4400. ASSERT(FALSE);
  4401. return false;
  4402. }
  4403. }
  4404. return false;
  4405. }
  4406. //地址效验
  4407. bool CTableFrame::EfficacyIPAddress(IServerUserItem * pIServerUserItem)
  4408. {
  4409. //管理员不受限制
  4410. if (pIServerUserItem->GetMasterOrder() != 0) return true;
  4411. //规则判断
  4412. //if (CServerRule::IsForfendGameRule(m_pGameServiceOption->dwServerRule) == true) return true;
  4413. //防作弊
  4414. //if (CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule)) return true;
  4415. //百人不限制
  4416. if (m_wChairCount > MAX_CHAIR_GENERAL) return true;
  4417. //地址效验
  4418. const tagUserRule * pUserRule = pIServerUserItem->GetUserRule(), *pTableUserRule = NULL;
  4419. bool bCheckSameIP = true;
  4420. //地址效验
  4421. if (bCheckSameIP == true)
  4422. {
  4423. DWORD dwUserIP = pIServerUserItem->GetClientAddr();
  4424. for (WORD i = 0; i < m_wChairCount; i++)
  4425. {
  4426. //获取用户
  4427. IServerUserItem * pITableUserItem = GetTableUserItem(i);
  4428. if(pITableUserItem != NULL) if (pITableUserItem->GetClientAddr() == 0) continue;
  4429. if ((pITableUserItem != NULL) && (pITableUserItem != pIServerUserItem) && (!pITableUserItem->IsAndroidUser()) && (pITableUserItem->GetMasterOrder() == 0) && (pITableUserItem->GetClientAddr() == dwUserIP))
  4430. {
  4431. if (!pUserRule->bLimitSameIP)
  4432. {
  4433. //发送信息
  4434. LPCTSTR pszDescribe = TEXT("此游戏桌玩家设置了不跟相同 IP 地址的玩家游戏,您 IP 地址与此玩家的 IP 地址相同,不能加入游戏!");
  4435. SendRequestFailure(pIServerUserItem, pszDescribe, REQUEST_FAILURE_NORMAL);
  4436. return false;
  4437. }
  4438. else
  4439. {
  4440. //发送信息
  4441. LPCTSTR pszDescribe = TEXT("您设置了不跟相同 IP 地址的玩家游戏,此游戏桌存在与您 IP 地址相同的玩家,不能加入游戏!");
  4442. SendRequestFailure(pIServerUserItem, pszDescribe, REQUEST_FAILURE_NORMAL);
  4443. return false;
  4444. }
  4445. }
  4446. }
  4447. for (WORD i = 0; i < m_wChairCount - 1; i++)
  4448. {
  4449. //获取用户
  4450. IServerUserItem * pITableUserItem = GetTableUserItem(i);
  4451. if (pITableUserItem != NULL && (!pITableUserItem->IsAndroidUser()) && (pITableUserItem->GetMasterOrder() == 0))
  4452. {
  4453. for (WORD j = i + 1; j < m_wChairCount; j++)
  4454. {
  4455. //获取用户
  4456. IServerUserItem * pITableNextUserItem = GetTableUserItem(j);
  4457. if (pITableUserItem != NULL) if (pITableUserItem->GetClientAddr() == 0) continue;
  4458. if ((pITableNextUserItem != NULL) && (!pITableNextUserItem->IsAndroidUser()) && (pITableNextUserItem->GetMasterOrder() == 0) && (pITableUserItem->GetClientAddr() == pITableNextUserItem->GetClientAddr()))
  4459. {
  4460. LPCTSTR pszDescribe = TEXT("您设置了不跟相同 IP 地址的玩家游戏,此游戏桌存在 IP 地址相同的玩家,不能加入游戏!");
  4461. SendRequestFailure(pIServerUserItem, pszDescribe, REQUEST_FAILURE_NORMAL);
  4462. return false;
  4463. }
  4464. }
  4465. }
  4466. }
  4467. }
  4468. return true;
  4469. }
  4470. //积分效验
  4471. bool CTableFrame::EfficacyScoreRule(IServerUserItem * pIServerUserItem)
  4472. {
  4473. //管理员不受限制
  4474. if (pIServerUserItem->GetMasterOrder() != 0) return true;
  4475. //规则判断
  4476. if (CServerRule::IsForfendGameRule(m_pGameServiceOption->dwServerRule) == true) return true;
  4477. //防作弊
  4478. if (CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule)) return true;
  4479. //百人不限制
  4480. if (m_wChairCount > MAX_CHAIR_GENERAL) return true;
  4481. //变量定义
  4482. WORD wWinRate = pIServerUserItem->GetUserWinRate();
  4483. WORD wFleeRate = pIServerUserItem->GetUserFleeRate();
  4484. //积分范围
  4485. for (WORD i = 0; i < m_wChairCount; i++)
  4486. {
  4487. //获取用户
  4488. IServerUserItem * pITableUserItem = GetTableUserItem(i);
  4489. //规则效验
  4490. if (pITableUserItem != NULL)
  4491. {
  4492. //获取规则
  4493. tagUserRule * pTableUserRule = pITableUserItem->GetUserRule();
  4494. //逃率效验
  4495. if ((pTableUserRule->bLimitFleeRate) && (wFleeRate > pTableUserRule->wMaxFleeRate))
  4496. {
  4497. //构造信息
  4498. TCHAR szDescribe[128] = TEXT("");
  4499. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("您的逃跑率太高,与 %s 设置的设置不符,不能加入游戏!"), pITableUserItem->GetNickName());
  4500. //发送信息
  4501. SendRequestFailure(pIServerUserItem, szDescribe, REQUEST_FAILURE_NORMAL);
  4502. return false;
  4503. }
  4504. //胜率效验
  4505. if ((pTableUserRule->bLimitWinRate) && (wWinRate < pTableUserRule->wMinWinRate))
  4506. {
  4507. //构造信息
  4508. TCHAR szDescribe[128] = TEXT("");
  4509. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("您的胜率太低,与 %s 设置的设置不符,不能加入游戏!"), pITableUserItem->GetNickName());
  4510. //发送信息
  4511. SendRequestFailure(pIServerUserItem, szDescribe, REQUEST_FAILURE_NORMAL);
  4512. return false;
  4513. }
  4514. //积分效验
  4515. if (pTableUserRule->bLimitGameScore == true)
  4516. {
  4517. //最高积分
  4518. if (pIServerUserItem->GetUserScore() > pTableUserRule->lMaxGameScore)
  4519. {
  4520. //构造信息
  4521. TCHAR szDescribe[128] = TEXT("");
  4522. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("您的积分太高,与 %s 设置的设置不符,不能加入游戏!"), pITableUserItem->GetNickName());
  4523. //发送信息
  4524. SendRequestFailure(pIServerUserItem, szDescribe, REQUEST_FAILURE_NORMAL);
  4525. return false;
  4526. }
  4527. //最低积分
  4528. if (pIServerUserItem->GetUserScore() < pTableUserRule->lMinGameScore)
  4529. {
  4530. //构造信息
  4531. TCHAR szDescribe[128] = TEXT("");
  4532. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("您的积分太低,与 %s 设置的设置不符,不能加入游戏!"), pITableUserItem->GetNickName());
  4533. //发送信息
  4534. SendRequestFailure(pIServerUserItem, szDescribe, REQUEST_FAILURE_NORMAL);
  4535. return false;
  4536. }
  4537. }
  4538. }
  4539. }
  4540. return true;
  4541. }
  4542. //积分效验
  4543. bool CTableFrame::EfficacyEnterTableScoreRule(WORD wChairID, IServerUserItem * pIServerUserItem)
  4544. {
  4545. //积分变量
  4546. SCORE lUserScore = pIServerUserItem->GetUserScore();
  4547. SCORE lMinTableScore = m_pGameServiceOption->lMinTableScore;
  4548. SCORE lLessEnterScore = m_pITableFrameSink->QueryLessEnterScore(wChairID, pIServerUserItem);
  4549. if (((lMinTableScore != 0L) && (lUserScore < lMinTableScore)) || ((lLessEnterScore != 0L) && (lUserScore < lLessEnterScore)))
  4550. {
  4551. //构造信息
  4552. TCHAR szDescribe[128] = TEXT("");
  4553. if (m_pGameServiceOption->wServerType == GAME_GENRE_GOLD)
  4554. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("加入游戏至少需要 ") SCORE_STRING TEXT(" 的游戏币,您的游戏币不够,不能加入!"), __max(lMinTableScore, lLessEnterScore));
  4555. else if (m_pGameServiceOption->wServerType == GAME_GENRE_MATCH)
  4556. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("加入游戏至少需要 ") SCORE_STRING TEXT(" 的比赛币,您的比赛币不够,不能加入!"), __max(lMinTableScore, lLessEnterScore));
  4557. else
  4558. _sntprintf(szDescribe, CountArray(szDescribe), TEXT("加入游戏至少需要 ") SCORE_STRING TEXT(" 的游戏积分,您的积分不够,不能加入!"), __max(lMinTableScore, lLessEnterScore));
  4559. //发送信息
  4560. SendRequestFailure(pIServerUserItem, szDescribe, REQUEST_FAILURE_NOSCORE);
  4561. return false;
  4562. }
  4563. return true;
  4564. }
  4565. //检查分配
  4566. bool CTableFrame::CheckDistribute()
  4567. {
  4568. //防作弊
  4569. if (CServerRule::IsAllowAvertCheatMode(m_pGameServiceOption->dwServerRule))
  4570. {
  4571. //桌子状况
  4572. tagTableUserInfo TableUserInfo;
  4573. WORD wUserSitCount = GetTableUserInfo(TableUserInfo);
  4574. //用户起立
  4575. if (wUserSitCount < TableUserInfo.wMinUserCount)
  4576. {
  4577. return true;
  4578. }
  4579. }
  4580. return false;
  4581. }
  4582. //游戏记录
  4583. void CTableFrame::RecordGameScore(bool bDrawStarted, DWORD dwStartGameTime, bool bUpdateParent)
  4584. {
  4585. if (bDrawStarted == true)
  4586. {
  4587. //写入记录
  4588. if (CServerRule::IsRecordGameScore(m_pGameServiceOption->dwServerRule) == true)
  4589. {
  4590. //变量定义
  4591. DBR_GR_GameScoreRecord GameScoreRecord;
  4592. ZeroMemory(&GameScoreRecord, sizeof(GameScoreRecord));
  4593. //设置变量
  4594. GameScoreRecord.cbUpdateParent = bUpdateParent ? 1 : 0;
  4595. GameScoreRecord.wPrivateTableParentNodeID = m_wPrivateTablParentNodeID; //设置记录的父节点(0表示没有父节点)
  4596. lstrcpy(GameScoreRecord.szPrivateTableID, m_sPrivateTableID.c_str());
  4597. GameScoreRecord.wTableID = m_wTableID;
  4598. GameScoreRecord.wTableType = m_wTableKind;
  4599. GameScoreRecord.dwPlayTimeCount = (bDrawStarted == true) ? (DWORD)time(NULL) - m_dwDrawStartTime : 0;
  4600. GameScoreRecord.wRePlayRecordSize = m_ReplayRecordDataSize;
  4601. //游戏时间
  4602. if (dwStartGameTime != INVALID_DWORD)
  4603. {
  4604. CTime startTime(dwStartGameTime);
  4605. startTime.GetAsSystemTime(GameScoreRecord.SystemTimeStart);
  4606. }
  4607. else
  4608. {
  4609. GameScoreRecord.SystemTimeStart = m_SystemTimeStart;
  4610. }
  4611. GetLocalTime(&GameScoreRecord.SystemTimeConclude);
  4612. if (INVALID_TABLE == dwStartGameTime)
  4613. {
  4614. //游戏结束
  4615. int iPlayNum = m_wStartCount << 8;
  4616. GameScoreRecord.lWasteCount = mGameConfig.wSubGameID + iPlayNum;
  4617. GetLocalTime(&GameScoreRecord.SystemTimeConclude);
  4618. }
  4619. for (int i = 0; i < 4; i++)
  4620. {
  4621. //奖牌统计
  4622. GameScoreRecord.wUserMemal += m_pITableFrameSink->QueryTatolLaiGang(i);
  4623. }
  4624. GameScoreRecord.wDiFen = mGameConfig.wPlayRule;
  4625. //用户积分
  4626. for (INT_PTR i = 0; i < m_GameScoreRecordActive.GetCount(); i++)
  4627. {
  4628. //获取对象
  4629. ASSERT(m_GameScoreRecordActive[i] != NULL);
  4630. tagGameScoreRecord * pGameScoreRecord = m_GameScoreRecordActive[i];
  4631. //用户数目
  4632. if (pGameScoreRecord->cbAndroid == FALSE)
  4633. {
  4634. GameScoreRecord.wUserCount++;
  4635. }
  4636. else
  4637. {
  4638. GameScoreRecord.wAndroidCount++;
  4639. }
  4640. //统计信息
  4641. if (pGameScoreRecord->cbAndroid == FALSE)
  4642. {
  4643. //GameScoreRecord.lWasteCount -= (pGameScoreRecord->lScore + pGameScoreRecord->lRevenue);
  4644. GameScoreRecord.lRevenueCount += pGameScoreRecord->lRevenue;
  4645. }
  4646. //成绩信息
  4647. if (GameScoreRecord.wRecordCount<CountArray(GameScoreRecord.GameScoreRecord))
  4648. {
  4649. WORD wIndex = GameScoreRecord.wRecordCount++;
  4650. if (bUpdateParent)
  4651. {
  4652. //如果是结束桌子
  4653. //适配二人麻将
  4654. if (this->GetStartMode() == START_MODE_ALL_READY && wIndex == 1)
  4655. {
  4656. pGameScoreRecord->lScore = m_pITableFrameSink->QueryTatolScore(2);
  4657. }
  4658. else
  4659. {
  4660. pGameScoreRecord->lScore = m_pITableFrameSink->QueryTatolScore(wIndex);
  4661. }
  4662. CopyMemory(&GameScoreRecord.GameScoreRecord[wIndex], pGameScoreRecord, sizeof(tagGameScoreRecord));
  4663. }
  4664. else
  4665. {
  4666. CopyMemory(&GameScoreRecord.GameScoreRecord[wIndex], pGameScoreRecord, sizeof(tagGameScoreRecord));
  4667. }
  4668. }
  4669. }
  4670. if (this->GetStartMode() == START_MODE_ALL_READY && GameScoreRecord.wRecordCount == 2)//二人玩法额外加一条
  4671. {
  4672. CopyMemory(&GameScoreRecord.GameScoreRecord[2], &GameScoreRecord.GameScoreRecord[1], sizeof(tagGameScoreRecord));
  4673. GameScoreRecord.GameScoreRecord[1].lScore = 0;
  4674. GameScoreRecord.wRecordCount++;
  4675. }
  4676. //投递数据
  4677. if (GameScoreRecord.wUserCount > 0)
  4678. {
  4679. WORD wHeadSize = sizeof(GameScoreRecord)-sizeof(GameScoreRecord.GameScoreRecord);
  4680. WORD wDataSize = sizeof(GameScoreRecord.GameScoreRecord[0])*GameScoreRecord.wRecordCount;
  4681. int totalData = wHeadSize + wDataSize + m_ReplayRecordDataSize;
  4682. char *data = new char[totalData];
  4683. CopyMemory(data, &GameScoreRecord, wHeadSize + wDataSize);
  4684. if (m_ReplayRecordDataSize > 0)
  4685. {
  4686. //如果回放数据已存档,则删除
  4687. CopyMemory(data + wHeadSize + wDataSize,m_ReplayRecordData, m_ReplayRecordDataSize);
  4688. if (nullptr != m_ReplayRecordData)
  4689. {
  4690. delete[] m_ReplayRecordData;
  4691. m_ReplayRecordData = nullptr;
  4692. }
  4693. m_ReplayRecordDataSize = 0;
  4694. }
  4695. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GR_GAME_SCORE_RECORD, 0, data, totalData);
  4696. //内存泄露
  4697. if (data != NULL)
  4698. {
  4699. delete[] data;
  4700. data = NULL;
  4701. }
  4702. }
  4703. }
  4704. //清理记录
  4705. if (m_GameScoreRecordActive.GetCount() > 0L)
  4706. {
  4707. m_GameScoreRecordBuffer.Append(m_GameScoreRecordActive);
  4708. m_GameScoreRecordActive.RemoveAll();
  4709. m_GameScoreRecordActive.FreeMemory();
  4710. }
  4711. }
  4712. }
  4713. //扣钻 调用数据库接口
  4714. bool CTableFrame::DeductWLZuanshi(DWORD dwUserID)
  4715. {
  4716. m_pIRecordDataBaseEngine->PostDataBaseRequest(DBR_GP_DEDUCT_ZUANSHI_INFO, 0, &dwUserID, sizeof(dwUserID));
  4717. return true;
  4718. }
  4719. //////////////////////////////////////////////////////////////////////////////////