diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llcallingcard.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llcallingcard.cpp | 816 |
1 files changed, 816 insertions, 0 deletions
diff --git a/linden/indra/newview/llcallingcard.cpp b/linden/indra/newview/llcallingcard.cpp new file mode 100644 index 0000000..83a5fac --- /dev/null +++ b/linden/indra/newview/llcallingcard.cpp | |||
@@ -0,0 +1,816 @@ | |||
1 | /** | ||
2 | * @file llcallingcard.cpp | ||
3 | * @brief Implementation of the LLPreviewCallingCard class | ||
4 | * | ||
5 | * Copyright (c) 2002-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 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #if LL_WINDOWS | ||
31 | #pragma warning( disable : 4800 ) // performance warning in <functional> | ||
32 | #endif | ||
33 | |||
34 | #include "llcallingcard.h" | ||
35 | |||
36 | #include <vector> | ||
37 | #include <algorithm> | ||
38 | //#include <iterator> | ||
39 | |||
40 | #include "indra_constants.h" | ||
41 | #include "llcachename.h" | ||
42 | #include "llstl.h" | ||
43 | #include "lltimer.h" | ||
44 | #include "lluuid.h" | ||
45 | #include "message.h" | ||
46 | |||
47 | #include "llagent.h" | ||
48 | #include "llbutton.h" | ||
49 | //#include "llinventory.h" | ||
50 | #include "llinventorymodel.h" | ||
51 | #include "llnotify.h" | ||
52 | #include "llresmgr.h" | ||
53 | #include "llimview.h" | ||
54 | #include "llviewercontrol.h" | ||
55 | #include "llviewernetwork.h" | ||
56 | #include "llviewerobjectlist.h" | ||
57 | #include "llviewerwindow.h" | ||
58 | #include "llvoavatar.h" | ||
59 | |||
60 | ///---------------------------------------------------------------------------- | ||
61 | /// Local function declarations, constants, enums, and typedefs | ||
62 | ///---------------------------------------------------------------------------- | ||
63 | |||
64 | class LLTrackingData | ||
65 | { | ||
66 | public: | ||
67 | LLTrackingData(const LLUUID& avatar_id, const std::string& name); | ||
68 | bool haveTrackingInfo(); | ||
69 | void setTrackedCoarseLocation(const LLVector3d& global_pos); | ||
70 | void agentFound(const LLUUID& prey, | ||
71 | const LLVector3d& estimated_global_pos); | ||
72 | |||
73 | public: | ||
74 | LLUUID mAvatarID; | ||
75 | LLString mName; | ||
76 | LLVector3d mGlobalPositionEstimate; | ||
77 | bool mHaveInfo; | ||
78 | bool mHaveCoarseInfo; | ||
79 | LLTimer mCoarseLocationTimer; | ||
80 | LLTimer mUpdateTimer; | ||
81 | LLTimer mAgentGone; | ||
82 | }; | ||
83 | |||
84 | const F32 COARSE_FREQUENCY = 2.2f; | ||
85 | const F32 FIND_FREQUENCY = 29.7f; // This results in a database query, so cut these back | ||
86 | const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f; | ||
87 | |||
88 | // static | ||
89 | LLAvatarTracker LLAvatarTracker::sInstance; | ||
90 | |||
91 | /* | ||
92 | class LLAvatarTrackerInventoryObserver : public LLInventoryObserver | ||
93 | { | ||
94 | public: | ||
95 | LLAvatarTrackerInventoryObserver(LLAvatarTracker* at) : | ||
96 | mAT(at) {} | ||
97 | virtual ~LLAvatarTrackerInventoryObserver() {} | ||
98 | virtual void changed(U32 mask); | ||
99 | protected: | ||
100 | LLAvatarTracker* mAT; | ||
101 | }; | ||
102 | */ | ||
103 | |||
104 | /* | ||
105 | void LLAvatarTrackerInventoryObserver::changed(U32 mask) | ||
106 | { | ||
107 | // if there's a calling card change, just do it. | ||
108 | if((mask & LLInventoryObserver::CALLING_CARD) != 0) | ||
109 | { | ||
110 | mAT->inventoryChanged(); | ||
111 | } | ||
112 | } | ||
113 | */ | ||
114 | |||
115 | ///---------------------------------------------------------------------------- | ||
116 | /// Class LLAvatarTracker | ||
117 | ///---------------------------------------------------------------------------- | ||
118 | |||
119 | LLAvatarTracker::LLAvatarTracker() : | ||
120 | mTrackingData(NULL), | ||
121 | mTrackedAgentValid(false), | ||
122 | //mInventory(NULL), | ||
123 | //mInventoryObserver(NULL), | ||
124 | mModifyMask(0x0) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | LLAvatarTracker::~LLAvatarTracker() | ||
129 | { | ||
130 | deleteTrackingData(); | ||
131 | std::for_each(mObservers.begin(), mObservers.end(), DeletePointer()); | ||
132 | } | ||
133 | |||
134 | void LLAvatarTracker::track(const LLUUID& avatar_id, const std::string& name) | ||
135 | { | ||
136 | deleteTrackingData(); | ||
137 | mTrackedAgentValid = false; | ||
138 | mTrackingData = new LLTrackingData(avatar_id, name); | ||
139 | findAgent(); | ||
140 | |||
141 | // We track here because findAgent() is called on a timer (for now). | ||
142 | if(avatar_id.notNull()) | ||
143 | { | ||
144 | LLMessageSystem* msg = gMessageSystem; | ||
145 | msg->newMessageFast(_PREHASH_TrackAgent); | ||
146 | msg->nextBlockFast(_PREHASH_AgentData); | ||
147 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
148 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
149 | msg->nextBlockFast(_PREHASH_TargetData); | ||
150 | msg->addUUIDFast(_PREHASH_PreyID, avatar_id); | ||
151 | gAgent.sendReliableMessage(); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | void LLAvatarTracker::untrack(const LLUUID& avatar_id) | ||
156 | { | ||
157 | if (mTrackingData && mTrackingData->mAvatarID == avatar_id) | ||
158 | { | ||
159 | deleteTrackingData(); | ||
160 | mTrackedAgentValid = false; | ||
161 | LLMessageSystem* msg = gMessageSystem; | ||
162 | msg->newMessageFast(_PREHASH_TrackAgent); | ||
163 | msg->nextBlockFast(_PREHASH_AgentData); | ||
164 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
165 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
166 | msg->nextBlockFast(_PREHASH_TargetData); | ||
167 | msg->addUUIDFast(_PREHASH_PreyID, LLUUID::null); | ||
168 | gAgent.sendReliableMessage(); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | void LLAvatarTracker::setTrackedCoarseLocation(const LLVector3d& global_pos) | ||
173 | { | ||
174 | if(mTrackingData) | ||
175 | { | ||
176 | mTrackingData->setTrackedCoarseLocation(global_pos); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | bool LLAvatarTracker::haveTrackingInfo() | ||
181 | { | ||
182 | if(mTrackingData) | ||
183 | { | ||
184 | return mTrackingData->haveTrackingInfo(); | ||
185 | } | ||
186 | return false; | ||
187 | } | ||
188 | |||
189 | LLVector3d LLAvatarTracker::getGlobalPos() | ||
190 | { | ||
191 | if(!mTrackedAgentValid) return LLVector3d(); | ||
192 | LLVector3d global_pos; | ||
193 | |||
194 | LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID); | ||
195 | if(object && !object->isDead()) | ||
196 | { | ||
197 | global_pos = object->getPositionGlobal(); | ||
198 | // HACK - for making the tracker point above the avatar's head | ||
199 | // rather than its groin | ||
200 | global_pos.mdV[VZ] += 0.7f * ((LLVOAvatar *)object)->mBodySize.mV[VZ]; | ||
201 | |||
202 | mTrackingData->mGlobalPositionEstimate = global_pos; | ||
203 | } | ||
204 | else | ||
205 | { | ||
206 | global_pos = mTrackingData->mGlobalPositionEstimate; | ||
207 | } | ||
208 | |||
209 | return global_pos; | ||
210 | } | ||
211 | |||
212 | void LLAvatarTracker::getDegreesAndDist(F32& rot, | ||
213 | F64& horiz_dist, | ||
214 | F64& vert_dist) | ||
215 | { | ||
216 | if(!mTrackingData) return; | ||
217 | |||
218 | LLVector3d global_pos; | ||
219 | |||
220 | LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID); | ||
221 | if(object && !object->isDead()) | ||
222 | { | ||
223 | global_pos = object->getPositionGlobal(); | ||
224 | mTrackingData->mGlobalPositionEstimate = global_pos; | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | global_pos = mTrackingData->mGlobalPositionEstimate; | ||
229 | } | ||
230 | LLVector3d to_vec = global_pos - gAgent.getPositionGlobal(); | ||
231 | horiz_dist = sqrt(to_vec.mdV[VX] * to_vec.mdV[VX] + to_vec.mdV[VY] * to_vec.mdV[VY]); | ||
232 | vert_dist = to_vec.mdV[VZ]; | ||
233 | rot = F32(RAD_TO_DEG * atan2(to_vec.mdV[VY], to_vec.mdV[VX])); | ||
234 | } | ||
235 | |||
236 | const LLString& LLAvatarTracker::getName() | ||
237 | { | ||
238 | if(mTrackingData) | ||
239 | { | ||
240 | return mTrackingData->mName; | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | return LLString::null; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | const LLUUID& LLAvatarTracker::getAvatarID() | ||
249 | { | ||
250 | if(mTrackingData) | ||
251 | { | ||
252 | return mTrackingData->mAvatarID; | ||
253 | } | ||
254 | else | ||
255 | { | ||
256 | return LLUUID::null; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds) | ||
261 | { | ||
262 | using namespace std; | ||
263 | |||
264 | U32 new_buddy_count = 0; | ||
265 | char first[DB_FIRST_NAME_BUF_SIZE]; | ||
266 | char last[DB_LAST_NAME_BUF_SIZE]; | ||
267 | LLUUID agent_id; | ||
268 | for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr) | ||
269 | { | ||
270 | agent_id = (*itr).first; | ||
271 | if(mBuddyInfo.find(agent_id) == mBuddyInfo.end()) | ||
272 | { | ||
273 | ++new_buddy_count; | ||
274 | mBuddyInfo[agent_id] = (*itr).second; | ||
275 | gCacheName->getName(agent_id, first, last); | ||
276 | mModifyMask |= LLFriendObserver::ADD; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | return new_buddy_count; | ||
281 | } | ||
282 | |||
283 | |||
284 | void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const | ||
285 | { | ||
286 | buddy_map_t::const_iterator it = mBuddyInfo.begin(); | ||
287 | buddy_map_t::const_iterator end = mBuddyInfo.end(); | ||
288 | for(; it != end; ++it) | ||
289 | { | ||
290 | buddies[(*it).first] = (*it).second; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | void LLAvatarTracker::terminateBuddy(const LLUUID& id) | ||
295 | { | ||
296 | lldebugs << "LLAvatarTracker::terminateBuddy()" << llendl; | ||
297 | LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id); | ||
298 | if(!buddy) return; | ||
299 | mBuddyInfo.erase(id); | ||
300 | LLMessageSystem* msg = gMessageSystem; | ||
301 | msg->newMessage("TerminateFriendship"); | ||
302 | msg->nextBlock("AgentData"); | ||
303 | msg->addUUID("AgentID", gAgent.getID()); | ||
304 | msg->addUUID("SessionID", gAgent.getSessionID()); | ||
305 | msg->nextBlock("ExBlock"); | ||
306 | msg->addUUID("OtherID", id); | ||
307 | gAgent.sendReliableMessage(); | ||
308 | mModifyMask |= LLFriendObserver::REMOVE; | ||
309 | delete buddy; | ||
310 | } | ||
311 | |||
312 | // get all buddy info | ||
313 | const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const | ||
314 | { | ||
315 | if(id.isNull()) return NULL; | ||
316 | return get_ptr_in_map(mBuddyInfo, id); | ||
317 | } | ||
318 | |||
319 | // online status | ||
320 | void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online) | ||
321 | { | ||
322 | LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); | ||
323 | if(info) | ||
324 | { | ||
325 | info->online(is_online); | ||
326 | mModifyMask |= LLFriendObserver::ONLINE; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | bool LLAvatarTracker::isBuddyOnline(const LLUUID& id) const | ||
331 | { | ||
332 | LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); | ||
333 | if(info) | ||
334 | { | ||
335 | return info->isOnline(); | ||
336 | } | ||
337 | return false; | ||
338 | } | ||
339 | |||
340 | // empowered status | ||
341 | void LLAvatarTracker::setBuddyEmpowered(const LLUUID& id, bool is_empowered) | ||
342 | { | ||
343 | LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); | ||
344 | if(info) | ||
345 | { | ||
346 | info->grantRights(LLRelationship::GRANT_MODIFY_OBJECTS, 0); | ||
347 | mModifyMask |= LLFriendObserver::POWERS; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | bool LLAvatarTracker::isBuddyEmpowered(const LLUUID& id) const | ||
352 | { | ||
353 | LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); | ||
354 | if(info) | ||
355 | { | ||
356 | return info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS); | ||
357 | } | ||
358 | return false; | ||
359 | } | ||
360 | |||
361 | void LLAvatarTracker::empower(const LLUUID& id, bool grant) | ||
362 | { | ||
363 | // wrapper for ease of use in some situations. | ||
364 | buddy_map_t list; | ||
365 | /* | ||
366 | list.insert(id); | ||
367 | empowerList(list, grant); | ||
368 | */ | ||
369 | } | ||
370 | |||
371 | void LLAvatarTracker::empowerList(const buddy_map_t& list, bool grant) | ||
372 | { | ||
373 | llwarns << "LLAvatarTracker::empowerList() not implemented." << llendl; | ||
374 | /* | ||
375 | LLMessageSystem* msg = gMessageSystem; | ||
376 | const char* message_name; | ||
377 | const char* block_name; | ||
378 | const char* field_name; | ||
379 | if(grant) | ||
380 | { | ||
381 | message_name = _PREHASH_GrantModification; | ||
382 | block_name = _PREHASH_EmpoweredBlock; | ||
383 | field_name = _PREHASH_EmpoweredID; | ||
384 | } | ||
385 | else | ||
386 | { | ||
387 | message_name = _PREHASH_RevokeModification; | ||
388 | block_name = _PREHASH_RevokedBlock; | ||
389 | field_name = _PREHASH_RevokedID; | ||
390 | } | ||
391 | |||
392 | std::string name; | ||
393 | gAgent.buildFullnameAndTitle(name); | ||
394 | |||
395 | bool start_new_message = true; | ||
396 | buddy_list_t::const_iterator it = list.begin(); | ||
397 | buddy_list_t::const_iterator end = list.end(); | ||
398 | for(; it != end; ++it) | ||
399 | { | ||
400 | if(NULL == get_ptr_in_map(mBuddyInfo, (*it))) continue; | ||
401 | setBuddyEmpowered((*it), grant); | ||
402 | if(start_new_message) | ||
403 | { | ||
404 | start_new_message = false; | ||
405 | msg->newMessageFast(message_name); | ||
406 | msg->nextBlockFast(_PREHASH_AgentData); | ||
407 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
408 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
409 | msg->addStringFast(_PREHASH_GranterName, name); | ||
410 | } | ||
411 | msg->nextBlockFast(block_name); | ||
412 | msg->addUUIDFast(field_name, (*it)); | ||
413 | if(msg->isSendFullFast(block_name)) | ||
414 | { | ||
415 | start_new_message = true; | ||
416 | gAgent.sendReliableMessage(); | ||
417 | } | ||
418 | } | ||
419 | if(!start_new_message) | ||
420 | { | ||
421 | gAgent.sendReliableMessage(); | ||
422 | } | ||
423 | */ | ||
424 | } | ||
425 | |||
426 | void LLAvatarTracker::deleteTrackingData() | ||
427 | { | ||
428 | delete mTrackingData; | ||
429 | mTrackingData = NULL; | ||
430 | } | ||
431 | |||
432 | void LLAvatarTracker::findAgent() | ||
433 | { | ||
434 | if (!mTrackingData) return; | ||
435 | if (mTrackingData->mAvatarID.isNull()) return; | ||
436 | LLMessageSystem* msg = gMessageSystem; | ||
437 | msg->newMessageFast(_PREHASH_FindAgent); // Request | ||
438 | msg->nextBlockFast(_PREHASH_AgentBlock); | ||
439 | msg->addUUIDFast(_PREHASH_Hunter, gAgentID); | ||
440 | msg->addUUIDFast(_PREHASH_Prey, mTrackingData->mAvatarID); | ||
441 | msg->addU32Fast(_PREHASH_SpaceIP, 0); // will get filled in by userserver | ||
442 | msg->nextBlockFast(_PREHASH_LocationBlock); | ||
443 | const F64 NO_LOCATION = 0.0; | ||
444 | msg->addF64Fast(_PREHASH_GlobalX, NO_LOCATION); | ||
445 | msg->addF64Fast(_PREHASH_GlobalY, NO_LOCATION); | ||
446 | gAgent.sendReliableMessage(); | ||
447 | } | ||
448 | |||
449 | void LLAvatarTracker::addObserver(LLFriendObserver* observer) | ||
450 | { | ||
451 | if(observer) | ||
452 | { | ||
453 | mObservers.push_back(observer); | ||
454 | } | ||
455 | } | ||
456 | |||
457 | void LLAvatarTracker::removeObserver(LLFriendObserver* observer) | ||
458 | { | ||
459 | mObservers.erase( | ||
460 | std::remove(mObservers.begin(), mObservers.end(), observer), | ||
461 | mObservers.end()); | ||
462 | } | ||
463 | |||
464 | void LLAvatarTracker::notifyObservers() | ||
465 | { | ||
466 | observer_list_t observers(mObservers); | ||
467 | observer_list_t::iterator it = observers.begin(); | ||
468 | observer_list_t::iterator end = observers.end(); | ||
469 | for(; it != end; ++it) | ||
470 | { | ||
471 | (*it)->changed(mModifyMask); | ||
472 | } | ||
473 | mModifyMask = LLFriendObserver::NONE; | ||
474 | } | ||
475 | |||
476 | void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f) | ||
477 | { | ||
478 | buddy_map_t::iterator it = mBuddyInfo.begin(); | ||
479 | buddy_map_t::iterator end = mBuddyInfo.end(); | ||
480 | for(; it != end; ++it) | ||
481 | { | ||
482 | f((*it).first, (*it).second); | ||
483 | } | ||
484 | } | ||
485 | |||
486 | void LLAvatarTracker::registerCallbacks(LLMessageSystem* msg) | ||
487 | { | ||
488 | msg->setHandlerFuncFast(_PREHASH_FindAgent, processAgentFound); | ||
489 | msg->setHandlerFuncFast(_PREHASH_OnlineNotification, | ||
490 | processOnlineNotification); | ||
491 | msg->setHandlerFuncFast(_PREHASH_OfflineNotification, | ||
492 | processOfflineNotification); | ||
493 | //msg->setHandlerFuncFast(_PREHASH_GrantedProxies, | ||
494 | // processGrantedProxies); | ||
495 | msg->setHandlerFunc("TerminateFriendship", processTerminateFriendship); | ||
496 | msg->setHandlerFunc(_PREHASH_ChangeUserRights, processChangeUserRights); | ||
497 | } | ||
498 | |||
499 | // static | ||
500 | void LLAvatarTracker::processAgentFound(LLMessageSystem* msg, void**) | ||
501 | { | ||
502 | LLUUID id; | ||
503 | |||
504 | |||
505 | msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Hunter, id); | ||
506 | msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Prey, id); | ||
507 | // *FIX: should make sure prey id matches. | ||
508 | LLVector3d estimated_global_pos; | ||
509 | msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalX, | ||
510 | estimated_global_pos.mdV[VX]); | ||
511 | msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalY, | ||
512 | estimated_global_pos.mdV[VY]); | ||
513 | LLAvatarTracker::instance().agentFound(id, estimated_global_pos); | ||
514 | } | ||
515 | |||
516 | void LLAvatarTracker::agentFound(const LLUUID& prey, | ||
517 | const LLVector3d& estimated_global_pos) | ||
518 | { | ||
519 | if(!mTrackingData) return; | ||
520 | //if we get a valid reply from the server, that means the agent | ||
521 | //is our friend and mappable, so enable interest list based updates | ||
522 | LLAvatarTracker::instance().setTrackedAgentValid(true); | ||
523 | mTrackingData->agentFound(prey, estimated_global_pos); | ||
524 | } | ||
525 | |||
526 | // static | ||
527 | void LLAvatarTracker::processOnlineNotification(LLMessageSystem* msg, void**) | ||
528 | { | ||
529 | lldebugs << "LLAvatarTracker::processOnlineNotification()" << llendl; | ||
530 | instance().processNotify(msg, true); | ||
531 | } | ||
532 | |||
533 | // static | ||
534 | void LLAvatarTracker::processOfflineNotification(LLMessageSystem* msg, void**) | ||
535 | { | ||
536 | lldebugs << "LLAvatarTracker::processOfflineNotification()" << llendl; | ||
537 | instance().processNotify(msg, false); | ||
538 | } | ||
539 | |||
540 | void LLAvatarTracker::processChange(LLMessageSystem* msg) | ||
541 | { | ||
542 | S32 count = msg->getNumberOfBlocksFast(_PREHASH_Rights); | ||
543 | LLUUID agent_id, agent_related; | ||
544 | S32 new_rights; | ||
545 | msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); | ||
546 | for(int i = 0; i < count; ++i) | ||
547 | { | ||
548 | msg->getUUIDFast(_PREHASH_Rights, _PREHASH_AgentRelated, agent_related, i); | ||
549 | msg->getS32Fast(_PREHASH_Rights,_PREHASH_RelatedRights, new_rights, i); | ||
550 | if(agent_id == gAgent.getID()) | ||
551 | { | ||
552 | if(mBuddyInfo.find(agent_related) != mBuddyInfo.end()) | ||
553 | { | ||
554 | (mBuddyInfo[agent_related])->setRightsTo(new_rights); | ||
555 | } | ||
556 | } | ||
557 | else | ||
558 | { | ||
559 | if(mBuddyInfo.find(agent_id) != mBuddyInfo.end()) | ||
560 | { | ||
561 | if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS) | ||
562 | { | ||
563 | char first[DB_FIRST_NAME_BUF_SIZE]; | ||
564 | char last[DB_LAST_NAME_BUF_SIZE]; | ||
565 | LLStringBase<char>::format_map_t args; | ||
566 | if(gCacheName->getName(agent_id, first, last)) | ||
567 | { | ||
568 | args["[FIRST_NAME]"] = first; | ||
569 | args["[LAST_NAME]"] = last; | ||
570 | } | ||
571 | if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights) | ||
572 | { | ||
573 | gViewerWindow->alertXml("GrantedModifyRights",args); | ||
574 | } | ||
575 | else | ||
576 | { | ||
577 | gViewerWindow->alertXml("RevokedModifyRights",args); | ||
578 | } | ||
579 | } | ||
580 | (mBuddyInfo[agent_id])->setRightsFrom(new_rights); | ||
581 | } | ||
582 | } | ||
583 | } | ||
584 | mModifyMask |= LLFriendObserver::POWERS; | ||
585 | |||
586 | notifyObservers(); | ||
587 | } | ||
588 | |||
589 | void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**) | ||
590 | { | ||
591 | lldebugs << "LLAvatarTracker::processChangeUserRights()" << llendl; | ||
592 | instance().processChange(msg); | ||
593 | } | ||
594 | |||
595 | void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) | ||
596 | { | ||
597 | S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock); | ||
598 | BOOL chat_notify = gSavedSettings.getBOOL("ChatOnlineNotification"); | ||
599 | |||
600 | if(count > 0) | ||
601 | { | ||
602 | LLUUID agent_id; | ||
603 | const LLRelationship* info = NULL; | ||
604 | LLUUID tracking_id; | ||
605 | if(mTrackingData) | ||
606 | { | ||
607 | tracking_id = mTrackingData->mAvatarID; | ||
608 | } | ||
609 | BOOL notify = FALSE; | ||
610 | LLString::format_map_t args; | ||
611 | for(S32 i = 0; i < count; ++i) | ||
612 | { | ||
613 | msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_AgentID, agent_id, i); | ||
614 | info = getBuddyInfo(agent_id); | ||
615 | if(info) | ||
616 | { | ||
617 | setBuddyOnline(agent_id,online); | ||
618 | if(chat_notify) | ||
619 | { | ||
620 | char first[DB_FIRST_NAME_BUF_SIZE]; | ||
621 | char last[DB_LAST_NAME_BUF_SIZE]; | ||
622 | if(gCacheName->getName(agent_id, first, last)) | ||
623 | { | ||
624 | notify = TRUE; | ||
625 | args["[FIRST]"] = first; | ||
626 | args["[LAST]"] = last; | ||
627 | } | ||
628 | } | ||
629 | } | ||
630 | if(tracking_id == agent_id) | ||
631 | { | ||
632 | // we were tracking someone who went offline | ||
633 | deleteTrackingData(); | ||
634 | } | ||
635 | // *TODO: get actual inventory id | ||
636 | gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null); | ||
637 | } | ||
638 | if(notify) | ||
639 | { | ||
640 | LLNotifyBox::showXml(online ? "FriendOnline" : "FriendOffline", args); | ||
641 | } | ||
642 | |||
643 | mModifyMask |= LLFriendObserver::ONLINE; | ||
644 | instance().notifyObservers(); | ||
645 | gInventory.notifyObservers(); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | // XUI:translate | ||
650 | void LLAvatarTracker::formFriendship(const LLUUID& id) | ||
651 | { | ||
652 | if(id.notNull()) | ||
653 | { | ||
654 | LLRelationship* buddy_info = get_ptr_in_map(instance().mBuddyInfo, id); | ||
655 | if(!buddy_info) | ||
656 | { | ||
657 | LLAvatarTracker& at = LLAvatarTracker::instance(); | ||
658 | //The default for relationship establishment is to have both parties | ||
659 | //visible online to each other. | ||
660 | buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false); | ||
661 | at.mBuddyInfo[id] = buddy_info; | ||
662 | at.mModifyMask |= LLFriendObserver::ADD; | ||
663 | at.notifyObservers(); | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | |||
668 | void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**) | ||
669 | { | ||
670 | LLUUID id; | ||
671 | msg->getUUID("ExBlock", "OtherID", id); | ||
672 | if(id.notNull()) | ||
673 | { | ||
674 | LLAvatarTracker& at = LLAvatarTracker::instance(); | ||
675 | LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id); | ||
676 | if(!buddy) return; | ||
677 | at.mBuddyInfo.erase(id); | ||
678 | at.mModifyMask |= LLFriendObserver::REMOVE; | ||
679 | delete buddy; | ||
680 | at.notifyObservers(); | ||
681 | } | ||
682 | } | ||
683 | |||
684 | ///---------------------------------------------------------------------------- | ||
685 | /// Tracking Data | ||
686 | ///---------------------------------------------------------------------------- | ||
687 | |||
688 | LLTrackingData::LLTrackingData(const LLUUID& avatar_id, const std::string& name) | ||
689 | : mAvatarID(avatar_id), | ||
690 | mHaveInfo(false), | ||
691 | mHaveCoarseInfo(false) | ||
692 | { | ||
693 | mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY); | ||
694 | mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY); | ||
695 | mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); | ||
696 | if(!name.empty()) | ||
697 | { | ||
698 | mName = name; | ||
699 | } | ||
700 | } | ||
701 | |||
702 | void LLTrackingData::agentFound(const LLUUID& prey, | ||
703 | const LLVector3d& estimated_global_pos) | ||
704 | { | ||
705 | if(prey != mAvatarID) | ||
706 | { | ||
707 | llwarns << "LLTrackingData::agentFound() - found " << prey | ||
708 | << " but looking for " << mAvatarID << llendl; | ||
709 | } | ||
710 | mHaveInfo = true; | ||
711 | mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); | ||
712 | mGlobalPositionEstimate = estimated_global_pos; | ||
713 | } | ||
714 | |||
715 | bool LLTrackingData::haveTrackingInfo() | ||
716 | { | ||
717 | LLViewerObject* object = gObjectList.findObject(mAvatarID); | ||
718 | if(object && !object->isDead()) | ||
719 | { | ||
720 | mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY); | ||
721 | mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY); | ||
722 | mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); | ||
723 | mHaveInfo = true; | ||
724 | return true; | ||
725 | } | ||
726 | if(mHaveCoarseInfo && | ||
727 | !mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY)) | ||
728 | { | ||
729 | // if we reach here, then we have a 'recent' coarse update | ||
730 | mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY); | ||
731 | mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); | ||
732 | return true; | ||
733 | } | ||
734 | if(mUpdateTimer.checkExpirationAndReset(FIND_FREQUENCY)) | ||
735 | { | ||
736 | LLAvatarTracker::instance().findAgent(); | ||
737 | mHaveCoarseInfo = false; | ||
738 | } | ||
739 | if(mAgentGone.checkExpirationAndReset(OFFLINE_SECONDS)) | ||
740 | { | ||
741 | mHaveInfo = false; | ||
742 | mHaveCoarseInfo = false; | ||
743 | } | ||
744 | return mHaveInfo; | ||
745 | } | ||
746 | |||
747 | void LLTrackingData::setTrackedCoarseLocation(const LLVector3d& global_pos) | ||
748 | { | ||
749 | mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY); | ||
750 | mGlobalPositionEstimate = global_pos; | ||
751 | mHaveInfo = true; | ||
752 | mHaveCoarseInfo = true; | ||
753 | } | ||
754 | |||
755 | ///---------------------------------------------------------------------------- | ||
756 | // various buddy functors | ||
757 | ///---------------------------------------------------------------------------- | ||
758 | |||
759 | bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) | ||
760 | { | ||
761 | if(buddy->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS)) | ||
762 | { | ||
763 | mProxy.insert(buddy_id); | ||
764 | } | ||
765 | return true; | ||
766 | } | ||
767 | |||
768 | bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) | ||
769 | { | ||
770 | mFirst[0] = '\0'; | ||
771 | mLast[0] = '\0'; | ||
772 | gCacheName->getName(buddy_id, mFirst, mLast); | ||
773 | std::ostringstream fullname; | ||
774 | fullname << mFirst << " " << mLast; | ||
775 | buddy_map_t::value_type value(fullname.str(), buddy_id); | ||
776 | if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)) | ||
777 | { | ||
778 | mMappable.insert(value); | ||
779 | } | ||
780 | return true; | ||
781 | } | ||
782 | |||
783 | bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) | ||
784 | { | ||
785 | mFirst[0] = '\0'; | ||
786 | mLast[0] = '\0'; | ||
787 | gCacheName->getName(buddy_id, mFirst, mLast); | ||
788 | std::ostringstream fullname; | ||
789 | fullname << mFirst << " " << mLast; | ||
790 | buddy_map_t::value_type value(fullname.str(), buddy_id); | ||
791 | if(buddy->isOnline()) | ||
792 | { | ||
793 | mOnline.insert(value); | ||
794 | } | ||
795 | return true; | ||
796 | } | ||
797 | |||
798 | bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) | ||
799 | { | ||
800 | mFirst[0] = '\0'; | ||
801 | mLast[0] = '\0'; | ||
802 | gCacheName->getName(buddy_id, mFirst, mLast); | ||
803 | std::ostringstream fullname; | ||
804 | fullname << mFirst << " " << mLast; | ||
805 | buddy_map_t::value_type value(fullname.str(), buddy_id); | ||
806 | if(buddy->isOnline()) | ||
807 | { | ||
808 | mOnline.insert(value); | ||
809 | } | ||
810 | else | ||
811 | { | ||
812 | mOffline.insert(value); | ||
813 | } | ||
814 | return true; | ||
815 | } | ||
816 | |||