FriendMgr.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:31k
源码类别:

模拟服务器

开发平台:

C/C++

  1. // FriendMgr.cpp: implementation of the CFriendMgr class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "global.h"
  6. #include "FriendMgr.h"
  7. #include "assert.h"
  8. #include "malloc.h"
  9. #include "S3Relay.h"
  10. #include <list>
  11. #include <map>
  12. //////////////////////////////////////////////////////////////////////
  13. #define STR_NULL _T("")
  14. //////////////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////////////
  16. static char file_friendcfg[] = "relay_friendcfg.ini";
  17. const char sec_database[] = "database";
  18. const char key_path[] = "path";
  19. const char key_file[] = "file";
  20. const char key_updateinterval[] = "updateinterval";
  21. const char key_storeplayerperudtdb[] = "storeplayerperudtdb";
  22. const char key_loadplayerperudtdb[] = "loadplayerperudtdb";
  23. //////////////////////////////////////////////////////////////////////
  24. static std::_tstring s_dbpath = gGetPrivateProfileStringEx(sec_database, key_path, file_friendcfg);
  25. static std::_tstring s_dbfile = gGetPrivateProfileStringEx(sec_database, key_file, file_friendcfg);
  26. //////////////////////////////////////////////////////////////////////
  27. // Construction/Destruction
  28. //////////////////////////////////////////////////////////////////////
  29. CFriendMgr::CFriendMgr()
  30. : m_elapseUpdateDB(0), m_tickLast(0),
  31. m_StorePlayerPerUdtDB(0), m_LoadPlayerPerUdtDB(0), 
  32. m_dbFriend(s_dbpath.c_str(), s_dbfile.c_str()),
  33. m_dbFriendRO(s_dbpath.c_str(), s_dbfile.c_str()),
  34. m_cursorBkgrndUdtDB(0)
  35. {
  36. }
  37. CFriendMgr::~CFriendMgr()
  38. {
  39. }
  40. BOOL CFriendMgr::Initialize()
  41. {
  42. //open DB
  43. {{
  44. AUTOLOCKWRITE(m_lockDB);
  45. if (!m_dbFriend.open() || !m_dbFriendRO.open())
  46. return FALSE;
  47. }}
  48. {{
  49. AUTOLOCKWRITE(m_lockFriend);
  50. m_mapPlayers.clear();
  51. }}
  52. m_cursorBkgrndUdtDB = 0;
  53. m_StorePlayerPerUdtDB = (size_t)gGetPrivateProfileIntEx(sec_database, key_storeplayerperudtdb, file_friendcfg, 0);
  54. m_LoadPlayerPerUdtDB = (size_t)gGetPrivateProfileIntEx(sec_database, key_loadplayerperudtdb, file_friendcfg, 0);
  55. m_elapseUpdateDB = (UINT)gGetPrivateProfileIntEx(sec_database, key_updateinterval, file_friendcfg, 0);
  56. if (m_elapseUpdateDB > 0)
  57. {
  58. if (!gStartFriendTimingUpdateDB(m_elapseUpdateDB))
  59. return FALSE;
  60. }
  61. return TRUE;
  62. }
  63. BOOL CFriendMgr::Uninitialize()
  64. {
  65. if (m_elapseUpdateDB > 0)
  66. gStopFriendTimingUpdateDB();
  67. //update DB
  68. {{
  69. AUTOLOCKWRITE(m_lockFriend);
  70. for (PLAYERSMAP::iterator itPlayer = m_mapPlayers.begin(); itPlayer != m_mapPlayers.end(); itPlayer++)
  71. {
  72. std::_tstring someone((*itPlayer).first);
  73. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  74. if (!rPlayerInfo.loaded)
  75. {
  76. PLAYERSMAP::iterator itLoadPlayer = _LoadSomeone(someone);
  77. assert(itLoadPlayer == itPlayer);
  78. }
  79. _StoreSomeone(itPlayer);
  80. }
  81. m_mapPlayers.clear();
  82. }}
  83. m_cursorBkgrndUdtDB = 0;
  84. //close DB
  85. {{
  86. AUTOLOCKWRITE(m_lockDB);
  87. m_dbFriendRO.close();
  88. m_dbFriend.close();
  89. }}
  90. return TRUE;
  91. }
  92. BOOL CFriendMgr::SomeoneLogin(const std::string& role)
  93. {
  94. //use for notify online friends
  95. typedef std::list<tagPlusSrcInfo> PLAYERLIST;
  96. typedef std::map<DWORD, PLAYERLIST> IP2PLAYERSMAP;
  97. IP2PLAYERSMAP mapIp2Players;
  98. {{
  99. AUTOLOCKWRITE(m_lockFriend);
  100. PLAYERSMAP::iterator itPlayer = _LoadSomeone(role);
  101. if (itPlayer == m_mapPlayers.end())
  102. return FALSE;
  103. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  104. assert(rPlayerInfo.loaded);
  105. for (FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.begin(); itFriend != rPlayerInfo.friends.end(); itFriend++)
  106. {
  107. std::_tstring dst = (*itFriend).first;
  108. FRIENDINFO& rInfo = (*itFriend).second;
  109. assert(rInfo.pCheated);
  110. if (!rInfo.pCheated)
  111. continue;
  112. assert(!rInfo.cheating || !*rInfo.pCheated);
  113. if (rInfo.cheating && *rInfo.pCheated)
  114. continue;
  115. if (!*rInfo.pCheated)
  116. {//this friend is sincere for someone
  117. CNetConnectDup conndup2;
  118. DWORD nameid2 = 0;
  119. unsigned long param2 = 0;
  120. if (g_HostServer.FindPlayerByRole(NULL, dst, &conndup2, NULL, &nameid2, &param2))
  121. {//this friend is online
  122. tagPlusSrcInfo srcinfo;
  123. srcinfo.nameid = nameid2;
  124. srcinfo.lnID = param2;
  125. PLAYERLIST& rPlayers = mapIp2Players[conndup2.GetIP()];
  126. rPlayers.push_back(srcinfo);
  127. }
  128. }
  129. }
  130. }}
  131. if (!mapIp2Players.empty())
  132. {
  133. char buffer2[max_packagesize];
  134. size_t datasize2 = sizeof(FRIEND_STATE) + role.size() + 2;
  135. size_t basesize2 = sizeof(EXTEND_PASSTOBEVY) + datasize2;
  136. EXTEND_PASSTOBEVY* pEpb2 = (EXTEND_PASSTOBEVY*)buffer2;
  137. pEpb2->ProtocolFamily = pf_extend;
  138. pEpb2->ProtocolID = extend_s2c_passtobevy;
  139. pEpb2->datasize = datasize2;
  140. pEpb2->playercount = 0;
  141. FRIEND_STATE* pFs2 = (FRIEND_STATE*)(pEpb2 + 1);
  142. pFs2->ProtocolFamily = pf_friend;
  143. pFs2->ProtocolID = friend_s2c_friendstate;
  144. pFs2->state = stateOnline;
  145. char* pSrcRole2 = (char*)(pFs2 + 1);
  146. strcpy(pSrcRole2, role.c_str());
  147. pSrcRole2[role.size() + 1] = 0;
  148. tagPlusSrcInfo* pPlayer2 = (tagPlusSrcInfo*)(buffer2 + basesize2);
  149. for (IP2PLAYERSMAP::iterator itIP = mapIp2Players.begin(); itIP != mapIp2Players.end(); itIP++)
  150. {
  151. DWORD ip2 = (*itIP).first;
  152. PLAYERLIST& rPlayers = (*itIP).second;
  153. CNetConnectDup tongconndup2;
  154. tongconndup2 = g_TongServer.FindTongConnectByIP(ip2);
  155. if (!tongconndup2.IsValid())
  156. continue;
  157. size_t cursor2 = basesize2;
  158. for (PLAYERLIST::iterator itPlayer = rPlayers.begin(); itPlayer != rPlayers.end(); itPlayer++)
  159. {
  160. tagPlusSrcInfo& rSrcInfo = *itPlayer;
  161. if (cursor2 + sizeof(tagPlusSrcInfo) > max_packagesize)
  162. {
  163. tongconndup2.SendPackage(buffer2, cursor2);
  164. pEpb2->playercount = 0;
  165. cursor2 = basesize2;
  166. }
  167. pPlayer2[pEpb2->playercount ++] = rSrcInfo;
  168. cursor2 += sizeof(tagPlusSrcInfo);
  169. }
  170. if (cursor2 > basesize2)
  171. {
  172. assert(pEpb2->playercount > 0);
  173. tongconndup2.SendPackage(buffer2, cursor2);
  174. }
  175. }
  176. }
  177. return TRUE;
  178. }
  179. BOOL CFriendMgr::SomeoneLogout(const std::string& role)
  180. {
  181. AUTOLOCKWRITE(m_lockFriend);
  182. PLAYERSMAP::iterator itPlayer = m_mapPlayers.find(role);
  183. if (itPlayer == m_mapPlayers.end())
  184. return FALSE;
  185. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  186. assert(rPlayerInfo.loaded);
  187. size_t datasize2 = sizeof(FRIEND_STATE) + role.size() + 2;
  188. size_t pckgsize2 = sizeof(EXTEND_PASSTOSOMEONE) + datasize2;
  189. EXTEND_PASSTOSOMEONE* pEps2 = (EXTEND_PASSTOSOMEONE*)_alloca(pckgsize2);
  190. pEps2->ProtocolFamily = pf_extend;
  191. pEps2->ProtocolID = extend_s2c_passtosomeone;
  192. pEps2->datasize = datasize2;
  193. FRIEND_STATE* pFs2 = (FRIEND_STATE*)(pEps2 + 1);
  194. pFs2->ProtocolFamily = pf_friend;
  195. pFs2->ProtocolID = friend_s2c_friendstate;
  196. pFs2->state = stateOffline;
  197. char* pSrcRole2 = (char*)(pFs2 + 1);
  198. strcpy(pSrcRole2, role.c_str());
  199. pSrcRole2[role.size() + 1] = 0;
  200. for (FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.begin(); itFriend != rPlayerInfo.friends.end(); itFriend++)
  201. {
  202. std::_tstring dst = (*itFriend).first;
  203. FRIENDINFO& rInfo = (*itFriend).second;
  204. assert(rInfo.pCheated);
  205. if (!rInfo.pCheated)
  206. continue;
  207. assert(!rInfo.cheating || !*rInfo.pCheated);
  208. if (rInfo.cheating && *rInfo.pCheated)
  209. continue;
  210. if (!*rInfo.pCheated)
  211. {//notify
  212. CNetConnectDup conndup2;
  213. DWORD nameid2 = 0;
  214. unsigned long param2 = -1;
  215. if (g_HostServer.FindPlayerByRole(NULL, dst, &conndup2, NULL, &nameid2, &param2))
  216. {//this friend is online
  217. CNetConnectDup tongconndup2 = g_TongServer.FindTongConnectByIP(conndup2.GetIP());
  218. if (tongconndup2.IsValid())
  219. {
  220. pEps2->nameid = nameid2;
  221. pEps2->lnID = param2;
  222. tongconndup2.SendPackage(pEps2, pckgsize2);
  223. }
  224. }
  225. }
  226. }
  227. //不能并发写,因此这里不写DB
  228. //_StoreSomeone(itPlayer);
  229. return TRUE;
  230. }
  231. BOOL CFriendMgr::SomeoneSyncFriends(const std::string& role, unsigned long param, DWORD nameid, const CNetConnectDup& conndup, BOOL full, BYTE pckgid)
  232. {
  233. typedef std::pair<BYTE, std::_tstring> THEFRIEND; //first: state, second: name
  234. typedef std::list<THEFRIEND> FRIENDLIST;
  235. typedef std::map<std::_tstring, FRIENDLIST, _tstring_less> GRP2FRIENDSMAP;
  236. GRP2FRIENDSMAP mapGrp2Friends;
  237. {{
  238. AUTOLOCKREAD(m_lockFriend);
  239. PLAYERSMAP::iterator itPlayer = m_mapPlayers.find(role);
  240. if (itPlayer == m_mapPlayers.end())
  241. return FALSE;
  242. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  243. assert(rPlayerInfo.loaded);
  244. if (!rPlayerInfo.loaded)
  245. return FALSE;
  246. for (FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.begin(); itFriend != rPlayerInfo.friends.end(); itFriend++)
  247. {
  248. std::_tstring dst = (*itFriend).first;
  249. FRIENDINFO& rInfo = (*itFriend).second;
  250. assert(rInfo.pCheated);
  251. if (!rInfo.pCheated)
  252. continue;
  253. assert(!rInfo.cheating || !*rInfo.pCheated);
  254. if (rInfo.cheating && *rInfo.pCheated)
  255. continue;
  256. if (!rInfo.cheating)
  257. {
  258. BOOL online = g_HostServer.FindPlayerByRole(NULL, dst, NULL, NULL, NULL, NULL);
  259. if (!online && !full)
  260. continue;
  261. FRIENDLIST& rFriends = mapGrp2Friends[rInfo.group];
  262. rFriends.push_back(THEFRIEND(online ? stateOnline : stateOffline, dst));
  263. }
  264. }
  265. }}
  266. if (!mapGrp2Friends.empty())
  267. {
  268. char buffer[max_packagesize];
  269. size_t basesize = sizeof(EXTEND_PASSTOSOMEONE) + sizeof(REP_SYNCFRIENDLIST);
  270. EXTEND_PASSTOSOMEONE* pEps = (EXTEND_PASSTOSOMEONE*)buffer;
  271. pEps->ProtocolFamily = pf_extend;
  272. pEps->ProtocolID = extend_s2c_passtosomeone;
  273. pEps->nameid = nameid;
  274. pEps->lnID = param;
  275. REP_SYNCFRIENDLIST* pRsfl = (REP_SYNCFRIENDLIST*)(pEps + 1);
  276. pRsfl->ProtocolFamily = pf_friend;
  277. pRsfl->ProtocolID = friend_s2c_repsyncfriendlist;
  278. pRsfl->pckgid = pckgid;
  279. for (GRP2FRIENDSMAP::iterator itGrp = mapGrp2Friends.begin(); itGrp != mapGrp2Friends.end(); itGrp++)
  280. {
  281. size_t basecursor = basesize;
  282. std::_tstring grp = (*itGrp).first;
  283. FRIENDLIST& rFriends = (*itGrp).second;
  284. buffer[basecursor++] = specGroup;
  285. strcpy(buffer + basecursor, grp.c_str());
  286. basecursor += grp.size() + 1;
  287. size_t cursor = basecursor;
  288. for (FRIENDLIST::iterator itFriend = rFriends.begin(); itFriend != rFriends.end(); itFriend++)
  289. {
  290. THEFRIEND theFriend = *itFriend;
  291. // spec state name 0
  292. size_t appendsize = 1 + 1 + theFriend.second.size() + 1;
  293. // item specOver
  294. if (cursor + appendsize + 1 >  max_packagesize)
  295. {
  296. buffer[cursor++] = specOver;
  297. pEps->datasize = cursor - sizeof(EXTEND_PASSTOSOMEONE);
  298. conndup.SendPackage(buffer, cursor);
  299. cursor = basecursor;
  300. }
  301. buffer[cursor + 0] = specRole;
  302. buffer[cursor + 1] = theFriend.first;
  303. strcpy(buffer + cursor + 2, theFriend.second.c_str());
  304. cursor += appendsize;
  305. }
  306. if (cursor > basecursor)
  307. {
  308. buffer[cursor++] = specOver;
  309. pEps->datasize = cursor - sizeof(EXTEND_PASSTOSOMEONE);
  310. conndup.SendPackage(buffer, cursor);
  311. }
  312. }
  313. }
  314. rTRACE("sync friend list: %s (%s)", role.c_str(), full ? "full" : "part");
  315. return TRUE;
  316. }
  317. BOOL CFriendMgr::PlayerAddFriend(const std::_tstring& someone, const std::_tstring& dst)
  318. {
  319. if (_tstring_equal()(someone, dst))
  320. return FALSE;
  321. AUTOLOCKWRITE(m_lockFriend);
  322. PLAYERINFO& rSrcPlayerInfo = m_mapPlayers[someone];
  323. assert(rSrcPlayerInfo.loaded);
  324. FRIENDINFO& rSrcInfo = rSrcPlayerInfo.friends[dst];
  325. rSrcInfo.cheating = false;
  326. PLAYERINFO& rDstPlayerInfo = m_mapPlayers[dst];
  327. FRIENDINFO& rDstInfo = rDstPlayerInfo.friends[someone];
  328. rDstInfo.cheating = false;
  329. //binding
  330. rSrcInfo.pCheated = &rDstInfo.cheating;
  331. rDstInfo.pCheated = &rSrcInfo.cheating;
  332. rTRACE("Player Add Friend: %s [%s]", someone.c_str(), dst.c_str());
  333. return TRUE;
  334. }
  335. BOOL CFriendMgr::PlayerDelFriend(const std::_tstring& someone, const std::_tstring& dst)
  336. {
  337. AUTOLOCKWRITE(m_lockFriend);
  338. PLAYERSMAP::iterator itSrcPlayer = m_mapPlayers.find(someone);
  339. if (itSrcPlayer == m_mapPlayers.end())
  340. return FALSE;
  341. PLAYERINFO& rSrcPlayerInfo = (*itSrcPlayer).second;
  342. assert(rSrcPlayerInfo.loaded);
  343. if (!rSrcPlayerInfo.loaded)
  344. return FALSE;
  345. FRIENDSMAP::iterator itSrcFriend = rSrcPlayerInfo.friends.find(dst);
  346. if (itSrcFriend == rSrcPlayerInfo.friends.end())
  347. return FALSE;
  348. FRIENDINFO& rSrcInfo = (*itSrcFriend).second;
  349. assert(rSrcInfo.pCheated);
  350. if (!rSrcInfo.pCheated)
  351. return FALSE;
  352. //assert(!rSrcInfo.cheating || !*rSrcInfo.pCheated);
  353. //if (rSrcInfo.cheating && *rSrcInfo.pCheated)
  354. // return FALSE;
  355. rSrcInfo.cheating = true;
  356. if (!*rSrcInfo.pCheated)
  357. return TRUE;
  358. //erase...
  359. //dst
  360. PLAYERSMAP::iterator itDstPlayer = m_mapPlayers.find(dst);
  361. if (itDstPlayer != m_mapPlayers.end())
  362. {
  363. PLAYERINFO& rDstPlayerInfo = (*itDstPlayer).second;
  364. if (rDstPlayerInfo.loaded)
  365. rDstPlayerInfo.friends.erase(someone);
  366. else
  367. {
  368. FRIENDSMAP::iterator itDstFriend = rDstPlayerInfo.friends.find(someone);
  369. if (itDstFriend != rDstPlayerInfo.friends.end())
  370. {
  371. FRIENDINFO& rDstInfo = (*itDstFriend).second;
  372. rDstInfo.pCheated = NULL;
  373. }
  374. }
  375. }
  376. //src
  377. rSrcPlayerInfo.friends.erase(itSrcFriend);
  378. rTRACE("Player Del Friend: %s [%s]", someone.c_str(), dst.c_str());
  379. return TRUE;
  380. }
  381. BOOL CFriendMgr::PlayerIsFriend(const std::_tstring& someone, const std::_tstring& dst, BOOL rev)
  382. {
  383. AUTOLOCKREAD(m_lockFriend);
  384. PLAYERSMAP::iterator itPlayer = m_mapPlayers.find(someone);
  385. if (itPlayer == m_mapPlayers.end())
  386. return FALSE;
  387. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  388. FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.find(dst);
  389. if (itFriend == rPlayerInfo.friends.end())
  390. return FALSE;
  391. FRIENDINFO& rInfo = (*itFriend).second;
  392. if (!rInfo.pCheated)
  393. return FALSE;
  394. return !(rev ? *rInfo.pCheated : rInfo.cheating);
  395. }
  396. BOOL CFriendMgr::SetFriendGroup(const std::_tstring& someone, const std::_tstring& dst, const std::_tstring& group)
  397. {
  398. AUTOLOCKWRITE(m_lockFriend);
  399. PLAYERSMAP::iterator itPlayer = m_mapPlayers.find(someone);
  400. if (itPlayer == m_mapPlayers.end())
  401. return FALSE;
  402. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  403. FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.find(dst);
  404. if (itFriend == rPlayerInfo.friends.end())
  405. return FALSE;
  406. FRIENDINFO& rInfo = (*itFriend).second;
  407. assert(rInfo.pCheated);
  408. if (rInfo.pCheated == NULL)
  409. return FALSE;
  410. assert(!rInfo.cheating || !*rInfo.pCheated);
  411. if (rInfo.cheating && *rInfo.pCheated)
  412. return FALSE;
  413. rInfo.group = group;
  414. rTRACE("Player Group Friend: %s [%s] (%s)", someone.c_str(), dst.c_str(), group.c_str());
  415. return TRUE;
  416. }
  417. std::_tstring CFriendMgr::GetFriendGroup(const std::_tstring& someone, const std::_tstring& dst)
  418. {
  419. AUTOLOCKREAD(m_lockFriend);
  420. PLAYERSMAP::iterator itPlayer = m_mapPlayers.find(someone);
  421. if (itPlayer == m_mapPlayers.end())
  422. return STR_NULL;
  423. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  424. FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.find(dst);
  425. if (itFriend == rPlayerInfo.friends.end())
  426. return STR_NULL;
  427. FRIENDINFO& rInfo = (*itFriend).second;
  428. assert(rInfo.pCheated);
  429. if (!rInfo.pCheated)
  430. return STR_NULL;
  431. assert(!rInfo.cheating || !*rInfo.pCheated);
  432. if (rInfo.cheating && *rInfo.pCheated)
  433. return STR_NULL;
  434. return rInfo.group;
  435. }
  436. BOOL CFriendMgr::TrackAddFriend(const std::_tstring& src, const std::_tstring& dst, BYTE id)
  437. {
  438. AUTOLOCKWRITE(m_lockAddFriend);
  439. ADDFRIENDVALUE& rValue = m_mapAddFriends[ADDFRIENDKEY(id, src)];
  440. rValue.dst = dst;
  441. rValue.tick = ::GetTickCount();
  442. return TRUE;
  443. }
  444. BOOL CFriendMgr::ExtractAddFriend(const std::_tstring& src, const std::_tstring& dst, BYTE id)
  445. {
  446. AUTOLOCKWRITE(m_lockAddFriend);
  447. ADDFRIENDMAP::iterator it = m_mapAddFriends.find(ADDFRIENDKEY(id, src));
  448. if (it == m_mapAddFriends.end())
  449. return FALSE;
  450. ADDFRIENDVALUE& rValue = (*it).second;
  451. if (!_tstring_equal()(rValue.dst, dst))
  452. return FALSE;
  453. m_mapAddFriends.erase(it);
  454. return TRUE;
  455. }
  456. BOOL CFriendMgr::TidyAddFriend()
  457. {
  458. return TRUE;
  459. /*
  460. DWORD tick = ::GetTickCount();
  461. if (tick < m_tickLast + TIMEOUT_ADDFRIEND)
  462. return TRUE;
  463. AUTOLOCKWRITE(m_lockAddFriend);
  464. ADDFRIENDMAP::iterator it = m_mapAddFriends.begin();
  465. while (it != m_mapAddFriends.end())
  466. {
  467. ADDFRIENDMAP::iterator itMe = it++;
  468. ADDFRIENDVALUE& rValue = (*itMe).second;
  469. if (tick < rValue.tick + TIMEOUT_ADDFRIEND)
  470. continue;
  471. m_mapAddFriends.erase(itMe);
  472. }
  473. return TRUE;
  474. */
  475. }
  476. CFriendMgr::PLAYERSMAP::iterator CFriendMgr::_LoadSomeone(const std::_tstring& someone)
  477. {
  478. //assert(m_lockFriend._IsWriting());
  479. std::pair<PLAYERSMAP::iterator, bool> insret = m_mapPlayers.insert(PLAYERSMAP::value_type(someone, PLAYERINFO()));
  480. PLAYERINFO& rPlayerInfo = (*insret.first).second;
  481. if (!insret.second) //not insert someone
  482. {
  483. if (rPlayerInfo.loaded)
  484. return insret.first; //already loaded
  485. }
  486. rTRACE("load someone: %s", someone.c_str());
  487. //load from DB
  488. MEM_FRIENDRECORDLIST memFriends;
  489. if (!DB_LoadSomeone(someone, &memFriends))
  490. {
  491. rTRACE("except: load someone fail: %s", someone.c_str());
  492. return m_mapPlayers.end();
  493. }
  494. //update
  495. for (MEM_FRIENDRECORDLIST::iterator itMemFriend = memFriends.begin(); itMemFriend != memFriends.end(); itMemFriend++)
  496. {
  497. MEM_FRIENDRECORD& rmemFriendRec = *itMemFriend;
  498. std::pair<FRIENDSMAP::iterator, bool> insretfriend = rPlayerInfo.friends.insert(FRIENDSMAP::value_type(rmemFriendRec.name, FRIENDINFO()));
  499. FRIENDINFO& rInfo = (*insretfriend.first).second;
  500. if (insretfriend.second) //insert this friend
  501. {
  502. rInfo.group = rmemFriendRec.group;
  503. rInfo.cheating = rmemFriendRec.cheating;
  504. rInfo.orig_cheating = rmemFriendRec.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  505. rInfo.orig_cheated = rmemFriendRec.cheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  506. PLAYERINFO& rPlayerInfo2 = m_mapPlayers[rmemFriendRec.name];
  507. FRIENDINFO& rInfo2 = rPlayerInfo2.friends[someone];
  508. rInfo2.cheating = rmemFriendRec.cheated;
  509. rInfo.pCheated = &rInfo2.cheating;
  510. rInfo2.pCheated = &rInfo.cheating;
  511. }
  512. else
  513. {
  514. if (rInfo.pCheated == NULL)
  515. {
  516. rPlayerInfo.friends.erase(insretfriend.first);
  517. rPlayerInfo.dirty = TRUE;
  518. continue;
  519. }
  520. rInfo.group = rmemFriendRec.group;
  521. rInfo.orig_cheating = rmemFriendRec.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  522. rInfo.orig_cheated = rmemFriendRec.cheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  523. }
  524. }
  525. //clearup invalid items
  526. FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.begin();
  527. while (itFriend != rPlayerInfo.friends.end())
  528. {
  529. FRIENDSMAP::iterator itHere = itFriend++;
  530. FRIENDINFO& rInfo = (*itHere).second;
  531. if (rInfo.pCheated == NULL)
  532. {
  533. rPlayerInfo.friends.erase(itHere);
  534. rPlayerInfo.dirty = TRUE;
  535. }
  536. }
  537. rPlayerInfo.loaded = TRUE;
  538. return insret.first;
  539. }
  540. BOOL CFriendMgr::_StoreSomeone(PLAYERSMAP::iterator itSomeone)
  541. {
  542. //assert(m_lockFriend._IsRead());
  543. std::_tstring someone = (*itSomeone).first;
  544. PLAYERINFO& rPlayerInfo = (*itSomeone).second;
  545. assert(rPlayerInfo.loaded);
  546. if (!rPlayerInfo.loaded)
  547. {
  548. rTRACE("except: store someone outof mem: %s", someone.c_str());
  549. return FALSE;
  550. }
  551. rTRACE("store someone: %s", someone.c_str());
  552. BOOL needstore = rPlayerInfo.dirty;
  553. rPlayerInfo.dirty = FALSE;
  554. MEM_FRIENDRECORDLIST memFriends;
  555. for (FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.begin(); itFriend != rPlayerInfo.friends.end(); itFriend++)
  556. {
  557. std::_tstring name = (*itFriend).first;
  558. FRIENDINFO& rInfo = (*itFriend).second;
  559. assert(rInfo.pCheated);
  560. if (!rInfo.pCheated)
  561. continue;
  562. assert(!rInfo.cheating || !*rInfo.pCheated);
  563. if (rInfo.cheating && *rInfo.pCheated)
  564. continue;
  565. MEM_FRIENDRECORD memFriendRec;
  566. memFriendRec.name = name;
  567. memFriendRec.group = rInfo.group;
  568. memFriendRec.cheating = rInfo.cheating;
  569. memFriendRec.cheated = *rInfo.pCheated;
  570. memFriends.push_back(memFriendRec);
  571. if (!needstore
  572. && ((rInfo.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE) != rInfo.orig_cheating
  573. || (*rInfo.pCheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE) != rInfo.orig_cheated))
  574. {
  575. needstore = TRUE;
  576. }
  577. rInfo.orig_cheating = rInfo.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  578. rInfo.orig_cheated = *rInfo.pCheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  579. }
  580. if (!needstore) //mem & db is sync
  581. return TRUE;
  582. //store this friend's info into DB
  583. if (!DB_StoreSomeone(someone, memFriends))
  584. {
  585. rPlayerInfo.dirty = TRUE;
  586. rTRACE("error: store someone: %s", someone.c_str());
  587. return FALSE;
  588. }
  589. return TRUE;
  590. }
  591. std::_tstring CFriendMgr::NameToDBKey(const std::_tstring& name)
  592. {
  593. return name;
  594. }
  595. BOOL CFriendMgr::DB_AddSomeone(const std::_tstring& someone, const MEM_FRIENDRECORDLIST& memFriends)
  596. {
  597. return DB_StoreSomeone(someone, memFriends);
  598. }
  599. BOOL CFriendMgr::DB_DeleteSomeone(const std::_tstring& someone)
  600. {
  601. std::_tstring dbkey = NameToDBKey(someone);
  602. AUTOLOCKWRITE(m_lockDB);
  603. m_dbFriend.remove(dbkey.data(), dbkey.size());
  604. return TRUE;
  605. }
  606. BOOL CFriendMgr::DB_LoadSomeone(const std::_tstring& someone, MEM_FRIENDRECORDLIST* pmemFriends)
  607. {
  608. assert(pmemFriends && pmemFriends->empty());
  609. std::_tstring dbkey = NameToDBKey(someone);
  610. int valsize = 0;
  611. char* pValue = m_dbFriendRO.search(dbkey.data(), dbkey.size(), valsize);
  612. if (!pValue)
  613. return TRUE;
  614. DB_FRIENDRECORDLIST* pdbFriendList = (DB_FRIENDRECORDLIST*)pValue;
  615. DB_FRIENDRECORD* pCursor = (DB_FRIENDRECORD*)(pdbFriendList + 1);
  616. for (BYTE i = 0; i < pdbFriendList->count; i++)
  617. {
  618. MEM_FRIENDRECORD memFriend;
  619. memFriend.cheating = pCursor->cheating;
  620. memFriend.cheated = pCursor->cheated;
  621. _BASIC_STR* pName = (_BASIC_STR*)(pCursor + 1);
  622. assert(pName->strlen > 0 && pName->strlen < _NAME_LEN);
  623. char* strName = (char*)(pName + 1);
  624. memFriend.name.assign(strName, pName->strlen);
  625. _BASIC_STR* pGroup = (_BASIC_STR*)(strName + pName->strlen);
  626. assert(pGroup->strlen >= 0 && pGroup->strlen < _NAME_LEN);
  627. char* strGroup = (char*)(pGroup + 1);
  628. memFriend.group.assign(strGroup, pGroup->strlen);
  629. pmemFriends->push_back(memFriend);
  630. pCursor = (DB_FRIENDRECORD*)(strGroup + pGroup->strlen);
  631. }
  632. delete []pValue;
  633. return TRUE;
  634. }
  635. BOOL CFriendMgr::DB_StoreSomeone(const std::_tstring& someone, const MEM_FRIENDRECORDLIST& memFriends)
  636. {
  637. assert(!someone.empty());
  638. size_t cntFriends = memFriends.size();
  639. if (cntFriends <= 0)
  640. {//erase this someone record, because it's empty
  641. DB_DeleteSomeone(someone);
  642. return TRUE;
  643. }
  644. size_t sizeMax = sizeof(DB_FRIENDRECORD) + (sizeof(_BASIC_STR) + _NAME_LEN) * cntFriends;
  645. DB_FRIENDRECORDLIST* pdbFriendList = (DB_FRIENDRECORDLIST*)_alloca(sizeMax);
  646. pdbFriendList->count = cntFriends;
  647. DB_FRIENDRECORD* pCursor = (DB_FRIENDRECORD*)(pdbFriendList + 1);
  648. for (MEM_FRIENDRECORDLIST::const_iterator it = memFriends.begin(); it != memFriends.end(); it++)
  649. {
  650. const MEM_FRIENDRECORD& rmemFriendRec = *it;
  651. assert(rmemFriendRec.name.size() > 0 && rmemFriendRec.name.size() < _NAME_LEN);
  652. assert(rmemFriendRec.group.size() >= 0 && rmemFriendRec.group.size() < _NAME_LEN);
  653. pCursor->cheating = rmemFriendRec.cheating;
  654. pCursor->cheated = rmemFriendRec.cheated;
  655. _BASIC_STR* pName = (_BASIC_STR*)(pCursor + 1);
  656. pName->strlen = rmemFriendRec.name.size();
  657. char* strName = (char*)(pName + 1);
  658. memcpy(strName, rmemFriendRec.name.data(), rmemFriendRec.name.size());
  659. _BASIC_STR* pGroup = (_BASIC_STR*)(strName + rmemFriendRec.name.size());
  660. pGroup->strlen = rmemFriendRec.group.size();
  661. char* strGroup = (char*)(pGroup + 1);
  662. memcpy(strGroup, rmemFriendRec.group.data(), rmemFriendRec.group.size());
  663. pCursor = (DB_FRIENDRECORD*)(strGroup + rmemFriendRec.group.size());
  664. assert((BYTE*)pCursor <= (BYTE*)pdbFriendList + sizeMax);
  665. }
  666. size_t sizeUsed = (BYTE*)pCursor - (BYTE*)pdbFriendList;
  667. assert(sizeUsed > 0);
  668. std::_tstring dbkey = NameToDBKey(someone);
  669. AUTOLOCKWRITE(m_lockDB);
  670. return m_dbFriend.add(dbkey.data(), dbkey.size(), (const char*)pdbFriendList, sizeUsed);
  671. }
  672. BOOL CFriendMgr::BkgrndUpdateDB()
  673. {
  674. if (m_StorePlayerPerUdtDB <= 0)
  675. return TRUE;
  676. ONEPLAYERLIST listOnePlayer;
  677. {{
  678. //dup the data into mem
  679. typedef std::list<std::_tstring> MEMPLAYERS;
  680. MEMPLAYERS memPlayers;
  681. {{
  682. AUTOLOCKREAD(m_lockFriend);
  683. size_t playercount = m_mapPlayers.size();
  684. if (playercount <= 0)
  685. return TRUE;
  686. if (m_cursorBkgrndUdtDB >= playercount)
  687. m_cursorBkgrndUdtDB = 0;
  688. //seek to cursor
  689. PLAYERSMAP::iterator itBase;
  690. if (m_cursorBkgrndUdtDB <= playercount/2)
  691. {
  692. itBase = m_mapPlayers.begin();
  693. for (size_t i = 0; i < m_cursorBkgrndUdtDB; i++)
  694. ++ itBase;
  695. }
  696. else
  697. {
  698. itBase = m_mapPlayers.end();
  699. for (size_t i = playercount; i > m_cursorBkgrndUdtDB; i--)
  700. -- itBase;
  701. }
  702. PLAYERSMAP::iterator itPlayer = itBase;
  703. do
  704. {
  705. //limit store player count
  706. if (m_StorePlayerPerUdtDB != size_t(-1)
  707. && listOnePlayer.size() + memPlayers.size() > m_StorePlayerPerUdtDB)
  708. break;
  709. std::_tstring someone = (*itPlayer).first;
  710. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  711. if (rPlayerInfo.loaded)
  712. {
  713. listOnePlayer.push_back(ONEPLAYER());
  714. ONEPLAYER& rOnePlayer = listOnePlayer.back();
  715. BOOL needstore = rPlayerInfo.dirty;
  716. rPlayerInfo.dirty = FALSE;
  717. rOnePlayer.someone = someone;
  718. for (FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.begin(); itFriend != rPlayerInfo.friends.end(); itFriend++)
  719. {
  720. FRIENDINFO& rInfo = (*itFriend).second;
  721. assert(rInfo.pCheated);
  722. if (!rInfo.pCheated)
  723. continue;
  724. MEM_FRIENDRECORD memFriendRec;
  725. memFriendRec.name = (*itFriend).first;
  726. memFriendRec.group = rInfo.group;
  727. memFriendRec.cheating = rInfo.cheating;
  728. memFriendRec.cheated = *rInfo.pCheated;
  729. rOnePlayer.listFriends.push_back(memFriendRec);
  730. if (!needstore
  731. && ((rInfo.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE) != rInfo.orig_cheating
  732. || (*rInfo.pCheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE) != rInfo.orig_cheated))
  733. {
  734. needstore = TRUE;
  735. }
  736. rInfo.orig_cheating = rInfo.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  737. rInfo.orig_cheated = *rInfo.pCheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  738. }
  739. if (!needstore)
  740. listOnePlayer.pop_back();
  741. }
  742. else
  743. {
  744. //limit load player count
  745. if (m_LoadPlayerPerUdtDB != size_t(-1)
  746. && memPlayers.size() < m_LoadPlayerPerUdtDB)
  747. memPlayers.push_back(someone);
  748. }
  749. ++ itPlayer;
  750. if (itPlayer == m_mapPlayers.end())
  751. itPlayer = m_mapPlayers.begin();
  752. } while (itPlayer != itBase);
  753. }}
  754. {{
  755. if (!memPlayers.empty())
  756. {
  757. AUTOLOCKWRITE(m_lockFriend);
  758. for (MEMPLAYERS::iterator itMemPlayer = memPlayers.begin(); itMemPlayer != memPlayers.end(); itMemPlayer++)
  759. {
  760. std::_tstring player = *itMemPlayer;
  761. PLAYERSMAP::iterator itPlayer = _LoadSomeone(player);
  762. if (itPlayer != m_mapPlayers.end())
  763. {
  764. PLAYERINFO& rPlayerInfo = (*itPlayer).second;
  765. listOnePlayer.push_back(ONEPLAYER());
  766. ONEPLAYER& rOnePlayer = listOnePlayer.back();
  767. BOOL needstore = rPlayerInfo.dirty;
  768. rPlayerInfo.dirty = FALSE;
  769. rOnePlayer.someone = player;
  770. for (FRIENDSMAP::iterator itFriend = rPlayerInfo.friends.begin(); itFriend != rPlayerInfo.friends.end(); itFriend++)
  771. {
  772. FRIENDINFO& rInfo = (*itFriend).second;
  773. assert(rInfo.pCheated);
  774. MEM_FRIENDRECORD memFriendRec;
  775. memFriendRec.name = (*itFriend).first;
  776. memFriendRec.group = rInfo.group;
  777. memFriendRec.cheating = rInfo.cheating;
  778. memFriendRec.cheated = *rInfo.pCheated;
  779. rOnePlayer.listFriends.push_back(memFriendRec);
  780. if (!needstore
  781. && ((rInfo.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE) != rInfo.orig_cheating
  782. || (*rInfo.pCheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE) != rInfo.orig_cheated))
  783. {
  784. needstore = TRUE;
  785. }
  786. rInfo.orig_cheating = rInfo.cheating ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  787. rInfo.orig_cheated = *rInfo.pCheated ? FRIENDINFO::cheatTRUE : FRIENDINFO::cheatFALSE;
  788. }
  789. if (!needstore)
  790. listOnePlayer.pop_back();
  791. }
  792. }
  793. }
  794. }}
  795. }}
  796. {{
  797. //store mem data into DB
  798. for (ONEPLAYERLIST::iterator itOnePlayer = listOnePlayer.begin(); itOnePlayer != listOnePlayer.end(); itOnePlayer++)
  799. {
  800. ONEPLAYER& rOnePlayer = *itOnePlayer;
  801. if (!DB_StoreSomeone(rOnePlayer.someone, rOnePlayer.listFriends))
  802. {
  803. PLAYERINFO& rPlayerInfo = m_mapPlayers[rOnePlayer.someone];
  804. rPlayerInfo.dirty = TRUE;
  805. rTRACE("error: bkgrnp store someone: %s", rOnePlayer.someone.c_str());
  806. }
  807. }
  808. }}
  809. m_cursorBkgrndUdtDB += listOnePlayer.size();
  810. return TRUE;
  811. }
  812. size_t CFriendMgr::GetPlayerCount()
  813. {
  814. AUTOLOCKREAD(m_lockFriend);
  815. return m_mapPlayers.size();
  816. }
  817. size_t CFriendMgr::GetAFQSize()
  818. {
  819. AUTOLOCKREAD(m_lockAddFriend);
  820. return m_mapAddFriends.size();
  821. }
  822. BOOL CFriendMgr::PlayerAssociate(const std::_tstring& someone, const std::_tstring& dst, const std::_tstring& group, BYTE bidir)
  823. {
  824. AUTOLOCKWRITE(m_lockFriend);
  825. PLAYERINFO& rSrcPlayerInfo = m_mapPlayers[someone];
  826. assert(rSrcPlayerInfo.loaded);
  827. FRIENDINFO& rSrcInfo = rSrcPlayerInfo.friends[dst];
  828. rSrcInfo.cheating = false;
  829. rSrcInfo.group = group;
  830. PLAYERINFO& rDstPlayerInfo = m_mapPlayers[dst];
  831. FRIENDINFO& rDstInfo = rDstPlayerInfo.friends[someone];
  832. rDstInfo.cheating = bidir ? false : true;
  833. rDstInfo.group = group;
  834. //binding
  835. rSrcInfo.pCheated = &rDstInfo.cheating;
  836. rDstInfo.pCheated = &rSrcInfo.cheating;
  837. rTRACE("Player Associate: %s [%s] on <%s>, bidir: %u", someone.c_str(), dst.c_str(), group.c_str(), int(bidir));
  838. return TRUE;
  839. }
  840. BOOL CFriendMgr::PlayerAssociateBevy(const _BEVY& bevy, const std::_tstring& group)
  841. {
  842. if (bevy.size() < 2)
  843. return TRUE;
  844. AUTOLOCKWRITE(m_lockFriend);
  845. std::vector<PLAYERSMAP::iterator> vecPlayer;
  846. for (_BEVY::const_iterator itS = bevy.begin(); itS != bevy.end(); itS++)
  847. {
  848. std::string someone = *itS;
  849. assert(!someone.empty());
  850. std::pair<PLAYERSMAP::iterator, bool> insit = m_mapPlayers.insert(PLAYERSMAP::value_type(someone, PLAYERINFO()));
  851. assert(!insit.second && insit.first != m_mapPlayers.end() && (*insit.first).second.loaded);
  852. vecPlayer.push_back(insit.first);
  853. }
  854. if (vecPlayer.size() < 2)
  855. return TRUE;
  856. const size_t count = vecPlayer.size();
  857. const size_t last = count - 1;
  858. for (size_t idxSrc = 0; idxSrc < last; idxSrc++)
  859. {
  860. PLAYERSMAP::iterator itSrc = vecPlayer[idxSrc];
  861. std::_tstring src = (*itSrc).first;
  862. PLAYERINFO& rSrcPlayerInfo = (*itSrc).second;
  863. for (size_t idxDst = idxSrc + 1; idxDst < count; idxDst++)
  864. {
  865. PLAYERSMAP::iterator itDst = vecPlayer[idxDst];
  866. std::_tstring dst = (*itDst).first;
  867. PLAYERINFO& rDstPlayerInfo = (*itDst).second;
  868. if (!_tstring_equal()(dst, src))
  869. {
  870. FRIENDINFO& rSrcInfo = rSrcPlayerInfo.friends[dst];
  871. rSrcInfo.cheating = false;
  872. rSrcInfo.group = group;
  873. FRIENDINFO& rDstInfo = rDstPlayerInfo.friends[src];
  874. rDstInfo.cheating = false;
  875. rDstInfo.group = group;
  876. //binding
  877. rSrcInfo.pCheated = &rDstInfo.cheating;
  878. rDstInfo.pCheated = &rSrcInfo.cheating;
  879. }
  880. };
  881. }
  882. rTRACE("Players AssociateBevy: %u on <%s>", bevy.size(), group.c_str());
  883. return TRUE;
  884. }