llgroupmgr.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:51k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llgroupmgr.cpp
  3.  * @brief LLGroupMgr class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2004&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2004-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. /**
  33.  * Manager for aggregating all client knowledge for specific groups
  34.  * Keeps a cache of group information.
  35.  */
  36. #include "llviewerprecompiledheaders.h"
  37. #include "llgroupmgr.h"
  38. #include <vector>
  39. #include <algorithm>
  40. #include "llagent.h"
  41. #include "llui.h"
  42. #include "message.h"
  43. #include "roles_constants.h"
  44. #include "lltransactiontypes.h"
  45. #include "llstatusbar.h"
  46. #include "lleconomy.h"
  47. #include "llviewerwindow.h"
  48. #include "llpanelgroup.h"
  49. #include "llgroupactions.h"
  50. #include "llnotificationsutil.h"
  51. #include "lluictrlfactory.h"
  52. #include <boost/regex.hpp>
  53. const U32 MAX_CACHED_GROUPS = 10;
  54. //
  55. // LLRoleActionSet
  56. //
  57. LLRoleActionSet::LLRoleActionSet()
  58. : mActionSetData(NULL)
  59. { }
  60. LLRoleActionSet::~LLRoleActionSet()
  61. {
  62. delete mActionSetData;
  63. std::for_each(mActions.begin(), mActions.end(), DeletePointer());
  64. }
  65. //
  66. // LLGroupMemberData
  67. //
  68. LLGroupMemberData::LLGroupMemberData(const LLUUID& id, 
  69. S32 contribution,
  70. U64 agent_powers,
  71. const std::string& title,
  72. const std::string& online_status,
  73. BOOL is_owner) : 
  74. mID(id), 
  75. mContribution(contribution), 
  76. mAgentPowers(agent_powers), 
  77. mTitle(title), 
  78. mOnlineStatus(online_status),
  79. mIsOwner(is_owner)
  80. {
  81. }
  82. LLGroupMemberData::~LLGroupMemberData()
  83. {
  84. }
  85. void LLGroupMemberData::addRole(const LLUUID& role, LLGroupRoleData* rd)
  86. {
  87. mRolesList[role] = rd;
  88. }
  89. bool LLGroupMemberData::removeRole(const LLUUID& role)
  90. {
  91. role_list_t::iterator it = mRolesList.find(role);
  92. if (it != mRolesList.end())
  93. {
  94. mRolesList.erase(it);
  95. return true;
  96. }
  97. return false;
  98. }
  99. //
  100. // LLGroupRoleData
  101. //
  102. LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id, 
  103. const std::string& role_name,
  104. const std::string& role_title,
  105. const std::string& role_desc,
  106. const U64 role_powers,
  107. const S32 member_count) :
  108. mRoleID(role_id),
  109. mMemberCount(member_count),
  110. mMembersNeedsSort(FALSE)
  111. {
  112. mRoleData.mRoleName = role_name;
  113. mRoleData.mRoleTitle = role_title;
  114. mRoleData.mRoleDescription = role_desc;
  115. mRoleData.mRolePowers = role_powers;
  116. mRoleData.mChangeType = RC_UPDATE_NONE;
  117. }
  118. LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id, 
  119. LLRoleData role_data,
  120. const S32 member_count) :
  121. mRoleID(role_id),
  122. mRoleData(role_data),
  123. mMemberCount(member_count),
  124. mMembersNeedsSort(FALSE)
  125. {
  126. }
  127. LLGroupRoleData::~LLGroupRoleData()
  128. {
  129. }
  130. S32 LLGroupRoleData::getMembersInRole(std::vector<LLUUID> members,
  131.   BOOL needs_sort)
  132. {
  133. if (mRoleID.isNull())
  134. {
  135. // This is the everyone role, just return the size of members, 
  136. // because everyone is in the everyone role.
  137. return members.size();
  138. }
  139. // Sort the members list, if needed.
  140. if (mMembersNeedsSort)
  141. {
  142. std::sort(mMemberIDs.begin(), mMemberIDs.end());
  143. mMembersNeedsSort = FALSE;
  144. }
  145. if (needs_sort)
  146. {
  147. // Sort the members parameter.
  148. std::sort(members.begin(), members.end());
  149. }
  150. // Return the number of members in the intersection.
  151. S32 max_size = llmin( members.size(), mMemberIDs.size() );
  152. std::vector<LLUUID> in_role( max_size );
  153. std::vector<LLUUID>::iterator in_role_end;
  154. in_role_end = std::set_intersection(mMemberIDs.begin(), mMemberIDs.end(),
  155. members.begin(), members.end(),
  156. in_role.begin());
  157. return in_role_end - in_role.begin();
  158. }
  159.   
  160. void LLGroupRoleData::addMember(const LLUUID& member)
  161. {
  162. mMembersNeedsSort = TRUE;
  163. mMemberIDs.push_back(member);
  164. }
  165. bool LLGroupRoleData::removeMember(const LLUUID& member)
  166. {
  167. std::vector<LLUUID>::iterator it = std::find(mMemberIDs.begin(),mMemberIDs.end(),member);
  168. if (it != mMemberIDs.end())
  169. {
  170. mMembersNeedsSort = TRUE;
  171. mMemberIDs.erase(it);
  172. return true;
  173. }
  174. return false;
  175. }
  176. void LLGroupRoleData::clearMembers()
  177. {
  178. mMembersNeedsSort = FALSE;
  179. mMemberIDs.clear();
  180. }
  181. //
  182. // LLGroupMgrGroupData
  183. //
  184. LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) : 
  185. mID(id), 
  186. mShowInList(TRUE), 
  187. mOpenEnrollment(FALSE), 
  188. mMembershipFee(0),
  189. mAllowPublish(FALSE),
  190. mListInProfile(FALSE),
  191. mMaturePublish(FALSE),
  192. mChanged(FALSE),
  193. mMemberCount(0),
  194. mRoleCount(0),
  195. mReceivedRoleMemberPairs(0),
  196. mMemberDataComplete(FALSE),
  197. mRoleDataComplete(FALSE),
  198. mRoleMemberDataComplete(FALSE),
  199. mGroupPropertiesDataComplete(FALSE),
  200. mPendingRoleMemberRequest(FALSE)
  201. {
  202. }
  203. BOOL LLGroupMgrGroupData::getRoleData(const LLUUID& role_id, LLRoleData& role_data)
  204. {
  205. role_data_map_t::const_iterator it;
  206. // Do we have changes for it?
  207. it = mRoleChanges.find(role_id);
  208. if (it != mRoleChanges.end()) 
  209. {
  210. if ((*it).second.mChangeType == RC_DELETE) return FALSE;
  211. role_data = (*it).second;
  212. return TRUE;
  213. }
  214. // Ok, no changes, hasn't been deleted, isn't a new role, just find the role.
  215. role_list_t::const_iterator rit = mRoles.find(role_id);
  216. if (rit != mRoles.end())
  217. {
  218. role_data = (*rit).second->getRoleData();
  219. return TRUE;
  220. }
  221. // This role must not exist.
  222. return FALSE;
  223. }
  224. void LLGroupMgrGroupData::setRoleData(const LLUUID& role_id, LLRoleData role_data)
  225. {
  226. // If this is a newly created group, we need to change the data in the created list.
  227. role_data_map_t::iterator it;
  228. it = mRoleChanges.find(role_id);
  229. if (it != mRoleChanges.end())
  230. {
  231. if ((*it).second.mChangeType == RC_CREATE)
  232. {
  233. role_data.mChangeType = RC_CREATE;
  234. mRoleChanges[role_id] = role_data;
  235. return;
  236. }
  237. else if ((*it).second.mChangeType == RC_DELETE)
  238. {
  239. // Don't do anything for a role being deleted.
  240. return;
  241. }
  242. }
  243. // Not a new role, so put it in the changes list.
  244. LLRoleData old_role_data;
  245. role_list_t::iterator rit = mRoles.find(role_id);
  246. if (rit != mRoles.end())
  247. {
  248. bool data_change = ( ((*rit).second->mRoleData.mRoleDescription != role_data.mRoleDescription)
  249. || ((*rit).second->mRoleData.mRoleName != role_data.mRoleName)
  250. || ((*rit).second->mRoleData.mRoleTitle != role_data.mRoleTitle) );
  251. bool powers_change = ((*rit).second->mRoleData.mRolePowers != role_data.mRolePowers);
  252. if (!data_change && !powers_change)
  253. {
  254. // We are back to the original state, the changes have been 'undone' so take out the change.
  255. mRoleChanges.erase(role_id);
  256. return;
  257. }
  258. if (data_change && powers_change)
  259. {
  260. role_data.mChangeType = RC_UPDATE_ALL;
  261. }
  262. else if (data_change)
  263. {
  264. role_data.mChangeType = RC_UPDATE_DATA;
  265. }
  266. else
  267. {
  268. role_data.mChangeType = RC_UPDATE_POWERS;
  269. }
  270. mRoleChanges[role_id] = role_data;
  271. }
  272. else
  273. {
  274. llwarns << "Change being made to non-existant role " << role_id << llendl;
  275. }
  276. }
  277. BOOL LLGroupMgrGroupData::pendingRoleChanges()
  278. {
  279. return (!mRoleChanges.empty());
  280. }
  281. // This is a no-op if the role has already been created.
  282. void LLGroupMgrGroupData::createRole(const LLUUID& role_id, LLRoleData role_data)
  283. {
  284. if (mRoleChanges.find(role_id) != mRoleChanges.end())
  285. {
  286. llwarns << "create role for existing role! " << role_id << llendl;
  287. }
  288. else
  289. {
  290. role_data.mChangeType = RC_CREATE;
  291. mRoleChanges[role_id] = role_data;
  292. }
  293. }
  294. void LLGroupMgrGroupData::deleteRole(const LLUUID& role_id)
  295. {
  296. role_data_map_t::iterator it;
  297. // If this was a new role, just discard it.
  298. it = mRoleChanges.find(role_id);
  299. if (it != mRoleChanges.end() 
  300. && (*it).second.mChangeType == RC_CREATE)
  301. {
  302. mRoleChanges.erase(it);
  303. return;
  304. }
  305. LLRoleData rd;
  306. rd.mChangeType = RC_DELETE;
  307. mRoleChanges[role_id] = rd;
  308. }
  309. void LLGroupMgrGroupData::addRolePower(const LLUUID &role_id, U64 power)
  310. {
  311. LLRoleData rd;
  312. if (getRoleData(role_id,rd))
  313. {
  314. rd.mRolePowers |= power;
  315. setRoleData(role_id,rd);
  316. }
  317. else
  318. {
  319. llwarns << "addRolePower: no role data found for " << role_id << llendl;
  320. }
  321. }
  322. void LLGroupMgrGroupData::removeRolePower(const LLUUID &role_id, U64 power)
  323. {
  324. LLRoleData rd;
  325. if (getRoleData(role_id,rd))
  326. {
  327. rd.mRolePowers &= ~power;
  328. setRoleData(role_id,rd);
  329. }
  330. else
  331. {
  332. llwarns << "removeRolePower: no role data found for " << role_id << llendl;
  333. }
  334. }
  335. U64 LLGroupMgrGroupData::getRolePowers(const LLUUID& role_id)
  336. {
  337. LLRoleData rd;
  338. if (getRoleData(role_id,rd))
  339. {
  340. return rd.mRolePowers;
  341. }
  342. else
  343. {
  344. llwarns << "getRolePowers: no role data found for " << role_id << llendl;
  345. return GP_NO_POWERS;
  346. }
  347. }
  348. void LLGroupMgrGroupData::removeData()
  349. {
  350. // Remove member data first, because removeRoleData will walk the member list
  351. removeMemberData();
  352. removeRoleData();
  353. }
  354. void LLGroupMgrGroupData::removeMemberData()
  355. {
  356. for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
  357. {
  358. delete mi->second;
  359. }
  360. mMembers.clear();
  361. mMemberDataComplete = FALSE;
  362. }
  363. void LLGroupMgrGroupData::removeRoleData()
  364. {
  365. for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
  366. {
  367. LLGroupMemberData* data = mi->second;
  368. if (data)
  369. {
  370. data->clearRoles();
  371. }
  372. }
  373. for (role_list_t::iterator ri = mRoles.begin(); ri != mRoles.end(); ++ri)
  374. {
  375. LLGroupRoleData* data = ri->second;
  376. delete data;
  377. }
  378. mRoles.clear();
  379. mReceivedRoleMemberPairs = 0;
  380. mRoleDataComplete = FALSE;
  381. mRoleMemberDataComplete = FALSE;
  382. }
  383. void LLGroupMgrGroupData::removeRoleMemberData()
  384. {
  385. for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
  386. {
  387. LLGroupMemberData* data = mi->second;
  388. if (data)
  389. {
  390. data->clearRoles();
  391. }
  392. }
  393. for (role_list_t::iterator ri = mRoles.begin(); ri != mRoles.end(); ++ri)
  394. {
  395. LLGroupRoleData* data = ri->second;
  396. if (data)
  397. {
  398. data->clearMembers();
  399. }
  400. }
  401. mReceivedRoleMemberPairs = 0;
  402. mRoleMemberDataComplete = FALSE;
  403. }
  404. LLGroupMgrGroupData::~LLGroupMgrGroupData()
  405. {
  406. removeData();
  407. }
  408. bool LLGroupMgrGroupData::changeRoleMember(const LLUUID& role_id, 
  409.    const LLUUID& member_id, 
  410.    LLRoleMemberChangeType rmc)
  411. {
  412. role_list_t::iterator ri = mRoles.find(role_id);
  413. member_list_t::iterator mi = mMembers.find(member_id);
  414. if (ri == mRoles.end()
  415. || mi == mMembers.end() )
  416. {
  417. if (ri == mRoles.end()) llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't find role " << role_id << llendl;
  418. if (mi == mMembers.end()) llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't find member " << member_id << llendl;
  419. return false;
  420. }
  421. LLGroupRoleData* grd = ri->second;
  422. LLGroupMemberData* gmd = mi->second;
  423. if (!grd || !gmd)
  424. {
  425. llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't get member or role data." << llendl;
  426. return false;
  427. }
  428. if (RMC_ADD == rmc)
  429. {
  430. llinfos << " adding member to role." << llendl;
  431. grd->addMember(member_id);
  432. gmd->addRole(role_id,grd);
  433. //TODO move this into addrole function
  434. //see if they added someone to the owner role and update isOwner
  435. gmd->mIsOwner = (role_id == mOwnerRole) ? TRUE : gmd->mIsOwner;
  436. }
  437. else if (RMC_REMOVE == rmc)
  438. {
  439. llinfos << " removing member from role." << llendl;
  440. grd->removeMember(member_id);
  441. gmd->removeRole(role_id);
  442. //see if they removed someone from the owner role and update isOwner
  443. gmd->mIsOwner = (role_id == mOwnerRole) ? FALSE : gmd->mIsOwner;
  444. }
  445. lluuid_pair role_member;
  446. role_member.first = role_id;
  447. role_member.second = member_id;
  448. change_map_t::iterator it = mRoleMemberChanges.find(role_member);
  449. if (it != mRoleMemberChanges.end())
  450. {
  451. // There was already a role change for this role_member
  452. if (it->second.mChange == rmc)
  453. {
  454. // Already recorded this change?  Weird.
  455. llinfos << "Received duplicate change for "
  456. << " role: " << role_id << " member " << member_id 
  457. << " change " << (rmc == RMC_ADD ? "ADD" : "REMOVE") << llendl;
  458. }
  459. else
  460. {
  461. // The only two operations (add and remove) currently cancel each other out
  462. // If that changes this will need more logic
  463. if (rmc == RMC_NONE)
  464. {
  465. llwarns << "changeRoleMember: existing entry with 'RMC_NONE' change! This shouldn't happen." << llendl;
  466. LLRoleMemberChange rc(role_id,member_id,rmc);
  467. mRoleMemberChanges[role_member] = rc;
  468. }
  469. else
  470. {
  471. mRoleMemberChanges.erase(it);
  472. }
  473. }
  474. }
  475. else
  476. {
  477. LLRoleMemberChange rc(role_id,member_id,rmc);
  478. mRoleMemberChanges[role_member] = rc;
  479. }
  480. recalcAgentPowers(member_id);
  481. mChanged = TRUE;
  482. return true;
  483. }
  484. void LLGroupMgrGroupData::recalcAllAgentPowers()
  485. {
  486. LLGroupMemberData* gmd;
  487. for (member_list_t::iterator mit = mMembers.begin();
  488.  mit != mMembers.end(); ++mit)
  489. {
  490. gmd = mit->second;
  491. if (!gmd) continue;
  492. gmd->mAgentPowers = 0;
  493. for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin();
  494.  it != gmd->mRolesList.end(); ++it)
  495. {
  496. LLGroupRoleData* grd = (*it).second;
  497. if (!grd) continue;
  498. gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
  499. }
  500. }
  501. }
  502. void LLGroupMgrGroupData::recalcAgentPowers(const LLUUID& agent_id)
  503. {
  504. member_list_t::iterator mi = mMembers.find(agent_id);
  505. if (mi == mMembers.end()) return;
  506. LLGroupMemberData* gmd = mi->second;
  507. if (!gmd) return;
  508. gmd->mAgentPowers = 0;
  509. for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin();
  510.  it != gmd->mRolesList.end(); ++it)
  511. {
  512. LLGroupRoleData* grd = (*it).second;
  513. if (!grd) continue;
  514. gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
  515. }
  516. }
  517. bool packRoleUpdateMessageBlock(LLMessageSystem* msg, 
  518. const LLUUID& group_id,
  519. const LLUUID& role_id, 
  520. const LLRoleData& role_data, 
  521. bool start_message)
  522. {
  523. if (start_message)
  524. {
  525. msg->newMessage("GroupRoleUpdate");
  526. msg->nextBlock("AgentData");
  527. msg->addUUID("AgentID",gAgent.getID());
  528. msg->addUUID("SessionID",gAgent.getSessionID());
  529. msg->addUUID("GroupID",group_id);
  530. start_message = false;
  531. }
  532. msg->nextBlock("RoleData");
  533. msg->addUUID("RoleID",role_id);
  534. msg->addString("Name", role_data.mRoleName);
  535. msg->addString("Description", role_data.mRoleDescription);
  536. msg->addString("Title", role_data.mRoleTitle);
  537. msg->addU64("Powers", role_data.mRolePowers);
  538. msg->addU8("UpdateType", (U8)role_data.mChangeType);
  539. if (msg->isSendFullFast())
  540. {
  541. gAgent.sendReliableMessage();
  542. start_message = true;
  543. }
  544. return start_message;
  545. }
  546. void LLGroupMgrGroupData::sendRoleChanges()
  547. {
  548. // Commit changes locally
  549. LLGroupRoleData* grd;
  550. role_list_t::iterator role_it;
  551. LLMessageSystem* msg = gMessageSystem;
  552. bool start_message = true;
  553. bool need_role_cleanup = false;
  554. bool need_role_data = false;
  555. bool need_power_recalc = false;
  556. // Apply all changes
  557. for (role_data_map_t::iterator iter = mRoleChanges.begin();
  558.  iter != mRoleChanges.end(); )
  559. {
  560. role_data_map_t::iterator it = iter++; // safely incrament iter
  561. const LLUUID& role_id = (*it).first;
  562. const LLRoleData& role_data = (*it).second;
  563. // Commit to local data set
  564. role_it = mRoles.find((*it).first);
  565. if ( (mRoles.end() == role_it 
  566. && RC_CREATE != role_data.mChangeType)
  567. || (mRoles.end() != role_it
  568. && RC_CREATE == role_data.mChangeType))
  569. {
  570. continue;
  571. }
  572. // NOTE: role_it is valid EXCEPT for the RC_CREATE case
  573. switch (role_data.mChangeType)
  574. {
  575. case RC_CREATE:
  576. {
  577. // NOTE: role_it is NOT valid in this case
  578. grd = new LLGroupRoleData(role_id, role_data, 0);
  579. mRoles[role_id] = grd;
  580. need_role_data = true;
  581. break;
  582. }
  583. case RC_DELETE:
  584. {
  585. LLGroupRoleData* group_role_data = (*role_it).second;
  586. delete group_role_data;
  587. mRoles.erase(role_it);
  588. need_role_cleanup = true;
  589. need_power_recalc = true;
  590. break;
  591. }
  592. case RC_UPDATE_ALL:
  593. // fall through
  594. case RC_UPDATE_POWERS:
  595. need_power_recalc = true;
  596. // fall through
  597. case RC_UPDATE_DATA:
  598. // fall through
  599. default: 
  600. {
  601. LLGroupRoleData* group_role_data = (*role_it).second;
  602. group_role_data->setRoleData(role_data); // NOTE! might modify mRoleChanges!
  603. break;
  604. }
  605. }
  606. // Update dataserver
  607. start_message = packRoleUpdateMessageBlock(msg,getID(),role_id,role_data,start_message);
  608. }
  609. if (!start_message)
  610. {
  611. gAgent.sendReliableMessage();
  612. }
  613. // If we delete a role then all the role-member pairs are invalid!
  614. if (need_role_cleanup)
  615. {
  616. removeRoleMemberData();
  617. }
  618. // If we create a new role, then we need to re-fetch all the role data.
  619. if (need_role_data)
  620. {
  621. LLGroupMgr::getInstance()->sendGroupRoleDataRequest(getID());
  622. }
  623. // Clean up change lists
  624. mRoleChanges.clear();
  625. // Recalculate all the agent powers because role powers have now changed.
  626. if (need_power_recalc)
  627. {
  628. recalcAllAgentPowers();
  629. }
  630. }
  631. void LLGroupMgrGroupData::cancelRoleChanges()
  632. {
  633. // Clear out all changes!
  634. mRoleChanges.clear();
  635. }
  636. //
  637. // LLGroupMgr
  638. //
  639. LLGroupMgr::LLGroupMgr()
  640. {
  641. }
  642. LLGroupMgr::~LLGroupMgr()
  643. {
  644. clearGroups();
  645. }
  646. void LLGroupMgr::clearGroups()
  647. {
  648. std::for_each(mRoleActionSets.begin(), mRoleActionSets.end(), DeletePointer());
  649. mRoleActionSets.clear();
  650. std::for_each(mGroups.begin(), mGroups.end(), DeletePairedPointer());
  651. mGroups.clear();
  652. mObservers.clear();
  653. }
  654. void LLGroupMgr::clearGroupData(const LLUUID& group_id)
  655. {
  656. group_map_t::iterator iter = mGroups.find(group_id);
  657. if (iter != mGroups.end())
  658. {
  659. delete (*iter).second;
  660. mGroups.erase(iter);
  661. }
  662. }
  663. void LLGroupMgr::addObserver(LLGroupMgrObserver* observer) 
  664. if( observer->getID() != LLUUID::null )
  665. mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer));
  666. }
  667. void LLGroupMgr::addObserver(const LLUUID& group_id, LLParticularGroupObserver* observer)
  668. {
  669. if(group_id.notNull() && observer)
  670. {
  671. mParticularObservers[group_id].insert(observer);
  672. }
  673. }
  674. void LLGroupMgr::removeObserver(LLGroupMgrObserver* observer)
  675. {
  676. if (!observer)
  677. {
  678. return;
  679. }
  680. observer_multimap_t::iterator it;
  681. it = mObservers.find(observer->getID());
  682. while (it != mObservers.end())
  683. {
  684. if (it->second == observer)
  685. {
  686. mObservers.erase(it);
  687. break;
  688. }
  689. else
  690. {
  691. ++it;
  692. }
  693. }
  694. }
  695. void LLGroupMgr::removeObserver(const LLUUID& group_id, LLParticularGroupObserver* observer)
  696. {
  697. if(group_id.isNull() || !observer)
  698. {
  699. return;
  700. }
  701.     observer_map_t::iterator obs_it = mParticularObservers.find(group_id);
  702.     if(obs_it == mParticularObservers.end())
  703.         return;
  704.     obs_it->second.erase(observer);
  705.     if (obs_it->second.size() == 0)
  706.      mParticularObservers.erase(obs_it);
  707. }
  708. LLGroupMgrGroupData* LLGroupMgr::getGroupData(const LLUUID& id)
  709. {
  710. group_map_t::iterator gi = mGroups.find(id);
  711. if (gi != mGroups.end())
  712. {
  713. return gi->second;
  714. }
  715. return NULL;
  716. }
  717. // Helper function for LLGroupMgr::processGroupMembersReply
  718. // This reformats date strings from MM/DD/YYYY to YYYY/MM/DD ( e.g. 1/27/2008 -> 2008/1/27 )
  719. // so that the sorter can sort by year before month before day.
  720. static void formatDateString(std::string &date_string)
  721. {
  722. using namespace boost;
  723. cmatch result;
  724. const regex expression("([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})");
  725. if (regex_match(date_string.c_str(), result, expression))
  726. {
  727. std::string year = result[3];
  728. std::string month = result[1];
  729. std::string day = result[2];
  730. // ISO 8601 date format
  731. date_string = llformat("%02s/%02s/%04s", month.c_str(), day.c_str(), year.c_str());
  732. }
  733. }
  734. // static
  735. void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
  736. {
  737. lldebugs << "LLGroupMgr::processGroupMembersReply" << llendl;
  738. LLUUID agent_id;
  739. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  740. if (gAgent.getID() != agent_id)
  741. {
  742. llwarns << "Got group properties reply for another agent!" << llendl;
  743. return;
  744. }
  745. LLUUID group_id;
  746. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
  747. LLUUID request_id;
  748. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
  749. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->createGroupData(group_id);
  750. if (group_datap->mMemberRequestID != request_id)
  751. {
  752. llwarns << "processGroupMembersReply: Received incorrect (stale?) request id" << llendl;
  753. return;
  754. }
  755. msg->getS32(_PREHASH_GroupData, "MemberCount", group_datap->mMemberCount );
  756. if (group_datap->mMemberCount > 0)
  757. {
  758. S32 contribution = 0;
  759. std::string online_status;
  760. std::string title;
  761. U64 agent_powers = 0;
  762. BOOL is_owner = FALSE;
  763. S32 num_members = msg->getNumberOfBlocksFast(_PREHASH_MemberData);
  764. for (S32 i = 0; i < num_members; i++)
  765. {
  766. LLUUID member_id;
  767. msg->getUUIDFast(_PREHASH_MemberData, _PREHASH_AgentID, member_id, i );
  768. msg->getS32(_PREHASH_MemberData, _PREHASH_Contribution, contribution, i);
  769. msg->getU64(_PREHASH_MemberData, "AgentPowers", agent_powers, i);
  770. msg->getStringFast(_PREHASH_MemberData, _PREHASH_OnlineStatus, online_status, i);
  771. msg->getString(_PREHASH_MemberData, "Title", title, i);
  772. msg->getBOOL(_PREHASH_MemberData,"IsOwner",is_owner,i);
  773. if (member_id.notNull())
  774. {
  775. formatDateString(online_status); // reformat for sorting, e.g. 12/25/2008 -> 2008/12/25
  776. //llinfos << "Member " << member_id << " has powers " << std::hex << agent_powers << std::dec << llendl;
  777. LLGroupMemberData* newdata = new LLGroupMemberData(member_id, 
  778. contribution, 
  779. agent_powers, 
  780. title,
  781. online_status,
  782. is_owner);
  783. #if LL_DEBUG
  784. LLGroupMgrGroupData::member_list_t::iterator mit = group_datap->mMembers.find(member_id);
  785. if (mit != group_datap->mMembers.end())
  786. {
  787. llinfos << " *** Received duplicate member data for agent " << member_id << llendl;
  788. }
  789. #endif
  790. group_datap->mMembers[member_id] = newdata;
  791. }
  792. else
  793. {
  794. llinfos << "Received null group member data." << llendl;
  795. }
  796. }
  797. //if group members are loaded while titles are missing, load the titles.
  798. if(group_datap->mTitles.size() < 1)
  799. {
  800. LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id);
  801. }
  802. }
  803. if (group_datap->mMembers.size() ==  (U32)group_datap->mMemberCount)
  804. {
  805. group_datap->mMemberDataComplete = TRUE;
  806. group_datap->mMemberRequestID.setNull();
  807. // We don't want to make role-member data requests until we have all the members
  808. if (group_datap->mPendingRoleMemberRequest)
  809. {
  810. group_datap->mPendingRoleMemberRequest = FALSE;
  811. LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
  812. }
  813. }
  814. group_datap->mChanged = TRUE;
  815. LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
  816. }
  817. //static 
  818. void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
  819. {
  820. lldebugs << "LLGroupMgr::processGroupPropertiesReply" << llendl;
  821. LLUUID agent_id;
  822. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  823. if (gAgent.getID() != agent_id)
  824. {
  825. llwarns << "Got group properties reply for another agent!" << llendl;
  826. return;
  827. }
  828. LLUUID group_id;
  829. std::string name;
  830. std::string charter;
  831. BOOL show_in_list = FALSE;
  832. LLUUID founder_id;
  833. U64 powers_mask = GP_NO_POWERS;
  834. S32 money = 0;
  835. std::string member_title;
  836. LLUUID insignia_id;
  837. LLUUID owner_role;
  838. U32 membership_fee = 0;
  839. BOOL open_enrollment = FALSE;
  840. S32 num_group_members = 0;
  841. S32 num_group_roles = 0;
  842. BOOL allow_publish = FALSE;
  843. BOOL mature = FALSE;
  844. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
  845. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_FounderID, founder_id);
  846. msg->getStringFast(_PREHASH_GroupData, _PREHASH_Name, name );
  847. msg->getStringFast(_PREHASH_GroupData, _PREHASH_Charter, charter );
  848. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_ShowInList, show_in_list );
  849. msg->getStringFast(_PREHASH_GroupData, _PREHASH_MemberTitle, member_title );
  850. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_InsigniaID, insignia_id );
  851. msg->getU64Fast(_PREHASH_GroupData, _PREHASH_PowersMask, powers_mask );
  852. msg->getU32Fast(_PREHASH_GroupData, _PREHASH_MembershipFee, membership_fee );
  853. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_OpenEnrollment, open_enrollment );
  854. msg->getS32Fast(_PREHASH_GroupData, _PREHASH_GroupMembershipCount, num_group_members);
  855. msg->getS32(_PREHASH_GroupData, "GroupRolesCount", num_group_roles);
  856. msg->getS32Fast(_PREHASH_GroupData, _PREHASH_Money, money);
  857. msg->getBOOL("GroupData", "AllowPublish", allow_publish);
  858. msg->getBOOL("GroupData", "MaturePublish", mature);
  859. msg->getUUID(_PREHASH_GroupData, "OwnerRole", owner_role);
  860. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->createGroupData(group_id);
  861. group_datap->mName = name;
  862. group_datap->mCharter = charter;
  863. group_datap->mShowInList = show_in_list;
  864. group_datap->mInsigniaID = insignia_id;
  865. group_datap->mFounderID = founder_id;
  866. group_datap->mMembershipFee = membership_fee;
  867. group_datap->mOpenEnrollment = open_enrollment;
  868. group_datap->mAllowPublish = allow_publish;
  869. group_datap->mMaturePublish = mature;
  870. group_datap->mOwnerRole = owner_role;
  871. group_datap->mMemberCount = num_group_members;
  872. group_datap->mRoleCount = num_group_roles + 1; // Add the everyone role.
  873. group_datap->mGroupPropertiesDataComplete = TRUE;
  874. group_datap->mChanged = TRUE;
  875. LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES);
  876. }
  877. // static
  878. void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
  879. {
  880. lldebugs << "LLGroupMgr::processGroupRoleDataReply" << llendl;
  881. LLUUID agent_id;
  882. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  883. if (gAgent.getID() != agent_id)
  884. {
  885. llwarns << "Got group properties reply for another agent!" << llendl;
  886. return;
  887. }
  888. LLUUID group_id;
  889. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
  890. LLUUID request_id;
  891. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
  892. LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->createGroupData(group_id);
  893. if (group_data->mRoleDataRequestID != request_id)
  894. {
  895. llwarns << "processGroupRoleDataReply: Received incorrect (stale?) request id" << llendl;
  896. return;
  897. }
  898. msg->getS32(_PREHASH_GroupData, "RoleCount", group_data->mRoleCount );
  899. std::string name;
  900. std::string title;
  901. std::string desc;
  902. U64 powers = 0;
  903. U32 member_count = 0;
  904. LLUUID role_id;
  905. U32 num_blocks = msg->getNumberOfBlocks("RoleData");
  906. U32 i = 0;
  907. for (i=0; i< num_blocks; ++i)
  908. {
  909. msg->getUUID("RoleData", "RoleID", role_id, i );
  910. msg->getString("RoleData","Name",name,i);
  911. msg->getString("RoleData","Title",title,i);
  912. msg->getString("RoleData","Description",desc,i);
  913. msg->getU64("RoleData","Powers",powers,i);
  914. msg->getU32("RoleData","Members",member_count,i);
  915. lldebugs << "Adding role data: " << name << " {" << role_id << "}" << llendl;
  916. LLGroupRoleData* rd = new LLGroupRoleData(role_id,name,title,desc,powers,member_count);
  917. group_data->mRoles[role_id] = rd;
  918. }
  919. if (group_data->mRoles.size() == (U32)group_data->mRoleCount)
  920. {
  921. group_data->mRoleDataComplete = TRUE;
  922. group_data->mRoleDataRequestID.setNull();
  923. // We don't want to make role-member data requests until we have all the role data
  924. if (group_data->mPendingRoleMemberRequest)
  925. {
  926. group_data->mPendingRoleMemberRequest = FALSE;
  927. LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_data->mID);
  928. }
  929. }
  930. group_data->mChanged = TRUE;
  931. LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_DATA);
  932. }
  933. // static
  934. void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
  935. {
  936. lldebugs << "LLGroupMgr::processGroupRoleMembersReply" << llendl;
  937. LLUUID agent_id;
  938. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  939. if (gAgent.getID() != agent_id)
  940. {
  941. llwarns << "Got group properties reply for another agent!" << llendl;
  942. return;
  943. }
  944. LLUUID request_id;
  945. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
  946. LLUUID group_id;
  947. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
  948. U32 total_pairs;
  949. msg->getU32(_PREHASH_AgentData, "TotalPairs", total_pairs);
  950. LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->createGroupData(group_id);
  951. if (group_data->mRoleMembersRequestID != request_id)
  952. {
  953. llwarns << "processGroupRoleMembersReply: Received incorrect (stale?) role member request id" << llendl;
  954. return;
  955. }
  956. U32 num_blocks = msg->getNumberOfBlocks("MemberData");
  957. U32 i;
  958. LLUUID member_id;
  959. LLUUID role_id;
  960. LLGroupRoleData* rd = NULL;
  961. LLGroupMemberData* md = NULL;
  962. LLGroupMgrGroupData::role_list_t::iterator ri;
  963. LLGroupMgrGroupData::member_list_t::iterator mi;
  964. // If total_pairs == 0, there are no members in any custom roles.
  965. if (total_pairs > 0)
  966. {
  967. for (i = 0;i < num_blocks; ++i)
  968. {
  969. msg->getUUID("MemberData","RoleID",role_id,i);
  970. msg->getUUID("MemberData","MemberID",member_id,i);
  971. if (role_id.notNull() && member_id.notNull() )
  972. {
  973. rd = NULL;
  974. ri = group_data->mRoles.find(role_id);
  975. if (ri != group_data->mRoles.end())
  976. {
  977. rd = ri->second;
  978. }
  979. md = NULL;
  980. mi = group_data->mMembers.find(member_id);
  981. if (mi != group_data->mMembers.end())
  982. {
  983. md = mi->second;
  984. }
  985. if (rd && md)
  986. {
  987. lldebugs << "Adding role-member pair: " << role_id << ", " << member_id << llendl;
  988. rd->addMember(member_id);
  989. md->addRole(role_id,rd);
  990. }
  991. else
  992. {
  993. if (!rd) llwarns << "Received role data for unkown role " << role_id << " in group " << group_id << llendl;
  994. if (!md) llwarns << "Received role data for unkown member " << member_id << " in group " << group_id << llendl;
  995. }
  996. }
  997. }
  998. group_data->mReceivedRoleMemberPairs += num_blocks;
  999. }
  1000. if (group_data->mReceivedRoleMemberPairs == total_pairs)
  1001. {
  1002. // Add role data for the 'everyone' role to all members
  1003. LLGroupRoleData* everyone = group_data->mRoles[LLUUID::null];
  1004. if (!everyone)
  1005. {
  1006. llwarns << "Everyone role not found!" << llendl;
  1007. }
  1008. else
  1009. {
  1010. for (LLGroupMgrGroupData::member_list_t::iterator mi = group_data->mMembers.begin();
  1011.  mi != group_data->mMembers.end(); ++mi)
  1012. {
  1013. LLGroupMemberData* data = mi->second;
  1014. if (data)
  1015. {
  1016. data->addRole(LLUUID::null,everyone);
  1017. }
  1018. }
  1019. }
  1020.         group_data->mRoleMemberDataComplete = TRUE;
  1021. group_data->mRoleMembersRequestID.setNull();
  1022. }
  1023. group_data->mChanged = TRUE;
  1024. LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA);
  1025. }
  1026. // static
  1027. void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data)
  1028. {
  1029. lldebugs << "LLGroupMgr::processGroupTitlesReply" << llendl;
  1030. LLUUID agent_id;
  1031. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
  1032. if (gAgent.getID() != agent_id)
  1033. {
  1034. llwarns << "Got group properties reply for another agent!" << llendl;
  1035. return;
  1036. }
  1037. LLUUID group_id;
  1038. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
  1039. LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->createGroupData(group_id);
  1040. LLUUID request_id;
  1041. msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
  1042. if (group_data->mTitlesRequestID != request_id)
  1043. {
  1044. llwarns << "processGroupTitlesReply: Received incorrect (stale?) title request id" << llendl;
  1045. return;
  1046. }
  1047. LLGroupTitle title;
  1048. S32 i = 0;
  1049. S32 blocks = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
  1050. for (i=0; i<blocks; ++i)
  1051. {
  1052. msg->getString("GroupData","Title",title.mTitle,i);
  1053. msg->getUUID("GroupData","RoleID",title.mRoleID,i);
  1054. msg->getBOOL("GroupData","Selected",title.mSelected,i);
  1055. if (!title.mTitle.empty())
  1056. {
  1057. lldebugs << "LLGroupMgr adding title: " << title.mTitle << ", " << title.mRoleID << ", " << (title.mSelected ? 'Y' : 'N') << llendl;
  1058. group_data->mTitles.push_back(title);
  1059. }
  1060. }
  1061. group_data->mChanged = TRUE;
  1062. LLGroupMgr::getInstance()->notifyObservers(GC_TITLES);
  1063. }
  1064. // static
  1065. void LLGroupMgr::processEjectGroupMemberReply(LLMessageSystem* msg, void ** data)
  1066. {
  1067. lldebugs << "processEjectGroupMemberReply" << llendl;
  1068. LLUUID group_id;
  1069. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1070. BOOL success;
  1071. msg->getBOOLFast(_PREHASH_EjectData, _PREHASH_Success, success);
  1072. // If we had a failure, the group panel needs to be updated.
  1073. if (!success)
  1074. {
  1075. LLGroupActions::refresh(group_id);
  1076. }
  1077. }
  1078. // static
  1079. void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void ** data)
  1080. {
  1081. lldebugs << "processJoinGroupReply" << llendl;
  1082. LLUUID group_id;
  1083. BOOL success;
  1084. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1085. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_Success, success);
  1086. if (success)
  1087. {
  1088. // refresh all group information
  1089. gAgent.sendAgentDataUpdateRequest();
  1090. LLGroupMgr::getInstance()->clearGroupData(group_id);
  1091. // refresh the floater for this group, if any.
  1092. LLGroupActions::refresh(group_id);
  1093. }
  1094. }
  1095. // static
  1096. void LLGroupMgr::processLeaveGroupReply(LLMessageSystem* msg, void ** data)
  1097. {
  1098. lldebugs << "processLeaveGroupReply" << llendl;
  1099. LLUUID group_id;
  1100. BOOL success;
  1101. msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
  1102. msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_Success, success);
  1103. if (success)
  1104. {
  1105. // refresh all group information
  1106. gAgent.sendAgentDataUpdateRequest();
  1107. LLGroupMgr::getInstance()->clearGroupData(group_id);
  1108. // close the floater for this group, if any.
  1109. LLGroupActions::closeGroup(group_id);
  1110. }
  1111. }
  1112. // static
  1113. void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)
  1114. {
  1115. LLUUID group_id;
  1116. BOOL success;
  1117. std::string message;
  1118. msg->getUUIDFast(_PREHASH_ReplyData, _PREHASH_GroupID, group_id );
  1119. msg->getBOOLFast(_PREHASH_ReplyData, _PREHASH_Success, success );
  1120. msg->getStringFast(_PREHASH_ReplyData, _PREHASH_Message, message );
  1121. if (success)
  1122. {
  1123. // refresh all group information
  1124. gAgent.sendAgentDataUpdateRequest();
  1125. // HACK! We haven't gotten the agent group update yet, so ... um ... fake it.
  1126. // This is so when we go to modify the group we will be able to do so.
  1127. // This isn't actually too bad because real data will come down in 2 or 3 miliseconds and replace this.
  1128. LLGroupData gd;
  1129. gd.mAcceptNotices = TRUE;
  1130. gd.mListInProfile = TRUE;
  1131. gd.mContribution = 0;
  1132. gd.mID = group_id;
  1133. gd.mName = "new group";
  1134. gd.mPowers = GP_ALL_POWERS;
  1135. gAgent.mGroups.push_back(gd);
  1136. LLPanelGroup::refreshCreatedGroup(group_id);
  1137. //FIXME
  1138. //LLFloaterGroupInfo::closeCreateGroup();
  1139. //LLFloaterGroupInfo::showFromUUID(group_id,"roles_tab");
  1140. }
  1141. else
  1142. {
  1143. // *TODO: Translate
  1144. LLSD args;
  1145. args["MESSAGE"] = message;
  1146. LLNotificationsUtil::add("UnableToCreateGroup", args);
  1147. }
  1148. }
  1149. LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)
  1150. {
  1151. LLGroupMgrGroupData* group_datap;
  1152. group_map_t::iterator existing_group = LLGroupMgr::getInstance()->mGroups.find(id);
  1153. if (existing_group == LLGroupMgr::getInstance()->mGroups.end())
  1154. {
  1155. group_datap = new LLGroupMgrGroupData(id);
  1156. LLGroupMgr::getInstance()->addGroup(group_datap);
  1157. }
  1158. else
  1159. {
  1160. group_datap = existing_group->second;
  1161. }
  1162. return group_datap;
  1163. }
  1164. void LLGroupMgr::notifyObservers(LLGroupChange gc)
  1165. {
  1166. for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi)
  1167. {
  1168. LLUUID group_id = gi->first;
  1169. if (gi->second->mChanged)
  1170. {
  1171. // notify LLGroupMgrObserver
  1172. // Copy the map because observers may remove themselves on update
  1173. observer_multimap_t observers = mObservers;
  1174. // find all observers for this group id
  1175. observer_multimap_t::iterator oi = observers.lower_bound(group_id);
  1176. observer_multimap_t::iterator end = observers.upper_bound(group_id);
  1177. for (; oi != end; ++oi)
  1178. {
  1179. oi->second->changed(gc);
  1180. }
  1181. gi->second->mChanged = FALSE;
  1182. // notify LLParticularGroupObserver
  1183.     observer_map_t::iterator obs_it = mParticularObservers.find(group_id);
  1184.     if(obs_it == mParticularObservers.end())
  1185.         return;
  1186.     observer_set_t& obs = obs_it->second;
  1187.     for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ++ob_it)
  1188.     {
  1189.         (*ob_it)->changed(group_id, gc);
  1190.     }
  1191. }
  1192. }
  1193. }
  1194. void LLGroupMgr::addGroup(LLGroupMgrGroupData* group_datap)
  1195. {
  1196. if (mGroups.size() > MAX_CACHED_GROUPS)
  1197. {
  1198. // get rid of groups that aren't observed
  1199. for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end() && mGroups.size() > MAX_CACHED_GROUPS / 2; )
  1200. {
  1201. observer_multimap_t::iterator oi = mObservers.find(gi->first);
  1202. if (oi == mObservers.end())
  1203. {
  1204. // not observed
  1205. LLGroupMgrGroupData* unobserved_groupp = gi->second;
  1206. delete unobserved_groupp;
  1207. mGroups.erase(gi++);
  1208. }
  1209. else
  1210. {
  1211. ++gi;
  1212. }
  1213. }
  1214. }
  1215. mGroups[group_datap->getID()] = group_datap;
  1216. }
  1217. void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
  1218. {
  1219. lldebugs << "LLGroupMgr::sendGroupPropertiesRequest" << llendl;
  1220. // This will happen when we get the reply
  1221. //LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1222. LLMessageSystem* msg = gMessageSystem;
  1223. msg->newMessage("GroupProfileRequest");
  1224. msg->nextBlock("AgentData");
  1225. msg->addUUID("AgentID",gAgent.getID());
  1226. msg->addUUID("SessionID",gAgent.getSessionID());
  1227. msg->nextBlock("GroupData");
  1228. msg->addUUID("GroupID",group_id);
  1229. gAgent.sendReliableMessage();
  1230. }
  1231. void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id)
  1232. {
  1233. lldebugs << "LLGroupMgr::sendGroupMembersRequest" << llendl;
  1234. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1235. if (group_datap->mMemberRequestID.isNull())
  1236. {
  1237. group_datap->removeMemberData();
  1238. group_datap->mMemberRequestID.generate();
  1239. LLMessageSystem* msg = gMessageSystem;
  1240. msg->newMessage("GroupMembersRequest");
  1241. msg->nextBlock("AgentData");
  1242. msg->addUUID("AgentID",gAgent.getID());
  1243. msg->addUUID("SessionID",gAgent.getSessionID());
  1244. msg->nextBlock("GroupData");
  1245. msg->addUUID("GroupID",group_id);
  1246. msg->addUUID("RequestID",group_datap->mMemberRequestID);
  1247. gAgent.sendReliableMessage();
  1248. }
  1249. }
  1250. void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id)
  1251. {
  1252. lldebugs << "LLGroupMgr::sendGroupRoleDataRequest" << llendl;
  1253. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1254. if (group_datap->mRoleDataRequestID.isNull())
  1255. {
  1256. group_datap->removeRoleData();
  1257. group_datap->mRoleDataRequestID.generate();
  1258. LLMessageSystem* msg = gMessageSystem;
  1259. msg->newMessage("GroupRoleDataRequest");
  1260. msg->nextBlock("AgentData");
  1261. msg->addUUID("AgentID",gAgent.getID());
  1262. msg->addUUID("SessionID",gAgent.getSessionID());
  1263. msg->nextBlock("GroupData");
  1264. msg->addUUID("GroupID",group_id);
  1265. msg->addUUID("RequestID",group_datap->mRoleDataRequestID);
  1266. gAgent.sendReliableMessage();
  1267. }
  1268. }
  1269. void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
  1270. {
  1271. lldebugs << "LLGroupMgr::sendGroupRoleMembersRequest" << llendl;
  1272. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1273. if (group_datap->mRoleMembersRequestID.isNull())
  1274. {
  1275. // Don't send the request if we don't have all the member or role data
  1276. if (!group_datap->isMemberDataComplete()
  1277. || !group_datap->isRoleDataComplete())
  1278. {
  1279. // *TODO: KLW FIXME: Should we start a member or role data request?
  1280. llinfos << " Pending: " << (group_datap->mPendingRoleMemberRequest ? "Y" : "N")
  1281. << " MemberDataComplete: " << (group_datap->mMemberDataComplete ? "Y" : "N")
  1282. << " RoleDataComplete: " << (group_datap->mRoleDataComplete ? "Y" : "N") << llendl;
  1283. group_datap->mPendingRoleMemberRequest = TRUE;
  1284. return;
  1285. }
  1286. group_datap->removeRoleMemberData();
  1287. group_datap->mRoleMembersRequestID.generate();
  1288. LLMessageSystem* msg = gMessageSystem;
  1289. msg->newMessage("GroupRoleMembersRequest");
  1290. msg->nextBlock("AgentData");
  1291. msg->addUUID("AgentID",gAgent.getID());
  1292. msg->addUUID("SessionID",gAgent.getSessionID());
  1293. msg->nextBlock("GroupData");
  1294. msg->addUUID("GroupID",group_id);
  1295. msg->addUUID("RequestID",group_datap->mRoleMembersRequestID);
  1296. gAgent.sendReliableMessage();
  1297. }
  1298. }
  1299. void LLGroupMgr::sendGroupTitlesRequest(const LLUUID& group_id)
  1300. {
  1301. lldebugs << "LLGroupMgr::sendGroupTitlesRequest" << llendl;
  1302. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1303. group_datap->mTitles.clear();
  1304. group_datap->mTitlesRequestID.generate();
  1305. LLMessageSystem* msg = gMessageSystem;
  1306. msg->newMessage("GroupTitlesRequest");
  1307. msg->nextBlock("AgentData");
  1308. msg->addUUID("AgentID",gAgent.getID());
  1309. msg->addUUID("SessionID",gAgent.getSessionID());
  1310. msg->addUUID("GroupID",group_id);
  1311. msg->addUUID("RequestID",group_datap->mTitlesRequestID);
  1312. gAgent.sendReliableMessage();
  1313. }
  1314. void LLGroupMgr::sendGroupTitleUpdate(const LLUUID& group_id, const LLUUID& title_role_id)
  1315. {
  1316. lldebugs << "LLGroupMgr::sendGroupTitleUpdate" << llendl;
  1317. LLMessageSystem* msg = gMessageSystem;
  1318. msg->newMessage("GroupTitleUpdate");
  1319. msg->nextBlock("AgentData");
  1320. msg->addUUID("AgentID",gAgent.getID());
  1321. msg->addUUID("SessionID",gAgent.getSessionID());
  1322. msg->addUUID("GroupID",group_id);
  1323. msg->addUUID("TitleRoleID",title_role_id);
  1324. gAgent.sendReliableMessage();
  1325. // Save the change locally
  1326. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1327. for (std::vector<LLGroupTitle>::iterator iter = group_datap->mTitles.begin();
  1328.  iter != group_datap->mTitles.end(); ++iter)
  1329. {
  1330. if (iter->mRoleID == title_role_id)
  1331. {
  1332. iter->mSelected = TRUE;
  1333. }
  1334. else if (iter->mSelected)
  1335. {
  1336. iter->mSelected = FALSE;
  1337. }
  1338. }
  1339. }
  1340. // static
  1341. void LLGroupMgr::sendCreateGroupRequest(const std::string& name,
  1342. const std::string& charter,
  1343. U8 show_in_list,
  1344. const LLUUID& insignia,
  1345. S32 membership_fee,
  1346. BOOL open_enrollment,
  1347. BOOL allow_publish,
  1348. BOOL mature_publish)
  1349. {
  1350. LLMessageSystem* msg = gMessageSystem;
  1351. msg->newMessage("CreateGroupRequest");
  1352. msg->nextBlock("AgentData");
  1353. msg->addUUID("AgentID",gAgent.getID());
  1354. msg->addUUID("SessionID",gAgent.getSessionID());
  1355. msg->nextBlock("GroupData");
  1356. msg->addString("Name",name);
  1357. msg->addString("Charter",charter);
  1358. msg->addBOOL("ShowInList",show_in_list);
  1359. msg->addUUID("InsigniaID",insignia);
  1360. msg->addS32("MembershipFee",membership_fee);
  1361. msg->addBOOL("OpenEnrollment",open_enrollment);
  1362. msg->addBOOL("AllowPublish",allow_publish);
  1363. msg->addBOOL("MaturePublish",mature_publish);
  1364. gAgent.sendReliableMessage();
  1365. }
  1366. void LLGroupMgr::sendUpdateGroupInfo(const LLUUID& group_id)
  1367. {
  1368. lldebugs << "LLGroupMgr::sendUpdateGroupInfo" << llendl;
  1369. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1370. LLMessageSystem* msg = gMessageSystem;
  1371. msg->newMessageFast(_PREHASH_UpdateGroupInfo);
  1372. msg->nextBlockFast(_PREHASH_AgentData);
  1373. msg->addUUIDFast(_PREHASH_AgentID,gAgent.getID());
  1374. msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
  1375. msg->nextBlockFast(_PREHASH_GroupData);
  1376. msg->addUUIDFast(_PREHASH_GroupID,group_datap->getID());
  1377. msg->addStringFast(_PREHASH_Charter,group_datap->mCharter);
  1378. msg->addBOOLFast(_PREHASH_ShowInList,group_datap->mShowInList);
  1379. msg->addUUIDFast(_PREHASH_InsigniaID,group_datap->mInsigniaID);
  1380. msg->addS32Fast(_PREHASH_MembershipFee,group_datap->mMembershipFee);
  1381. msg->addBOOLFast(_PREHASH_OpenEnrollment,group_datap->mOpenEnrollment);
  1382. msg->addBOOLFast(_PREHASH_AllowPublish,group_datap->mAllowPublish);
  1383. msg->addBOOLFast(_PREHASH_MaturePublish,group_datap->mMaturePublish);
  1384. gAgent.sendReliableMessage();
  1385. // Not expecting a response, so let anyone else watching know the data has changed.
  1386. group_datap->mChanged = TRUE;
  1387. notifyObservers(GC_PROPERTIES);
  1388. }
  1389. void LLGroupMgr::sendGroupRoleMemberChanges(const LLUUID& group_id)
  1390. {
  1391. lldebugs << "LLGroupMgr::sendGroupRoleMemberChanges" << llendl;
  1392. LLGroupMgrGroupData* group_datap = createGroupData(group_id);
  1393. if (group_datap->mRoleMemberChanges.empty()) return;
  1394. LLMessageSystem* msg = gMessageSystem;
  1395. bool start_message = true;
  1396. for (LLGroupMgrGroupData::change_map_t::const_iterator citer = group_datap->mRoleMemberChanges.begin();
  1397.  citer != group_datap->mRoleMemberChanges.end(); ++citer)
  1398. {
  1399. if (start_message)
  1400. {
  1401. msg->newMessage("GroupRoleChanges");
  1402. msg->nextBlockFast(_PREHASH_AgentData);
  1403. msg->addUUIDFast(_PREHASH_AgentID,gAgent.getID());
  1404. msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
  1405. msg->addUUIDFast(_PREHASH_GroupID,group_id);
  1406. start_message = false;
  1407. }
  1408. msg->nextBlock("RoleChange");
  1409. msg->addUUID("RoleID",citer->second.mRole);
  1410. msg->addUUID("MemberID",citer->second.mMember);
  1411. msg->addU32("Change",(U32)citer->second.mChange);
  1412. if (msg->isSendFullFast())
  1413. {
  1414. gAgent.sendReliableMessage();
  1415. start_message = true;
  1416. }
  1417. }
  1418. if (!start_message)
  1419. {
  1420. gAgent.sendReliableMessage();
  1421. }
  1422. group_datap->mRoleMemberChanges.clear();
  1423. // Not expecting a response, so let anyone else watching know the data has changed.
  1424. group_datap->mChanged = TRUE;
  1425. notifyObservers(GC_ROLE_MEMBER_DATA);
  1426. }
  1427. //static
  1428. void LLGroupMgr::sendGroupMemberJoin(const LLUUID& group_id)
  1429. {
  1430. LLMessageSystem *msg = gMessageSystem;
  1431. msg->newMessageFast(_PREHASH_JoinGroupRequest);
  1432. msg->nextBlockFast(_PREHASH_AgentData);
  1433. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  1434. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  1435. msg->nextBlockFast(_PREHASH_GroupData);
  1436. msg->addUUIDFast(_PREHASH_GroupID, group_id);
  1437. gAgent.sendReliableMessage();
  1438. }
  1439. // member_role_pairs is <member_id,role_id>
  1440. // static
  1441. void LLGroupMgr::sendGroupMemberInvites(const LLUUID& group_id, std::map<LLUUID,LLUUID>& member_role_pairs)
  1442. {
  1443. bool start_message = true;
  1444. LLMessageSystem* msg = gMessageSystem;
  1445. for (std::map<LLUUID,LLUUID>::iterator it = member_role_pairs.begin();
  1446.  it != member_role_pairs.end(); ++it)
  1447. {
  1448. if (start_message)
  1449. {
  1450. msg->newMessage("InviteGroupRequest");
  1451. msg->nextBlock("AgentData");
  1452. msg->addUUID("AgentID",gAgent.getID());
  1453. msg->addUUID("SessionID",gAgent.getSessionID());
  1454. msg->nextBlock("GroupData");
  1455. msg->addUUID("GroupID",group_id);
  1456. start_message = false;
  1457. }
  1458. msg->nextBlock("InviteData");
  1459. msg->addUUID("InviteeID",(*it).first);
  1460. msg->addUUID("RoleID",(*it).second);
  1461. if (msg->isSendFull())
  1462. {
  1463. gAgent.sendReliableMessage();
  1464. start_message = true;
  1465. }
  1466. }
  1467. if (!start_message)
  1468. {
  1469. gAgent.sendReliableMessage();
  1470. }
  1471. }
  1472. //static
  1473. void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
  1474.    std::vector<LLUUID>& member_ids)
  1475. {
  1476. bool start_message = true;
  1477. LLMessageSystem* msg = gMessageSystem;
  1478. LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
  1479. if (!group_datap) return;
  1480. for (std::vector<LLUUID>::iterator it = member_ids.begin();
  1481.  it != member_ids.end(); ++it)
  1482. {
  1483. LLUUID& ejected_member_id = (*it);
  1484. // Can't use 'eject' to leave a group.
  1485. if (ejected_member_id == gAgent.getID()) continue;
  1486. // Make sure they are in the group, and we need the member data
  1487. LLGroupMgrGroupData::member_list_t::iterator mit = group_datap->mMembers.find(ejected_member_id);
  1488. if (mit != group_datap->mMembers.end())
  1489. {
  1490. LLGroupMemberData* member_data = (*mit).second;
  1491. // Add them to the message
  1492. if (start_message)
  1493. {
  1494. msg->newMessage("EjectGroupMemberRequest");
  1495. msg->nextBlock("AgentData");
  1496. msg->addUUID("AgentID",gAgent.getID());
  1497. msg->addUUID("SessionID",gAgent.getSessionID());
  1498. msg->nextBlock("GroupData");
  1499. msg->addUUID("GroupID",group_id);
  1500. start_message = false;
  1501. }
  1502. msg->nextBlock("EjectData");
  1503. msg->addUUID("EjecteeID",ejected_member_id);
  1504. if (msg->isSendFull())
  1505. {
  1506. gAgent.sendReliableMessage();
  1507. start_message = true;
  1508. }
  1509. // Clean up groupmgr
  1510. for (LLGroupMemberData::role_list_t::iterator rit = member_data->roleBegin();
  1511.  rit != member_data->roleEnd(); ++rit)
  1512. {
  1513. if ((*rit).first.notNull() && (*rit).second!=0)
  1514. {
  1515. (*rit).second->removeMember(ejected_member_id);
  1516. }
  1517. }
  1518. group_datap->mMembers.erase(ejected_member_id);
  1519. delete member_data;
  1520. }
  1521. }
  1522. if (!start_message)
  1523. {
  1524. gAgent.sendReliableMessage();
  1525. }
  1526. }
  1527. void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
  1528. {
  1529. lldebugs << "LLGroupMgr::sendGroupRoleChanges" << llendl;
  1530. LLGroupMgrGroupData* group_datap = getGroupData(group_id);
  1531. if (group_datap && group_datap->pendingRoleChanges())
  1532. {
  1533. group_datap->sendRoleChanges();
  1534. // Not expecting a response, so let anyone else watching know the data has changed.
  1535. group_datap->mChanged = TRUE;
  1536. notifyObservers(GC_ROLE_DATA);
  1537. }
  1538. }
  1539. void LLGroupMgr::cancelGroupRoleChanges(const LLUUID& group_id)
  1540. {
  1541. lldebugs << "LLGroupMgr::cancelGroupRoleChanges" << llendl;
  1542. LLGroupMgrGroupData* group_datap = getGroupData(group_id);
  1543. if (group_datap) group_datap->cancelRoleChanges();
  1544. }
  1545. //static
  1546. bool LLGroupMgr::parseRoleActions(const std::string& xml_filename)
  1547. {
  1548. LLXMLNodePtr root;
  1549. BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
  1550. if (!success || !root || !root->hasName( "role_actions" ))
  1551. {
  1552. llerrs << "Problem reading UI role_actions file: " << xml_filename << llendl;
  1553. return false;
  1554. }
  1555. LLXMLNodeList role_list;
  1556. root->getChildren("action_set", role_list, false);
  1557. for (LLXMLNodeList::iterator role_iter = role_list.begin(); role_iter != role_list.end(); ++role_iter)
  1558. {
  1559. LLXMLNodePtr action_set = role_iter->second;
  1560. LLRoleActionSet* role_action_set = new LLRoleActionSet();
  1561. LLRoleAction* role_action_data = new LLRoleAction();
  1562. // name=
  1563. std::string action_set_name;
  1564. if (action_set->getAttributeString("name", action_set_name))
  1565. {
  1566. lldebugs << "Loading action set " << action_set_name << llendl;
  1567. role_action_data->mName = action_set_name;
  1568. }
  1569. else
  1570. {
  1571. llwarns << "Unable to parse action set with no name" << llendl;
  1572. delete role_action_set;
  1573. delete role_action_data;
  1574. continue;
  1575. }
  1576. // description=
  1577. std::string set_description;
  1578. if (action_set->getAttributeString("description", set_description))
  1579. {
  1580. role_action_data->mDescription = set_description;
  1581. }
  1582. // long description=
  1583. std::string set_longdescription;
  1584. if (action_set->getAttributeString("longdescription", set_longdescription))
  1585. {
  1586. role_action_data->mLongDescription = set_longdescription;
  1587. }
  1588. // power mask=
  1589. U64 set_power_mask = 0;
  1590. LLXMLNodeList action_list;
  1591. LLXMLNodeList::iterator action_iter;
  1592. action_set->getChildren("action", action_list, false);
  1593. for (action_iter = action_list.begin(); action_iter != action_list.end(); ++action_iter)
  1594. {
  1595. LLXMLNodePtr action = action_iter->second;
  1596. LLRoleAction* role_action = new LLRoleAction();
  1597. // name=
  1598. std::string action_name;
  1599. if (action->getAttributeString("name", action_name))
  1600. {
  1601. lldebugs << "Loading action " << action_name << llendl;
  1602. role_action->mName = action_name;
  1603. }
  1604. else
  1605. {
  1606. llwarns << "Unable to parse action with no name" << llendl;
  1607. delete role_action;
  1608. continue;
  1609. }
  1610. // description=
  1611. std::string description;
  1612. if (action->getAttributeString("description", description))
  1613. {
  1614. role_action->mDescription = description;
  1615. }
  1616. // long description=
  1617. std::string longdescription;
  1618. if (action->getAttributeString("longdescription", longdescription))
  1619. {
  1620. role_action->mLongDescription = longdescription;
  1621. }
  1622. // description=
  1623. S32 power_bit = 0;
  1624. if (action->getAttributeS32("value", power_bit))
  1625. {
  1626. if (0 <= power_bit && power_bit < 64)
  1627. {
  1628. role_action->mPowerBit = 0x1LL << power_bit;
  1629. }
  1630. }
  1631. set_power_mask |= role_action->mPowerBit;
  1632. role_action_set->mActions.push_back(role_action);
  1633. }
  1634. role_action_data->mPowerBit = set_power_mask;
  1635. role_action_set->mActionSetData = role_action_data;
  1636. LLGroupMgr::getInstance()->mRoleActionSets.push_back(role_action_set);
  1637. }
  1638. return true;
  1639. }
  1640. // static
  1641. void LLGroupMgr::debugClearAllGroups(void*)
  1642. {
  1643. LLGroupMgr::getInstance()->clearGroups();
  1644. LLGroupMgr::parseRoleActions("role_actions.xml");
  1645. }