00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #if LL_WINDOWS
00035 #pragma warning( disable : 4800 ) // performance warning in <functional>
00036 #endif
00037 
00038 #include "llcallingcard.h"
00039 
00040 #include <vector>
00041 #include <algorithm>
00042 
00043 
00044 #include "indra_constants.h"
00045 #include "llcachename.h"
00046 #include "llstl.h"
00047 #include "lltimer.h"
00048 #include "lluuid.h"
00049 #include "message.h"
00050 
00051 #include "llagent.h"
00052 #include "llbutton.h"
00053 
00054 #include "llinventorymodel.h"
00055 #include "llnotify.h"
00056 #include "llresmgr.h"
00057 #include "llimview.h"
00058 #include "llviewercontrol.h"
00059 #include "llviewernetwork.h"
00060 #include "llviewerobjectlist.h"
00061 #include "llviewerwindow.h"
00062 #include "llvoavatar.h"
00063 
00067 
00068 class LLTrackingData
00069 {
00070 public:
00071         LLTrackingData(const LLUUID& avatar_id, const std::string& name);
00072         bool haveTrackingInfo();
00073         void setTrackedCoarseLocation(const LLVector3d& global_pos);
00074         void agentFound(const LLUUID& prey,
00075                                         const LLVector3d& estimated_global_pos);
00076         
00077 public:
00078         LLUUID mAvatarID;
00079         LLString mName;
00080         LLVector3d mGlobalPositionEstimate;
00081         bool mHaveInfo;
00082         bool mHaveCoarseInfo;
00083         LLTimer mCoarseLocationTimer;
00084         LLTimer mUpdateTimer;
00085         LLTimer mAgentGone;
00086 };
00087 
00088 const F32 COARSE_FREQUENCY = 2.2f;
00089 const F32 FIND_FREQUENCY = 29.7f;       
00090 const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
00091 
00092 
00093 LLAvatarTracker LLAvatarTracker::sInstance;
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00122 
00123 LLAvatarTracker::LLAvatarTracker() :
00124         mTrackingData(NULL),
00125         mTrackedAgentValid(false),
00126         
00127         
00128         mModifyMask(0x0)        
00129 {
00130 }
00131 
00132 LLAvatarTracker::~LLAvatarTracker()
00133 {
00134         deleteTrackingData();
00135         std::for_each(mObservers.begin(), mObservers.end(), DeletePointer());
00136         std::for_each(mBuddyInfo.begin(), mBuddyInfo.end(), DeletePairedPointer());
00137 }
00138 
00139 void LLAvatarTracker::track(const LLUUID& avatar_id, const std::string& name)
00140 {
00141         deleteTrackingData();
00142         mTrackedAgentValid = false;
00143         mTrackingData = new LLTrackingData(avatar_id, name);
00144         findAgent();
00145 
00146         
00147         if(avatar_id.notNull())
00148         {
00149                 LLMessageSystem* msg = gMessageSystem;
00150                 msg->newMessageFast(_PREHASH_TrackAgent);
00151                 msg->nextBlockFast(_PREHASH_AgentData);
00152                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00153                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00154                 msg->nextBlockFast(_PREHASH_TargetData);
00155                 msg->addUUIDFast(_PREHASH_PreyID, avatar_id);
00156                 gAgent.sendReliableMessage();
00157         }
00158 }
00159 
00160 void LLAvatarTracker::untrack(const LLUUID& avatar_id)
00161 {
00162         if (mTrackingData && mTrackingData->mAvatarID == avatar_id)
00163         {
00164                 deleteTrackingData();
00165                 mTrackedAgentValid = false;
00166                 LLMessageSystem* msg = gMessageSystem;
00167                 msg->newMessageFast(_PREHASH_TrackAgent);
00168                 msg->nextBlockFast(_PREHASH_AgentData);
00169                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00170                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00171                 msg->nextBlockFast(_PREHASH_TargetData);
00172                 msg->addUUIDFast(_PREHASH_PreyID, LLUUID::null);
00173                 gAgent.sendReliableMessage();
00174         }
00175 }
00176 
00177 void LLAvatarTracker::setTrackedCoarseLocation(const LLVector3d& global_pos)
00178 {
00179         if(mTrackingData)
00180         {
00181                 mTrackingData->setTrackedCoarseLocation(global_pos);
00182         }
00183 }
00184 
00185 bool LLAvatarTracker::haveTrackingInfo()
00186 {
00187         if(mTrackingData)
00188         {
00189                 return mTrackingData->haveTrackingInfo();
00190         }
00191         return false;
00192 }
00193 
00194 LLVector3d LLAvatarTracker::getGlobalPos()
00195 {
00196         if(!mTrackedAgentValid) return LLVector3d();
00197         LLVector3d global_pos;
00198         
00199         LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID);
00200         if(object && !object->isDead())
00201         {
00202                 global_pos = object->getPositionGlobal();
00203                 
00204                 
00205                 global_pos.mdV[VZ] += 0.7f * ((LLVOAvatar *)object)->mBodySize.mV[VZ];
00206 
00207                 mTrackingData->mGlobalPositionEstimate = global_pos;
00208         }
00209         else
00210         {
00211                 global_pos = mTrackingData->mGlobalPositionEstimate;
00212         }
00213 
00214         return global_pos;
00215 }
00216 
00217 void LLAvatarTracker::getDegreesAndDist(F32& rot,
00218                                                                                 F64& horiz_dist,
00219                                                                                 F64& vert_dist)
00220 {
00221         if(!mTrackingData) return;
00222 
00223         LLVector3d global_pos;
00224 
00225         LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID);
00226         if(object && !object->isDead())
00227         {
00228                 global_pos = object->getPositionGlobal();
00229                 mTrackingData->mGlobalPositionEstimate = global_pos;
00230         }
00231         else
00232         {
00233                 global_pos = mTrackingData->mGlobalPositionEstimate;
00234         }
00235         LLVector3d to_vec = global_pos - gAgent.getPositionGlobal();
00236         horiz_dist = sqrt(to_vec.mdV[VX] * to_vec.mdV[VX] + to_vec.mdV[VY] * to_vec.mdV[VY]);
00237         vert_dist = to_vec.mdV[VZ];
00238         rot = F32(RAD_TO_DEG * atan2(to_vec.mdV[VY], to_vec.mdV[VX]));
00239 }
00240 
00241 const LLString& LLAvatarTracker::getName()
00242 {
00243         if(mTrackingData)
00244         {
00245                 return mTrackingData->mName;
00246         }
00247         else
00248         {
00249                 return LLString::null;
00250         }
00251 }
00252 
00253 const LLUUID& LLAvatarTracker::getAvatarID()
00254 {
00255         if(mTrackingData)
00256         {
00257                 return mTrackingData->mAvatarID;
00258         }
00259         else
00260         {
00261                 return LLUUID::null;
00262         }
00263 }
00264 
00265 S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
00266 {
00267         using namespace std;
00268 
00269         U32 new_buddy_count = 0;        
00270         char first[DB_FIRST_NAME_BUF_SIZE];             
00271         char last[DB_LAST_NAME_BUF_SIZE];               
00272         LLUUID agent_id;
00273         for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr)
00274         {
00275                 agent_id = (*itr).first;
00276                 buddy_map_t::const_iterator existing_buddy = mBuddyInfo.find(agent_id);
00277                 if(existing_buddy == mBuddyInfo.end())
00278                 {
00279                         ++new_buddy_count;
00280                         mBuddyInfo[agent_id] = (*itr).second;
00281                         gCacheName->getName(agent_id, first, last);
00282                         mModifyMask |= LLFriendObserver::ADD;
00283                         lldebugs << "Added buddy " << agent_id
00284                                         << ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
00285                                         << ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo()
00286                                         << ", FROM: " << mBuddyInfo[agent_id]->getRightsGrantedFrom()
00287                                         << llendl;
00288                 }
00289                 else
00290                 {
00291                         LLRelationship* e_r = (*existing_buddy).second;
00292                         LLRelationship* n_r = (*itr).second;
00293                         llwarns << "!! Add buddy for existing buddy: " << agent_id
00294                                         << " [" << (e_r->isOnline() ? "Online" : "Offline") << "->" << (n_r->isOnline() ? "Online" : "Offline")
00295                                         << ", " <<  e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo()
00296                                         << ", " <<  e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo()
00297                                         << "]" << llendl;
00298                 }
00299         }
00300         notifyObservers();
00301         
00302         return new_buddy_count;
00303 }
00304 
00305 
00306 void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const
00307 {
00308         buddy_map_t::const_iterator it = mBuddyInfo.begin();
00309         buddy_map_t::const_iterator end = mBuddyInfo.end();
00310         for(; it != end; ++it)
00311         {
00312                 buddies[(*it).first] = (*it).second;
00313         }
00314 }
00315 
00316 void LLAvatarTracker::terminateBuddy(const LLUUID& id)
00317 {
00318         lldebugs << "LLAvatarTracker::terminateBuddy()" << llendl;
00319         LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id);
00320         if(!buddy) return;
00321         mBuddyInfo.erase(id);
00322         LLMessageSystem* msg = gMessageSystem;
00323         msg->newMessage("TerminateFriendship");
00324         msg->nextBlock("AgentData");
00325         msg->addUUID("AgentID", gAgent.getID());
00326         msg->addUUID("SessionID", gAgent.getSessionID());
00327         msg->nextBlock("ExBlock");
00328         msg->addUUID("OtherID", id);
00329         gAgent.sendReliableMessage();
00330         mModifyMask |= LLFriendObserver::REMOVE;
00331         delete buddy;
00332 }
00333 
00334 
00335 const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const
00336 {
00337         if(id.isNull()) return NULL;
00338         return get_ptr_in_map(mBuddyInfo, id);
00339 }
00340 
00341 
00342 void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
00343 {
00344         LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
00345         if(info)
00346         {
00347                 info->online(is_online);
00348                 mModifyMask |= LLFriendObserver::ONLINE;
00349                 lldebugs << "Set buddy " << id << (is_online ? " Online" : " Offline") << llendl;
00350         }
00351         else
00352         {
00353                 llwarns << "!! No buddy info found for " << id 
00354                                 << ", setting to " << (is_online ? "Online" : "Offline") << llendl;
00355         }
00356 }
00357 
00358 bool LLAvatarTracker::isBuddyOnline(const LLUUID& id) const
00359 {
00360         LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
00361         if(info)
00362         {
00363                 return info->isOnline();
00364         }
00365         return false;
00366 }
00367 
00368 
00369 void LLAvatarTracker::setBuddyEmpowered(const LLUUID& id, bool is_empowered)
00370 {
00371         LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
00372         if(info)
00373         {
00374                 info->grantRights(LLRelationship::GRANT_MODIFY_OBJECTS, 0);
00375                 mModifyMask |= LLFriendObserver::POWERS;
00376         }
00377 }
00378 
00379 bool LLAvatarTracker::isBuddyEmpowered(const LLUUID& id) const
00380 {
00381         LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
00382         if(info)
00383         {
00384                 return info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
00385         }
00386         return false;
00387 }
00388 
00389 void LLAvatarTracker::empower(const LLUUID& id, bool grant)
00390 {
00391         
00392         buddy_map_t list;
00393         
00394 
00395 
00396 
00397 }
00398 
00399 void LLAvatarTracker::empowerList(const buddy_map_t& list, bool grant)
00400 {
00401         llwarns << "LLAvatarTracker::empowerList() not implemented." << llendl;
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 }
00453 
00454 void LLAvatarTracker::deleteTrackingData()
00455 {
00456         delete mTrackingData;
00457         mTrackingData = NULL;
00458 }
00459 
00460 void LLAvatarTracker::findAgent()
00461 {
00462         if (!mTrackingData) return;
00463         if (mTrackingData->mAvatarID.isNull()) return;
00464         LLMessageSystem* msg = gMessageSystem;
00465         msg->newMessageFast(_PREHASH_FindAgent); 
00466         msg->nextBlockFast(_PREHASH_AgentBlock);
00467         msg->addUUIDFast(_PREHASH_Hunter, gAgentID);
00468         msg->addUUIDFast(_PREHASH_Prey, mTrackingData->mAvatarID);
00469         msg->addU32Fast(_PREHASH_SpaceIP, 0); 
00470         msg->nextBlockFast(_PREHASH_LocationBlock);
00471         const F64 NO_LOCATION = 0.0;
00472         msg->addF64Fast(_PREHASH_GlobalX, NO_LOCATION);
00473         msg->addF64Fast(_PREHASH_GlobalY, NO_LOCATION);
00474         gAgent.sendReliableMessage();
00475 }
00476 
00477 void LLAvatarTracker::addObserver(LLFriendObserver* observer)
00478 {
00479         if(observer)
00480         {
00481                 mObservers.push_back(observer);
00482         }
00483 }
00484 
00485 void LLAvatarTracker::removeObserver(LLFriendObserver* observer)
00486 {
00487         mObservers.erase(
00488                 std::remove(mObservers.begin(), mObservers.end(), observer),
00489                 mObservers.end());
00490 }
00491 
00492 void LLAvatarTracker::notifyObservers()
00493 {
00494         observer_list_t observers(mObservers);
00495         observer_list_t::iterator it = observers.begin();
00496         observer_list_t::iterator end = observers.end();
00497         for(; it != end; ++it)
00498         {
00499                 (*it)->changed(mModifyMask);
00500         }
00501         mModifyMask = LLFriendObserver::NONE;
00502 }
00503 
00504 void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f)
00505 {
00506         buddy_map_t::iterator it = mBuddyInfo.begin();
00507         buddy_map_t::iterator end = mBuddyInfo.end();
00508         for(; it != end; ++it)
00509         {
00510                 f((*it).first, (*it).second);
00511         }
00512 }
00513 
00514 void LLAvatarTracker::registerCallbacks(LLMessageSystem* msg)
00515 {
00516         msg->setHandlerFuncFast(_PREHASH_FindAgent, processAgentFound);
00517         msg->setHandlerFuncFast(_PREHASH_OnlineNotification,
00518                                                 processOnlineNotification);
00519         msg->setHandlerFuncFast(_PREHASH_OfflineNotification,
00520                                                 processOfflineNotification);
00521         
00522         
00523         msg->setHandlerFunc("TerminateFriendship", processTerminateFriendship);
00524         msg->setHandlerFunc(_PREHASH_ChangeUserRights, processChangeUserRights);
00525 }
00526 
00527 
00528 void LLAvatarTracker::processAgentFound(LLMessageSystem* msg, void**)
00529 {
00530         LLUUID id;
00531 
00532         
00533         msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Hunter, id);
00534         msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Prey, id);
00535         
00536         LLVector3d estimated_global_pos;
00537         msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalX,
00538                                  estimated_global_pos.mdV[VX]);
00539         msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalY,
00540                                  estimated_global_pos.mdV[VY]);
00541         LLAvatarTracker::instance().agentFound(id, estimated_global_pos);
00542 }
00543 
00544 void LLAvatarTracker::agentFound(const LLUUID& prey,
00545                                                                  const LLVector3d& estimated_global_pos)
00546 {
00547         if(!mTrackingData) return;
00548         
00549         
00550         LLAvatarTracker::instance().setTrackedAgentValid(true);
00551         mTrackingData->agentFound(prey, estimated_global_pos);
00552 }
00553 
00554 
00555 void LLAvatarTracker::processOnlineNotification(LLMessageSystem* msg, void**)
00556 {
00557         lldebugs << "LLAvatarTracker::processOnlineNotification()" << llendl;
00558         instance().processNotify(msg, true);
00559 }
00560 
00561 
00562 void LLAvatarTracker::processOfflineNotification(LLMessageSystem* msg, void**)
00563 {
00564         lldebugs << "LLAvatarTracker::processOfflineNotification()" << llendl;
00565         instance().processNotify(msg, false);
00566 }
00567 
00568 void LLAvatarTracker::processChange(LLMessageSystem* msg)
00569 {
00570         S32 count = msg->getNumberOfBlocksFast(_PREHASH_Rights);
00571         LLUUID agent_id, agent_related;
00572         S32 new_rights;
00573         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
00574         for(int i = 0; i < count; ++i)
00575         {
00576                 msg->getUUIDFast(_PREHASH_Rights, _PREHASH_AgentRelated, agent_related, i);
00577                 msg->getS32Fast(_PREHASH_Rights,_PREHASH_RelatedRights, new_rights, i);
00578                 if(agent_id == gAgent.getID())
00579                 {
00580                         if(mBuddyInfo.find(agent_related) != mBuddyInfo.end())
00581                         {
00582                                 (mBuddyInfo[agent_related])->setRightsTo(new_rights);
00583                         }
00584                 }
00585                 else
00586                 {
00587                         if(mBuddyInfo.find(agent_id) != mBuddyInfo.end())
00588                         {
00589                                 if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^  new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
00590                                 {
00591                                         char first[DB_FIRST_NAME_BUF_SIZE];             
00592                                         char last[DB_LAST_NAME_BUF_SIZE];               
00593                                         LLStringBase<char>::format_map_t args;
00594                                         if(gCacheName->getName(agent_id, first, last))
00595                                         {
00596                                                 args["[FIRST_NAME]"] = first;
00597                                                 args["[LAST_NAME]"] = last;     
00598                                         }
00599                                         if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
00600                                         {
00601                                                 gViewerWindow->alertXml("GrantedModifyRights",args);
00602                                         }
00603                                         else
00604                                         {
00605                                                 gViewerWindow->alertXml("RevokedModifyRights",args);
00606                                         }
00607                                 }
00608                                 (mBuddyInfo[agent_id])->setRightsFrom(new_rights);
00609                         }
00610                 }
00611         }
00612         mModifyMask |= LLFriendObserver::POWERS;
00613 
00614         notifyObservers();
00615 }
00616 
00617 void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**)
00618 {
00619         lldebugs << "LLAvatarTracker::processChangeUserRights()" << llendl;
00620         instance().processChange(msg);
00621 }
00622 
00623 void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
00624 {
00625         S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock);
00626         BOOL chat_notify = gSavedSettings.getBOOL("ChatOnlineNotification");
00627 
00628         lldebugs << "Received " << count << " online notifications **** " << llendl;
00629         if(count > 0)
00630         {
00631                 LLUUID agent_id;
00632                 const LLRelationship* info = NULL;
00633                 LLUUID tracking_id;
00634                 if(mTrackingData)
00635                 {
00636                         tracking_id = mTrackingData->mAvatarID;
00637                 }
00638                 BOOL notify = FALSE;
00639                 LLString::format_map_t args;
00640                 for(S32 i = 0; i < count; ++i)
00641                 {
00642                         msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_AgentID, agent_id, i);
00643                         info = getBuddyInfo(agent_id);
00644                         if(info)
00645                         {
00646                                 setBuddyOnline(agent_id,online);
00647                                 if(chat_notify)
00648                                 {
00649                                         char first[DB_FIRST_NAME_BUF_SIZE];             
00650                                         char last[DB_LAST_NAME_BUF_SIZE];               
00651                                         if(gCacheName->getName(agent_id, first, last))
00652                                         {
00653                                                 notify = TRUE;
00654                                                 args["[FIRST]"] = first;
00655                                                 args["[LAST]"] = last;
00656                                         }
00657                                 }
00658                         }
00659                         else
00660                         {
00661                                 llwarns << "Received online notification for unknown buddy: " 
00662                                         << agent_id << " is " << (online ? "ONLINE" : "OFFLINE") << llendl;
00663                         }
00664 
00665                         if(tracking_id == agent_id)
00666                         {
00667                                 
00668                                 deleteTrackingData();
00669                         }
00670                         
00671                         gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null);
00672                 }
00673                 if(notify)
00674                 {
00675                         LLNotifyBox::showXml(online ? "FriendOnline" : "FriendOffline", args);
00676                 }
00677 
00678                 mModifyMask |= LLFriendObserver::ONLINE;
00679                 instance().notifyObservers();
00680                 gInventory.notifyObservers();
00681         }
00682 }
00683 
00684 void LLAvatarTracker::formFriendship(const LLUUID& id)
00685 {
00686         if(id.notNull())
00687         {
00688                 LLRelationship* buddy_info = get_ptr_in_map(instance().mBuddyInfo, id);
00689                 if(!buddy_info)
00690                 {
00691                         LLAvatarTracker& at = LLAvatarTracker::instance();
00692                         
00693                         
00694                         buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false);
00695                         at.mBuddyInfo[id] = buddy_info;
00696                         at.mModifyMask |= LLFriendObserver::ADD;
00697                         at.notifyObservers();
00698                 }
00699         }
00700 }
00701 
00702 void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**)
00703 {
00704         LLUUID id;
00705         msg->getUUID("ExBlock", "OtherID", id);
00706         if(id.notNull())
00707         {
00708                 LLAvatarTracker& at = LLAvatarTracker::instance();
00709                 LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id);
00710                 if(!buddy) return;
00711                 at.mBuddyInfo.erase(id);
00712                 at.mModifyMask |= LLFriendObserver::REMOVE;
00713                 delete buddy;
00714                 at.notifyObservers();
00715         }
00716 }
00717 
00721 
00722 LLTrackingData::LLTrackingData(const LLUUID& avatar_id, const std::string& name)
00723 :       mAvatarID(avatar_id),
00724         mHaveInfo(false),
00725         mHaveCoarseInfo(false)
00726 {
00727         mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
00728         mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
00729         mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
00730         if(!name.empty())
00731         {
00732                 mName = name;
00733         }
00734 }
00735 
00736 void LLTrackingData::agentFound(const LLUUID& prey,
00737                                                                 const LLVector3d& estimated_global_pos)
00738 {
00739         if(prey != mAvatarID)
00740         {
00741                 llwarns << "LLTrackingData::agentFound() - found " << prey
00742                                 << " but looking for " << mAvatarID << llendl;
00743         }
00744         mHaveInfo = true;
00745         mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
00746         mGlobalPositionEstimate = estimated_global_pos;
00747 }
00748 
00749 bool LLTrackingData::haveTrackingInfo()
00750 {
00751         LLViewerObject* object = gObjectList.findObject(mAvatarID);
00752         if(object && !object->isDead())
00753         {
00754                 mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY);
00755                 mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
00756                 mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
00757                 mHaveInfo = true;
00758                 return true;
00759         }
00760         if(mHaveCoarseInfo &&
00761            !mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY))
00762         {
00763                 
00764                 mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
00765                 mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
00766                 return true;
00767         }
00768         if(mUpdateTimer.checkExpirationAndReset(FIND_FREQUENCY))
00769         {
00770                 LLAvatarTracker::instance().findAgent();
00771                 mHaveCoarseInfo = false;
00772         }
00773         if(mAgentGone.checkExpirationAndReset(OFFLINE_SECONDS))
00774         {
00775                 mHaveInfo = false;
00776                 mHaveCoarseInfo = false;
00777         }
00778         return mHaveInfo;
00779 }
00780 
00781 void LLTrackingData::setTrackedCoarseLocation(const LLVector3d& global_pos)
00782 {
00783         mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
00784         mGlobalPositionEstimate = global_pos;
00785         mHaveInfo = true;
00786         mHaveCoarseInfo = true;
00787 }
00788 
00790 
00792 
00793 bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
00794 {
00795         if(buddy->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS))
00796         {
00797                 mProxy.insert(buddy_id);
00798         }
00799         return true;
00800 }
00801 
00802 bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
00803 {
00804         mFirst[0] = '\0';
00805         mLast[0] = '\0';
00806         gCacheName->getName(buddy_id, mFirst, mLast);
00807         std::ostringstream fullname;
00808         fullname << mFirst << " " << mLast;
00809         buddy_map_t::value_type value(fullname.str(), buddy_id);
00810         if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION))
00811         {
00812                 mMappable.insert(value);
00813         }
00814         return true;
00815 }
00816 
00817 bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
00818 {
00819         mFirst[0] = '\0';
00820         mLast[0] = '\0';
00821         gCacheName->getName(buddy_id, mFirst, mLast);
00822         std::ostringstream fullname;
00823         fullname << mFirst << " " << mLast;
00824         buddy_map_t::value_type value(fullname.str(), buddy_id);
00825         if(buddy->isOnline())
00826         {
00827                 mOnline.insert(value);
00828         }
00829         return true;
00830 }
00831 
00832 bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
00833 {
00834         mFirst[0] = '\0';
00835         mLast[0] = '\0';
00836         gCacheName->getName(buddy_id, mFirst, mLast);
00837         std::ostringstream fullname;
00838         fullname << mFirst << " " << mLast;
00839         buddy_map_t::value_type value(fullname.str(), buddy_id);
00840         if(buddy->isOnline())
00841         {
00842                 mOnline.insert(value);
00843         }
00844         else
00845         {
00846                 mOffline.insert(value);
00847         }
00848         return true;
00849 }
00850 
00851