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