diff options
Diffstat (limited to 'linden/indra/newview/llgroupmgr.cpp')
-rw-r--r-- | linden/indra/newview/llgroupmgr.cpp | 1835 |
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 | |||
52 | LLGroupMgr sGroupMgr; // use local instance so that it gets cleaned up on application exit | ||
53 | LLGroupMgr* gGroupMgr = &sGroupMgr; | ||
54 | |||
55 | const U32 MAX_CACHED_GROUPS = 10; | ||
56 | |||
57 | // | ||
58 | // LLRoleActionSet | ||
59 | // | ||
60 | LLRoleActionSet::LLRoleActionSet() | ||
61 | : mActionSetData(NULL) | ||
62 | { } | ||
63 | |||
64 | LLRoleActionSet::~LLRoleActionSet() | ||
65 | { | ||
66 | delete mActionSetData; | ||
67 | std::for_each(mActions.begin(), mActions.end(), DeletePointer()); | ||
68 | } | ||
69 | |||
70 | // | ||
71 | // LLGroupMemberData | ||
72 | // | ||
73 | |||
74 | LLGroupMemberData::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 | |||
89 | LLGroupMemberData::~LLGroupMemberData() | ||
90 | { | ||
91 | } | ||
92 | |||
93 | void LLGroupMemberData::addRole(const LLUUID& role, LLGroupRoleData* rd) | ||
94 | { | ||
95 | mRoles[role] = rd; | ||
96 | } | ||
97 | |||
98 | bool 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 | |||
115 | LLGroupRoleData::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 | |||
132 | LLGroupRoleData::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 | |||
143 | LLGroupRoleData::~LLGroupRoleData() | ||
144 | { | ||
145 | } | ||
146 | |||
147 | S32 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 | |||
179 | void LLGroupRoleData::addMember(const LLUUID& member) | ||
180 | { | ||
181 | mMembersNeedsSort = TRUE; | ||
182 | mMemberIDs.push_back(member); | ||
183 | } | ||
184 | |||
185 | bool 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 | |||
199 | void LLGroupRoleData::clearMembers() | ||
200 | { | ||
201 | mMembersNeedsSort = FALSE; | ||
202 | mMemberIDs.clear(); | ||
203 | } | ||
204 | |||
205 | |||
206 | // | ||
207 | // LLGroupMgrGroupData | ||
208 | // | ||
209 | |||
210 | LLGroupMgrGroupData::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 | |||
229 | BOOL 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 | |||
256 | void 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 | |||
314 | BOOL LLGroupMgrGroupData::pendingRoleChanges() | ||
315 | { | ||
316 | return (!mRoleChanges.empty()); | ||
317 | } | ||
318 | |||
319 | // This is a no-op if the role has already been created. | ||
320 | void 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 | |||
333 | void 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 | |||
351 | void 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 | |||
365 | void 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 | |||
379 | U64 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 | |||
393 | void LLGroupMgrGroupData::removeData() | ||
394 | { | ||
395 | // Remove member data first, because removeRoleData will walk the member list | ||
396 | removeMemberData(); | ||
397 | removeRoleData(); | ||
398 | } | ||
399 | |||
400 | void 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 | |||
410 | void 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 | |||
432 | void 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 | |||
456 | LLGroupMgrGroupData::~LLGroupMgrGroupData() | ||
457 | { | ||
458 | removeData(); | ||
459 | } | ||
460 | |||
461 | bool 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 | |||
548 | void 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 | |||
573 | void 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 | |||
595 | bool 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 | |||
628 | void 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 | |||
720 | void LLGroupMgrGroupData::cancelRoleChanges() | ||
721 | { | ||
722 | // Clear out all changes! | ||
723 | mRoleChanges.clear(); | ||
724 | } | ||
725 | // | ||
726 | // LLGroupMgr | ||
727 | // | ||
728 | |||
729 | LLGroupMgr::LLGroupMgr() | ||
730 | { | ||
731 | } | ||
732 | |||
733 | LLGroupMgr::~LLGroupMgr() | ||
734 | { | ||
735 | clearGroups(); | ||
736 | } | ||
737 | |||
738 | void 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 | |||
747 | void 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 | |||
757 | void LLGroupMgr::addObserver(LLGroupMgrObserver* observer) | ||
758 | { | ||
759 | mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer)); | ||
760 | } | ||
761 | |||
762 | void 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 | |||
781 | LLGroupMgrGroupData* 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 | ||
793 | void 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 | ||
882 | void 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 | ||
950 | void 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 | ||
1018 | void 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 | ||
1129 | void 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 | ||
1180 | void 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 | ||
1196 | void 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 | ||
1218 | void 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 | ||
1240 | void 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 | |||
1280 | LLGroupMgrGroupData* 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 | |||
1297 | void 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 | |||
1314 | void 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 | |||
1339 | void 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 | |||
1355 | void 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 | |||
1376 | void 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 | |||
1397 | void 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 | |||
1431 | void 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 | |||
1450 | void 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 | ||
1483 | void 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 | |||
1511 | void 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 | |||
1540 | void 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 | ||
1589 | void 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 | ||
1605 | void 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 | ||
1643 | void 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 | |||
1705 | void 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 | |||
1720 | void 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 | ||
1729 | bool 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 | ||
1830 | void LLGroupMgr::debugClearAllGroups(void*) | ||
1831 | { | ||
1832 | gGroupMgr->clearGroups(); | ||
1833 | LLGroupMgr::parseRoleActions("role_actions.xml"); | ||
1834 | } | ||
1835 | |||