diff options
| author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
|---|---|---|
| committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
| commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
| tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llcallingcard.cpp | |
| parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
| parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (diff) | |
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts:
# autobuild.xml
# indra/cmake/CMakeLists.txt
# indra/cmake/GoogleMock.cmake
# indra/llaudio/llaudioengine_fmodstudio.cpp
# indra/llaudio/llaudioengine_fmodstudio.h
# indra/llaudio/lllistener_fmodstudio.cpp
# indra/llaudio/lllistener_fmodstudio.h
# indra/llaudio/llstreamingaudio_fmodstudio.cpp
# indra/llaudio/llstreamingaudio_fmodstudio.h
# indra/llcharacter/llmultigesture.cpp
# indra/llcharacter/llmultigesture.h
# indra/llimage/llimage.cpp
# indra/llimage/llimagepng.cpp
# indra/llimage/llimageworker.cpp
# indra/llimage/tests/llimageworker_test.cpp
# indra/llmessage/tests/llmockhttpclient.h
# indra/llprimitive/llgltfmaterial.h
# indra/llrender/llfontfreetype.cpp
# indra/llui/llcombobox.cpp
# indra/llui/llfolderview.cpp
# indra/llui/llfolderviewmodel.h
# indra/llui/lllineeditor.cpp
# indra/llui/lllineeditor.h
# indra/llui/lltextbase.cpp
# indra/llui/lltextbase.h
# indra/llui/lltexteditor.cpp
# indra/llui/lltextvalidate.cpp
# indra/llui/lltextvalidate.h
# indra/llui/lluictrl.h
# indra/llui/llview.cpp
# indra/llwindow/llwindowmacosx.cpp
# indra/newview/app_settings/settings.xml
# indra/newview/llappearancemgr.cpp
# indra/newview/llappearancemgr.h
# indra/newview/llavatarpropertiesprocessor.cpp
# indra/newview/llavatarpropertiesprocessor.h
# indra/newview/llbreadcrumbview.cpp
# indra/newview/llbreadcrumbview.h
# indra/newview/llbreastmotion.cpp
# indra/newview/llbreastmotion.h
# indra/newview/llconversationmodel.h
# indra/newview/lldensityctrl.cpp
# indra/newview/lldensityctrl.h
# indra/newview/llface.inl
# indra/newview/llfloatereditsky.cpp
# indra/newview/llfloatereditwater.cpp
# indra/newview/llfloateremojipicker.h
# indra/newview/llfloaterimsessiontab.cpp
# indra/newview/llfloaterprofiletexture.cpp
# indra/newview/llfloaterprofiletexture.h
# indra/newview/llgesturemgr.cpp
# indra/newview/llgesturemgr.h
# indra/newview/llimpanel.cpp
# indra/newview/llimpanel.h
# indra/newview/llinventorybridge.cpp
# indra/newview/llinventorybridge.h
# indra/newview/llinventoryclipboard.cpp
# indra/newview/llinventoryclipboard.h
# indra/newview/llinventoryfunctions.cpp
# indra/newview/llinventoryfunctions.h
# indra/newview/llinventorygallery.cpp
# indra/newview/lllistbrowser.cpp
# indra/newview/lllistbrowser.h
# indra/newview/llpanelobjectinventory.cpp
# indra/newview/llpanelprofile.cpp
# indra/newview/llpanelprofile.h
# indra/newview/llpreviewgesture.cpp
# indra/newview/llsavedsettingsglue.cpp
# indra/newview/llsavedsettingsglue.h
# indra/newview/lltooldraganddrop.cpp
# indra/newview/llurllineeditorctrl.cpp
# indra/newview/llvectorperfoptions.cpp
# indra/newview/llvectorperfoptions.h
# indra/newview/llviewerparceloverlay.cpp
# indra/newview/llviewertexlayer.cpp
# indra/newview/llviewertexturelist.cpp
# indra/newview/macmain.h
# indra/test/test.cpp
Diffstat (limited to 'indra/newview/llcallingcard.cpp')
| -rw-r--r-- | indra/newview/llcallingcard.cpp | 1850 |
1 files changed, 925 insertions, 925 deletions
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 9396be0a4e..5db62086b4 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -1,925 +1,925 @@ -/** - * @file llcallingcard.cpp - * @brief Implementation of the LLPreviewCallingCard class - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#if LL_WINDOWS -#pragma warning( disable : 4800 ) // performance warning in <functional> -#endif - -#include "llcallingcard.h" - -#include <algorithm> - -#include "indra_constants.h" -//#include "llcachename.h" -#include "llstl.h" -#include "lltimer.h" -#include "lluuid.h" -#include "message.h" - -#include "llagent.h" -#include "llavatarnamecache.h" -#include "llinventoryobserver.h" -#include "llinventorymodel.h" -#include "llnotifications.h" -#include "llslurl.h" -#include "llimview.h" -#include "lltrans.h" -#include "llviewercontrol.h" -#include "llviewerobjectlist.h" -#include "llvoavatar.h" -#include "llavataractions.h" -#include "lluiusage.h" - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -class LLTrackingData -{ -public: - LLTrackingData(const LLUUID& avatar_id, const std::string& name); - bool haveTrackingInfo(); - void setTrackedCoarseLocation(const LLVector3d& global_pos); - void agentFound(const LLUUID& prey, - const LLVector3d& estimated_global_pos); - -public: - LLUUID mAvatarID; - std::string mName; - LLVector3d mGlobalPositionEstimate; - bool mHaveInfo; - bool mHaveCoarseInfo; - LLTimer mCoarseLocationTimer; - LLTimer mUpdateTimer; - LLTimer mAgentGone; -}; - -const F32 COARSE_FREQUENCY = 2.2f; -const F32 FIND_FREQUENCY = 29.7f; // This results in a database query, so cut these back -const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f; - -// static -LLAvatarTracker LLAvatarTracker::sInstance; - -static void on_avatar_name_cache_notify(const LLUUID& agent_id, - const LLAvatarName& av_name, - bool online, - LLSD payload); - -///---------------------------------------------------------------------------- -/// Class LLAvatarTracker -///---------------------------------------------------------------------------- - -LLAvatarTracker::LLAvatarTracker() : - mTrackingData(NULL), - mTrackedAgentValid(false), - mModifyMask(0x0), - mIsNotifyObservers(false) -{ -} - -LLAvatarTracker::~LLAvatarTracker() -{ - deleteTrackingData(); - std::for_each(mObservers.begin(), mObservers.end(), DeletePointer()); - mObservers.clear(); - std::for_each(mBuddyInfo.begin(), mBuddyInfo.end(), DeletePairedPointer()); - mBuddyInfo.clear(); -} - -void LLAvatarTracker::track(const LLUUID& avatar_id, const std::string& name) -{ - deleteTrackingData(); - mTrackedAgentValid = false; - mTrackingData = new LLTrackingData(avatar_id, name); - findAgent(); - - // We track here because findAgent() is called on a timer (for now). - if(avatar_id.notNull()) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_TrackAgent); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TargetData); - msg->addUUIDFast(_PREHASH_PreyID, avatar_id); - gAgent.sendReliableMessage(); - } -} - -void LLAvatarTracker::untrack(const LLUUID& avatar_id) -{ - if (mTrackingData && mTrackingData->mAvatarID == avatar_id) - { - deleteTrackingData(); - mTrackedAgentValid = false; - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_TrackAgent); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TargetData); - msg->addUUIDFast(_PREHASH_PreyID, LLUUID::null); - gAgent.sendReliableMessage(); - } -} - -void LLAvatarTracker::setTrackedCoarseLocation(const LLVector3d& global_pos) -{ - if(mTrackingData) - { - mTrackingData->setTrackedCoarseLocation(global_pos); - } -} - -bool LLAvatarTracker::haveTrackingInfo() -{ - if(mTrackingData) - { - return mTrackingData->haveTrackingInfo(); - } - return false; -} - -LLVector3d LLAvatarTracker::getGlobalPos() -{ - if(!mTrackedAgentValid || !mTrackingData) return LLVector3d(); - LLVector3d global_pos; - - LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID); - if(object && !object->isDead()) - { - global_pos = object->getPositionGlobal(); - // HACK - for making the tracker point above the avatar's head - // rather than its groin - LLVOAvatar* av = (LLVOAvatar*)object; - global_pos.mdV[VZ] += 0.7f * (av->mBodySize.mV[VZ] + av->mAvatarOffset.mV[VZ]); - - mTrackingData->mGlobalPositionEstimate = global_pos; - } - else - { - global_pos = mTrackingData->mGlobalPositionEstimate; - } - - return global_pos; -} - -void LLAvatarTracker::getDegreesAndDist(F32& rot, - F64& horiz_dist, - F64& vert_dist) -{ - if(!mTrackingData) return; - - LLVector3d global_pos; - - LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID); - if(object && !object->isDead()) - { - global_pos = object->getPositionGlobal(); - mTrackingData->mGlobalPositionEstimate = global_pos; - } - else - { - global_pos = mTrackingData->mGlobalPositionEstimate; - } - LLVector3d to_vec = global_pos - gAgent.getPositionGlobal(); - horiz_dist = sqrt(to_vec.mdV[VX] * to_vec.mdV[VX] + to_vec.mdV[VY] * to_vec.mdV[VY]); - vert_dist = to_vec.mdV[VZ]; - rot = F32(RAD_TO_DEG * atan2(to_vec.mdV[VY], to_vec.mdV[VX])); -} - -const std::string& LLAvatarTracker::getName() -{ - if(mTrackingData) - { - return mTrackingData->mName; - } - else - { - return LLStringUtil::null; - } -} - -const LLUUID& LLAvatarTracker::getAvatarID() -{ - if(mTrackingData) - { - return mTrackingData->mAvatarID; - } - else - { - return LLUUID::null; - } -} - -S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds) -{ - using namespace std; - - U32 new_buddy_count = 0; - LLUUID agent_id; - for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr) - { - agent_id = (*itr).first; - buddy_map_t::const_iterator existing_buddy = mBuddyInfo.find(agent_id); - if(existing_buddy == mBuddyInfo.end()) - { - ++new_buddy_count; - mBuddyInfo[agent_id] = (*itr).second; - - // pre-request name for notifications? - LLAvatarName av_name; - LLAvatarNameCache::get(agent_id, &av_name); - - addChangedMask(LLFriendObserver::ADD, agent_id); - LL_DEBUGS() << "Added buddy " << agent_id - << ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline") - << ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo() - << ", FROM: " << mBuddyInfo[agent_id]->getRightsGrantedFrom() - << LL_ENDL; - } - else - { - LLRelationship* e_r = (*existing_buddy).second; - LLRelationship* n_r = (*itr).second; - LL_WARNS() << "!! Add buddy for existing buddy: " << agent_id - << " [" << (e_r->isOnline() ? "Online" : "Offline") << "->" << (n_r->isOnline() ? "Online" : "Offline") - << ", " << e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo() - << ", " << e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo() - << "]" << LL_ENDL; - } - } - // do not notify observers here - list can be large so let it be done on idle. - - return new_buddy_count; -} - - -void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const -{ - buddy_map_t::const_iterator it = mBuddyInfo.begin(); - buddy_map_t::const_iterator end = mBuddyInfo.end(); - for(; it != end; ++it) - { - buddies[(*it).first] = (*it).second; - } -} - -void LLAvatarTracker::terminateBuddy(const LLUUID& id) -{ - LL_DEBUGS() << "LLAvatarTracker::terminateBuddy()" << LL_ENDL; - LLUIUsage::instance().logCommand("Agent.TerminateFriendship"); - - LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id); - if(!buddy) return; - mBuddyInfo.erase(id); - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("TerminateFriendship"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("ExBlock"); - msg->addUUID("OtherID", id); - gAgent.sendReliableMessage(); - - addChangedMask(LLFriendObserver::REMOVE, id); - delete buddy; -} - -// get all buddy info -const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const -{ - if(id.isNull()) return NULL; - return get_ptr_in_map(mBuddyInfo, id); -} - -bool LLAvatarTracker::isBuddy(const LLUUID& id) const -{ - LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); - return (info != NULL); -} - -// online status -void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online) -{ - LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); - if(info) - { - info->online(is_online); - addChangedMask(LLFriendObserver::ONLINE, id); - LL_DEBUGS() << "Set buddy " << id << (is_online ? " Online" : " Offline") << LL_ENDL; - } - else - { - LL_WARNS() << "!! No buddy info found for " << id - << ", setting to " << (is_online ? "Online" : "Offline") << LL_ENDL; - } -} - -bool LLAvatarTracker::isBuddyOnline(const LLUUID& id) const -{ - LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); - if(info) - { - return info->isOnline(); - } - return false; -} - -// empowered status -void LLAvatarTracker::setBuddyEmpowered(const LLUUID& id, bool is_empowered) -{ - LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); - if(info) - { - info->grantRights(LLRelationship::GRANT_MODIFY_OBJECTS, 0); - mModifyMask |= LLFriendObserver::POWERS; - } -} - -bool LLAvatarTracker::isBuddyEmpowered(const LLUUID& id) const -{ - LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); - if(info) - { - return info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS); - } - return false; -} - -void LLAvatarTracker::empower(const LLUUID& id, bool grant) -{ - // wrapper for ease of use in some situations. - buddy_map_t list; - /* - list.insert(id); - empowerList(list, grant); - */ -} - -void LLAvatarTracker::empowerList(const buddy_map_t& list, bool grant) -{ - LL_WARNS() << "LLAvatarTracker::empowerList() not implemented." << LL_ENDL; -/* - LLMessageSystem* msg = gMessageSystem; - const char* message_name; - const char* block_name; - const char* field_name; - if(grant) - { - message_name = _PREHASH_GrantModification; - block_name = _PREHASH_EmpoweredBlock; - field_name = _PREHASH_EmpoweredID; - } - else - { - message_name = _PREHASH_RevokeModification; - block_name = _PREHASH_RevokedBlock; - field_name = _PREHASH_RevokedID; - } - - std::string name; - gAgent.buildFullnameAndTitle(name); - - bool start_new_message = true; - buddy_list_t::const_iterator it = list.begin(); - buddy_list_t::const_iterator end = list.end(); - for(; it != end; ++it) - { - if(NULL == get_ptr_in_map(mBuddyInfo, (*it))) continue; - setBuddyEmpowered((*it), grant); - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(message_name); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addStringFast(_PREHASH_GranterName, name); - } - msg->nextBlockFast(block_name); - msg->addUUIDFast(field_name, (*it)); - if(msg->isSendFullFast(block_name)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - } - } - if(!start_new_message) - { - gAgent.sendReliableMessage(); - } -*/ -} - -void LLAvatarTracker::deleteTrackingData() -{ - //make sure mTrackingData never points to freed memory - LLTrackingData* tmp = mTrackingData; - mTrackingData = NULL; - delete tmp; -} - -void LLAvatarTracker::findAgent() -{ - if (!mTrackingData) return; - if (mTrackingData->mAvatarID.isNull()) return; - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_FindAgent); // Request - msg->nextBlockFast(_PREHASH_AgentBlock); - msg->addUUIDFast(_PREHASH_Hunter, gAgentID); - msg->addUUIDFast(_PREHASH_Prey, mTrackingData->mAvatarID); - msg->addU32Fast(_PREHASH_SpaceIP, 0); // will get filled in by simulator - msg->nextBlockFast(_PREHASH_LocationBlock); - const F64 NO_LOCATION = 0.0; - msg->addF64Fast(_PREHASH_GlobalX, NO_LOCATION); - msg->addF64Fast(_PREHASH_GlobalY, NO_LOCATION); - gAgent.sendReliableMessage(); -} - -void LLAvatarTracker::addObserver(LLFriendObserver* observer) -{ - if(observer) - { - mObservers.push_back(observer); - } -} - -void LLAvatarTracker::removeObserver(LLFriendObserver* observer) -{ - mObservers.erase( - std::remove(mObservers.begin(), mObservers.end(), observer), - mObservers.end()); -} - -void LLAvatarTracker::idleNotifyObservers() -{ - if (mModifyMask == LLFriendObserver::NONE && mChangedBuddyIDs.size() == 0) - { - return; - } - notifyObservers(); -} - -void LLAvatarTracker::notifyObservers() -{ - if (mIsNotifyObservers) - { - // Don't allow multiple calls. - // new masks and ids will be processed later from idle. - return; - } - LL_PROFILE_ZONE_SCOPED - mIsNotifyObservers = true; - - observer_list_t observers(mObservers); - observer_list_t::iterator it = observers.begin(); - observer_list_t::iterator end = observers.end(); - for(; it != end; ++it) - { - (*it)->changed(mModifyMask); - } - - for (changed_buddy_t::iterator it = mChangedBuddyIDs.begin(); it != mChangedBuddyIDs.end(); it++) - { - notifyParticularFriendObservers(*it); - } - - mModifyMask = LLFriendObserver::NONE; - mChangedBuddyIDs.clear(); - mIsNotifyObservers = false; -} - -void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer) -{ - if (buddy_id.notNull() && observer) - mParticularFriendObserverMap[buddy_id].insert(observer); -} - -void LLAvatarTracker::removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer) -{ - if (buddy_id.isNull() || !observer) - return; - - observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id); - if(obs_it == mParticularFriendObserverMap.end()) - return; - - obs_it->second.erase(observer); - - // purge empty sets from the map - if (obs_it->second.size() == 0) - mParticularFriendObserverMap.erase(obs_it); -} - -void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id) -{ - observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id); - if(obs_it == mParticularFriendObserverMap.end()) - return; - - // Notify observers interested in buddy_id. - observer_set_t& obs = obs_it->second; - for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ob_it++) - { - (*ob_it)->changed(mModifyMask); - } -} - -// store flag for change -// and id of object change applies to -void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent) -{ - mModifyMask |= mask; - if (referent.notNull()) - { - mChangedBuddyIDs.insert(referent); - } -} - -void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f) -{ - buddy_map_t::iterator it = mBuddyInfo.begin(); - buddy_map_t::iterator end = mBuddyInfo.end(); - for(; it != end; ++it) - { - f((*it).first, (*it).second); - } -} - -void LLAvatarTracker::registerCallbacks(LLMessageSystem* msg) -{ - msg->setHandlerFuncFast(_PREHASH_FindAgent, processAgentFound); - msg->setHandlerFuncFast(_PREHASH_OnlineNotification, - processOnlineNotification); - msg->setHandlerFuncFast(_PREHASH_OfflineNotification, - processOfflineNotification); - //msg->setHandlerFuncFast(_PREHASH_GrantedProxies, - // processGrantedProxies); - msg->setHandlerFunc("TerminateFriendship", processTerminateFriendship); - msg->setHandlerFunc(_PREHASH_ChangeUserRights, processChangeUserRights); -} - -// static -void LLAvatarTracker::processAgentFound(LLMessageSystem* msg, void**) -{ - LLUUID id; - - - msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Hunter, id); - msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Prey, id); - // *FIX: should make sure prey id matches. - LLVector3d estimated_global_pos; - msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalX, - estimated_global_pos.mdV[VX]); - msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalY, - estimated_global_pos.mdV[VY]); - LLAvatarTracker::instance().agentFound(id, estimated_global_pos); -} - -void LLAvatarTracker::agentFound(const LLUUID& prey, - const LLVector3d& estimated_global_pos) -{ - if(!mTrackingData) return; - //if we get a valid reply from the server, that means the agent - //is our friend and mappable, so enable interest list based updates - LLAvatarTracker::instance().setTrackedAgentValid(true); - mTrackingData->agentFound(prey, estimated_global_pos); -} - -// static -void LLAvatarTracker::processOnlineNotification(LLMessageSystem* msg, void**) -{ - LL_DEBUGS() << "LLAvatarTracker::processOnlineNotification()" << LL_ENDL; - instance().processNotify(msg, true); -} - -// static -void LLAvatarTracker::processOfflineNotification(LLMessageSystem* msg, void**) -{ - LL_DEBUGS() << "LLAvatarTracker::processOfflineNotification()" << LL_ENDL; - instance().processNotify(msg, false); -} - -void LLAvatarTracker::processChange(LLMessageSystem* msg) -{ - S32 count = msg->getNumberOfBlocksFast(_PREHASH_Rights); - LLUUID agent_id, agent_related; - S32 new_rights; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); - for(int i = 0; i < count; ++i) - { - msg->getUUIDFast(_PREHASH_Rights, _PREHASH_AgentRelated, agent_related, i); - msg->getS32Fast(_PREHASH_Rights,_PREHASH_RelatedRights, new_rights, i); - if(agent_id == gAgent.getID()) - { - if(mBuddyInfo.find(agent_related) != mBuddyInfo.end()) - { - (mBuddyInfo[agent_related])->setRightsTo(new_rights); - mChangedBuddyIDs.insert(agent_related); - } - } - else - { - if(mBuddyInfo.find(agent_id) != mBuddyInfo.end()) - { - if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)) - { - LLSD args; - args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString(); - - LLSD payload; - payload["from_id"] = agent_id; - if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights) - { - LLNotifications::instance().add("GrantedModifyRights",args, payload); - } - else - { - LLNotifications::instance().add("RevokedModifyRights",args, payload); - } - } - (mBuddyInfo[agent_id])->setRightsFrom(new_rights); - } - } - } - - addChangedMask(LLFriendObserver::POWERS, agent_id); - notifyObservers(); -} - -void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**) -{ - LL_DEBUGS() << "LLAvatarTracker::processChangeUserRights()" << LL_ENDL; - instance().processChange(msg); -} - -void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) -{ - LL_PROFILE_ZONE_SCOPED - S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock); - bool chat_notify = gSavedSettings.getBOOL("ChatOnlineNotification"); - - LL_DEBUGS() << "Received " << count << " online notifications **** " << LL_ENDL; - if(count > 0) - { - LLUUID agent_id; - const LLRelationship* info = NULL; - LLUUID tracking_id; - if(mTrackingData) - { - tracking_id = mTrackingData->mAvatarID; - } - LLSD payload; - for(S32 i = 0; i < count; ++i) - { - msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_AgentID, agent_id, i); - payload["FROM_ID"] = agent_id; - info = getBuddyInfo(agent_id); - if(info) - { - setBuddyOnline(agent_id,online); - } - else - { - LL_WARNS() << "Received online notification for unknown buddy: " - << agent_id << " is " << (online ? "ONLINE" : "OFFLINE") << LL_ENDL; - } - - if(tracking_id == agent_id) - { - // we were tracking someone who went offline - deleteTrackingData(); - } - - if(chat_notify) - { - // Look up the name of this agent for the notification - LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload)); - } - } - - mModifyMask |= LLFriendObserver::ONLINE; - instance().notifyObservers(); - gInventory.notifyObservers(); - } -} - -static void on_avatar_name_cache_notify(const LLUUID& agent_id, - const LLAvatarName& av_name, - bool online, - LLSD payload) -{ - // Popup a notify box with online status of this agent - // Use display name only because this user is your friend - LLSD args; - args["NAME"] = av_name.getDisplayName(); - args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus"); - - LLNotificationPtr notification; - if (online) - { - notification = - LLNotifications::instance().add("FriendOnlineOffline", - args, - payload.with("respond_on_mousedown", true), - boost::bind(&LLAvatarActions::startIM, agent_id)); - } - else - { - notification = - LLNotifications::instance().add("FriendOnlineOffline", args, payload); - } - - // If there's an open IM session with this agent, send a notification there too. - LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id); - std::string notify_msg = notification->getMessage(); - LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg); -} - -void LLAvatarTracker::formFriendship(const LLUUID& id) -{ - if(id.notNull()) - { - LLRelationship* buddy_info = get_ptr_in_map(instance().mBuddyInfo, id); - if(!buddy_info) - { - LLAvatarTracker& at = LLAvatarTracker::instance(); - //The default for relationship establishment is to have both parties - //visible online to each other. - buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false); - at.mBuddyInfo[id] = buddy_info; - at.addChangedMask(LLFriendObserver::ADD, id); - at.notifyObservers(); - } - } -} - -void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**) -{ - LLUUID id; - msg->getUUID("ExBlock", "OtherID", id); - if(id.notNull()) - { - LLAvatarTracker& at = LLAvatarTracker::instance(); - LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id); - if(!buddy) return; - at.mBuddyInfo.erase(id); - at.addChangedMask(LLFriendObserver::REMOVE, id); - delete buddy; - at.notifyObservers(); - } -} - -///---------------------------------------------------------------------------- -/// Tracking Data -///---------------------------------------------------------------------------- - -LLTrackingData::LLTrackingData(const LLUUID& avatar_id, const std::string& name) -: mAvatarID(avatar_id), - mHaveInfo(false), - mHaveCoarseInfo(false) -{ - mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY); - mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY); - mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); - if(!name.empty()) - { - mName = name; - } -} - -void LLTrackingData::agentFound(const LLUUID& prey, - const LLVector3d& estimated_global_pos) -{ - if(prey != mAvatarID) - { - LL_WARNS() << "LLTrackingData::agentFound() - found " << prey - << " but looking for " << mAvatarID << LL_ENDL; - } - mHaveInfo = true; - mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); - mGlobalPositionEstimate = estimated_global_pos; -} - -bool LLTrackingData::haveTrackingInfo() -{ - LLViewerObject* object = gObjectList.findObject(mAvatarID); - if(object && !object->isDead()) - { - mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY); - mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY); - mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); - mHaveInfo = true; - return true; - } - if(mHaveCoarseInfo && - !mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY)) - { - // if we reach here, then we have a 'recent' coarse update - mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY); - mAgentGone.setTimerExpirySec(OFFLINE_SECONDS); - return true; - } - if(mUpdateTimer.checkExpirationAndReset(FIND_FREQUENCY)) - { - LLAvatarTracker::instance().findAgent(); - mHaveCoarseInfo = false; - } - if(mAgentGone.checkExpirationAndReset(OFFLINE_SECONDS)) - { - mHaveInfo = false; - mHaveCoarseInfo = false; - } - return mHaveInfo; -} - -void LLTrackingData::setTrackedCoarseLocation(const LLVector3d& global_pos) -{ - mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY); - mGlobalPositionEstimate = global_pos; - mHaveInfo = true; - mHaveCoarseInfo = true; -} - -///---------------------------------------------------------------------------- -// various buddy functors -///---------------------------------------------------------------------------- - -bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) -{ - if(buddy->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS)) - { - mProxy.insert(buddy_id); - } - return true; -} - -bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) -{ - LLAvatarName av_name; - LLAvatarNameCache::get( buddy_id, &av_name); - buddy_map_t::value_type value(buddy_id, av_name.getDisplayName()); - if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)) - { - mMappable.insert(value); - } - return true; -} - -bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) -{ - LLAvatarName av_name; - LLAvatarNameCache::get(buddy_id, &av_name); - mFullName = av_name.getUserName(); - buddy_map_t::value_type value(buddy_id, mFullName); - if(buddy->isOnline()) - { - mOnline.insert(value); - } - return true; -} - -bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy) -{ - LLAvatarName av_name; - LLAvatarNameCache::get(buddy_id, &av_name); - mFullName = av_name.getCompleteName(); - buddy_map_t::value_type value(buddy_id, mFullName); - if(buddy->isOnline()) - { - mOnline.insert(value); - } - else - { - mOffline.insert(value); - } - return true; -} +/**
+ * @file llcallingcard.cpp
+ * @brief Implementation of the LLPreviewCallingCard class
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#if LL_WINDOWS
+#pragma warning( disable : 4800 ) // performance warning in <functional>
+#endif
+
+#include "llcallingcard.h"
+
+#include <algorithm>
+
+#include "indra_constants.h"
+//#include "llcachename.h"
+#include "llstl.h"
+#include "lltimer.h"
+#include "lluuid.h"
+#include "message.h"
+
+#include "llagent.h"
+#include "llavatarnamecache.h"
+#include "llinventoryobserver.h"
+#include "llinventorymodel.h"
+#include "llnotifications.h"
+#include "llslurl.h"
+#include "llimview.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llavataractions.h"
+#include "lluiusage.h"
+
+///----------------------------------------------------------------------------
+/// Local function declarations, constants, enums, and typedefs
+///----------------------------------------------------------------------------
+
+class LLTrackingData
+{
+public:
+ LLTrackingData(const LLUUID& avatar_id, const std::string& name);
+ bool haveTrackingInfo();
+ void setTrackedCoarseLocation(const LLVector3d& global_pos);
+ void agentFound(const LLUUID& prey,
+ const LLVector3d& estimated_global_pos);
+
+public:
+ LLUUID mAvatarID;
+ std::string mName;
+ LLVector3d mGlobalPositionEstimate;
+ bool mHaveInfo;
+ bool mHaveCoarseInfo;
+ LLTimer mCoarseLocationTimer;
+ LLTimer mUpdateTimer;
+ LLTimer mAgentGone;
+};
+
+const F32 COARSE_FREQUENCY = 2.2f;
+const F32 FIND_FREQUENCY = 29.7f; // This results in a database query, so cut these back
+const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
+
+// static
+LLAvatarTracker LLAvatarTracker::sInstance;
+
+static void on_avatar_name_cache_notify(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ bool online,
+ LLSD payload);
+
+///----------------------------------------------------------------------------
+/// Class LLAvatarTracker
+///----------------------------------------------------------------------------
+
+LLAvatarTracker::LLAvatarTracker() :
+ mTrackingData(NULL),
+ mTrackedAgentValid(false),
+ mModifyMask(0x0),
+ mIsNotifyObservers(false)
+{
+}
+
+LLAvatarTracker::~LLAvatarTracker()
+{
+ deleteTrackingData();
+ std::for_each(mObservers.begin(), mObservers.end(), DeletePointer());
+ mObservers.clear();
+ std::for_each(mBuddyInfo.begin(), mBuddyInfo.end(), DeletePairedPointer());
+ mBuddyInfo.clear();
+}
+
+void LLAvatarTracker::track(const LLUUID& avatar_id, const std::string& name)
+{
+ deleteTrackingData();
+ mTrackedAgentValid = false;
+ mTrackingData = new LLTrackingData(avatar_id, name);
+ findAgent();
+
+ // We track here because findAgent() is called on a timer (for now).
+ if(avatar_id.notNull())
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_TrackAgent);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_TargetData);
+ msg->addUUIDFast(_PREHASH_PreyID, avatar_id);
+ gAgent.sendReliableMessage();
+ }
+}
+
+void LLAvatarTracker::untrack(const LLUUID& avatar_id)
+{
+ if (mTrackingData && mTrackingData->mAvatarID == avatar_id)
+ {
+ deleteTrackingData();
+ mTrackedAgentValid = false;
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_TrackAgent);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_TargetData);
+ msg->addUUIDFast(_PREHASH_PreyID, LLUUID::null);
+ gAgent.sendReliableMessage();
+ }
+}
+
+void LLAvatarTracker::setTrackedCoarseLocation(const LLVector3d& global_pos)
+{
+ if(mTrackingData)
+ {
+ mTrackingData->setTrackedCoarseLocation(global_pos);
+ }
+}
+
+bool LLAvatarTracker::haveTrackingInfo()
+{
+ if(mTrackingData)
+ {
+ return mTrackingData->haveTrackingInfo();
+ }
+ return false;
+}
+
+LLVector3d LLAvatarTracker::getGlobalPos()
+{
+ if(!mTrackedAgentValid || !mTrackingData) return LLVector3d();
+ LLVector3d global_pos;
+
+ LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID);
+ if(object && !object->isDead())
+ {
+ global_pos = object->getPositionGlobal();
+ // HACK - for making the tracker point above the avatar's head
+ // rather than its groin
+ LLVOAvatar* av = (LLVOAvatar*)object;
+ global_pos.mdV[VZ] += 0.7f * (av->mBodySize.mV[VZ] + av->mAvatarOffset.mV[VZ]);
+
+ mTrackingData->mGlobalPositionEstimate = global_pos;
+ }
+ else
+ {
+ global_pos = mTrackingData->mGlobalPositionEstimate;
+ }
+
+ return global_pos;
+}
+
+void LLAvatarTracker::getDegreesAndDist(F32& rot,
+ F64& horiz_dist,
+ F64& vert_dist)
+{
+ if(!mTrackingData) return;
+
+ LLVector3d global_pos;
+
+ LLViewerObject* object = gObjectList.findObject(mTrackingData->mAvatarID);
+ if(object && !object->isDead())
+ {
+ global_pos = object->getPositionGlobal();
+ mTrackingData->mGlobalPositionEstimate = global_pos;
+ }
+ else
+ {
+ global_pos = mTrackingData->mGlobalPositionEstimate;
+ }
+ LLVector3d to_vec = global_pos - gAgent.getPositionGlobal();
+ horiz_dist = sqrt(to_vec.mdV[VX] * to_vec.mdV[VX] + to_vec.mdV[VY] * to_vec.mdV[VY]);
+ vert_dist = to_vec.mdV[VZ];
+ rot = F32(RAD_TO_DEG * atan2(to_vec.mdV[VY], to_vec.mdV[VX]));
+}
+
+const std::string& LLAvatarTracker::getName()
+{
+ if(mTrackingData)
+ {
+ return mTrackingData->mName;
+ }
+ else
+ {
+ return LLStringUtil::null;
+ }
+}
+
+const LLUUID& LLAvatarTracker::getAvatarID()
+{
+ if(mTrackingData)
+ {
+ return mTrackingData->mAvatarID;
+ }
+ else
+ {
+ return LLUUID::null;
+ }
+}
+
+S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
+{
+ using namespace std;
+
+ U32 new_buddy_count = 0;
+ LLUUID agent_id;
+ for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr)
+ {
+ agent_id = (*itr).first;
+ buddy_map_t::const_iterator existing_buddy = mBuddyInfo.find(agent_id);
+ if(existing_buddy == mBuddyInfo.end())
+ {
+ ++new_buddy_count;
+ mBuddyInfo[agent_id] = (*itr).second;
+
+ // pre-request name for notifications?
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(agent_id, &av_name);
+
+ addChangedMask(LLFriendObserver::ADD, agent_id);
+ LL_DEBUGS() << "Added buddy " << agent_id
+ << ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
+ << ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo()
+ << ", FROM: " << mBuddyInfo[agent_id]->getRightsGrantedFrom()
+ << LL_ENDL;
+ }
+ else
+ {
+ LLRelationship* e_r = (*existing_buddy).second;
+ LLRelationship* n_r = (*itr).second;
+ LL_WARNS() << "!! Add buddy for existing buddy: " << agent_id
+ << " [" << (e_r->isOnline() ? "Online" : "Offline") << "->" << (n_r->isOnline() ? "Online" : "Offline")
+ << ", " << e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo()
+ << ", " << e_r->getRightsGrantedTo() << "->" << n_r->getRightsGrantedTo()
+ << "]" << LL_ENDL;
+ }
+ }
+ // do not notify observers here - list can be large so let it be done on idle.
+
+ return new_buddy_count;
+}
+
+
+void LLAvatarTracker::copyBuddyList(buddy_map_t& buddies) const
+{
+ buddy_map_t::const_iterator it = mBuddyInfo.begin();
+ buddy_map_t::const_iterator end = mBuddyInfo.end();
+ for(; it != end; ++it)
+ {
+ buddies[(*it).first] = (*it).second;
+ }
+}
+
+void LLAvatarTracker::terminateBuddy(const LLUUID& id)
+{
+ LL_DEBUGS() << "LLAvatarTracker::terminateBuddy()" << LL_ENDL;
+ LLUIUsage::instance().logCommand("Agent.TerminateFriendship");
+
+ LLRelationship* buddy = get_ptr_in_map(mBuddyInfo, id);
+ if(!buddy) return;
+ mBuddyInfo.erase(id);
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("TerminateFriendship");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("ExBlock");
+ msg->addUUID("OtherID", id);
+ gAgent.sendReliableMessage();
+
+ addChangedMask(LLFriendObserver::REMOVE, id);
+ delete buddy;
+}
+
+// get all buddy info
+const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const
+{
+ if(id.isNull()) return NULL;
+ return get_ptr_in_map(mBuddyInfo, id);
+}
+
+bool LLAvatarTracker::isBuddy(const LLUUID& id) const
+{
+ LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
+ return (info != NULL);
+}
+
+// online status
+void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
+{
+ LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
+ if(info)
+ {
+ info->online(is_online);
+ addChangedMask(LLFriendObserver::ONLINE, id);
+ LL_DEBUGS() << "Set buddy " << id << (is_online ? " Online" : " Offline") << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "!! No buddy info found for " << id
+ << ", setting to " << (is_online ? "Online" : "Offline") << LL_ENDL;
+ }
+}
+
+bool LLAvatarTracker::isBuddyOnline(const LLUUID& id) const
+{
+ LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
+ if(info)
+ {
+ return info->isOnline();
+ }
+ return false;
+}
+
+// empowered status
+void LLAvatarTracker::setBuddyEmpowered(const LLUUID& id, bool is_empowered)
+{
+ LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
+ if(info)
+ {
+ info->grantRights(LLRelationship::GRANT_MODIFY_OBJECTS, 0);
+ mModifyMask |= LLFriendObserver::POWERS;
+ }
+}
+
+bool LLAvatarTracker::isBuddyEmpowered(const LLUUID& id) const
+{
+ LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
+ if(info)
+ {
+ return info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS);
+ }
+ return false;
+}
+
+void LLAvatarTracker::empower(const LLUUID& id, bool grant)
+{
+ // wrapper for ease of use in some situations.
+ buddy_map_t list;
+ /*
+ list.insert(id);
+ empowerList(list, grant);
+ */
+}
+
+void LLAvatarTracker::empowerList(const buddy_map_t& list, bool grant)
+{
+ LL_WARNS() << "LLAvatarTracker::empowerList() not implemented." << LL_ENDL;
+/*
+ LLMessageSystem* msg = gMessageSystem;
+ const char* message_name;
+ const char* block_name;
+ const char* field_name;
+ if(grant)
+ {
+ message_name = _PREHASH_GrantModification;
+ block_name = _PREHASH_EmpoweredBlock;
+ field_name = _PREHASH_EmpoweredID;
+ }
+ else
+ {
+ message_name = _PREHASH_RevokeModification;
+ block_name = _PREHASH_RevokedBlock;
+ field_name = _PREHASH_RevokedID;
+ }
+
+ std::string name;
+ gAgent.buildFullnameAndTitle(name);
+
+ bool start_new_message = true;
+ buddy_list_t::const_iterator it = list.begin();
+ buddy_list_t::const_iterator end = list.end();
+ for(; it != end; ++it)
+ {
+ if(NULL == get_ptr_in_map(mBuddyInfo, (*it))) continue;
+ setBuddyEmpowered((*it), grant);
+ if(start_new_message)
+ {
+ start_new_message = false;
+ msg->newMessageFast(message_name);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addStringFast(_PREHASH_GranterName, name);
+ }
+ msg->nextBlockFast(block_name);
+ msg->addUUIDFast(field_name, (*it));
+ if(msg->isSendFullFast(block_name))
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ }
+*/
+}
+
+void LLAvatarTracker::deleteTrackingData()
+{
+ //make sure mTrackingData never points to freed memory
+ LLTrackingData* tmp = mTrackingData;
+ mTrackingData = NULL;
+ delete tmp;
+}
+
+void LLAvatarTracker::findAgent()
+{
+ if (!mTrackingData) return;
+ if (mTrackingData->mAvatarID.isNull()) return;
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_FindAgent); // Request
+ msg->nextBlockFast(_PREHASH_AgentBlock);
+ msg->addUUIDFast(_PREHASH_Hunter, gAgentID);
+ msg->addUUIDFast(_PREHASH_Prey, mTrackingData->mAvatarID);
+ msg->addU32Fast(_PREHASH_SpaceIP, 0); // will get filled in by simulator
+ msg->nextBlockFast(_PREHASH_LocationBlock);
+ const F64 NO_LOCATION = 0.0;
+ msg->addF64Fast(_PREHASH_GlobalX, NO_LOCATION);
+ msg->addF64Fast(_PREHASH_GlobalY, NO_LOCATION);
+ gAgent.sendReliableMessage();
+}
+
+void LLAvatarTracker::addObserver(LLFriendObserver* observer)
+{
+ if(observer)
+ {
+ mObservers.push_back(observer);
+ }
+}
+
+void LLAvatarTracker::removeObserver(LLFriendObserver* observer)
+{
+ mObservers.erase(
+ std::remove(mObservers.begin(), mObservers.end(), observer),
+ mObservers.end());
+}
+
+void LLAvatarTracker::idleNotifyObservers()
+{
+ if (mModifyMask == LLFriendObserver::NONE && mChangedBuddyIDs.size() == 0)
+ {
+ return;
+ }
+ notifyObservers();
+}
+
+void LLAvatarTracker::notifyObservers()
+{
+ if (mIsNotifyObservers)
+ {
+ // Don't allow multiple calls.
+ // new masks and ids will be processed later from idle.
+ return;
+ }
+ LL_PROFILE_ZONE_SCOPED
+ mIsNotifyObservers = true;
+
+ observer_list_t observers(mObservers);
+ observer_list_t::iterator it = observers.begin();
+ observer_list_t::iterator end = observers.end();
+ for(; it != end; ++it)
+ {
+ (*it)->changed(mModifyMask);
+ }
+
+ for (changed_buddy_t::iterator it = mChangedBuddyIDs.begin(); it != mChangedBuddyIDs.end(); it++)
+ {
+ notifyParticularFriendObservers(*it);
+ }
+
+ mModifyMask = LLFriendObserver::NONE;
+ mChangedBuddyIDs.clear();
+ mIsNotifyObservers = false;
+}
+
+void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+ if (buddy_id.notNull() && observer)
+ mParticularFriendObserverMap[buddy_id].insert(observer);
+}
+
+void LLAvatarTracker::removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+ if (buddy_id.isNull() || !observer)
+ return;
+
+ observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+ if(obs_it == mParticularFriendObserverMap.end())
+ return;
+
+ obs_it->second.erase(observer);
+
+ // purge empty sets from the map
+ if (obs_it->second.size() == 0)
+ mParticularFriendObserverMap.erase(obs_it);
+}
+
+void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id)
+{
+ observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+ if(obs_it == mParticularFriendObserverMap.end())
+ return;
+
+ // Notify observers interested in buddy_id.
+ observer_set_t& obs = obs_it->second;
+ for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ob_it++)
+ {
+ (*ob_it)->changed(mModifyMask);
+ }
+}
+
+// store flag for change
+// and id of object change applies to
+void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
+{
+ mModifyMask |= mask;
+ if (referent.notNull())
+ {
+ mChangedBuddyIDs.insert(referent);
+ }
+}
+
+void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f)
+{
+ buddy_map_t::iterator it = mBuddyInfo.begin();
+ buddy_map_t::iterator end = mBuddyInfo.end();
+ for(; it != end; ++it)
+ {
+ f((*it).first, (*it).second);
+ }
+}
+
+void LLAvatarTracker::registerCallbacks(LLMessageSystem* msg)
+{
+ msg->setHandlerFuncFast(_PREHASH_FindAgent, processAgentFound);
+ msg->setHandlerFuncFast(_PREHASH_OnlineNotification,
+ processOnlineNotification);
+ msg->setHandlerFuncFast(_PREHASH_OfflineNotification,
+ processOfflineNotification);
+ //msg->setHandlerFuncFast(_PREHASH_GrantedProxies,
+ // processGrantedProxies);
+ msg->setHandlerFunc("TerminateFriendship", processTerminateFriendship);
+ msg->setHandlerFunc(_PREHASH_ChangeUserRights, processChangeUserRights);
+}
+
+// static
+void LLAvatarTracker::processAgentFound(LLMessageSystem* msg, void**)
+{
+ LLUUID id;
+
+
+ msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Hunter, id);
+ msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_Prey, id);
+ // *FIX: should make sure prey id matches.
+ LLVector3d estimated_global_pos;
+ msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalX,
+ estimated_global_pos.mdV[VX]);
+ msg->getF64Fast(_PREHASH_LocationBlock, _PREHASH_GlobalY,
+ estimated_global_pos.mdV[VY]);
+ LLAvatarTracker::instance().agentFound(id, estimated_global_pos);
+}
+
+void LLAvatarTracker::agentFound(const LLUUID& prey,
+ const LLVector3d& estimated_global_pos)
+{
+ if(!mTrackingData) return;
+ //if we get a valid reply from the server, that means the agent
+ //is our friend and mappable, so enable interest list based updates
+ LLAvatarTracker::instance().setTrackedAgentValid(true);
+ mTrackingData->agentFound(prey, estimated_global_pos);
+}
+
+// static
+void LLAvatarTracker::processOnlineNotification(LLMessageSystem* msg, void**)
+{
+ LL_DEBUGS() << "LLAvatarTracker::processOnlineNotification()" << LL_ENDL;
+ instance().processNotify(msg, true);
+}
+
+// static
+void LLAvatarTracker::processOfflineNotification(LLMessageSystem* msg, void**)
+{
+ LL_DEBUGS() << "LLAvatarTracker::processOfflineNotification()" << LL_ENDL;
+ instance().processNotify(msg, false);
+}
+
+void LLAvatarTracker::processChange(LLMessageSystem* msg)
+{
+ S32 count = msg->getNumberOfBlocksFast(_PREHASH_Rights);
+ LLUUID agent_id, agent_related;
+ S32 new_rights;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ for(int i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_Rights, _PREHASH_AgentRelated, agent_related, i);
+ msg->getS32Fast(_PREHASH_Rights,_PREHASH_RelatedRights, new_rights, i);
+ if(agent_id == gAgent.getID())
+ {
+ if(mBuddyInfo.find(agent_related) != mBuddyInfo.end())
+ {
+ (mBuddyInfo[agent_related])->setRightsTo(new_rights);
+ mChangedBuddyIDs.insert(agent_related);
+ }
+ }
+ else
+ {
+ if(mBuddyInfo.find(agent_id) != mBuddyInfo.end())
+ {
+ if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS))
+ {
+ LLSD args;
+ args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
+
+ LLSD payload;
+ payload["from_id"] = agent_id;
+ if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
+ {
+ LLNotifications::instance().add("GrantedModifyRights",args, payload);
+ }
+ else
+ {
+ LLNotifications::instance().add("RevokedModifyRights",args, payload);
+ }
+ }
+ (mBuddyInfo[agent_id])->setRightsFrom(new_rights);
+ }
+ }
+ }
+
+ addChangedMask(LLFriendObserver::POWERS, agent_id);
+ notifyObservers();
+}
+
+void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**)
+{
+ LL_DEBUGS() << "LLAvatarTracker::processChangeUserRights()" << LL_ENDL;
+ instance().processChange(msg);
+}
+
+void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
+{
+ LL_PROFILE_ZONE_SCOPED
+ S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock);
+ bool chat_notify = gSavedSettings.getBOOL("ChatOnlineNotification");
+
+ LL_DEBUGS() << "Received " << count << " online notifications **** " << LL_ENDL;
+ if(count > 0)
+ {
+ LLUUID agent_id;
+ const LLRelationship* info = NULL;
+ LLUUID tracking_id;
+ if(mTrackingData)
+ {
+ tracking_id = mTrackingData->mAvatarID;
+ }
+ LLSD payload;
+ for(S32 i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_AgentID, agent_id, i);
+ payload["FROM_ID"] = agent_id;
+ info = getBuddyInfo(agent_id);
+ if(info)
+ {
+ setBuddyOnline(agent_id,online);
+ }
+ else
+ {
+ LL_WARNS() << "Received online notification for unknown buddy: "
+ << agent_id << " is " << (online ? "ONLINE" : "OFFLINE") << LL_ENDL;
+ }
+
+ if(tracking_id == agent_id)
+ {
+ // we were tracking someone who went offline
+ deleteTrackingData();
+ }
+
+ if(chat_notify)
+ {
+ // Look up the name of this agent for the notification
+ LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload));
+ }
+ }
+
+ mModifyMask |= LLFriendObserver::ONLINE;
+ instance().notifyObservers();
+ gInventory.notifyObservers();
+ }
+}
+
+static void on_avatar_name_cache_notify(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ bool online,
+ LLSD payload)
+{
+ // Popup a notify box with online status of this agent
+ // Use display name only because this user is your friend
+ LLSD args;
+ args["NAME"] = av_name.getDisplayName();
+ args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus");
+
+ LLNotificationPtr notification;
+ if (online)
+ {
+ notification =
+ LLNotifications::instance().add("FriendOnlineOffline",
+ args,
+ payload.with("respond_on_mousedown", true),
+ boost::bind(&LLAvatarActions::startIM, agent_id));
+ }
+ else
+ {
+ notification =
+ LLNotifications::instance().add("FriendOnlineOffline", args, payload);
+ }
+
+ // If there's an open IM session with this agent, send a notification there too.
+ LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
+ std::string notify_msg = notification->getMessage();
+ LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
+}
+
+void LLAvatarTracker::formFriendship(const LLUUID& id)
+{
+ if(id.notNull())
+ {
+ LLRelationship* buddy_info = get_ptr_in_map(instance().mBuddyInfo, id);
+ if(!buddy_info)
+ {
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ //The default for relationship establishment is to have both parties
+ //visible online to each other.
+ buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false);
+ at.mBuddyInfo[id] = buddy_info;
+ at.addChangedMask(LLFriendObserver::ADD, id);
+ at.notifyObservers();
+ }
+ }
+}
+
+void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**)
+{
+ LLUUID id;
+ msg->getUUID("ExBlock", "OtherID", id);
+ if(id.notNull())
+ {
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id);
+ if(!buddy) return;
+ at.mBuddyInfo.erase(id);
+ at.addChangedMask(LLFriendObserver::REMOVE, id);
+ delete buddy;
+ at.notifyObservers();
+ }
+}
+
+///----------------------------------------------------------------------------
+/// Tracking Data
+///----------------------------------------------------------------------------
+
+LLTrackingData::LLTrackingData(const LLUUID& avatar_id, const std::string& name)
+: mAvatarID(avatar_id),
+ mHaveInfo(false),
+ mHaveCoarseInfo(false)
+{
+ mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
+ mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
+ mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
+ if(!name.empty())
+ {
+ mName = name;
+ }
+}
+
+void LLTrackingData::agentFound(const LLUUID& prey,
+ const LLVector3d& estimated_global_pos)
+{
+ if(prey != mAvatarID)
+ {
+ LL_WARNS() << "LLTrackingData::agentFound() - found " << prey
+ << " but looking for " << mAvatarID << LL_ENDL;
+ }
+ mHaveInfo = true;
+ mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
+ mGlobalPositionEstimate = estimated_global_pos;
+}
+
+bool LLTrackingData::haveTrackingInfo()
+{
+ LLViewerObject* object = gObjectList.findObject(mAvatarID);
+ if(object && !object->isDead())
+ {
+ mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY);
+ mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
+ mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
+ mHaveInfo = true;
+ return true;
+ }
+ if(mHaveCoarseInfo &&
+ !mCoarseLocationTimer.checkExpirationAndReset(COARSE_FREQUENCY))
+ {
+ // if we reach here, then we have a 'recent' coarse update
+ mUpdateTimer.setTimerExpirySec(FIND_FREQUENCY);
+ mAgentGone.setTimerExpirySec(OFFLINE_SECONDS);
+ return true;
+ }
+ if(mUpdateTimer.checkExpirationAndReset(FIND_FREQUENCY))
+ {
+ LLAvatarTracker::instance().findAgent();
+ mHaveCoarseInfo = false;
+ }
+ if(mAgentGone.checkExpirationAndReset(OFFLINE_SECONDS))
+ {
+ mHaveInfo = false;
+ mHaveCoarseInfo = false;
+ }
+ return mHaveInfo;
+}
+
+void LLTrackingData::setTrackedCoarseLocation(const LLVector3d& global_pos)
+{
+ mCoarseLocationTimer.setTimerExpirySec(COARSE_FREQUENCY);
+ mGlobalPositionEstimate = global_pos;
+ mHaveInfo = true;
+ mHaveCoarseInfo = true;
+}
+
+///----------------------------------------------------------------------------
+// various buddy functors
+///----------------------------------------------------------------------------
+
+bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
+{
+ if(buddy->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS))
+ {
+ mProxy.insert(buddy_id);
+ }
+ return true;
+}
+
+bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
+{
+ LLAvatarName av_name;
+ LLAvatarNameCache::get( buddy_id, &av_name);
+ buddy_map_t::value_type value(buddy_id, av_name.getDisplayName());
+ if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION))
+ {
+ mMappable.insert(value);
+ }
+ return true;
+}
+
+bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
+{
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(buddy_id, &av_name);
+ mFullName = av_name.getUserName();
+ buddy_map_t::value_type value(buddy_id, mFullName);
+ if(buddy->isOnline())
+ {
+ mOnline.insert(value);
+ }
+ return true;
+}
+
+bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
+{
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(buddy_id, &av_name);
+ mFullName = av_name.getCompleteName();
+ buddy_map_t::value_type value(buddy_id, mFullName);
+ if(buddy->isOnline())
+ {
+ mOnline.insert(value);
+ }
+ else
+ {
+ mOffline.insert(value);
+ }
+ return true;
+}
|
