From de2ce3f51ff54e67017d765c95264c66211c89da Mon Sep 17 00:00:00 2001 From: Chris Baker Date: Thu, 23 Aug 2012 19:40:10 -0700 Subject: Start of getting WSGI service on viewer --- indra/newview/llgroupmgr.cpp | 91 + indra/newview/llgroupmgr.h | 3 + indra/newview/llpanelgroupgeneral.cpp | 9 +- indra/newview/llpanelgroupinvite.cpp | 9 +- indra/newview/llpanelgrouproles.cpp | 22 +- indra/newview/llviewerregion.cpp | 3739 ++++++++++++++++----------------- 6 files changed, 1997 insertions(+), 1876 deletions(-) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index aceb7f0614..3300034f7f 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1500,6 +1500,10 @@ void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id) } } + + + + void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id) { lldebugs << "LLGroupMgr::sendGroupRoleDataRequest" << llendl; @@ -1832,6 +1836,93 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id, } } + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// STUBBED IN FOR code completion +class GroupMemberDataResponder : public LLHTTPClient::Responder +{ +public: + GroupMemberDataResponder() {} + virtual ~GroupMemberDataResponder() {} + virtual void result(const LLSD& pContent); + virtual void error(U32 pStatus, const std::string& pReason) {} +private: + LLSD mMemberData; +}; + +void GroupMemberDataResponder::result(const LLSD& pContent) +{ + LL_INFOS("BAKER") << "BAKER TAG ////////////////////////////////////////////////////////////////" << LL_ENDL; + // Did we get anything in pContent? + if(pContent.size()) + { + LL_INFOS("BAKER") << "Lik dis if u cry evertim" << LL_ENDL; + + // BAKER TODO: + // Figure out what to do with all the dataz. + // Looks like processGroupMembersReply does the work + LLUUID agent_id = pContent["agent_id"]; + LLUUID group_id = pContent["group_id"]; + LLSD member_list = pContent["members"]; + LLSD titles = pContent["titles"]; + LLSD defaults = pContent["defaults"]; + + int i = 0; + ++i; + + + + } + else + { + LL_INFOS("BAKER") << "WE AIN'T FOUND SHIT!" << LL_ENDL; + + // BAKER TODO: + // Handle this case + + } + LL_INFOS("BAKER") << "//////////////////////////////////////////////////////////////////////////\n" << LL_ENDL; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// BAKER +// static +void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) +{ + //sendGroupMembersRequest(group_id); + //return; + +#if 1 + LLViewerRegion* currentRegion = gAgent.getRegion(); + + // Check to make sure we have our capabilities + if(!currentRegion->capabilitiesReceived()) + { + LL_INFOS("BAKER") << " Capabilities not received! -- OSHITSON --" << LL_ENDL; + // BAKER TODO: Handle this! + } + + // Get our capability + std::string cap_url = currentRegion->getCapability("GroupMemberData"); + + // Post to our service. Add a body containing the group_id. + LLSD body = LLSD::emptyMap(); + body["group_id"] = group_id; + + LLHTTPClient::ResponderPtr grp_data_responder = new GroupMemberDataResponder(); + // This could take a while to finish, timeout after 10 minutes. + LLHTTPClient::post(cap_url, body, grp_data_responder, LLSD(), 600); +#endif +} +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + + void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id) { lldebugs << "LLGroupMgr::sendGroupRoleChanges" << llendl; diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index df3cd17e03..5b535f5056 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -340,6 +340,9 @@ public: static void sendGroupMemberEjects(const LLUUID& group_id, uuid_vec_t& member_ids); + // BAKER + void sendCapGroupMembersRequest(const LLUUID& group_id); + void cancelGroupRoleChanges(const LLUUID& group_id); static void processGroupPropertiesReply(LLMessageSystem* msg, void** data); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index bc594b5517..fa5f5574dc 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -317,7 +317,12 @@ void LLPanelGroupGeneral::activate() if (!gdatap || !gdatap->isMemberDataComplete() ) { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + ////////////////////////////////////////////////////////////////////////// + // BAKER TODO: + // Use cap here! + ////////////////////////////////////////////////////////////////////////// + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); + //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } mFirstUse = FALSE; @@ -714,7 +719,7 @@ void LLPanelGroupGeneral::updateMembers() for( ; mMemberProgress != gdatap->mMembers.end() && ifirst << ", " << iter->second->getTitle() << llendl; + llinfos << "Adding " << mMemberProgress->first << ", " << mMemberProgress->second->getTitle() << llendl; LLGroupMemberData* member = mMemberProgress->second; if (!member) { diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 00dd206571..f05358bf59 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -570,7 +570,14 @@ void LLPanelGroupInvite::updateLists() if (!mPendingUpdate) { LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID); - LLGroupMgr::getInstance()->sendGroupMembersRequest(mImplementation->mGroupID); + + ////////////////////////////////////////////////////////////////////////// + // BAKER TODO: + // Use cap here! + ////////////////////////////////////////////////////////////////////////// + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); + //LLGroupMgr::getInstance()->sendGroupMembersRequest(mImplementation->mGroupID); + LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID); } mPendingUpdate = TRUE; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index f825ee3215..9b0fb37693 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -356,7 +356,12 @@ void LLPanelGroupRoles::activate() if (!gdatap || !gdatap->isMemberDataComplete() ) { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + ////////////////////////////////////////////////////////////////////////// + // BAKER TODO: + // Use cap here! + ////////////////////////////////////////////////////////////////////////// + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); + //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } // Check role data. @@ -1987,7 +1992,12 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) if (!gdatap || !gdatap->isMemberDataComplete()) { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + ////////////////////////////////////////////////////////////////////////// + // BAKER TODO: + // Use cap here! + ////////////////////////////////////////////////////////////////////////// + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); + //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } if (!gdatap || !gdatap->isRoleMemberDataComplete()) @@ -2580,7 +2590,12 @@ void LLPanelGroupActionsSubTab::handleActionSelect() } else { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + ////////////////////////////////////////////////////////////////////////// + // BAKER TODO: + // Use cap here! + ////////////////////////////////////////////////////////////////////////// + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); + //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } if (gdatap->isRoleDataComplete()) @@ -2604,6 +2619,7 @@ void LLPanelGroupActionsSubTab::handleActionSelect() LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID); } } + void LLPanelGroupRoles::setGroupID(const LLUUID& id) { LLPanelGroupTab::setGroupID(id); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index effa368b7a..c00d4e91d7 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1,1870 +1,1869 @@ -/** - * @file llviewerregion.cpp - * @brief Implementation of the LLViewerRegion class. - * - * $LicenseInfo:firstyear=2000&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" - -#include "llviewerregion.h" - -// linden libraries -#include "indra_constants.h" -#include "llavatarnamecache.h" // name lookup cap url -#include "llfloaterreg.h" -#include "llmath.h" -#include "llhttpclient.h" -#include "llregionflags.h" -#include "llregionhandle.h" -#include "llsurface.h" -#include "message.h" -//#include "vmath.h" -#include "v3math.h" -#include "v4math.h" - -#include "llagent.h" -#include "llagentcamera.h" -#include "llcallingcard.h" -#include "llcaphttpsender.h" -#include "llcapabilitylistener.h" -#include "llcommandhandler.h" -#include "lldir.h" -#include "lleventpoll.h" -#include "llfloatergodtools.h" -#include "llfloaterreporter.h" -#include "llfloaterregioninfo.h" -#include "llhttpnode.h" -#include "llregioninfomodel.h" -#include "llsdutil.h" -#include "llstartup.h" -#include "lltrans.h" -#include "llurldispatcher.h" -#include "llviewerobjectlist.h" -#include "llviewerparceloverlay.h" -#include "llviewerstatsrecorder.h" -#include "llvlmanager.h" -#include "llvlcomposition.h" -#include "llvocache.h" -#include "llworld.h" -#include "llspatialpartition.h" -#include "stringize.h" -#include "llviewercontrol.h" -#include "llsdserialize.h" - -#ifdef LL_WINDOWS - #pragma warning(disable:4355) -#endif - -const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region -const S16 MAX_MAP_DIST = 10; -// The server only keeps our pending agent info for 60 seconds. -// We want to allow for seed cap retry, but its not useful after that 60 seconds. -// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up. -const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; -const F32 CAP_REQUEST_TIMEOUT = 18; -// Even though we gave up on login, keep trying for caps after we are logged in: -const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; - -typedef std::map CapabilityMap; - -class LLViewerRegionImpl { -public: - LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) - : mHost(host), - mCompositionp(NULL), - mEventPoll(NULL), - mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), - mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), - mSeedCapAttempts(0), - mHttpResponderID(0), - // I'd prefer to set the LLCapabilityListener name to match the region - // name -- it's disappointing that's not available at construction time. - // We could instead store an LLCapabilityListener*, making - // setRegionNameAndZone() replace the instance. Would that pose - // consistency problems? Can we even request a capability before calling - // setRegionNameAndZone()? - // For testability -- the new Michael Feathers paradigm -- - // LLCapabilityListener binds all the globals it expects to need at - // construction time. - mCapabilityListener(host.getString(), gMessageSystem, *region, - gAgent.getID(), gAgent.getSessionID()) - { - } - - void buildCapabilityNames(LLSD& capabilityNames); - - // The surfaces and other layers - LLSurface* mLandp; - - // Region geometry data - LLVector3d mOriginGlobal; // Location of southwest corner of region (meters) - LLVector3d mCenterGlobal; // Location of center in world space (meters) - LLHost mHost; - - // The unique ID for this region. - LLUUID mRegionID; - - // region/estate owner - usually null. - LLUUID mOwnerID; - - // Network statistics for the region's circuit... - LLTimer mLastNetUpdate; - - // Misc - LLVLComposition *mCompositionp; // Composition layer for the surface - - LLVOCacheEntry::vocache_entry_map_t mCacheMap; - // time? - // LRU info? - - // Cache ID is unique per-region, across renames, moving locations, - // etc. - LLUUID mCacheID; - - CapabilityMap mCapabilities; - - LLEventPoll* mEventPoll; - - S32 mSeedCapMaxAttempts; - S32 mSeedCapMaxAttemptsBeforeLogin; - S32 mSeedCapAttempts; - - S32 mHttpResponderID; - - /// Post an event to this LLCapabilityListener to invoke a capability message on - /// this LLViewerRegion's server - /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) - LLCapabilityListener mCapabilityListener; - - //spatial partitions for objects in this region - std::vector mObjectPartition; -}; - -// support for secondlife:///app/region/{REGION} SLapps -// N.B. this is defined to work exactly like the classic secondlife://{REGION} -// However, the later syntax cannot support spaces in the region name because -// spaces (and %20 chars) are illegal in the hostname of an http URL. Some -// browsers let you get away with this, but some do not (such as Qt's Webkit). -// Hence we introduced the newer secondlife:///app/region alternative. -class LLRegionHandler : public LLCommandHandler -{ -public: - // requests will be throttled from a non-trusted browser - LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {} - - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) - { - // make sure that we at least have a region name - int num_params = params.size(); - if (num_params < 1) - { - return false; - } - - // build a secondlife://{PLACE} SLurl from this SLapp - std::string url = "secondlife://"; - for (int i = 0; i < num_params; i++) - { - if (i > 0) - { - url += "/"; - } - url += params[i].asString(); - } - - // Process the SLapp as if it was a secondlife://{PLACE} SLurl - LLURLDispatcher::dispatch(url, "clicked", web, true); - return true; - } -}; -LLRegionHandler gRegionHandler; - -class BaseCapabilitiesComplete : public LLHTTPClient::Responder -{ - LOG_CLASS(BaseCapabilitiesComplete); -public: - BaseCapabilitiesComplete(U64 region_handle, S32 id) - : mRegionHandle(region_handle), mID(id) - { } - virtual ~BaseCapabilitiesComplete() - { } - - void error(U32 statusNum, const std::string& reason) - { - LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL; - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if (regionp) - { - regionp->failedSeedCapability(); - } - } - - void result(const LLSD& content) - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if(!regionp) //region was removed - { - LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } - if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder - { - LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL; - return ; - } - - LLSD::map_const_iterator iter; - for(iter = content.beginMap(); iter != content.endMap(); ++iter) - { - regionp->setCapability(iter->first, iter->second); - LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " - << iter->first << LL_ENDL; - - /* HACK we're waiting for the ServerReleaseNotes */ - if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested()) - { - regionp->showReleaseNotes(); - } - } - - regionp->setCapabilitiesReceived(true); - - if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - } - - static boost::intrusive_ptr build( U64 region_handle, S32 id ) - { - return boost::intrusive_ptr( - new BaseCapabilitiesComplete(region_handle, id) ); - } - -private: - U64 mRegionHandle; - S32 mID; -}; - - -LLViewerRegion::LLViewerRegion(const U64 &handle, - const LLHost &host, - const U32 grids_per_region_edge, - const U32 grids_per_patch_edge, - const F32 region_width_meters) -: mImpl(new LLViewerRegionImpl(this, host)), - mHandle(handle), - mTimeDilation(1.0f), - mName(""), - mZoning(""), - mIsEstateManager(FALSE), - mRegionFlags( REGION_FLAGS_DEFAULT ), - mSimAccess( SIM_ACCESS_MIN ), - mBillableFactor(1.0), - mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), - mClassID(0), - mCPURatio(0), - mColoName("unknown"), - mProductSKU("unknown"), - mProductName("unknown"), - mHttpUrl(""), - mCacheLoaded(FALSE), - mCacheDirty(FALSE), - mReleaseNotesRequested(FALSE), - mCapabilitiesReceived(false) -{ - mWidth = region_width_meters; - mImpl->mOriginGlobal = from_region_handle(handle); - updateRenderMatrix(); - - mImpl->mLandp = new LLSurface('l', NULL); - - // Create the composition layer for the surface - mImpl->mCompositionp = - new LLVLComposition(mImpl->mLandp, - grids_per_region_edge, - region_width_meters / grids_per_region_edge); - mImpl->mCompositionp->setSurface(mImpl->mLandp); - - // Create the surfaces - mImpl->mLandp->setRegion(this); - mImpl->mLandp->create(grids_per_region_edge, - grids_per_patch_edge, - mImpl->mOriginGlobal, - mWidth); - - mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters); - - setOriginGlobal(from_region_handle(handle)); - calculateCenterGlobal(); - - // Create the object lists - initStats(); - - //create object partitions - //MUST MATCH declaration of eObjectPartitions - mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD - mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN - mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER - mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER - mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE - mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE - mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS - mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME - mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE - mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE - mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE -} - - -void LLViewerRegion::initStats() -{ - mImpl->mLastNetUpdate.reset(); - mPacketsIn = 0; - mBitsIn = 0; - mLastBitsIn = 0; - mLastPacketsIn = 0; - mPacketsOut = 0; - mLastPacketsOut = 0; - mPacketsLost = 0; - mLastPacketsLost = 0; - mPingDelay = 0; - mAlive = false; // can become false if circuit disconnects -} - -LLViewerRegion::~LLViewerRegion() -{ - gVLManager.cleanupData(this); - // Can't do this on destruction, because the neighbor pointers might be invalid. - // This should be reference counted... - disconnectAllNeighbors(); - LLViewerPartSim::getInstance()->cleanupRegion(this); - - gObjectList.killObjects(this); - - delete mImpl->mCompositionp; - delete mParcelOverlay; - delete mImpl->mLandp; - delete mImpl->mEventPoll; - LLHTTPSender::clearSender(mImpl->mHost); - - saveObjectCache(); - - std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); - - delete mImpl; - mImpl = NULL; -} - -LLEventPump& LLViewerRegion::getCapAPI() const -{ - return mImpl->mCapabilityListener.getCapAPI(); -} - -/*virtual*/ -const LLHost& LLViewerRegion::getHost() const -{ - return mImpl->mHost; -} - -LLSurface & LLViewerRegion::getLand() const -{ - return *mImpl->mLandp; -} - -const LLUUID& LLViewerRegion::getRegionID() const -{ - return mImpl->mRegionID; -} - -void LLViewerRegion::setRegionID(const LLUUID& region_id) -{ - mImpl->mRegionID = region_id; -} - -void LLViewerRegion::loadObjectCache() -{ - if (mCacheLoaded) - { - return; - } - - // Presume success. If it fails, we don't want to try again. - mCacheLoaded = TRUE; - - if(LLVOCache::hasInstance()) - { - LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ; - } -} - - -void LLViewerRegion::saveObjectCache() -{ - if (!mCacheLoaded) - { - return; - } - - if (mImpl->mCacheMap.empty()) - { - return; - } - - if(LLVOCache::hasInstance()) - { - LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ; - mCacheDirty = FALSE; - } - - for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) - { - delete iter->second; - } - mImpl->mCacheMap.clear(); -} - -void LLViewerRegion::sendMessage() -{ - gMessageSystem->sendMessage(mImpl->mHost); -} - -void LLViewerRegion::sendReliableMessage() -{ - gMessageSystem->sendReliable(mImpl->mHost); -} - -void LLViewerRegion::setFlags(BOOL b, U32 flags) -{ - if (b) - { - mRegionFlags |= flags; - } - else - { - mRegionFlags &= ~flags; - } -} - -void LLViewerRegion::setWaterHeight(F32 water_level) -{ - mImpl->mLandp->setWaterHeight(water_level); -} - -F32 LLViewerRegion::getWaterHeight() const -{ - return mImpl->mLandp->getWaterHeight(); -} - -BOOL LLViewerRegion::isVoiceEnabled() const -{ - return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE); -} - -void LLViewerRegion::setRegionFlags(U32 flags) -{ - mRegionFlags = flags; -} - - -void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) -{ - mImpl->mOriginGlobal = origin_global; - updateRenderMatrix(); - mImpl->mLandp->setOriginGlobal(origin_global); - mWind.setOriginGlobal(origin_global); - calculateCenterGlobal(); -} - -void LLViewerRegion::updateRenderMatrix() -{ - mRenderMatrix.setTranslation(getOriginAgent()); -} - -void LLViewerRegion::setTimeDilation(F32 time_dilation) -{ - mTimeDilation = time_dilation; -} - -const LLVector3d & LLViewerRegion::getOriginGlobal() const -{ - return mImpl->mOriginGlobal; -} - -LLVector3 LLViewerRegion::getOriginAgent() const -{ - return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal); -} - -const LLVector3d & LLViewerRegion::getCenterGlobal() const -{ - return mImpl->mCenterGlobal; -} - -LLVector3 LLViewerRegion::getCenterAgent() const -{ - return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal); -} - -void LLViewerRegion::setOwner(const LLUUID& owner_id) -{ - mImpl->mOwnerID = owner_id; -} - -const LLUUID& LLViewerRegion::getOwner() const -{ - return mImpl->mOwnerID; -} - -void LLViewerRegion::setRegionNameAndZone (const std::string& name_zone) -{ - std::string::size_type pipe_pos = name_zone.find('|'); - S32 length = name_zone.size(); - if (pipe_pos != std::string::npos) - { - mName = name_zone.substr(0, pipe_pos); - mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1)); - } - else - { - mName = name_zone; - mZoning = ""; - } - - LLStringUtil::stripNonprintable(mName); - LLStringUtil::stripNonprintable(mZoning); -} - -BOOL LLViewerRegion::canManageEstate() const -{ - return gAgent.isGodlike() - || isEstateManager() - || gAgent.getID() == getOwner(); -} - -const std::string LLViewerRegion::getSimAccessString() const -{ - return accessToString(mSimAccess); -} - -std::string LLViewerRegion::getLocalizedSimProductName() const -{ - std::string localized_spn; - return LLTrans::findString(localized_spn, mProductName) ? localized_spn : mProductName; -} - -// static -std::string LLViewerRegion::regionFlagsToString(U32 flags) -{ - std::string result; - - if (flags & REGION_FLAGS_SANDBOX) - { - result += "Sandbox"; - } - - if (flags & REGION_FLAGS_ALLOW_DAMAGE) - { - result += " Not Safe"; - } - - return result; -} - -// static -std::string LLViewerRegion::accessToString(U8 sim_access) -{ - switch(sim_access) - { - case SIM_ACCESS_PG: - return LLTrans::getString("SIM_ACCESS_PG"); - - case SIM_ACCESS_MATURE: - return LLTrans::getString("SIM_ACCESS_MATURE"); - - case SIM_ACCESS_ADULT: - return LLTrans::getString("SIM_ACCESS_ADULT"); - - case SIM_ACCESS_DOWN: - return LLTrans::getString("SIM_ACCESS_DOWN"); - - case SIM_ACCESS_MIN: - default: - return LLTrans::getString("SIM_ACCESS_MIN"); - } -} - -// static -std::string LLViewerRegion::getAccessIcon(U8 sim_access) -{ - switch(sim_access) - { - case SIM_ACCESS_MATURE: - return "Parcel_M_Dark"; - - case SIM_ACCESS_ADULT: - return "Parcel_R_Light"; - - case SIM_ACCESS_PG: - return "Parcel_PG_Light"; - - case SIM_ACCESS_MIN: - default: - return ""; - } -} - -// static -std::string LLViewerRegion::accessToShortString(U8 sim_access) -{ - switch(sim_access) /* Flawfinder: ignore */ - { - case SIM_ACCESS_PG: - return "PG"; - - case SIM_ACCESS_MATURE: - return "M"; - - case SIM_ACCESS_ADULT: - return "A"; - - case SIM_ACCESS_MIN: - default: - return "U"; - } -} - -// static -U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) -{ - U8 accessValue; - - if (LLStringUtil::compareStrings(sim_access, "PG") == 0) - { - accessValue = SIM_ACCESS_PG; - } - else if (LLStringUtil::compareStrings(sim_access, "M") == 0) - { - accessValue = SIM_ACCESS_MATURE; - } - else if (LLStringUtil::compareStrings(sim_access, "A") == 0) - { - accessValue = SIM_ACCESS_ADULT; - } - else - { - accessValue = SIM_ACCESS_MIN; - } - - return accessValue; -} - -// static -void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) -{ - // send it to 'observers' - // *TODO: switch the floaters to using LLRegionInfoModel - llinfos << "Processing region info" << llendl; - LLRegionInfoModel::instance().update(msg); - LLFloaterGodTools::processRegionInfo(msg); - LLFloaterRegionInfo::processRegionInfo(msg); - LLFloaterReporter::processRegionInfo(msg); -} - -void LLViewerRegion::setCacheID(const LLUUID& id) -{ - mImpl->mCacheID = id; -} - -S32 LLViewerRegion::renderPropertyLines() -{ - if (mParcelOverlay) - { - return mParcelOverlay->renderPropertyLines(); - } - else - { - return 0; - } -} - -// This gets called when the height field changes. -void LLViewerRegion::dirtyHeights() -{ - // Property lines need to be reconstructed when the land changes. - if (mParcelOverlay) - { - mParcelOverlay->setDirty(); - } -} - -BOOL LLViewerRegion::idleUpdate(F32 max_update_time) -{ - LLMemType mt_ivr(LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION); - // did_update returns TRUE if we did at least one significant update - BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time); - - if (mParcelOverlay) - { - // Hopefully not a significant time sink... - mParcelOverlay->idleUpdate(); - } - - return did_update; -} - - -// As above, but forcibly do the update. -void LLViewerRegion::forceUpdate() -{ - mImpl->mLandp->idleUpdate(0.f); - - if (mParcelOverlay) - { - mParcelOverlay->idleUpdate(true); - } -} - -void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction) -{ - mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); -} - - -void LLViewerRegion::disconnectAllNeighbors() -{ - mImpl->mLandp->disconnectAllNeighbors(); -} - -LLVLComposition * LLViewerRegion::getComposition() const -{ - return mImpl->mCompositionp; -} - -F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const -{ - if (x >= 256) - { - if (y >= 256) - { - LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled(255, 255); - F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - else - { - LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y); - F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - } - else if (y >= 256) - { - LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f); - F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - - return getComposition()->getValueScaled((F32)x, (F32)y); -} - -void LLViewerRegion::calculateCenterGlobal() -{ - mImpl->mCenterGlobal = mImpl->mOriginGlobal; - mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth; - mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth; - mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ(); -} - -void LLViewerRegion::calculateCameraDistance() -{ - mCameraDistanceSquared = (F32)(gAgentCamera.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared(); -} - -std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion) -{ - s << "{ "; - s << region.mImpl->mHost; - s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n"; - std::string name(region.getName()), zone(region.getZoning()); - if (! name.empty()) - { - s << " mName = " << name << '\n'; - } - if (! zone.empty()) - { - s << " mZoning = " << zone << '\n'; - } - s << "}"; - return s; -} - - -// ---------------- Protected Member Functions ---------------- - -void LLViewerRegion::updateNetStats() -{ - F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32(); - - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); - if (!cdp) - { - mAlive = false; - return; - } - - mAlive = true; - mDeltaTime = dt; - - mLastPacketsIn = mPacketsIn; - mLastBitsIn = mBitsIn; - mLastPacketsOut = mPacketsOut; - mLastPacketsLost = mPacketsLost; - - mPacketsIn = cdp->getPacketsIn(); - mBitsIn = 8 * cdp->getBytesIn(); - mPacketsOut = cdp->getPacketsOut(); - mPacketsLost = cdp->getPacketsLost(); - mPingDelay = cdp->getPingDelay(); - - mBitStat.addValue(mBitsIn - mLastBitsIn); - mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); - mPacketsLostStat.addValue(mPacketsLost); -} - - -U32 LLViewerRegion::getPacketsLost() const -{ - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); - if (!cdp) - { - llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << llendl; - return 0; - } - else - { - return cdp->getPacketsLost(); - } -} - -S32 LLViewerRegion::getHttpResponderID() const -{ - return mImpl->mHttpResponderID; -} - -BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const -{ - LLVector3 pos_region = getPosRegionFromGlobal(point_global); - - if (pos_region.mV[VX] < 0) - { - return FALSE; - } - if (pos_region.mV[VX] >= mWidth) - { - return FALSE; - } - if (pos_region.mV[VY] < 0) - { - return FALSE; - } - if (pos_region.mV[VY] >= mWidth) - { - return FALSE; - } - return TRUE; -} - -LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const -{ - LLVector3 pos_region; - pos_region.setVec(point_global - mImpl->mOriginGlobal); - return pos_region; -} - -LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) const -{ - LLVector3d pos_region_d; - pos_region_d.setVec(pos_region); - return pos_region_d + mImpl->mOriginGlobal; -} - -LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const -{ - LLVector3d pos_global = getPosGlobalFromRegion(pos_region); - - return gAgent.getPosAgentFromGlobal(pos_global); -} - -LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const -{ - return pos_agent - getOriginAgent(); -} - -F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos) -{ - return mImpl->mLandp->resolveHeightRegion( region_pos ); -} - -bool LLViewerRegion::isAlive() -{ - return mAlive; -} - -BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos) -{ - if (mParcelOverlay) - { - return mParcelOverlay->isOwnedSelf(pos); - } else { - return FALSE; - } -} - -// Owned by a group you belong to? (officer or member) -BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos) -{ - if (mParcelOverlay) - { - return mParcelOverlay->isOwnedGroup(pos); - } else { - return FALSE; - } -} - -// the new TCP coarse location handler node -class CoarseLocationUpdate : public LLHTTPNode -{ -public: - virtual void post( - ResponsePtr responder, - const LLSD& context, - const LLSD& input) const - { - LLHost host(input["sender"].asString()); - LLViewerRegion* region = LLWorld::getInstance()->getRegion(host); - if( !region ) - { - return; - } - - S32 target_index = input["body"]["Index"][0]["Prey"].asInteger(); - S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); - - LLDynamicArray* avatar_locs = ®ion->mMapAvatars; - LLDynamicArray* avatar_ids = ®ion->mMapAvatarIDs; - avatar_locs->reset(); - avatar_ids->reset(); - - //llinfos << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << llendl; - //llinfos << "my agent id = " << gAgent.getID() << llendl; - //llinfos << ll_pretty_print_sd(input) << llendl; - - LLSD - locs = input["body"]["Location"], - agents = input["body"]["AgentData"]; - LLSD::array_iterator - locs_it = locs.beginArray(), - agents_it = agents.beginArray(); - BOOL has_agent_data = input["body"].has("AgentData"); - - for(int i=0; - locs_it != locs.endArray(); - i++, locs_it++) - { - U8 - x = locs_it->get("X").asInteger(), - y = locs_it->get("Y").asInteger(), - z = locs_it->get("Z").asInteger(); - // treat the target specially for the map, and don't add you or the target - if(i == target_index) - { - LLVector3d global_pos(region->getOriginGlobal()); - global_pos.mdV[VX] += (F64)x; - global_pos.mdV[VY] += (F64)y; - global_pos.mdV[VZ] += (F64)z * 4.0; - LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); - } - else if( i != you_index) - { - U32 loc = x << 16 | y << 8 | z; loc = loc; - U32 pos = 0x0; - pos |= x; - pos <<= 8; - pos |= y; - pos <<= 8; - pos |= z; - avatar_locs->put(pos); - //llinfos << "next pos: " << x << "," << y << "," << z << ": " << pos << llendl; - if(has_agent_data) // for backwards compatibility with old message format - { - LLUUID agent_id(agents_it->get("AgentID").asUUID()); - //llinfos << "next agent: " << agent_id.asString() << llendl; - avatar_ids->put(agent_id); - } - } - if (has_agent_data) - { - agents_it++; - } - } - } -}; - -// build the coarse location HTTP node under the "/message" URL -LLHTTPRegistration - gHTTPRegistrationCoarseLocationUpdate( - "/message/CoarseLocationUpdate"); - - -// the deprecated coarse location handler -void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg) -{ - //llinfos << "CoarseLocationUpdate" << llendl; - mMapAvatars.reset(); - mMapAvatarIDs.reset(); // only matters in a rare case but it's good to be safe. - - U8 x_pos = 0; - U8 y_pos = 0; - U8 z_pos = 0; - - U32 pos = 0x0; - - S16 agent_index; - S16 target_index; - msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index); - msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index); - - BOOL has_agent_data = msg->has(_PREHASH_AgentData); - S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location); - for(S32 i = 0; i < count; i++) - { - msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i); - msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i); - msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i); - LLUUID agent_id = LLUUID::null; - if(has_agent_data) - { - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id, i); - } - - //llinfos << " object X: " << (S32)x_pos << " Y: " << (S32)y_pos - // << " Z: " << (S32)(z_pos * 4) - // << llendl; - - // treat the target specially for the map - if(i == target_index) - { - LLVector3d global_pos(mImpl->mOriginGlobal); - global_pos.mdV[VX] += (F64)(x_pos); - global_pos.mdV[VY] += (F64)(y_pos); - global_pos.mdV[VZ] += (F64)(z_pos) * 4.0; - LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); - } - - //don't add you - if( i != agent_index) - { - pos = 0x0; - pos |= x_pos; - pos <<= 8; - pos |= y_pos; - pos <<= 8; - pos |= z_pos; - mMapAvatars.put(pos); - if(has_agent_data) - { - mMapAvatarIDs.put(agent_id); - } - } - } -} - -void LLViewerRegion::getInfo(LLSD& info) -{ - info["Region"]["Host"] = getHost().getIPandPort(); - info["Region"]["Name"] = getName(); - U32 x, y; - from_region_handle(getHandle(), &x, &y); - info["Region"]["Handle"]["x"] = (LLSD::Integer)x; - info["Region"]["Handle"]["y"] = (LLSD::Integer)y; -} - -void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) -{ - sim_features = mSimulatorFeatures; - -} - -void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) -{ - std::stringstream str; - - LLSDSerialize::toPrettyXML(sim_features, str); - llinfos << str.str() << llendl; - mSimulatorFeatures = sim_features; -} - -LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) -{ - U32 local_id = objectp->getLocalID(); - U32 crc = objectp->getCRC(); - - LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); - - if (entry) - { - // we've seen this object before - if (entry->getCRC() == crc) - { - // Record a hit - entry->recordDupe(); - return CACHE_UPDATE_DUPE; - } - - // Update the cache entry - mImpl->mCacheMap.erase(local_id); - delete entry; - entry = new LLVOCacheEntry(local_id, crc, dp); - mImpl->mCacheMap[local_id] = entry; - return CACHE_UPDATE_CHANGED; - } - - // we haven't seen this object before - - // Create new entry and add to map - eCacheUpdateResult result = CACHE_UPDATE_ADDED; - if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) - { - delete mImpl->mCacheMap.begin()->second ; - mImpl->mCacheMap.erase(mImpl->mCacheMap.begin()); - result = CACHE_UPDATE_REPLACED; - - } - entry = new LLVOCacheEntry(local_id, crc, dp); - - mImpl->mCacheMap[local_id] = entry; - return result; -} - -// Get data packer for this object, if we have cached data -// AND the CRC matches. JC -LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type) -{ - //llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18 - - LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); - - if (entry) - { - // we've seen this object before - if (entry->getCRC() == crc) - { - // Record a hit - entry->recordHit(); - cache_miss_type = CACHE_MISS_TYPE_NONE; - return entry->getDP(crc); - } - else - { - // llinfos << "CRC miss for " << local_id << llendl; - cache_miss_type = CACHE_MISS_TYPE_CRC; - mCacheMissCRC.put(local_id); - } - } - else - { - // llinfos << "Cache miss for " << local_id << llendl; - cache_miss_type = CACHE_MISS_TYPE_FULL; - mCacheMissFull.put(local_id); - } - - return NULL; -} - -void LLViewerRegion::addCacheMissFull(const U32 local_id) -{ - mCacheMissFull.put(local_id); -} - -void LLViewerRegion::requestCacheMisses() -{ - S32 full_count = mCacheMissFull.count(); - S32 crc_count = mCacheMissCRC.count(); - if (full_count == 0 && crc_count == 0) return; - - LLMessageSystem* msg = gMessageSystem; - BOOL start_new_message = TRUE; - S32 blocks = 0; - S32 i; - - // Send full cache miss updates. For these, we KNOW we don't - // have a viewer object. - for (i = 0; i < full_count; i++) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_RequestMultipleObjects); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL); - msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]); - blocks++; - - if (blocks >= 255) - { - sendReliableMessage(); - start_new_message = TRUE; - blocks = 0; - } - } - - // Send CRC miss updates. For these, we _might_ have a viewer object, - // but probably not. - for (i = 0; i < crc_count; i++) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_RequestMultipleObjects); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC); - msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]); - blocks++; - - if (blocks >= 255) - { - sendReliableMessage(); - start_new_message = TRUE; - blocks = 0; - } - } - - // finish any pending message - if (!start_new_message) - { - sendReliableMessage(); - } - mCacheMissFull.reset(); - mCacheMissCRC.reset(); - - mCacheDirty = TRUE ; - // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; - #if LL_RECORD_VIEWER_STATS - LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); - LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count); - LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); - #endif -} - -void LLViewerRegion::dumpCache() -{ - const S32 BINS = 4; - S32 hit_bin[BINS]; - S32 change_bin[BINS]; - - S32 i; - for (i = 0; i < BINS; ++i) - { - hit_bin[i] = 0; - change_bin[i] = 0; - } - - LLVOCacheEntry *entry; - for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) - { - entry = iter->second ; - - S32 hits = entry->getHitCount(); - S32 changes = entry->getCRCChangeCount(); - - hits = llclamp(hits, 0, BINS-1); - changes = llclamp(changes, 0, BINS-1); - - hit_bin[hits]++; - change_bin[changes]++; - } - - llinfos << "Count " << mImpl->mCacheMap.size() << llendl; - for (i = 0; i < BINS; i++) - { - llinfos << "Hits " << i << " " << hit_bin[i] << llendl; - } - for (i = 0; i < BINS; i++) - { - llinfos << "Changes " << i << " " << change_bin[i] << llendl; - } -} - -void LLViewerRegion::unpackRegionHandshake() -{ - LLMessageSystem *msg = gMessageSystem; - - U32 region_flags; - U8 sim_access; - std::string sim_name; - LLUUID sim_owner; - BOOL is_estate_manager; - F32 water_height; - F32 billable_factor; - LLUUID cache_id; - - msg->getU32 ("RegionInfo", "RegionFlags", region_flags); - msg->getU8 ("RegionInfo", "SimAccess", sim_access); - msg->getString ("RegionInfo", "SimName", sim_name); - msg->getUUID ("RegionInfo", "SimOwner", sim_owner); - msg->getBOOL ("RegionInfo", "IsEstateManager", is_estate_manager); - msg->getF32 ("RegionInfo", "WaterHeight", water_height); - msg->getF32 ("RegionInfo", "BillableFactor", billable_factor); - msg->getUUID ("RegionInfo", "CacheID", cache_id ); - - setRegionFlags(region_flags); - setSimAccess(sim_access); - setRegionNameAndZone(sim_name); - setOwner(sim_owner); - setIsEstateManager(is_estate_manager); - setWaterHeight(water_height); - setBillableFactor(billable_factor); - setCacheID(cache_id); - - LLUUID region_id; - msg->getUUID("RegionInfo2", "RegionID", region_id); - setRegionID(region_id); - - // Retrieve the CR-53 (Homestead/Land SKU) information - S32 classID = 0; - S32 cpuRatio = 0; - std::string coloName; - std::string productSKU; - std::string productName; - - // the only reasonable way to decide if we actually have any data is to - // check to see if any of these fields have positive sizes - if (msg->getSize("RegionInfo3", "ColoName") > 0 || - msg->getSize("RegionInfo3", "ProductSKU") > 0 || - msg->getSize("RegionInfo3", "ProductName") > 0) - { - msg->getS32 ("RegionInfo3", "CPUClassID", classID); - msg->getS32 ("RegionInfo3", "CPURatio", cpuRatio); - msg->getString ("RegionInfo3", "ColoName", coloName); - msg->getString ("RegionInfo3", "ProductSKU", productSKU); - msg->getString ("RegionInfo3", "ProductName", productName); - - mClassID = classID; - mCPURatio = cpuRatio; - mColoName = coloName; - mProductSKU = productSKU; - mProductName = productName; - } - - LLVLComposition *compp = getComposition(); - if (compp) - { - LLUUID tmp_id; - - msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); - compp->setDetailTextureID(0, tmp_id); - msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); - compp->setDetailTextureID(1, tmp_id); - msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); - compp->setDetailTextureID(2, tmp_id); - msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); - compp->setDetailTextureID(3, tmp_id); - - F32 tmp_f32; - msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32); - compp->setStartHeight(0, tmp_f32); - msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32); - compp->setStartHeight(1, tmp_f32); - msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32); - compp->setStartHeight(2, tmp_f32); - msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32); - compp->setStartHeight(3, tmp_f32); - - msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32); - compp->setHeightRange(0, tmp_f32); - msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32); - compp->setHeightRange(1, tmp_f32); - msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32); - compp->setHeightRange(2, tmp_f32); - msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32); - compp->setHeightRange(3, tmp_f32); - - // If this is an UPDATE (params already ready, we need to regenerate - // all of our terrain stuff, by - if (compp->getParamsReady()) - { - //this line creates frame stalls on region crossing and removing it appears to have no effect - //getLand().dirtyAllPatches(); - } - else - { - compp->setParamsReady(); - } - } - - - // Now that we have the name, we can load the cache file - // off disk. - loadObjectCache(); - - // After loading cache, signal that simulator can start - // sending data. - // TODO: Send all upstream viewer->sim handshake info here. - LLHost host = msg->getSender(); - msg->newMessage("RegionHandshakeReply"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("RegionInfo"); - msg->addU32("Flags", 0x0 ); - msg->sendReliable(host); -} - -void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) -{ - capabilityNames.append("AgentState"); - capabilityNames.append("AttachmentResources"); - capabilityNames.append("AvatarPickerSearch"); - capabilityNames.append("CharacterProperties"); - capabilityNames.append("ChatSessionRequest"); - capabilityNames.append("CopyInventoryFromNotecard"); - capabilityNames.append("CreateInventoryCategory"); - capabilityNames.append("DispatchRegionInfo"); - capabilityNames.append("EstateChangeInfo"); - capabilityNames.append("EventQueueGet"); - capabilityNames.append("EnvironmentSettings"); - capabilityNames.append("ObjectMedia"); - capabilityNames.append("ObjectMediaNavigate"); - - if (gSavedSettings.getBOOL("UseHTTPInventory")) - { - capabilityNames.append("FetchLib2"); - capabilityNames.append("FetchLibDescendents2"); - capabilityNames.append("FetchInventory2"); - capabilityNames.append("FetchInventoryDescendents2"); - } - - capabilityNames.append("GetDisplayNames"); - capabilityNames.append("GetTexture"); - capabilityNames.append("GetMesh"); - capabilityNames.append("GetObjectCost"); - capabilityNames.append("GetObjectPhysicsData"); - capabilityNames.append("GroupProposalBallot"); - capabilityNames.append("HomeLocation"); - capabilityNames.append("LandResources"); - capabilityNames.append("MapLayer"); - capabilityNames.append("MapLayerGod"); - capabilityNames.append("MeshUploadFlag"); - capabilityNames.append("NavMeshGenerationStatus"); - capabilityNames.append("NewFileAgentInventory"); - capabilityNames.append("ObjectNavMeshProperties"); - capabilityNames.append("ParcelPropertiesUpdate"); - capabilityNames.append("ParcelNavigateMedia"); - capabilityNames.append("ParcelVoiceInfoRequest"); - capabilityNames.append("ProductInfoRequest"); - capabilityNames.append("ProvisionVoiceAccountRequest"); - capabilityNames.append("RemoteParcelRequest"); - capabilityNames.append("RequestTextureDownload"); - capabilityNames.append("ResourceCostSelected"); - capabilityNames.append("RetrieveNavMeshSrc"); - capabilityNames.append("SearchStatRequest"); - capabilityNames.append("SearchStatTracking"); - capabilityNames.append("SendPostcard"); - capabilityNames.append("SendUserReport"); - capabilityNames.append("SendUserReportWithScreenshot"); - capabilityNames.append("ServerReleaseNotes"); - capabilityNames.append("SimConsole"); - capabilityNames.append("SimulatorFeatures"); - capabilityNames.append("SetDisplayName"); - capabilityNames.append("SimConsoleAsync"); - capabilityNames.append("StartGroupProposal"); - capabilityNames.append("TerrainNavMeshProperties"); - capabilityNames.append("TextureStats"); - capabilityNames.append("UntrustedSimulatorMessage"); - capabilityNames.append("UpdateAgentInformation"); - capabilityNames.append("UpdateAgentLanguage"); - capabilityNames.append("UpdateGestureAgentInventory"); - capabilityNames.append("UpdateNotecardAgentInventory"); - capabilityNames.append("UpdateScriptAgent"); - capabilityNames.append("UpdateGestureTaskInventory"); - capabilityNames.append("UpdateNotecardTaskInventory"); - capabilityNames.append("UpdateScriptTask"); - capabilityNames.append("UploadBakedTexture"); - capabilityNames.append("ViewerMetrics"); - capabilityNames.append("ViewerStartAuction"); - capabilityNames.append("ViewerStats"); - - // Please add new capabilities alphabetically to reduce - // merge conflicts. -} - -void LLViewerRegion::setSeedCapability(const std::string& url) -{ - if (getCapability("Seed") == url) - { - // llwarns << "Ignoring duplicate seed capability" << llendl; - return; - } - - delete mImpl->mEventPoll; - mImpl->mEventPoll = NULL; - - mImpl->mCapabilities.clear(); - setCapability("Seed", url); - - LLSD capabilityNames = LLSD::emptyArray(); - mImpl->buildCapabilityNames(capabilityNames); - - llinfos << "posting to seed " << url << llendl; - - S32 id = ++mImpl->mHttpResponderID; - LLHTTPClient::post(url, capabilityNames, - BaseCapabilitiesComplete::build(getHandle(), id), - LLSD(), CAP_REQUEST_TIMEOUT); -} - -S32 LLViewerRegion::getNumSeedCapRetries() -{ - return mImpl->mSeedCapAttempts; -} - -void LLViewerRegion::failedSeedCapability() -{ - // Should we retry asking for caps? - mImpl->mSeedCapAttempts++; - std::string url = getCapability("Seed"); - if ( url.empty() ) - { - LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL; - return; - } - // After a few attempts, continue login. We will keep trying once in-world: - if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin && - STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() ) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - - if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts) - { - LLSD capabilityNames = LLSD::emptyArray(); - mImpl->buildCapabilityNames(capabilityNames); - - llinfos << "posting to seed " << url << " (retry " - << mImpl->mSeedCapAttempts << ")" << llendl; - - S32 id = ++mImpl->mHttpResponderID; - LLHTTPClient::post(url, capabilityNames, - BaseCapabilitiesComplete::build(getHandle(), id), - LLSD(), CAP_REQUEST_TIMEOUT); - } - else - { - // *TODO: Give a user pop-up about this error? - LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts. Giving up!" << LL_ENDL; - } -} - -class SimulatorFeaturesReceived : public LLHTTPClient::Responder -{ - LOG_CLASS(SimulatorFeaturesReceived); -public: - SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, - S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) - : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) - { } - - - void error(U32 statusNum, const std::string& reason) - { - LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; - retry(); - } - - void result(const LLSD& content) - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if(!regionp) //region is removed or responder is not created. - { - LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } - - regionp->setSimulatorFeatures(content); - } - -private: - void retry() - { - if (mAttempt < mMaxAttempts) - { - mAttempt++; - LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; - LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); - } - } - - std::string mRetryURL; - U64 mRegionHandle; - S32 mAttempt; - S32 mMaxAttempts; -}; - - -void LLViewerRegion::setCapability(const std::string& name, const std::string& url) -{ - if(name == "EventQueueGet") - { - delete mImpl->mEventPoll; - mImpl->mEventPoll = NULL; - mImpl->mEventPoll = new LLEventPoll(url, getHost()); - } - else if(name == "UntrustedSimulatorMessage") - { - LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url)); - } - else if (name == "SimulatorFeatures") - { - // kick off a request for simulator features - LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT); - } - else - { - mImpl->mCapabilities[name] = url; - if(name == "GetTexture") - { - mHttpUrl = url ; - } - } -} - -bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) -{ - return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; -} - -std::string LLViewerRegion::getCapability(const std::string& name) const -{ - CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); - if(iter == mImpl->mCapabilities.end()) - { - return ""; - } - - return iter->second; -} - -bool LLViewerRegion::capabilitiesReceived() const -{ - return mCapabilitiesReceived; -} - -void LLViewerRegion::setCapabilitiesReceived(bool received) -{ - mCapabilitiesReceived = received; - - // Tell interested parties that we've received capabilities, - // so that they can safely use getCapability(). - if (received) - { - mCapabilitiesReceivedSignal(getRegionID()); - - // This is a single-shot signal. Forget callbacks to save resources. - mCapabilitiesReceivedSignal.disconnect_all_slots(); - } -} - -boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb) -{ - return mCapabilitiesReceivedSignal.connect(cb); -} - -void LLViewerRegion::logActiveCapabilities() const -{ - int count = 0; - CapabilityMap::const_iterator iter; - for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count) - { - if (!iter->second.empty()) - { - llinfos << iter->first << " URL is " << iter->second << llendl; - } - } - llinfos << "Dumped " << count << " entries." << llendl; -} - -LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) -{ - if (type < mImpl->mObjectPartition.size()) - { - return mImpl->mObjectPartition[type]; - } - return NULL; -} - -// the viewer can not yet distinquish between normal- and estate-owned objects -// so we collapse these two bits and enable the UI if either are set -const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT - | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; - -bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const -{ - return (mParcelOverlay != NULL) - && (mParcelOverlay->isOwnedSelf(pos) - || mParcelOverlay->isOwnedGroup(pos) - || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) - && mParcelOverlay->encroachesOwned(boxes)) ); -} - -bool LLViewerRegion::childrenObjectReturnable( const std::vector& boxes ) const -{ - bool result = false; - result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0; - return result; -} - -bool LLViewerRegion::objectsCrossParcel(const std::vector& boxes) const -{ - return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes); -} - -void LLViewerRegion::getNeighboringRegions( std::vector& uniqueRegions ) -{ - mImpl->mLandp->getNeighboringRegions( uniqueRegions ); -} -void LLViewerRegion::getNeighboringRegionsStatus( std::vector& regions ) -{ - mImpl->mLandp->getNeighboringRegionsStatus( regions ); -} -void LLViewerRegion::showReleaseNotes() -{ - std::string url = this->getCapability("ServerReleaseNotes"); - - if (url.empty()) { - // HACK haven't received the capability yet, we'll wait until - // it arives. - mReleaseNotesRequested = TRUE; - return; - } - - LLWeb::loadURL(url); - mReleaseNotesRequested = FALSE; -} - -std::string LLViewerRegion::getDescription() const -{ - return stringize(*this); -} - -bool LLViewerRegion::meshUploadEnabled() const -{ - return (mSimulatorFeatures.has("MeshUploadEnabled") && - mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); -} - -bool LLViewerRegion::meshRezEnabled() const -{ - return (mSimulatorFeatures.has("MeshRezEnabled") && - mSimulatorFeatures["MeshRezEnabled"].asBoolean()); -} - -bool LLViewerRegion::dynamicPathfindingEnabled() const -{ - return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") && - mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); -} - +/** + * @file llviewerregion.cpp + * @brief Implementation of the LLViewerRegion class. + * + * $LicenseInfo:firstyear=2000&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" + +#include "llviewerregion.h" + +// linden libraries +#include "indra_constants.h" +#include "llavatarnamecache.h" // name lookup cap url +#include "llfloaterreg.h" +#include "llmath.h" +#include "llhttpclient.h" +#include "llregionflags.h" +#include "llregionhandle.h" +#include "llsurface.h" +#include "message.h" +//#include "vmath.h" +#include "v3math.h" +#include "v4math.h" + +#include "llagent.h" +#include "llagentcamera.h" +#include "llcallingcard.h" +#include "llcaphttpsender.h" +#include "llcapabilitylistener.h" +#include "llcommandhandler.h" +#include "lldir.h" +#include "lleventpoll.h" +#include "llfloatergodtools.h" +#include "llfloaterreporter.h" +#include "llfloaterregioninfo.h" +#include "llhttpnode.h" +#include "llregioninfomodel.h" +#include "llsdutil.h" +#include "llstartup.h" +#include "lltrans.h" +#include "llurldispatcher.h" +#include "llviewerobjectlist.h" +#include "llviewerparceloverlay.h" +#include "llviewerstatsrecorder.h" +#include "llvlmanager.h" +#include "llvlcomposition.h" +#include "llvocache.h" +#include "llworld.h" +#include "llspatialpartition.h" +#include "stringize.h" +#include "llviewercontrol.h" +#include "llsdserialize.h" + +#ifdef LL_WINDOWS + #pragma warning(disable:4355) +#endif + +const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region +const S16 MAX_MAP_DIST = 10; +// The server only keeps our pending agent info for 60 seconds. +// We want to allow for seed cap retry, but its not useful after that 60 seconds. +// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up. +const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; +const F32 CAP_REQUEST_TIMEOUT = 18; +// Even though we gave up on login, keep trying for caps after we are logged in: +const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; + +typedef std::map CapabilityMap; + +class LLViewerRegionImpl { +public: + LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) + : mHost(host), + mCompositionp(NULL), + mEventPoll(NULL), + mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), + mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), + mSeedCapAttempts(0), + mHttpResponderID(0), + // I'd prefer to set the LLCapabilityListener name to match the region + // name -- it's disappointing that's not available at construction time. + // We could instead store an LLCapabilityListener*, making + // setRegionNameAndZone() replace the instance. Would that pose + // consistency problems? Can we even request a capability before calling + // setRegionNameAndZone()? + // For testability -- the new Michael Feathers paradigm -- + // LLCapabilityListener binds all the globals it expects to need at + // construction time. + mCapabilityListener(host.getString(), gMessageSystem, *region, + gAgent.getID(), gAgent.getSessionID()) + { + } + + void buildCapabilityNames(LLSD& capabilityNames); + + // The surfaces and other layers + LLSurface* mLandp; + + // Region geometry data + LLVector3d mOriginGlobal; // Location of southwest corner of region (meters) + LLVector3d mCenterGlobal; // Location of center in world space (meters) + LLHost mHost; + + // The unique ID for this region. + LLUUID mRegionID; + + // region/estate owner - usually null. + LLUUID mOwnerID; + + // Network statistics for the region's circuit... + LLTimer mLastNetUpdate; + + // Misc + LLVLComposition *mCompositionp; // Composition layer for the surface + + LLVOCacheEntry::vocache_entry_map_t mCacheMap; + // time? + // LRU info? + + // Cache ID is unique per-region, across renames, moving locations, + // etc. + LLUUID mCacheID; + + CapabilityMap mCapabilities; + + LLEventPoll* mEventPoll; + + S32 mSeedCapMaxAttempts; + S32 mSeedCapMaxAttemptsBeforeLogin; + S32 mSeedCapAttempts; + + S32 mHttpResponderID; + + /// Post an event to this LLCapabilityListener to invoke a capability message on + /// this LLViewerRegion's server + /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) + LLCapabilityListener mCapabilityListener; + + //spatial partitions for objects in this region + std::vector mObjectPartition; +}; + +// support for secondlife:///app/region/{REGION} SLapps +// N.B. this is defined to work exactly like the classic secondlife://{REGION} +// However, the later syntax cannot support spaces in the region name because +// spaces (and %20 chars) are illegal in the hostname of an http URL. Some +// browsers let you get away with this, but some do not (such as Qt's Webkit). +// Hence we introduced the newer secondlife:///app/region alternative. +class LLRegionHandler : public LLCommandHandler +{ +public: + // requests will be throttled from a non-trusted browser + LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {} + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + // make sure that we at least have a region name + int num_params = params.size(); + if (num_params < 1) + { + return false; + } + + // build a secondlife://{PLACE} SLurl from this SLapp + std::string url = "secondlife://"; + for (int i = 0; i < num_params; i++) + { + if (i > 0) + { + url += "/"; + } + url += params[i].asString(); + } + + // Process the SLapp as if it was a secondlife://{PLACE} SLurl + LLURLDispatcher::dispatch(url, "clicked", web, true); + return true; + } +}; +LLRegionHandler gRegionHandler; + +class BaseCapabilitiesComplete : public LLHTTPClient::Responder +{ + LOG_CLASS(BaseCapabilitiesComplete); +public: + BaseCapabilitiesComplete(U64 region_handle, S32 id) + : mRegionHandle(region_handle), mID(id) + { } + virtual ~BaseCapabilitiesComplete() + { } + + void error(U32 statusNum, const std::string& reason) + { + LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL; + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (regionp) + { + regionp->failedSeedCapability(); + } + } + + void result(const LLSD& content) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if(!regionp) //region was removed + { + LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; + return ; + } + if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder + { + LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL; + return ; + } + + LLSD::map_const_iterator iter; + for(iter = content.beginMap(); iter != content.endMap(); ++iter) + { + regionp->setCapability(iter->first, iter->second); + LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " + << iter->first << LL_ENDL; + + /* HACK we're waiting for the ServerReleaseNotes */ + if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested()) + { + regionp->showReleaseNotes(); + } + } + + regionp->setCapabilitiesReceived(true); + + if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) + { + LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); + } + } + + static boost::intrusive_ptr build( U64 region_handle, S32 id ) + { + return boost::intrusive_ptr( + new BaseCapabilitiesComplete(region_handle, id) ); + } + +private: + U64 mRegionHandle; + S32 mID; +}; + + +LLViewerRegion::LLViewerRegion(const U64 &handle, + const LLHost &host, + const U32 grids_per_region_edge, + const U32 grids_per_patch_edge, + const F32 region_width_meters) +: mImpl(new LLViewerRegionImpl(this, host)), + mHandle(handle), + mTimeDilation(1.0f), + mName(""), + mZoning(""), + mIsEstateManager(FALSE), + mRegionFlags( REGION_FLAGS_DEFAULT ), + mSimAccess( SIM_ACCESS_MIN ), + mBillableFactor(1.0), + mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), + mClassID(0), + mCPURatio(0), + mColoName("unknown"), + mProductSKU("unknown"), + mProductName("unknown"), + mHttpUrl(""), + mCacheLoaded(FALSE), + mCacheDirty(FALSE), + mReleaseNotesRequested(FALSE), + mCapabilitiesReceived(false) +{ + mWidth = region_width_meters; + mImpl->mOriginGlobal = from_region_handle(handle); + updateRenderMatrix(); + + mImpl->mLandp = new LLSurface('l', NULL); + + // Create the composition layer for the surface + mImpl->mCompositionp = + new LLVLComposition(mImpl->mLandp, + grids_per_region_edge, + region_width_meters / grids_per_region_edge); + mImpl->mCompositionp->setSurface(mImpl->mLandp); + + // Create the surfaces + mImpl->mLandp->setRegion(this); + mImpl->mLandp->create(grids_per_region_edge, + grids_per_patch_edge, + mImpl->mOriginGlobal, + mWidth); + + mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters); + + setOriginGlobal(from_region_handle(handle)); + calculateCenterGlobal(); + + // Create the object lists + initStats(); + + //create object partitions + //MUST MATCH declaration of eObjectPartitions + mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD + mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN + mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER + mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER + mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE + mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE + mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS + mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME + mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE + mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE + mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE +} + + +void LLViewerRegion::initStats() +{ + mImpl->mLastNetUpdate.reset(); + mPacketsIn = 0; + mBitsIn = 0; + mLastBitsIn = 0; + mLastPacketsIn = 0; + mPacketsOut = 0; + mLastPacketsOut = 0; + mPacketsLost = 0; + mLastPacketsLost = 0; + mPingDelay = 0; + mAlive = false; // can become false if circuit disconnects +} + +LLViewerRegion::~LLViewerRegion() +{ + gVLManager.cleanupData(this); + // Can't do this on destruction, because the neighbor pointers might be invalid. + // This should be reference counted... + disconnectAllNeighbors(); + LLViewerPartSim::getInstance()->cleanupRegion(this); + + gObjectList.killObjects(this); + + delete mImpl->mCompositionp; + delete mParcelOverlay; + delete mImpl->mLandp; + delete mImpl->mEventPoll; + LLHTTPSender::clearSender(mImpl->mHost); + + saveObjectCache(); + + std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); + + delete mImpl; + mImpl = NULL; +} + +LLEventPump& LLViewerRegion::getCapAPI() const +{ + return mImpl->mCapabilityListener.getCapAPI(); +} + +/*virtual*/ +const LLHost& LLViewerRegion::getHost() const +{ + return mImpl->mHost; +} + +LLSurface & LLViewerRegion::getLand() const +{ + return *mImpl->mLandp; +} + +const LLUUID& LLViewerRegion::getRegionID() const +{ + return mImpl->mRegionID; +} + +void LLViewerRegion::setRegionID(const LLUUID& region_id) +{ + mImpl->mRegionID = region_id; +} + +void LLViewerRegion::loadObjectCache() +{ + if (mCacheLoaded) + { + return; + } + + // Presume success. If it fails, we don't want to try again. + mCacheLoaded = TRUE; + + if(LLVOCache::hasInstance()) + { + LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ; + } +} + + +void LLViewerRegion::saveObjectCache() +{ + if (!mCacheLoaded) + { + return; + } + + if (mImpl->mCacheMap.empty()) + { + return; + } + + if(LLVOCache::hasInstance()) + { + LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ; + mCacheDirty = FALSE; + } + + for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) + { + delete iter->second; + } + mImpl->mCacheMap.clear(); +} + +void LLViewerRegion::sendMessage() +{ + gMessageSystem->sendMessage(mImpl->mHost); +} + +void LLViewerRegion::sendReliableMessage() +{ + gMessageSystem->sendReliable(mImpl->mHost); +} + +void LLViewerRegion::setFlags(BOOL b, U32 flags) +{ + if (b) + { + mRegionFlags |= flags; + } + else + { + mRegionFlags &= ~flags; + } +} + +void LLViewerRegion::setWaterHeight(F32 water_level) +{ + mImpl->mLandp->setWaterHeight(water_level); +} + +F32 LLViewerRegion::getWaterHeight() const +{ + return mImpl->mLandp->getWaterHeight(); +} + +BOOL LLViewerRegion::isVoiceEnabled() const +{ + return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE); +} + +void LLViewerRegion::setRegionFlags(U32 flags) +{ + mRegionFlags = flags; +} + + +void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) +{ + mImpl->mOriginGlobal = origin_global; + updateRenderMatrix(); + mImpl->mLandp->setOriginGlobal(origin_global); + mWind.setOriginGlobal(origin_global); + calculateCenterGlobal(); +} + +void LLViewerRegion::updateRenderMatrix() +{ + mRenderMatrix.setTranslation(getOriginAgent()); +} + +void LLViewerRegion::setTimeDilation(F32 time_dilation) +{ + mTimeDilation = time_dilation; +} + +const LLVector3d & LLViewerRegion::getOriginGlobal() const +{ + return mImpl->mOriginGlobal; +} + +LLVector3 LLViewerRegion::getOriginAgent() const +{ + return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal); +} + +const LLVector3d & LLViewerRegion::getCenterGlobal() const +{ + return mImpl->mCenterGlobal; +} + +LLVector3 LLViewerRegion::getCenterAgent() const +{ + return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal); +} + +void LLViewerRegion::setOwner(const LLUUID& owner_id) +{ + mImpl->mOwnerID = owner_id; +} + +const LLUUID& LLViewerRegion::getOwner() const +{ + return mImpl->mOwnerID; +} + +void LLViewerRegion::setRegionNameAndZone (const std::string& name_zone) +{ + std::string::size_type pipe_pos = name_zone.find('|'); + S32 length = name_zone.size(); + if (pipe_pos != std::string::npos) + { + mName = name_zone.substr(0, pipe_pos); + mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1)); + } + else + { + mName = name_zone; + mZoning = ""; + } + + LLStringUtil::stripNonprintable(mName); + LLStringUtil::stripNonprintable(mZoning); +} + +BOOL LLViewerRegion::canManageEstate() const +{ + return gAgent.isGodlike() + || isEstateManager() + || gAgent.getID() == getOwner(); +} + +const std::string LLViewerRegion::getSimAccessString() const +{ + return accessToString(mSimAccess); +} + +std::string LLViewerRegion::getLocalizedSimProductName() const +{ + std::string localized_spn; + return LLTrans::findString(localized_spn, mProductName) ? localized_spn : mProductName; +} + +// static +std::string LLViewerRegion::regionFlagsToString(U32 flags) +{ + std::string result; + + if (flags & REGION_FLAGS_SANDBOX) + { + result += "Sandbox"; + } + + if (flags & REGION_FLAGS_ALLOW_DAMAGE) + { + result += " Not Safe"; + } + + return result; +} + +// static +std::string LLViewerRegion::accessToString(U8 sim_access) +{ + switch(sim_access) + { + case SIM_ACCESS_PG: + return LLTrans::getString("SIM_ACCESS_PG"); + + case SIM_ACCESS_MATURE: + return LLTrans::getString("SIM_ACCESS_MATURE"); + + case SIM_ACCESS_ADULT: + return LLTrans::getString("SIM_ACCESS_ADULT"); + + case SIM_ACCESS_DOWN: + return LLTrans::getString("SIM_ACCESS_DOWN"); + + case SIM_ACCESS_MIN: + default: + return LLTrans::getString("SIM_ACCESS_MIN"); + } +} + +// static +std::string LLViewerRegion::getAccessIcon(U8 sim_access) +{ + switch(sim_access) + { + case SIM_ACCESS_MATURE: + return "Parcel_M_Dark"; + + case SIM_ACCESS_ADULT: + return "Parcel_R_Light"; + + case SIM_ACCESS_PG: + return "Parcel_PG_Light"; + + case SIM_ACCESS_MIN: + default: + return ""; + } +} + +// static +std::string LLViewerRegion::accessToShortString(U8 sim_access) +{ + switch(sim_access) /* Flawfinder: ignore */ + { + case SIM_ACCESS_PG: + return "PG"; + + case SIM_ACCESS_MATURE: + return "M"; + + case SIM_ACCESS_ADULT: + return "A"; + + case SIM_ACCESS_MIN: + default: + return "U"; + } +} + +// static +U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) +{ + U8 accessValue; + + if (LLStringUtil::compareStrings(sim_access, "PG") == 0) + { + accessValue = SIM_ACCESS_PG; + } + else if (LLStringUtil::compareStrings(sim_access, "M") == 0) + { + accessValue = SIM_ACCESS_MATURE; + } + else if (LLStringUtil::compareStrings(sim_access, "A") == 0) + { + accessValue = SIM_ACCESS_ADULT; + } + else + { + accessValue = SIM_ACCESS_MIN; + } + + return accessValue; +} + +// static +void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) +{ + // send it to 'observers' + // *TODO: switch the floaters to using LLRegionInfoModel + llinfos << "Processing region info" << llendl; + LLRegionInfoModel::instance().update(msg); + LLFloaterGodTools::processRegionInfo(msg); + LLFloaterRegionInfo::processRegionInfo(msg); + LLFloaterReporter::processRegionInfo(msg); +} + +void LLViewerRegion::setCacheID(const LLUUID& id) +{ + mImpl->mCacheID = id; +} + +S32 LLViewerRegion::renderPropertyLines() +{ + if (mParcelOverlay) + { + return mParcelOverlay->renderPropertyLines(); + } + else + { + return 0; + } +} + +// This gets called when the height field changes. +void LLViewerRegion::dirtyHeights() +{ + // Property lines need to be reconstructed when the land changes. + if (mParcelOverlay) + { + mParcelOverlay->setDirty(); + } +} + +BOOL LLViewerRegion::idleUpdate(F32 max_update_time) +{ + LLMemType mt_ivr(LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION); + // did_update returns TRUE if we did at least one significant update + BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time); + + if (mParcelOverlay) + { + // Hopefully not a significant time sink... + mParcelOverlay->idleUpdate(); + } + + return did_update; +} + + +// As above, but forcibly do the update. +void LLViewerRegion::forceUpdate() +{ + mImpl->mLandp->idleUpdate(0.f); + + if (mParcelOverlay) + { + mParcelOverlay->idleUpdate(true); + } +} + +void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction) +{ + mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); +} + + +void LLViewerRegion::disconnectAllNeighbors() +{ + mImpl->mLandp->disconnectAllNeighbors(); +} + +LLVLComposition * LLViewerRegion::getComposition() const +{ + return mImpl->mCompositionp; +} + +F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const +{ + if (x >= 256) + { + if (y >= 256) + { + LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled(255, 255); + F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + else + { + LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y); + F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + } + else if (y >= 256) + { + LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f); + F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + + return getComposition()->getValueScaled((F32)x, (F32)y); +} + +void LLViewerRegion::calculateCenterGlobal() +{ + mImpl->mCenterGlobal = mImpl->mOriginGlobal; + mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth; + mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth; + mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ(); +} + +void LLViewerRegion::calculateCameraDistance() +{ + mCameraDistanceSquared = (F32)(gAgentCamera.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared(); +} + +std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion) +{ + s << "{ "; + s << region.mImpl->mHost; + s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n"; + std::string name(region.getName()), zone(region.getZoning()); + if (! name.empty()) + { + s << " mName = " << name << '\n'; + } + if (! zone.empty()) + { + s << " mZoning = " << zone << '\n'; + } + s << "}"; + return s; +} + + +// ---------------- Protected Member Functions ---------------- + +void LLViewerRegion::updateNetStats() +{ + F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32(); + + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); + if (!cdp) + { + mAlive = false; + return; + } + + mAlive = true; + mDeltaTime = dt; + + mLastPacketsIn = mPacketsIn; + mLastBitsIn = mBitsIn; + mLastPacketsOut = mPacketsOut; + mLastPacketsLost = mPacketsLost; + + mPacketsIn = cdp->getPacketsIn(); + mBitsIn = 8 * cdp->getBytesIn(); + mPacketsOut = cdp->getPacketsOut(); + mPacketsLost = cdp->getPacketsLost(); + mPingDelay = cdp->getPingDelay(); + + mBitStat.addValue(mBitsIn - mLastBitsIn); + mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); + mPacketsLostStat.addValue(mPacketsLost); +} + + +U32 LLViewerRegion::getPacketsLost() const +{ + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); + if (!cdp) + { + llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << llendl; + return 0; + } + else + { + return cdp->getPacketsLost(); + } +} + +S32 LLViewerRegion::getHttpResponderID() const +{ + return mImpl->mHttpResponderID; +} + +BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const +{ + LLVector3 pos_region = getPosRegionFromGlobal(point_global); + + if (pos_region.mV[VX] < 0) + { + return FALSE; + } + if (pos_region.mV[VX] >= mWidth) + { + return FALSE; + } + if (pos_region.mV[VY] < 0) + { + return FALSE; + } + if (pos_region.mV[VY] >= mWidth) + { + return FALSE; + } + return TRUE; +} + +LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const +{ + LLVector3 pos_region; + pos_region.setVec(point_global - mImpl->mOriginGlobal); + return pos_region; +} + +LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) const +{ + LLVector3d pos_region_d; + pos_region_d.setVec(pos_region); + return pos_region_d + mImpl->mOriginGlobal; +} + +LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const +{ + LLVector3d pos_global = getPosGlobalFromRegion(pos_region); + + return gAgent.getPosAgentFromGlobal(pos_global); +} + +LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const +{ + return pos_agent - getOriginAgent(); +} + +F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos) +{ + return mImpl->mLandp->resolveHeightRegion( region_pos ); +} + +bool LLViewerRegion::isAlive() +{ + return mAlive; +} + +BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos) +{ + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedSelf(pos); + } else { + return FALSE; + } +} + +// Owned by a group you belong to? (officer or member) +BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos) +{ + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedGroup(pos); + } else { + return FALSE; + } +} + +// the new TCP coarse location handler node +class CoarseLocationUpdate : public LLHTTPNode +{ +public: + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + LLHost host(input["sender"].asString()); + LLViewerRegion* region = LLWorld::getInstance()->getRegion(host); + if( !region ) + { + return; + } + + S32 target_index = input["body"]["Index"][0]["Prey"].asInteger(); + S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); + + LLDynamicArray* avatar_locs = ®ion->mMapAvatars; + LLDynamicArray* avatar_ids = ®ion->mMapAvatarIDs; + avatar_locs->reset(); + avatar_ids->reset(); + + //llinfos << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << llendl; + //llinfos << "my agent id = " << gAgent.getID() << llendl; + //llinfos << ll_pretty_print_sd(input) << llendl; + + LLSD + locs = input["body"]["Location"], + agents = input["body"]["AgentData"]; + LLSD::array_iterator + locs_it = locs.beginArray(), + agents_it = agents.beginArray(); + BOOL has_agent_data = input["body"].has("AgentData"); + + for(int i=0; + locs_it != locs.endArray(); + i++, locs_it++) + { + U8 + x = locs_it->get("X").asInteger(), + y = locs_it->get("Y").asInteger(), + z = locs_it->get("Z").asInteger(); + // treat the target specially for the map, and don't add you or the target + if(i == target_index) + { + LLVector3d global_pos(region->getOriginGlobal()); + global_pos.mdV[VX] += (F64)x; + global_pos.mdV[VY] += (F64)y; + global_pos.mdV[VZ] += (F64)z * 4.0; + LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); + } + else if( i != you_index) + { + U32 loc = x << 16 | y << 8 | z; loc = loc; + U32 pos = 0x0; + pos |= x; + pos <<= 8; + pos |= y; + pos <<= 8; + pos |= z; + avatar_locs->put(pos); + //llinfos << "next pos: " << x << "," << y << "," << z << ": " << pos << llendl; + if(has_agent_data) // for backwards compatibility with old message format + { + LLUUID agent_id(agents_it->get("AgentID").asUUID()); + //llinfos << "next agent: " << agent_id.asString() << llendl; + avatar_ids->put(agent_id); + } + } + if (has_agent_data) + { + agents_it++; + } + } + } +}; + +// build the coarse location HTTP node under the "/message" URL +LLHTTPRegistration + gHTTPRegistrationCoarseLocationUpdate( + "/message/CoarseLocationUpdate"); + + +// the deprecated coarse location handler +void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg) +{ + //llinfos << "CoarseLocationUpdate" << llendl; + mMapAvatars.reset(); + mMapAvatarIDs.reset(); // only matters in a rare case but it's good to be safe. + + U8 x_pos = 0; + U8 y_pos = 0; + U8 z_pos = 0; + + U32 pos = 0x0; + + S16 agent_index; + S16 target_index; + msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index); + msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index); + + BOOL has_agent_data = msg->has(_PREHASH_AgentData); + S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location); + for(S32 i = 0; i < count; i++) + { + msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i); + msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i); + msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i); + LLUUID agent_id = LLUUID::null; + if(has_agent_data) + { + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id, i); + } + + //llinfos << " object X: " << (S32)x_pos << " Y: " << (S32)y_pos + // << " Z: " << (S32)(z_pos * 4) + // << llendl; + + // treat the target specially for the map + if(i == target_index) + { + LLVector3d global_pos(mImpl->mOriginGlobal); + global_pos.mdV[VX] += (F64)(x_pos); + global_pos.mdV[VY] += (F64)(y_pos); + global_pos.mdV[VZ] += (F64)(z_pos) * 4.0; + LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); + } + + //don't add you + if( i != agent_index) + { + pos = 0x0; + pos |= x_pos; + pos <<= 8; + pos |= y_pos; + pos <<= 8; + pos |= z_pos; + mMapAvatars.put(pos); + if(has_agent_data) + { + mMapAvatarIDs.put(agent_id); + } + } + } +} + +void LLViewerRegion::getInfo(LLSD& info) +{ + info["Region"]["Host"] = getHost().getIPandPort(); + info["Region"]["Name"] = getName(); + U32 x, y; + from_region_handle(getHandle(), &x, &y); + info["Region"]["Handle"]["x"] = (LLSD::Integer)x; + info["Region"]["Handle"]["y"] = (LLSD::Integer)y; +} + +void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) +{ + sim_features = mSimulatorFeatures; + +} + +void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) +{ + std::stringstream str; + + LLSDSerialize::toPrettyXML(sim_features, str); + llinfos << str.str() << llendl; + mSimulatorFeatures = sim_features; +} + +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) +{ + U32 local_id = objectp->getLocalID(); + U32 crc = objectp->getCRC(); + + LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); + + if (entry) + { + // we've seen this object before + if (entry->getCRC() == crc) + { + // Record a hit + entry->recordDupe(); + return CACHE_UPDATE_DUPE; + } + + // Update the cache entry + mImpl->mCacheMap.erase(local_id); + delete entry; + entry = new LLVOCacheEntry(local_id, crc, dp); + mImpl->mCacheMap[local_id] = entry; + return CACHE_UPDATE_CHANGED; + } + + // we haven't seen this object before + + // Create new entry and add to map + eCacheUpdateResult result = CACHE_UPDATE_ADDED; + if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) + { + delete mImpl->mCacheMap.begin()->second ; + mImpl->mCacheMap.erase(mImpl->mCacheMap.begin()); + result = CACHE_UPDATE_REPLACED; + + } + entry = new LLVOCacheEntry(local_id, crc, dp); + + mImpl->mCacheMap[local_id] = entry; + return result; +} + +// Get data packer for this object, if we have cached data +// AND the CRC matches. JC +LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type) +{ + //llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18 + + LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); + + if (entry) + { + // we've seen this object before + if (entry->getCRC() == crc) + { + // Record a hit + entry->recordHit(); + cache_miss_type = CACHE_MISS_TYPE_NONE; + return entry->getDP(crc); + } + else + { + // llinfos << "CRC miss for " << local_id << llendl; + cache_miss_type = CACHE_MISS_TYPE_CRC; + mCacheMissCRC.put(local_id); + } + } + else + { + // llinfos << "Cache miss for " << local_id << llendl; + cache_miss_type = CACHE_MISS_TYPE_FULL; + mCacheMissFull.put(local_id); + } + + return NULL; +} + +void LLViewerRegion::addCacheMissFull(const U32 local_id) +{ + mCacheMissFull.put(local_id); +} + +void LLViewerRegion::requestCacheMisses() +{ + S32 full_count = mCacheMissFull.count(); + S32 crc_count = mCacheMissCRC.count(); + if (full_count == 0 && crc_count == 0) return; + + LLMessageSystem* msg = gMessageSystem; + BOOL start_new_message = TRUE; + S32 blocks = 0; + S32 i; + + // Send full cache miss updates. For these, we KNOW we don't + // have a viewer object. + for (i = 0; i < full_count; i++) + { + if (start_new_message) + { + msg->newMessageFast(_PREHASH_RequestMultipleObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + start_new_message = FALSE; + } + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL); + msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]); + blocks++; + + if (blocks >= 255) + { + sendReliableMessage(); + start_new_message = TRUE; + blocks = 0; + } + } + + // Send CRC miss updates. For these, we _might_ have a viewer object, + // but probably not. + for (i = 0; i < crc_count; i++) + { + if (start_new_message) + { + msg->newMessageFast(_PREHASH_RequestMultipleObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + start_new_message = FALSE; + } + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC); + msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]); + blocks++; + + if (blocks >= 255) + { + sendReliableMessage(); + start_new_message = TRUE; + blocks = 0; + } + } + + // finish any pending message + if (!start_new_message) + { + sendReliableMessage(); + } + mCacheMissFull.reset(); + mCacheMissCRC.reset(); + + mCacheDirty = TRUE ; + // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; + #if LL_RECORD_VIEWER_STATS + LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); + LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count); + LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); + #endif +} + +void LLViewerRegion::dumpCache() +{ + const S32 BINS = 4; + S32 hit_bin[BINS]; + S32 change_bin[BINS]; + + S32 i; + for (i = 0; i < BINS; ++i) + { + hit_bin[i] = 0; + change_bin[i] = 0; + } + + LLVOCacheEntry *entry; + for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) + { + entry = iter->second ; + + S32 hits = entry->getHitCount(); + S32 changes = entry->getCRCChangeCount(); + + hits = llclamp(hits, 0, BINS-1); + changes = llclamp(changes, 0, BINS-1); + + hit_bin[hits]++; + change_bin[changes]++; + } + + llinfos << "Count " << mImpl->mCacheMap.size() << llendl; + for (i = 0; i < BINS; i++) + { + llinfos << "Hits " << i << " " << hit_bin[i] << llendl; + } + for (i = 0; i < BINS; i++) + { + llinfos << "Changes " << i << " " << change_bin[i] << llendl; + } +} + +void LLViewerRegion::unpackRegionHandshake() +{ + LLMessageSystem *msg = gMessageSystem; + + U32 region_flags; + U8 sim_access; + std::string sim_name; + LLUUID sim_owner; + BOOL is_estate_manager; + F32 water_height; + F32 billable_factor; + LLUUID cache_id; + + msg->getU32 ("RegionInfo", "RegionFlags", region_flags); + msg->getU8 ("RegionInfo", "SimAccess", sim_access); + msg->getString ("RegionInfo", "SimName", sim_name); + msg->getUUID ("RegionInfo", "SimOwner", sim_owner); + msg->getBOOL ("RegionInfo", "IsEstateManager", is_estate_manager); + msg->getF32 ("RegionInfo", "WaterHeight", water_height); + msg->getF32 ("RegionInfo", "BillableFactor", billable_factor); + msg->getUUID ("RegionInfo", "CacheID", cache_id ); + + setRegionFlags(region_flags); + setSimAccess(sim_access); + setRegionNameAndZone(sim_name); + setOwner(sim_owner); + setIsEstateManager(is_estate_manager); + setWaterHeight(water_height); + setBillableFactor(billable_factor); + setCacheID(cache_id); + + LLUUID region_id; + msg->getUUID("RegionInfo2", "RegionID", region_id); + setRegionID(region_id); + + // Retrieve the CR-53 (Homestead/Land SKU) information + S32 classID = 0; + S32 cpuRatio = 0; + std::string coloName; + std::string productSKU; + std::string productName; + + // the only reasonable way to decide if we actually have any data is to + // check to see if any of these fields have positive sizes + if (msg->getSize("RegionInfo3", "ColoName") > 0 || + msg->getSize("RegionInfo3", "ProductSKU") > 0 || + msg->getSize("RegionInfo3", "ProductName") > 0) + { + msg->getS32 ("RegionInfo3", "CPUClassID", classID); + msg->getS32 ("RegionInfo3", "CPURatio", cpuRatio); + msg->getString ("RegionInfo3", "ColoName", coloName); + msg->getString ("RegionInfo3", "ProductSKU", productSKU); + msg->getString ("RegionInfo3", "ProductName", productName); + + mClassID = classID; + mCPURatio = cpuRatio; + mColoName = coloName; + mProductSKU = productSKU; + mProductName = productName; + } + + LLVLComposition *compp = getComposition(); + if (compp) + { + LLUUID tmp_id; + + msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); + compp->setDetailTextureID(0, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); + compp->setDetailTextureID(1, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); + compp->setDetailTextureID(2, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); + compp->setDetailTextureID(3, tmp_id); + + F32 tmp_f32; + msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32); + compp->setStartHeight(0, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32); + compp->setStartHeight(1, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32); + compp->setStartHeight(2, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32); + compp->setStartHeight(3, tmp_f32); + + msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32); + compp->setHeightRange(0, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32); + compp->setHeightRange(1, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32); + compp->setHeightRange(2, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32); + compp->setHeightRange(3, tmp_f32); + + // If this is an UPDATE (params already ready, we need to regenerate + // all of our terrain stuff, by + if (compp->getParamsReady()) + { + //this line creates frame stalls on region crossing and removing it appears to have no effect + //getLand().dirtyAllPatches(); + } + else + { + compp->setParamsReady(); + } + } + + + // Now that we have the name, we can load the cache file + // off disk. + loadObjectCache(); + + // After loading cache, signal that simulator can start + // sending data. + // TODO: Send all upstream viewer->sim handshake info here. + LLHost host = msg->getSender(); + msg->newMessage("RegionHandshakeReply"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("RegionInfo"); + msg->addU32("Flags", 0x0 ); + msg->sendReliable(host); +} + +void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) +{ + capabilityNames.append("AgentState"); + capabilityNames.append("AttachmentResources"); + capabilityNames.append("AvatarPickerSearch"); + capabilityNames.append("CharacterProperties"); + capabilityNames.append("ChatSessionRequest"); + capabilityNames.append("CopyInventoryFromNotecard"); + capabilityNames.append("CreateInventoryCategory"); + capabilityNames.append("DispatchRegionInfo"); + capabilityNames.append("EnvironmentSettings"); + capabilityNames.append("EstateChangeInfo"); + capabilityNames.append("EventQueueGet"); + + if (gSavedSettings.getBOOL("UseHTTPInventory")) + { + capabilityNames.append("FetchLib2"); + capabilityNames.append("FetchLibDescendents2"); + capabilityNames.append("FetchInventory2"); + capabilityNames.append("FetchInventoryDescendents2"); + } + + capabilityNames.append("GetDisplayNames"); + capabilityNames.append("GetMesh"); + capabilityNames.append("GetObjectCost"); + capabilityNames.append("GetObjectPhysicsData"); + capabilityNames.append("GetTexture"); + capabilityNames.append("GroupMemberData"); + capabilityNames.append("GroupProposalBallot"); + capabilityNames.append("HomeLocation"); + capabilityNames.append("LandResources"); + capabilityNames.append("MapLayer"); + capabilityNames.append("MapLayerGod"); + capabilityNames.append("MeshUploadFlag"); + capabilityNames.append("NavMeshGenerationStatus"); + capabilityNames.append("NewFileAgentInventory"); + capabilityNames.append("ObjectMedia"); + capabilityNames.append("ObjectMediaNavigate"); + capabilityNames.append("ObjectNavMeshProperties"); + capabilityNames.append("ParcelPropertiesUpdate"); + capabilityNames.append("ParcelVoiceInfoRequest"); + capabilityNames.append("ProductInfoRequest"); + capabilityNames.append("ProvisionVoiceAccountRequest"); + capabilityNames.append("RemoteParcelRequest"); + capabilityNames.append("RequestTextureDownload"); + capabilityNames.append("ResourceCostSelected"); + capabilityNames.append("RetrieveNavMeshSrc"); + capabilityNames.append("SearchStatRequest"); + capabilityNames.append("SearchStatTracking"); + capabilityNames.append("SendPostcard"); + capabilityNames.append("SendUserReport"); + capabilityNames.append("SendUserReportWithScreenshot"); + capabilityNames.append("ServerReleaseNotes"); + capabilityNames.append("SetDisplayName"); + capabilityNames.append("SimConsoleAsync"); + capabilityNames.append("SimulatorFeatures"); + capabilityNames.append("StartGroupProposal"); + capabilityNames.append("TerrainNavMeshProperties"); + capabilityNames.append("TextureStats"); + capabilityNames.append("UntrustedSimulatorMessage"); + capabilityNames.append("UpdateAgentInformation"); + capabilityNames.append("UpdateAgentLanguage"); + capabilityNames.append("UpdateGestureAgentInventory"); + capabilityNames.append("UpdateGestureTaskInventory"); + capabilityNames.append("UpdateNotecardAgentInventory"); + capabilityNames.append("UpdateNotecardTaskInventory"); + capabilityNames.append("UpdateScriptAgent"); + capabilityNames.append("UpdateScriptTask"); + capabilityNames.append("UploadBakedTexture"); + capabilityNames.append("ViewerMetrics"); + capabilityNames.append("ViewerStartAuction"); + capabilityNames.append("ViewerStats"); + + // Please add new capabilities alphabetically to reduce + // merge conflicts. +} + +void LLViewerRegion::setSeedCapability(const std::string& url) +{ + if (getCapability("Seed") == url) + { + // llwarns << "Ignoring duplicate seed capability" << llendl; + return; + } + + delete mImpl->mEventPoll; + mImpl->mEventPoll = NULL; + + mImpl->mCapabilities.clear(); + setCapability("Seed", url); + + LLSD capabilityNames = LLSD::emptyArray(); + mImpl->buildCapabilityNames(capabilityNames); + + llinfos << "posting to seed " << url << llendl; + + S32 id = ++mImpl->mHttpResponderID; + LLHTTPClient::post(url, capabilityNames, + BaseCapabilitiesComplete::build(getHandle(), id), + LLSD(), CAP_REQUEST_TIMEOUT); +} + +S32 LLViewerRegion::getNumSeedCapRetries() +{ + return mImpl->mSeedCapAttempts; +} + +void LLViewerRegion::failedSeedCapability() +{ + // Should we retry asking for caps? + mImpl->mSeedCapAttempts++; + std::string url = getCapability("Seed"); + if ( url.empty() ) + { + LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL; + return; + } + // After a few attempts, continue login. We will keep trying once in-world: + if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin && + STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() ) + { + LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); + } + + if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts) + { + LLSD capabilityNames = LLSD::emptyArray(); + mImpl->buildCapabilityNames(capabilityNames); + + llinfos << "posting to seed " << url << " (retry " + << mImpl->mSeedCapAttempts << ")" << llendl; + + S32 id = ++mImpl->mHttpResponderID; + LLHTTPClient::post(url, capabilityNames, + BaseCapabilitiesComplete::build(getHandle(), id), + LLSD(), CAP_REQUEST_TIMEOUT); + } + else + { + // *TODO: Give a user pop-up about this error? + LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts. Giving up!" << LL_ENDL; + } +} + +class SimulatorFeaturesReceived : public LLHTTPClient::Responder +{ + LOG_CLASS(SimulatorFeaturesReceived); +public: + SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, + S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) + : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) + { } + + + void error(U32 statusNum, const std::string& reason) + { + LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; + retry(); + } + + void result(const LLSD& content) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if(!regionp) //region is removed or responder is not created. + { + LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL; + return ; + } + + regionp->setSimulatorFeatures(content); + } + +private: + void retry() + { + if (mAttempt < mMaxAttempts) + { + mAttempt++; + LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; + LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); + } + } + + std::string mRetryURL; + U64 mRegionHandle; + S32 mAttempt; + S32 mMaxAttempts; +}; + + +void LLViewerRegion::setCapability(const std::string& name, const std::string& url) +{ + if(name == "EventQueueGet") + { + delete mImpl->mEventPoll; + mImpl->mEventPoll = NULL; + mImpl->mEventPoll = new LLEventPoll(url, getHost()); + } + else if(name == "UntrustedSimulatorMessage") + { + LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url)); + } + else if (name == "SimulatorFeatures") + { + // kick off a request for simulator features + LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT); + } + else + { + mImpl->mCapabilities[name] = url; + if(name == "GetTexture") + { + mHttpUrl = url ; + } + } +} + +bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) +{ + return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; +} + +std::string LLViewerRegion::getCapability(const std::string& name) const +{ + CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); + if(iter == mImpl->mCapabilities.end()) + { + return ""; + } + + return iter->second; +} + +bool LLViewerRegion::capabilitiesReceived() const +{ + return mCapabilitiesReceived; +} + +void LLViewerRegion::setCapabilitiesReceived(bool received) +{ + mCapabilitiesReceived = received; + + // Tell interested parties that we've received capabilities, + // so that they can safely use getCapability(). + if (received) + { + mCapabilitiesReceivedSignal(getRegionID()); + + // This is a single-shot signal. Forget callbacks to save resources. + mCapabilitiesReceivedSignal.disconnect_all_slots(); + } +} + +boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb) +{ + return mCapabilitiesReceivedSignal.connect(cb); +} + +void LLViewerRegion::logActiveCapabilities() const +{ + int count = 0; + CapabilityMap::const_iterator iter; + for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count) + { + if (!iter->second.empty()) + { + llinfos << iter->first << " URL is " << iter->second << llendl; + } + } + llinfos << "Dumped " << count << " entries." << llendl; +} + +LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) +{ + if (type < mImpl->mObjectPartition.size()) + { + return mImpl->mObjectPartition[type]; + } + return NULL; +} + +// the viewer can not yet distinquish between normal- and estate-owned objects +// so we collapse these two bits and enable the UI if either are set +const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT + | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + +bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const +{ + return (mParcelOverlay != NULL) + && (mParcelOverlay->isOwnedSelf(pos) + || mParcelOverlay->isOwnedGroup(pos) + || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) + && mParcelOverlay->encroachesOwned(boxes)) ); +} + +bool LLViewerRegion::childrenObjectReturnable( const std::vector& boxes ) const +{ + bool result = false; + result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0; + return result; +} + +bool LLViewerRegion::objectsCrossParcel(const std::vector& boxes) const +{ + return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes); +} + +void LLViewerRegion::getNeighboringRegions( std::vector& uniqueRegions ) +{ + mImpl->mLandp->getNeighboringRegions( uniqueRegions ); +} +void LLViewerRegion::getNeighboringRegionsStatus( std::vector& regions ) +{ + mImpl->mLandp->getNeighboringRegionsStatus( regions ); +} +void LLViewerRegion::showReleaseNotes() +{ + std::string url = this->getCapability("ServerReleaseNotes"); + + if (url.empty()) { + // HACK haven't received the capability yet, we'll wait until + // it arives. + mReleaseNotesRequested = TRUE; + return; + } + + LLWeb::loadURL(url); + mReleaseNotesRequested = FALSE; +} + +std::string LLViewerRegion::getDescription() const +{ + return stringize(*this); +} + +bool LLViewerRegion::meshUploadEnabled() const +{ + return (mSimulatorFeatures.has("MeshUploadEnabled") && + mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); +} + +bool LLViewerRegion::meshRezEnabled() const +{ + return (mSimulatorFeatures.has("MeshRezEnabled") && + mSimulatorFeatures["MeshRezEnabled"].asBoolean()); +} + +bool LLViewerRegion::dynamicPathfindingEnabled() const +{ + return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") && + mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); +} + -- cgit v1.2.3 From 238ac6c0e869d1c8c380e3e7b70d4803c385f352 Mon Sep 17 00:00:00 2001 From: Chris Baker Date: Tue, 28 Aug 2012 17:32:01 -0700 Subject: Got viewer displaying new data format --- indra/newview/llgroupmgr.cpp | 142 ++++++++++++++++++++++++++++++++++--------- indra/newview/llgroupmgr.h | 2 + 2 files changed, 114 insertions(+), 30 deletions(-) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 3300034f7f..2e1d1d5c77 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1851,38 +1851,13 @@ private: LLSD mMemberData; }; -void GroupMemberDataResponder::result(const LLSD& pContent) +void GroupMemberDataResponder::result(const LLSD& content) { LL_INFOS("BAKER") << "BAKER TAG ////////////////////////////////////////////////////////////////" << LL_ENDL; - // Did we get anything in pContent? - if(pContent.size()) - { - LL_INFOS("BAKER") << "Lik dis if u cry evertim" << LL_ENDL; - - // BAKER TODO: - // Figure out what to do with all the dataz. - // Looks like processGroupMembersReply does the work - LLUUID agent_id = pContent["agent_id"]; - LLUUID group_id = pContent["group_id"]; - LLSD member_list = pContent["members"]; - LLSD titles = pContent["titles"]; - LLSD defaults = pContent["defaults"]; - - int i = 0; - ++i; - - - - } - else - { - LL_INFOS("BAKER") << "WE AIN'T FOUND SHIT!" << LL_ENDL; - - // BAKER TODO: - // Handle this case - - } + LL_INFOS("BAKER") << "Got data from responder" << LL_ENDL; + LLGroupMgr::processCapGroupMembersRequest(content); LL_INFOS("BAKER") << "//////////////////////////////////////////////////////////////////////////\n" << LL_ENDL; + } ////////////////////////////////////////////////////////////////////////// @@ -1898,6 +1873,7 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) //return; #if 1 + LLViewerRegion* currentRegion = gAgent.getRegion(); // Check to make sure we have our capabilities @@ -1912,13 +1888,119 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) // Post to our service. Add a body containing the group_id. LLSD body = LLSD::emptyMap(); - body["group_id"] = group_id; + body["group_id"] = group_id; + // Session id? LLHTTPClient::ResponderPtr grp_data_responder = new GroupMemberDataResponder(); // This could take a while to finish, timeout after 10 minutes. LLHTTPClient::post(cap_url, body, grp_data_responder, LLSD(), 600); + #endif } + + +// static +void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) +{ + LL_INFOS("BAKER") << "BAKER TAG ////////////////////////////////////////////////////////////////" << LL_ENDL; + // Did we get anything in content? + if(!content.size()) + { + LL_INFOS("BAKER") << "WE AIN'T FOUND SHIT!" << LL_ENDL; + // BAKER TODO: + // Handle this case + } + + LL_INFOS("BAKER") << "Lik dis if u cry evertim" << LL_ENDL; + + // If we have no members, there's no reason to do anything else + S32 num_members = content["member_count"]; + if(num_members < 1) + return; + + LLUUID group_id = content["group_id"].asUUID(); + + LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id); + if(!group_datap) + { + LL_WARNS("GrpMgr") << "Received incorrect, possibly stale, group or request id" << LL_ENDL; + return; + } + + group_datap->mMemberCount = num_members; + + LLSD member_list = content["members"]; + LLSD titles = content["titles"]; + LLSD defaults = content["defaults"]; + + std::string online_status; + std::string title; + S32 contribution; + U64 member_powers; + // If this is changed to a bool, make sure to change the LLGroupMemberData constructor + BOOL is_owner; + + // Compute this once, rather than every time. + U64 default_powers = llstrtou64(defaults["default_powers"].asString().c_str(), NULL, 16); + + LLSD::map_const_iterator member_iter_start = member_list.beginMap(); + LLSD::map_const_iterator member_iter_end = member_list.endMap(); + for( ; member_iter_start != member_iter_end; ++member_iter_start) + { + // Reset defaults + online_status = "unknown"; + title = titles[0]; + contribution = 0; + member_powers = default_powers; + is_owner = false; + + const LLUUID member_id(member_iter_start->first); + LLSD member_info = member_iter_start->second; + + // Online Status + if(member_info.has("last_login")) + { + online_status = member_info["last_login"]; + if(online_status == "Online") + online_status = LLTrans::getString("group_member_status_online"); + else + formatDateString(online_status); + } + + // Title + if(member_info.has("title")) + title = titles[member_info["title"].asInteger()]; + + // Powers + if(member_info.has("powers")) + member_powers = llstrtou64(member_info["powers"].asString().c_str(), NULL, 16); + + // Land Contribution + if(member_info.has("donated_square_meters")) + contribution = member_info["donated_square_meters"]; + + if(member_info.has("owner")) + is_owner = true; + + LLGroupMemberData* data = new LLGroupMemberData(member_id, + contribution, + member_powers, + title, + online_status, + is_owner); + + group_datap->mMembers[member_id] = data; + } + + group_datap->mMemberDataComplete = TRUE; + group_datap->mRoleMemberDataComplete = TRUE; + group_datap->mMemberRequestID.setNull(); + group_datap->mChanged = TRUE; + LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA); + + LL_INFOS("BAKER") << "//////////////////////////////////////////////////////////////////////////\n" << LL_ENDL; +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 5b535f5056..b0c3cd025d 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -341,7 +341,9 @@ public: uuid_vec_t& member_ids); // BAKER + //static void sendCapGroupMembersRequest(const LLUUID& group_id); void sendCapGroupMembersRequest(const LLUUID& group_id); + static void processCapGroupMembersRequest(const LLSD& content); void cancelGroupRoleChanges(const LLUUID& group_id); -- cgit v1.2.3 From 7ecf3ce40f4ec27a43878a3a2192c97479d22fcf Mon Sep 17 00:00:00 2001 From: Chris Baker Date: Fri, 31 Aug 2012 17:53:47 -0700 Subject: - Fixed an issue where service was called twice in a frame - Changed level of output logs - Cleaned up comments --- indra/newview/llgroupmgr.cpp | 54 +++++++++++++++++------------------ indra/newview/llgroupmgr.h | 3 +- indra/newview/llpanelgroupgeneral.cpp | 16 ++++------- indra/newview/llpanelgroupinvite.cpp | 4 --- indra/newview/llpanelgrouproles.cpp | 12 -------- 5 files changed, 34 insertions(+), 55 deletions(-) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 2e1d1d5c77..b9bcedda13 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -36,6 +36,7 @@ #include #include +#include "llappviewer.h" #include "llagent.h" #include "llui.h" #include "message.h" @@ -745,6 +746,7 @@ void LLGroupMgrGroupData::cancelRoleChanges() LLGroupMgr::LLGroupMgr() { + mLastGroupMembersRequestFrame = 0; } LLGroupMgr::~LLGroupMgr() @@ -1501,9 +1503,6 @@ void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id) } - - - void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id) { lldebugs << "LLGroupMgr::sendGroupRoleDataRequest" << llendl; @@ -1839,7 +1838,7 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id, ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -// STUBBED IN FOR code completion +// I DON'T KNOW WHERE TO PUT THIS class GroupMemberDataResponder : public LLHTTPClient::Responder { public: @@ -1853,26 +1852,18 @@ private: void GroupMemberDataResponder::result(const LLSD& content) { - LL_INFOS("BAKER") << "BAKER TAG ////////////////////////////////////////////////////////////////" << LL_ENDL; - LL_INFOS("BAKER") << "Got data from responder" << LL_ENDL; LLGroupMgr::processCapGroupMembersRequest(content); - LL_INFOS("BAKER") << "//////////////////////////////////////////////////////////////////////////\n" << LL_ENDL; - } - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -// BAKER + + // static void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) { - //sendGroupMembersRequest(group_id); - //return; - -#if 1 + // Have we requested the information already this frame? + if(mLastGroupMembersRequestFrame == gFrameCount) + return; LLViewerRegion* currentRegion = gAgent.getRegion(); @@ -1895,24 +1886,20 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) // This could take a while to finish, timeout after 10 minutes. LLHTTPClient::post(cap_url, body, grp_data_responder, LLSD(), 600); -#endif + mLastGroupMembersRequestFrame = gFrameCount; } // static void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) { - LL_INFOS("BAKER") << "BAKER TAG ////////////////////////////////////////////////////////////////" << LL_ENDL; // Did we get anything in content? if(!content.size()) { - LL_INFOS("BAKER") << "WE AIN'T FOUND SHIT!" << LL_ENDL; // BAKER TODO: - // Handle this case + // Maybe display a popup saying something went wrong? } - LL_INFOS("BAKER") << "Lik dis if u cry evertim" << LL_ENDL; - // If we have no members, there's no reason to do anything else S32 num_members = content["member_count"]; if(num_members < 1) @@ -1979,6 +1966,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) if(member_info.has("donated_square_meters")) contribution = member_info["donated_square_meters"]; + // Owner Flag if(member_info.has("owner")) is_owner = true; @@ -1992,18 +1980,28 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) group_datap->mMembers[member_id] = data; } + // Technically, we have this data, but to prevent completely overhauling + // this entire system (it would be nice, but I don't have the time), + // I'm going to be dumb and just call services I most likely don't need + // with the thought being that the system might need it to be done. + if(group_datap->mTitles.size() < 1) + LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id); + + group_datap->mMemberDataComplete = TRUE; - group_datap->mRoleMemberDataComplete = TRUE; group_datap->mMemberRequestID.setNull(); + // Make the role-member data request + if (group_datap->mPendingRoleMemberRequest) + { + group_datap->mPendingRoleMemberRequest = FALSE; + LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_id); + } + group_datap->mChanged = TRUE; LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA); - LL_INFOS("BAKER") << "//////////////////////////////////////////////////////////////////////////\n" << LL_ENDL; } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id) { diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index b0c3cd025d..62b2978f21 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -341,7 +341,6 @@ public: uuid_vec_t& member_ids); // BAKER - //static void sendCapGroupMembersRequest(const LLUUID& group_id); void sendCapGroupMembersRequest(const LLUUID& group_id); static void processCapGroupMembersRequest(const LLSD& content); @@ -380,6 +379,8 @@ private: typedef std::set observer_set_t; typedef std::map observer_map_t; observer_map_t mParticularObservers; + + S32 mLastGroupMembersRequestFrame; }; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index fa5f5574dc..5b1c15ca45 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -317,10 +317,6 @@ void LLPanelGroupGeneral::activate() if (!gdatap || !gdatap->isMemberDataComplete() ) { - ////////////////////////////////////////////////////////////////////////// - // BAKER TODO: - // Use cap here! - ////////////////////////////////////////////////////////////////////////// LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } @@ -719,7 +715,7 @@ void LLPanelGroupGeneral::updateMembers() for( ; mMemberProgress != gdatap->mMembers.end() && ifirst << ", " << mMemberProgress->second->getTitle() << llendl; + lldebugs << "Adding " << mMemberProgress->first << ", " << mMemberProgress->second->getTitle() << llendl; LLGroupMemberData* member = mMemberProgress->second; if (!member) { @@ -763,15 +759,15 @@ void LLPanelGroupGeneral::updateMembers() } sAllTime += all_timer.getElapsedTimeF32(); - llinfos << "Updated " << i << " of " << UPDATE_MEMBERS_PER_FRAME << "members in the list." << llendl; + lldebugs << "Updated " << i << " of " << UPDATE_MEMBERS_PER_FRAME << "members in the list." << llendl; if (mMemberProgress == gdatap->mMembers.end()) { - llinfos << " member list completed." << llendl; + lldebugs << " member list completed." << llendl; mListVisibleMembers->setEnabled(TRUE); - llinfos << "All Time: " << sAllTime << llendl; - llinfos << "SD Time: " << sSDTime << llendl; - llinfos << "Element Time: " << sElementTime << llendl; + lldebugs << "All Time: " << sAllTime << llendl; + lldebugs << "SD Time: " << sSDTime << llendl; + lldebugs << "Element Time: " << sElementTime << llendl; } else { diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index f05358bf59..f1ba84ec36 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -571,10 +571,6 @@ void LLPanelGroupInvite::updateLists() { LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID); - ////////////////////////////////////////////////////////////////////////// - // BAKER TODO: - // Use cap here! - ////////////////////////////////////////////////////////////////////////// LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); //LLGroupMgr::getInstance()->sendGroupMembersRequest(mImplementation->mGroupID); diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 9b0fb37693..0e40224346 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -356,10 +356,6 @@ void LLPanelGroupRoles::activate() if (!gdatap || !gdatap->isMemberDataComplete() ) { - ////////////////////////////////////////////////////////////////////////// - // BAKER TODO: - // Use cap here! - ////////////////////////////////////////////////////////////////////////// LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } @@ -1992,10 +1988,6 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) if (!gdatap || !gdatap->isMemberDataComplete()) { - ////////////////////////////////////////////////////////////////////////// - // BAKER TODO: - // Use cap here! - ////////////////////////////////////////////////////////////////////////// LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } @@ -2590,10 +2582,6 @@ void LLPanelGroupActionsSubTab::handleActionSelect() } else { - ////////////////////////////////////////////////////////////////////////// - // BAKER TODO: - // Use cap here! - ////////////////////////////////////////////////////////////////////////// LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } -- cgit v1.2.3 From 5dfbc62c1bbab145b1f1b826833c0e485fc73250 Mon Sep 17 00:00:00 2001 From: Chris Baker Date: Tue, 4 Sep 2012 10:54:16 -0700 Subject: Cleaned up comments --- indra/newview/llgroupmgr.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index b9bcedda13..7a738bd9ea 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1836,9 +1836,7 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id, } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -// I DON'T KNOW WHERE TO PUT THIS +// Responder class for capability group management class GroupMemberDataResponder : public LLHTTPClient::Responder { public: @@ -1854,8 +1852,6 @@ void GroupMemberDataResponder::result(const LLSD& content) { LLGroupMgr::processCapGroupMembersRequest(content); } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// // static @@ -1870,8 +1866,8 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) // Check to make sure we have our capabilities if(!currentRegion->capabilitiesReceived()) { - LL_INFOS("BAKER") << " Capabilities not received! -- OSHITSON --" << LL_ENDL; - // BAKER TODO: Handle this! + LL_INFOS("BAKER") << " Capabilities not received!" << LL_ENDL; + return; } // Get our capability @@ -1880,10 +1876,10 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) // Post to our service. Add a body containing the group_id. LLSD body = LLSD::emptyMap(); body["group_id"] = group_id; - // Session id? LLHTTPClient::ResponderPtr grp_data_responder = new GroupMemberDataResponder(); - // This could take a while to finish, timeout after 10 minutes. + + // This could take a while to finish, timeout after 10 minutes. LLHTTPClient::post(cap_url, body, grp_data_responder, LLSD(), 600); mLastGroupMembersRequestFrame = gFrameCount; @@ -1896,8 +1892,8 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) // Did we get anything in content? if(!content.size()) { - // BAKER TODO: - // Maybe display a popup saying something went wrong? + LL_DEBUGS("GrpMgr") << "No group member data received." << LL_ENDL; + return; } // If we have no members, there's no reason to do anything else @@ -1943,8 +1939,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) const LLUUID member_id(member_iter_start->first); LLSD member_info = member_iter_start->second; - - // Online Status + if(member_info.has("last_login")) { online_status = member_info["last_login"]; @@ -1954,19 +1949,15 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) formatDateString(online_status); } - // Title if(member_info.has("title")) title = titles[member_info["title"].asInteger()]; - // Powers if(member_info.has("powers")) member_powers = llstrtou64(member_info["powers"].asString().c_str(), NULL, 16); - // Land Contribution if(member_info.has("donated_square_meters")) contribution = member_info["donated_square_meters"]; - // Owner Flag if(member_info.has("owner")) is_owner = true; -- cgit v1.2.3 From e459024c8283a26a1aefce0db65e0d7dd2c7e16d Mon Sep 17 00:00:00 2001 From: Baker Linden Date: Wed, 5 Sep 2012 15:55:34 -0700 Subject: [MAINT-513] Large group management - Reduced the timeout to 5 minutes, down from 10 minutes. - Provided output for GroupMemberResponder error - Removed commented calls to sendGroupMembersRequest - Reordered calls to sendCapGroupMembersRequest so it's called last --- indra/newview/llgroupmgr.cpp | 16 ++++++++++++---- indra/newview/llpanelgroupgeneral.cpp | 2 -- indra/newview/llpanelgroupinvite.cpp | 5 +---- indra/newview/llpanelgrouproles.cpp | 3 --- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 7a738bd9ea..3fed8bb9b0 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1843,11 +1843,16 @@ public: GroupMemberDataResponder() {} virtual ~GroupMemberDataResponder() {} virtual void result(const LLSD& pContent); - virtual void error(U32 pStatus, const std::string& pReason) {} + virtual void error(U32 pStatus, const std::string& pReason); private: LLSD mMemberData; }; +void GroupMemberDataResponder::error(U32 pStatus, const std::string& pReason) +{ + LL_WARNS("GrpMgr") << "Error receiving group member data." << LL_ENDL; +} + void GroupMemberDataResponder::result(const LLSD& content) { LLGroupMgr::processCapGroupMembersRequest(content); @@ -1866,7 +1871,7 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) // Check to make sure we have our capabilities if(!currentRegion->capabilitiesReceived()) { - LL_INFOS("BAKER") << " Capabilities not received!" << LL_ENDL; + LL_WARNS("GrpMgr") << " Capabilities not received!" << LL_ENDL; return; } @@ -1879,8 +1884,8 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) LLHTTPClient::ResponderPtr grp_data_responder = new GroupMemberDataResponder(); - // This could take a while to finish, timeout after 10 minutes. - LLHTTPClient::post(cap_url, body, grp_data_responder, LLSD(), 600); + // This could take a while to finish, timeout after 5 minutes. + LLHTTPClient::post(cap_url, body, grp_data_responder, LLSD(), 300); mLastGroupMembersRequestFrame = gFrameCount; } @@ -1975,6 +1980,9 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) // this entire system (it would be nice, but I don't have the time), // I'm going to be dumb and just call services I most likely don't need // with the thought being that the system might need it to be done. + // + // TODO: + // Refactor to reduce multiple calls for data we already have. if(group_datap->mTitles.size() < 1) LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 5b1c15ca45..f6ce7de47e 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -313,12 +313,10 @@ void LLPanelGroupGeneral::activate() { LLGroupMgr::getInstance()->sendGroupTitlesRequest(mGroupID); LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID); - if (!gdatap || !gdatap->isMemberDataComplete() ) { LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } mFirstUse = FALSE; diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index f1ba84ec36..1ed8d8cf03 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -570,11 +570,8 @@ void LLPanelGroupInvite::updateLists() if (!mPendingUpdate) { LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID); - - LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); - //LLGroupMgr::getInstance()->sendGroupMembersRequest(mImplementation->mGroupID); - LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); } mPendingUpdate = TRUE; } diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 0e40224346..bbe47ae943 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -357,7 +357,6 @@ void LLPanelGroupRoles::activate() if (!gdatap || !gdatap->isMemberDataComplete() ) { LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } // Check role data. @@ -1989,7 +1988,6 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) if (!gdatap || !gdatap->isMemberDataComplete()) { LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } if (!gdatap || !gdatap->isRoleMemberDataComplete()) @@ -2583,7 +2581,6 @@ void LLPanelGroupActionsSubTab::handleActionSelect() else { LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - //LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); } if (gdatap->isRoleDataComplete()) -- cgit v1.2.3 From c30ecf2ebd6ff6b6b4def9da25aea2b4c975328d Mon Sep 17 00:00:00 2001 From: Baker Linden Date: Thu, 6 Sep 2012 15:19:05 -0700 Subject: Added explicit casting for Linux build, hopefully making it work. --- indra/newview/llgroupmgr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 3fed8bb9b0..9841eda625 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1937,7 +1937,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) { // Reset defaults online_status = "unknown"; - title = titles[0]; + title = (std::string)titles[0]; contribution = 0; member_powers = default_powers; is_owner = false; @@ -1947,7 +1947,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) if(member_info.has("last_login")) { - online_status = member_info["last_login"]; + online_status = (std::string)member_info["last_login"]; if(online_status == "Online") online_status = LLTrans::getString("group_member_status_online"); else @@ -1955,7 +1955,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) } if(member_info.has("title")) - title = titles[member_info["title"].asInteger()]; + title = (std::string)titles[member_info["title"].asInteger()]; if(member_info.has("powers")) member_powers = llstrtou64(member_info["powers"].asString().c_str(), NULL, 16); -- cgit v1.2.3 From 5520bebaeb486462a3482173ccc8518d9158e0d5 Mon Sep 17 00:00:00 2001 From: Baker Linden Date: Thu, 6 Sep 2012 16:00:59 -0700 Subject: Do the proper fix this time... --- indra/newview/llgroupmgr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 9841eda625..9c0a30e689 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1937,7 +1937,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) { // Reset defaults online_status = "unknown"; - title = (std::string)titles[0]; + title = titles[0].asString(); contribution = 0; member_powers = default_powers; is_owner = false; @@ -1947,7 +1947,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) if(member_info.has("last_login")) { - online_status = (std::string)member_info["last_login"]; + online_status = member_info["last_login"].asString(); if(online_status == "Online") online_status = LLTrans::getString("group_member_status_online"); else @@ -1955,7 +1955,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) } if(member_info.has("title")) - title = (std::string)titles[member_info["title"].asInteger()]; + title = titles[member_info["title"].asInteger()].asString(); if(member_info.has("powers")) member_powers = llstrtou64(member_info["powers"].asString().c_str(), NULL, 16); -- cgit v1.2.3 From 3759a91ba70939c04e12202fe53673f51accab72 Mon Sep 17 00:00:00 2001 From: Baker Linden Date: Mon, 10 Sep 2012 16:30:45 -0700 Subject: Fixed line endings from DOS to UNIX. --- indra/newview/llviewerregion.cpp | 3738 +++++++++++++++++++------------------- 1 file changed, 1869 insertions(+), 1869 deletions(-) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index c00d4e91d7..d825646da0 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1,1869 +1,1869 @@ -/** - * @file llviewerregion.cpp - * @brief Implementation of the LLViewerRegion class. - * - * $LicenseInfo:firstyear=2000&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" - -#include "llviewerregion.h" - -// linden libraries -#include "indra_constants.h" -#include "llavatarnamecache.h" // name lookup cap url -#include "llfloaterreg.h" -#include "llmath.h" -#include "llhttpclient.h" -#include "llregionflags.h" -#include "llregionhandle.h" -#include "llsurface.h" -#include "message.h" -//#include "vmath.h" -#include "v3math.h" -#include "v4math.h" - -#include "llagent.h" -#include "llagentcamera.h" -#include "llcallingcard.h" -#include "llcaphttpsender.h" -#include "llcapabilitylistener.h" -#include "llcommandhandler.h" -#include "lldir.h" -#include "lleventpoll.h" -#include "llfloatergodtools.h" -#include "llfloaterreporter.h" -#include "llfloaterregioninfo.h" -#include "llhttpnode.h" -#include "llregioninfomodel.h" -#include "llsdutil.h" -#include "llstartup.h" -#include "lltrans.h" -#include "llurldispatcher.h" -#include "llviewerobjectlist.h" -#include "llviewerparceloverlay.h" -#include "llviewerstatsrecorder.h" -#include "llvlmanager.h" -#include "llvlcomposition.h" -#include "llvocache.h" -#include "llworld.h" -#include "llspatialpartition.h" -#include "stringize.h" -#include "llviewercontrol.h" -#include "llsdserialize.h" - -#ifdef LL_WINDOWS - #pragma warning(disable:4355) -#endif - -const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region -const S16 MAX_MAP_DIST = 10; -// The server only keeps our pending agent info for 60 seconds. -// We want to allow for seed cap retry, but its not useful after that 60 seconds. -// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up. -const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; -const F32 CAP_REQUEST_TIMEOUT = 18; -// Even though we gave up on login, keep trying for caps after we are logged in: -const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; - -typedef std::map CapabilityMap; - -class LLViewerRegionImpl { -public: - LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) - : mHost(host), - mCompositionp(NULL), - mEventPoll(NULL), - mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), - mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), - mSeedCapAttempts(0), - mHttpResponderID(0), - // I'd prefer to set the LLCapabilityListener name to match the region - // name -- it's disappointing that's not available at construction time. - // We could instead store an LLCapabilityListener*, making - // setRegionNameAndZone() replace the instance. Would that pose - // consistency problems? Can we even request a capability before calling - // setRegionNameAndZone()? - // For testability -- the new Michael Feathers paradigm -- - // LLCapabilityListener binds all the globals it expects to need at - // construction time. - mCapabilityListener(host.getString(), gMessageSystem, *region, - gAgent.getID(), gAgent.getSessionID()) - { - } - - void buildCapabilityNames(LLSD& capabilityNames); - - // The surfaces and other layers - LLSurface* mLandp; - - // Region geometry data - LLVector3d mOriginGlobal; // Location of southwest corner of region (meters) - LLVector3d mCenterGlobal; // Location of center in world space (meters) - LLHost mHost; - - // The unique ID for this region. - LLUUID mRegionID; - - // region/estate owner - usually null. - LLUUID mOwnerID; - - // Network statistics for the region's circuit... - LLTimer mLastNetUpdate; - - // Misc - LLVLComposition *mCompositionp; // Composition layer for the surface - - LLVOCacheEntry::vocache_entry_map_t mCacheMap; - // time? - // LRU info? - - // Cache ID is unique per-region, across renames, moving locations, - // etc. - LLUUID mCacheID; - - CapabilityMap mCapabilities; - - LLEventPoll* mEventPoll; - - S32 mSeedCapMaxAttempts; - S32 mSeedCapMaxAttemptsBeforeLogin; - S32 mSeedCapAttempts; - - S32 mHttpResponderID; - - /// Post an event to this LLCapabilityListener to invoke a capability message on - /// this LLViewerRegion's server - /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) - LLCapabilityListener mCapabilityListener; - - //spatial partitions for objects in this region - std::vector mObjectPartition; -}; - -// support for secondlife:///app/region/{REGION} SLapps -// N.B. this is defined to work exactly like the classic secondlife://{REGION} -// However, the later syntax cannot support spaces in the region name because -// spaces (and %20 chars) are illegal in the hostname of an http URL. Some -// browsers let you get away with this, but some do not (such as Qt's Webkit). -// Hence we introduced the newer secondlife:///app/region alternative. -class LLRegionHandler : public LLCommandHandler -{ -public: - // requests will be throttled from a non-trusted browser - LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {} - - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) - { - // make sure that we at least have a region name - int num_params = params.size(); - if (num_params < 1) - { - return false; - } - - // build a secondlife://{PLACE} SLurl from this SLapp - std::string url = "secondlife://"; - for (int i = 0; i < num_params; i++) - { - if (i > 0) - { - url += "/"; - } - url += params[i].asString(); - } - - // Process the SLapp as if it was a secondlife://{PLACE} SLurl - LLURLDispatcher::dispatch(url, "clicked", web, true); - return true; - } -}; -LLRegionHandler gRegionHandler; - -class BaseCapabilitiesComplete : public LLHTTPClient::Responder -{ - LOG_CLASS(BaseCapabilitiesComplete); -public: - BaseCapabilitiesComplete(U64 region_handle, S32 id) - : mRegionHandle(region_handle), mID(id) - { } - virtual ~BaseCapabilitiesComplete() - { } - - void error(U32 statusNum, const std::string& reason) - { - LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL; - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if (regionp) - { - regionp->failedSeedCapability(); - } - } - - void result(const LLSD& content) - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if(!regionp) //region was removed - { - LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } - if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder - { - LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL; - return ; - } - - LLSD::map_const_iterator iter; - for(iter = content.beginMap(); iter != content.endMap(); ++iter) - { - regionp->setCapability(iter->first, iter->second); - LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " - << iter->first << LL_ENDL; - - /* HACK we're waiting for the ServerReleaseNotes */ - if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested()) - { - regionp->showReleaseNotes(); - } - } - - regionp->setCapabilitiesReceived(true); - - if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - } - - static boost::intrusive_ptr build( U64 region_handle, S32 id ) - { - return boost::intrusive_ptr( - new BaseCapabilitiesComplete(region_handle, id) ); - } - -private: - U64 mRegionHandle; - S32 mID; -}; - - -LLViewerRegion::LLViewerRegion(const U64 &handle, - const LLHost &host, - const U32 grids_per_region_edge, - const U32 grids_per_patch_edge, - const F32 region_width_meters) -: mImpl(new LLViewerRegionImpl(this, host)), - mHandle(handle), - mTimeDilation(1.0f), - mName(""), - mZoning(""), - mIsEstateManager(FALSE), - mRegionFlags( REGION_FLAGS_DEFAULT ), - mSimAccess( SIM_ACCESS_MIN ), - mBillableFactor(1.0), - mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), - mClassID(0), - mCPURatio(0), - mColoName("unknown"), - mProductSKU("unknown"), - mProductName("unknown"), - mHttpUrl(""), - mCacheLoaded(FALSE), - mCacheDirty(FALSE), - mReleaseNotesRequested(FALSE), - mCapabilitiesReceived(false) -{ - mWidth = region_width_meters; - mImpl->mOriginGlobal = from_region_handle(handle); - updateRenderMatrix(); - - mImpl->mLandp = new LLSurface('l', NULL); - - // Create the composition layer for the surface - mImpl->mCompositionp = - new LLVLComposition(mImpl->mLandp, - grids_per_region_edge, - region_width_meters / grids_per_region_edge); - mImpl->mCompositionp->setSurface(mImpl->mLandp); - - // Create the surfaces - mImpl->mLandp->setRegion(this); - mImpl->mLandp->create(grids_per_region_edge, - grids_per_patch_edge, - mImpl->mOriginGlobal, - mWidth); - - mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters); - - setOriginGlobal(from_region_handle(handle)); - calculateCenterGlobal(); - - // Create the object lists - initStats(); - - //create object partitions - //MUST MATCH declaration of eObjectPartitions - mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD - mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN - mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER - mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER - mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE - mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE - mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS - mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME - mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE - mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE - mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE -} - - -void LLViewerRegion::initStats() -{ - mImpl->mLastNetUpdate.reset(); - mPacketsIn = 0; - mBitsIn = 0; - mLastBitsIn = 0; - mLastPacketsIn = 0; - mPacketsOut = 0; - mLastPacketsOut = 0; - mPacketsLost = 0; - mLastPacketsLost = 0; - mPingDelay = 0; - mAlive = false; // can become false if circuit disconnects -} - -LLViewerRegion::~LLViewerRegion() -{ - gVLManager.cleanupData(this); - // Can't do this on destruction, because the neighbor pointers might be invalid. - // This should be reference counted... - disconnectAllNeighbors(); - LLViewerPartSim::getInstance()->cleanupRegion(this); - - gObjectList.killObjects(this); - - delete mImpl->mCompositionp; - delete mParcelOverlay; - delete mImpl->mLandp; - delete mImpl->mEventPoll; - LLHTTPSender::clearSender(mImpl->mHost); - - saveObjectCache(); - - std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); - - delete mImpl; - mImpl = NULL; -} - -LLEventPump& LLViewerRegion::getCapAPI() const -{ - return mImpl->mCapabilityListener.getCapAPI(); -} - -/*virtual*/ -const LLHost& LLViewerRegion::getHost() const -{ - return mImpl->mHost; -} - -LLSurface & LLViewerRegion::getLand() const -{ - return *mImpl->mLandp; -} - -const LLUUID& LLViewerRegion::getRegionID() const -{ - return mImpl->mRegionID; -} - -void LLViewerRegion::setRegionID(const LLUUID& region_id) -{ - mImpl->mRegionID = region_id; -} - -void LLViewerRegion::loadObjectCache() -{ - if (mCacheLoaded) - { - return; - } - - // Presume success. If it fails, we don't want to try again. - mCacheLoaded = TRUE; - - if(LLVOCache::hasInstance()) - { - LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ; - } -} - - -void LLViewerRegion::saveObjectCache() -{ - if (!mCacheLoaded) - { - return; - } - - if (mImpl->mCacheMap.empty()) - { - return; - } - - if(LLVOCache::hasInstance()) - { - LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ; - mCacheDirty = FALSE; - } - - for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) - { - delete iter->second; - } - mImpl->mCacheMap.clear(); -} - -void LLViewerRegion::sendMessage() -{ - gMessageSystem->sendMessage(mImpl->mHost); -} - -void LLViewerRegion::sendReliableMessage() -{ - gMessageSystem->sendReliable(mImpl->mHost); -} - -void LLViewerRegion::setFlags(BOOL b, U32 flags) -{ - if (b) - { - mRegionFlags |= flags; - } - else - { - mRegionFlags &= ~flags; - } -} - -void LLViewerRegion::setWaterHeight(F32 water_level) -{ - mImpl->mLandp->setWaterHeight(water_level); -} - -F32 LLViewerRegion::getWaterHeight() const -{ - return mImpl->mLandp->getWaterHeight(); -} - -BOOL LLViewerRegion::isVoiceEnabled() const -{ - return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE); -} - -void LLViewerRegion::setRegionFlags(U32 flags) -{ - mRegionFlags = flags; -} - - -void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) -{ - mImpl->mOriginGlobal = origin_global; - updateRenderMatrix(); - mImpl->mLandp->setOriginGlobal(origin_global); - mWind.setOriginGlobal(origin_global); - calculateCenterGlobal(); -} - -void LLViewerRegion::updateRenderMatrix() -{ - mRenderMatrix.setTranslation(getOriginAgent()); -} - -void LLViewerRegion::setTimeDilation(F32 time_dilation) -{ - mTimeDilation = time_dilation; -} - -const LLVector3d & LLViewerRegion::getOriginGlobal() const -{ - return mImpl->mOriginGlobal; -} - -LLVector3 LLViewerRegion::getOriginAgent() const -{ - return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal); -} - -const LLVector3d & LLViewerRegion::getCenterGlobal() const -{ - return mImpl->mCenterGlobal; -} - -LLVector3 LLViewerRegion::getCenterAgent() const -{ - return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal); -} - -void LLViewerRegion::setOwner(const LLUUID& owner_id) -{ - mImpl->mOwnerID = owner_id; -} - -const LLUUID& LLViewerRegion::getOwner() const -{ - return mImpl->mOwnerID; -} - -void LLViewerRegion::setRegionNameAndZone (const std::string& name_zone) -{ - std::string::size_type pipe_pos = name_zone.find('|'); - S32 length = name_zone.size(); - if (pipe_pos != std::string::npos) - { - mName = name_zone.substr(0, pipe_pos); - mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1)); - } - else - { - mName = name_zone; - mZoning = ""; - } - - LLStringUtil::stripNonprintable(mName); - LLStringUtil::stripNonprintable(mZoning); -} - -BOOL LLViewerRegion::canManageEstate() const -{ - return gAgent.isGodlike() - || isEstateManager() - || gAgent.getID() == getOwner(); -} - -const std::string LLViewerRegion::getSimAccessString() const -{ - return accessToString(mSimAccess); -} - -std::string LLViewerRegion::getLocalizedSimProductName() const -{ - std::string localized_spn; - return LLTrans::findString(localized_spn, mProductName) ? localized_spn : mProductName; -} - -// static -std::string LLViewerRegion::regionFlagsToString(U32 flags) -{ - std::string result; - - if (flags & REGION_FLAGS_SANDBOX) - { - result += "Sandbox"; - } - - if (flags & REGION_FLAGS_ALLOW_DAMAGE) - { - result += " Not Safe"; - } - - return result; -} - -// static -std::string LLViewerRegion::accessToString(U8 sim_access) -{ - switch(sim_access) - { - case SIM_ACCESS_PG: - return LLTrans::getString("SIM_ACCESS_PG"); - - case SIM_ACCESS_MATURE: - return LLTrans::getString("SIM_ACCESS_MATURE"); - - case SIM_ACCESS_ADULT: - return LLTrans::getString("SIM_ACCESS_ADULT"); - - case SIM_ACCESS_DOWN: - return LLTrans::getString("SIM_ACCESS_DOWN"); - - case SIM_ACCESS_MIN: - default: - return LLTrans::getString("SIM_ACCESS_MIN"); - } -} - -// static -std::string LLViewerRegion::getAccessIcon(U8 sim_access) -{ - switch(sim_access) - { - case SIM_ACCESS_MATURE: - return "Parcel_M_Dark"; - - case SIM_ACCESS_ADULT: - return "Parcel_R_Light"; - - case SIM_ACCESS_PG: - return "Parcel_PG_Light"; - - case SIM_ACCESS_MIN: - default: - return ""; - } -} - -// static -std::string LLViewerRegion::accessToShortString(U8 sim_access) -{ - switch(sim_access) /* Flawfinder: ignore */ - { - case SIM_ACCESS_PG: - return "PG"; - - case SIM_ACCESS_MATURE: - return "M"; - - case SIM_ACCESS_ADULT: - return "A"; - - case SIM_ACCESS_MIN: - default: - return "U"; - } -} - -// static -U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) -{ - U8 accessValue; - - if (LLStringUtil::compareStrings(sim_access, "PG") == 0) - { - accessValue = SIM_ACCESS_PG; - } - else if (LLStringUtil::compareStrings(sim_access, "M") == 0) - { - accessValue = SIM_ACCESS_MATURE; - } - else if (LLStringUtil::compareStrings(sim_access, "A") == 0) - { - accessValue = SIM_ACCESS_ADULT; - } - else - { - accessValue = SIM_ACCESS_MIN; - } - - return accessValue; -} - -// static -void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) -{ - // send it to 'observers' - // *TODO: switch the floaters to using LLRegionInfoModel - llinfos << "Processing region info" << llendl; - LLRegionInfoModel::instance().update(msg); - LLFloaterGodTools::processRegionInfo(msg); - LLFloaterRegionInfo::processRegionInfo(msg); - LLFloaterReporter::processRegionInfo(msg); -} - -void LLViewerRegion::setCacheID(const LLUUID& id) -{ - mImpl->mCacheID = id; -} - -S32 LLViewerRegion::renderPropertyLines() -{ - if (mParcelOverlay) - { - return mParcelOverlay->renderPropertyLines(); - } - else - { - return 0; - } -} - -// This gets called when the height field changes. -void LLViewerRegion::dirtyHeights() -{ - // Property lines need to be reconstructed when the land changes. - if (mParcelOverlay) - { - mParcelOverlay->setDirty(); - } -} - -BOOL LLViewerRegion::idleUpdate(F32 max_update_time) -{ - LLMemType mt_ivr(LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION); - // did_update returns TRUE if we did at least one significant update - BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time); - - if (mParcelOverlay) - { - // Hopefully not a significant time sink... - mParcelOverlay->idleUpdate(); - } - - return did_update; -} - - -// As above, but forcibly do the update. -void LLViewerRegion::forceUpdate() -{ - mImpl->mLandp->idleUpdate(0.f); - - if (mParcelOverlay) - { - mParcelOverlay->idleUpdate(true); - } -} - -void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction) -{ - mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); -} - - -void LLViewerRegion::disconnectAllNeighbors() -{ - mImpl->mLandp->disconnectAllNeighbors(); -} - -LLVLComposition * LLViewerRegion::getComposition() const -{ - return mImpl->mCompositionp; -} - -F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const -{ - if (x >= 256) - { - if (y >= 256) - { - LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled(255, 255); - F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - else - { - LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y); - F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - } - else if (y >= 256) - { - LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f); - F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - - return getComposition()->getValueScaled((F32)x, (F32)y); -} - -void LLViewerRegion::calculateCenterGlobal() -{ - mImpl->mCenterGlobal = mImpl->mOriginGlobal; - mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth; - mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth; - mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ(); -} - -void LLViewerRegion::calculateCameraDistance() -{ - mCameraDistanceSquared = (F32)(gAgentCamera.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared(); -} - -std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion) -{ - s << "{ "; - s << region.mImpl->mHost; - s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n"; - std::string name(region.getName()), zone(region.getZoning()); - if (! name.empty()) - { - s << " mName = " << name << '\n'; - } - if (! zone.empty()) - { - s << " mZoning = " << zone << '\n'; - } - s << "}"; - return s; -} - - -// ---------------- Protected Member Functions ---------------- - -void LLViewerRegion::updateNetStats() -{ - F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32(); - - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); - if (!cdp) - { - mAlive = false; - return; - } - - mAlive = true; - mDeltaTime = dt; - - mLastPacketsIn = mPacketsIn; - mLastBitsIn = mBitsIn; - mLastPacketsOut = mPacketsOut; - mLastPacketsLost = mPacketsLost; - - mPacketsIn = cdp->getPacketsIn(); - mBitsIn = 8 * cdp->getBytesIn(); - mPacketsOut = cdp->getPacketsOut(); - mPacketsLost = cdp->getPacketsLost(); - mPingDelay = cdp->getPingDelay(); - - mBitStat.addValue(mBitsIn - mLastBitsIn); - mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); - mPacketsLostStat.addValue(mPacketsLost); -} - - -U32 LLViewerRegion::getPacketsLost() const -{ - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); - if (!cdp) - { - llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << llendl; - return 0; - } - else - { - return cdp->getPacketsLost(); - } -} - -S32 LLViewerRegion::getHttpResponderID() const -{ - return mImpl->mHttpResponderID; -} - -BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const -{ - LLVector3 pos_region = getPosRegionFromGlobal(point_global); - - if (pos_region.mV[VX] < 0) - { - return FALSE; - } - if (pos_region.mV[VX] >= mWidth) - { - return FALSE; - } - if (pos_region.mV[VY] < 0) - { - return FALSE; - } - if (pos_region.mV[VY] >= mWidth) - { - return FALSE; - } - return TRUE; -} - -LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const -{ - LLVector3 pos_region; - pos_region.setVec(point_global - mImpl->mOriginGlobal); - return pos_region; -} - -LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) const -{ - LLVector3d pos_region_d; - pos_region_d.setVec(pos_region); - return pos_region_d + mImpl->mOriginGlobal; -} - -LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const -{ - LLVector3d pos_global = getPosGlobalFromRegion(pos_region); - - return gAgent.getPosAgentFromGlobal(pos_global); -} - -LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const -{ - return pos_agent - getOriginAgent(); -} - -F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos) -{ - return mImpl->mLandp->resolveHeightRegion( region_pos ); -} - -bool LLViewerRegion::isAlive() -{ - return mAlive; -} - -BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos) -{ - if (mParcelOverlay) - { - return mParcelOverlay->isOwnedSelf(pos); - } else { - return FALSE; - } -} - -// Owned by a group you belong to? (officer or member) -BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos) -{ - if (mParcelOverlay) - { - return mParcelOverlay->isOwnedGroup(pos); - } else { - return FALSE; - } -} - -// the new TCP coarse location handler node -class CoarseLocationUpdate : public LLHTTPNode -{ -public: - virtual void post( - ResponsePtr responder, - const LLSD& context, - const LLSD& input) const - { - LLHost host(input["sender"].asString()); - LLViewerRegion* region = LLWorld::getInstance()->getRegion(host); - if( !region ) - { - return; - } - - S32 target_index = input["body"]["Index"][0]["Prey"].asInteger(); - S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); - - LLDynamicArray* avatar_locs = ®ion->mMapAvatars; - LLDynamicArray* avatar_ids = ®ion->mMapAvatarIDs; - avatar_locs->reset(); - avatar_ids->reset(); - - //llinfos << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << llendl; - //llinfos << "my agent id = " << gAgent.getID() << llendl; - //llinfos << ll_pretty_print_sd(input) << llendl; - - LLSD - locs = input["body"]["Location"], - agents = input["body"]["AgentData"]; - LLSD::array_iterator - locs_it = locs.beginArray(), - agents_it = agents.beginArray(); - BOOL has_agent_data = input["body"].has("AgentData"); - - for(int i=0; - locs_it != locs.endArray(); - i++, locs_it++) - { - U8 - x = locs_it->get("X").asInteger(), - y = locs_it->get("Y").asInteger(), - z = locs_it->get("Z").asInteger(); - // treat the target specially for the map, and don't add you or the target - if(i == target_index) - { - LLVector3d global_pos(region->getOriginGlobal()); - global_pos.mdV[VX] += (F64)x; - global_pos.mdV[VY] += (F64)y; - global_pos.mdV[VZ] += (F64)z * 4.0; - LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); - } - else if( i != you_index) - { - U32 loc = x << 16 | y << 8 | z; loc = loc; - U32 pos = 0x0; - pos |= x; - pos <<= 8; - pos |= y; - pos <<= 8; - pos |= z; - avatar_locs->put(pos); - //llinfos << "next pos: " << x << "," << y << "," << z << ": " << pos << llendl; - if(has_agent_data) // for backwards compatibility with old message format - { - LLUUID agent_id(agents_it->get("AgentID").asUUID()); - //llinfos << "next agent: " << agent_id.asString() << llendl; - avatar_ids->put(agent_id); - } - } - if (has_agent_data) - { - agents_it++; - } - } - } -}; - -// build the coarse location HTTP node under the "/message" URL -LLHTTPRegistration - gHTTPRegistrationCoarseLocationUpdate( - "/message/CoarseLocationUpdate"); - - -// the deprecated coarse location handler -void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg) -{ - //llinfos << "CoarseLocationUpdate" << llendl; - mMapAvatars.reset(); - mMapAvatarIDs.reset(); // only matters in a rare case but it's good to be safe. - - U8 x_pos = 0; - U8 y_pos = 0; - U8 z_pos = 0; - - U32 pos = 0x0; - - S16 agent_index; - S16 target_index; - msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index); - msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index); - - BOOL has_agent_data = msg->has(_PREHASH_AgentData); - S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location); - for(S32 i = 0; i < count; i++) - { - msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i); - msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i); - msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i); - LLUUID agent_id = LLUUID::null; - if(has_agent_data) - { - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id, i); - } - - //llinfos << " object X: " << (S32)x_pos << " Y: " << (S32)y_pos - // << " Z: " << (S32)(z_pos * 4) - // << llendl; - - // treat the target specially for the map - if(i == target_index) - { - LLVector3d global_pos(mImpl->mOriginGlobal); - global_pos.mdV[VX] += (F64)(x_pos); - global_pos.mdV[VY] += (F64)(y_pos); - global_pos.mdV[VZ] += (F64)(z_pos) * 4.0; - LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); - } - - //don't add you - if( i != agent_index) - { - pos = 0x0; - pos |= x_pos; - pos <<= 8; - pos |= y_pos; - pos <<= 8; - pos |= z_pos; - mMapAvatars.put(pos); - if(has_agent_data) - { - mMapAvatarIDs.put(agent_id); - } - } - } -} - -void LLViewerRegion::getInfo(LLSD& info) -{ - info["Region"]["Host"] = getHost().getIPandPort(); - info["Region"]["Name"] = getName(); - U32 x, y; - from_region_handle(getHandle(), &x, &y); - info["Region"]["Handle"]["x"] = (LLSD::Integer)x; - info["Region"]["Handle"]["y"] = (LLSD::Integer)y; -} - -void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) -{ - sim_features = mSimulatorFeatures; - -} - -void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) -{ - std::stringstream str; - - LLSDSerialize::toPrettyXML(sim_features, str); - llinfos << str.str() << llendl; - mSimulatorFeatures = sim_features; -} - -LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) -{ - U32 local_id = objectp->getLocalID(); - U32 crc = objectp->getCRC(); - - LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); - - if (entry) - { - // we've seen this object before - if (entry->getCRC() == crc) - { - // Record a hit - entry->recordDupe(); - return CACHE_UPDATE_DUPE; - } - - // Update the cache entry - mImpl->mCacheMap.erase(local_id); - delete entry; - entry = new LLVOCacheEntry(local_id, crc, dp); - mImpl->mCacheMap[local_id] = entry; - return CACHE_UPDATE_CHANGED; - } - - // we haven't seen this object before - - // Create new entry and add to map - eCacheUpdateResult result = CACHE_UPDATE_ADDED; - if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) - { - delete mImpl->mCacheMap.begin()->second ; - mImpl->mCacheMap.erase(mImpl->mCacheMap.begin()); - result = CACHE_UPDATE_REPLACED; - - } - entry = new LLVOCacheEntry(local_id, crc, dp); - - mImpl->mCacheMap[local_id] = entry; - return result; -} - -// Get data packer for this object, if we have cached data -// AND the CRC matches. JC -LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type) -{ - //llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18 - - LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); - - if (entry) - { - // we've seen this object before - if (entry->getCRC() == crc) - { - // Record a hit - entry->recordHit(); - cache_miss_type = CACHE_MISS_TYPE_NONE; - return entry->getDP(crc); - } - else - { - // llinfos << "CRC miss for " << local_id << llendl; - cache_miss_type = CACHE_MISS_TYPE_CRC; - mCacheMissCRC.put(local_id); - } - } - else - { - // llinfos << "Cache miss for " << local_id << llendl; - cache_miss_type = CACHE_MISS_TYPE_FULL; - mCacheMissFull.put(local_id); - } - - return NULL; -} - -void LLViewerRegion::addCacheMissFull(const U32 local_id) -{ - mCacheMissFull.put(local_id); -} - -void LLViewerRegion::requestCacheMisses() -{ - S32 full_count = mCacheMissFull.count(); - S32 crc_count = mCacheMissCRC.count(); - if (full_count == 0 && crc_count == 0) return; - - LLMessageSystem* msg = gMessageSystem; - BOOL start_new_message = TRUE; - S32 blocks = 0; - S32 i; - - // Send full cache miss updates. For these, we KNOW we don't - // have a viewer object. - for (i = 0; i < full_count; i++) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_RequestMultipleObjects); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL); - msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]); - blocks++; - - if (blocks >= 255) - { - sendReliableMessage(); - start_new_message = TRUE; - blocks = 0; - } - } - - // Send CRC miss updates. For these, we _might_ have a viewer object, - // but probably not. - for (i = 0; i < crc_count; i++) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_RequestMultipleObjects); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC); - msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]); - blocks++; - - if (blocks >= 255) - { - sendReliableMessage(); - start_new_message = TRUE; - blocks = 0; - } - } - - // finish any pending message - if (!start_new_message) - { - sendReliableMessage(); - } - mCacheMissFull.reset(); - mCacheMissCRC.reset(); - - mCacheDirty = TRUE ; - // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; - #if LL_RECORD_VIEWER_STATS - LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); - LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count); - LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); - #endif -} - -void LLViewerRegion::dumpCache() -{ - const S32 BINS = 4; - S32 hit_bin[BINS]; - S32 change_bin[BINS]; - - S32 i; - for (i = 0; i < BINS; ++i) - { - hit_bin[i] = 0; - change_bin[i] = 0; - } - - LLVOCacheEntry *entry; - for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) - { - entry = iter->second ; - - S32 hits = entry->getHitCount(); - S32 changes = entry->getCRCChangeCount(); - - hits = llclamp(hits, 0, BINS-1); - changes = llclamp(changes, 0, BINS-1); - - hit_bin[hits]++; - change_bin[changes]++; - } - - llinfos << "Count " << mImpl->mCacheMap.size() << llendl; - for (i = 0; i < BINS; i++) - { - llinfos << "Hits " << i << " " << hit_bin[i] << llendl; - } - for (i = 0; i < BINS; i++) - { - llinfos << "Changes " << i << " " << change_bin[i] << llendl; - } -} - -void LLViewerRegion::unpackRegionHandshake() -{ - LLMessageSystem *msg = gMessageSystem; - - U32 region_flags; - U8 sim_access; - std::string sim_name; - LLUUID sim_owner; - BOOL is_estate_manager; - F32 water_height; - F32 billable_factor; - LLUUID cache_id; - - msg->getU32 ("RegionInfo", "RegionFlags", region_flags); - msg->getU8 ("RegionInfo", "SimAccess", sim_access); - msg->getString ("RegionInfo", "SimName", sim_name); - msg->getUUID ("RegionInfo", "SimOwner", sim_owner); - msg->getBOOL ("RegionInfo", "IsEstateManager", is_estate_manager); - msg->getF32 ("RegionInfo", "WaterHeight", water_height); - msg->getF32 ("RegionInfo", "BillableFactor", billable_factor); - msg->getUUID ("RegionInfo", "CacheID", cache_id ); - - setRegionFlags(region_flags); - setSimAccess(sim_access); - setRegionNameAndZone(sim_name); - setOwner(sim_owner); - setIsEstateManager(is_estate_manager); - setWaterHeight(water_height); - setBillableFactor(billable_factor); - setCacheID(cache_id); - - LLUUID region_id; - msg->getUUID("RegionInfo2", "RegionID", region_id); - setRegionID(region_id); - - // Retrieve the CR-53 (Homestead/Land SKU) information - S32 classID = 0; - S32 cpuRatio = 0; - std::string coloName; - std::string productSKU; - std::string productName; - - // the only reasonable way to decide if we actually have any data is to - // check to see if any of these fields have positive sizes - if (msg->getSize("RegionInfo3", "ColoName") > 0 || - msg->getSize("RegionInfo3", "ProductSKU") > 0 || - msg->getSize("RegionInfo3", "ProductName") > 0) - { - msg->getS32 ("RegionInfo3", "CPUClassID", classID); - msg->getS32 ("RegionInfo3", "CPURatio", cpuRatio); - msg->getString ("RegionInfo3", "ColoName", coloName); - msg->getString ("RegionInfo3", "ProductSKU", productSKU); - msg->getString ("RegionInfo3", "ProductName", productName); - - mClassID = classID; - mCPURatio = cpuRatio; - mColoName = coloName; - mProductSKU = productSKU; - mProductName = productName; - } - - LLVLComposition *compp = getComposition(); - if (compp) - { - LLUUID tmp_id; - - msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); - compp->setDetailTextureID(0, tmp_id); - msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); - compp->setDetailTextureID(1, tmp_id); - msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); - compp->setDetailTextureID(2, tmp_id); - msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); - compp->setDetailTextureID(3, tmp_id); - - F32 tmp_f32; - msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32); - compp->setStartHeight(0, tmp_f32); - msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32); - compp->setStartHeight(1, tmp_f32); - msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32); - compp->setStartHeight(2, tmp_f32); - msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32); - compp->setStartHeight(3, tmp_f32); - - msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32); - compp->setHeightRange(0, tmp_f32); - msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32); - compp->setHeightRange(1, tmp_f32); - msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32); - compp->setHeightRange(2, tmp_f32); - msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32); - compp->setHeightRange(3, tmp_f32); - - // If this is an UPDATE (params already ready, we need to regenerate - // all of our terrain stuff, by - if (compp->getParamsReady()) - { - //this line creates frame stalls on region crossing and removing it appears to have no effect - //getLand().dirtyAllPatches(); - } - else - { - compp->setParamsReady(); - } - } - - - // Now that we have the name, we can load the cache file - // off disk. - loadObjectCache(); - - // After loading cache, signal that simulator can start - // sending data. - // TODO: Send all upstream viewer->sim handshake info here. - LLHost host = msg->getSender(); - msg->newMessage("RegionHandshakeReply"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("RegionInfo"); - msg->addU32("Flags", 0x0 ); - msg->sendReliable(host); -} - -void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) -{ - capabilityNames.append("AgentState"); - capabilityNames.append("AttachmentResources"); - capabilityNames.append("AvatarPickerSearch"); - capabilityNames.append("CharacterProperties"); - capabilityNames.append("ChatSessionRequest"); - capabilityNames.append("CopyInventoryFromNotecard"); - capabilityNames.append("CreateInventoryCategory"); - capabilityNames.append("DispatchRegionInfo"); - capabilityNames.append("EnvironmentSettings"); - capabilityNames.append("EstateChangeInfo"); - capabilityNames.append("EventQueueGet"); - - if (gSavedSettings.getBOOL("UseHTTPInventory")) - { - capabilityNames.append("FetchLib2"); - capabilityNames.append("FetchLibDescendents2"); - capabilityNames.append("FetchInventory2"); - capabilityNames.append("FetchInventoryDescendents2"); - } - - capabilityNames.append("GetDisplayNames"); - capabilityNames.append("GetMesh"); - capabilityNames.append("GetObjectCost"); - capabilityNames.append("GetObjectPhysicsData"); - capabilityNames.append("GetTexture"); - capabilityNames.append("GroupMemberData"); - capabilityNames.append("GroupProposalBallot"); - capabilityNames.append("HomeLocation"); - capabilityNames.append("LandResources"); - capabilityNames.append("MapLayer"); - capabilityNames.append("MapLayerGod"); - capabilityNames.append("MeshUploadFlag"); - capabilityNames.append("NavMeshGenerationStatus"); - capabilityNames.append("NewFileAgentInventory"); - capabilityNames.append("ObjectMedia"); - capabilityNames.append("ObjectMediaNavigate"); - capabilityNames.append("ObjectNavMeshProperties"); - capabilityNames.append("ParcelPropertiesUpdate"); - capabilityNames.append("ParcelVoiceInfoRequest"); - capabilityNames.append("ProductInfoRequest"); - capabilityNames.append("ProvisionVoiceAccountRequest"); - capabilityNames.append("RemoteParcelRequest"); - capabilityNames.append("RequestTextureDownload"); - capabilityNames.append("ResourceCostSelected"); - capabilityNames.append("RetrieveNavMeshSrc"); - capabilityNames.append("SearchStatRequest"); - capabilityNames.append("SearchStatTracking"); - capabilityNames.append("SendPostcard"); - capabilityNames.append("SendUserReport"); - capabilityNames.append("SendUserReportWithScreenshot"); - capabilityNames.append("ServerReleaseNotes"); - capabilityNames.append("SetDisplayName"); - capabilityNames.append("SimConsoleAsync"); - capabilityNames.append("SimulatorFeatures"); - capabilityNames.append("StartGroupProposal"); - capabilityNames.append("TerrainNavMeshProperties"); - capabilityNames.append("TextureStats"); - capabilityNames.append("UntrustedSimulatorMessage"); - capabilityNames.append("UpdateAgentInformation"); - capabilityNames.append("UpdateAgentLanguage"); - capabilityNames.append("UpdateGestureAgentInventory"); - capabilityNames.append("UpdateGestureTaskInventory"); - capabilityNames.append("UpdateNotecardAgentInventory"); - capabilityNames.append("UpdateNotecardTaskInventory"); - capabilityNames.append("UpdateScriptAgent"); - capabilityNames.append("UpdateScriptTask"); - capabilityNames.append("UploadBakedTexture"); - capabilityNames.append("ViewerMetrics"); - capabilityNames.append("ViewerStartAuction"); - capabilityNames.append("ViewerStats"); - - // Please add new capabilities alphabetically to reduce - // merge conflicts. -} - -void LLViewerRegion::setSeedCapability(const std::string& url) -{ - if (getCapability("Seed") == url) - { - // llwarns << "Ignoring duplicate seed capability" << llendl; - return; - } - - delete mImpl->mEventPoll; - mImpl->mEventPoll = NULL; - - mImpl->mCapabilities.clear(); - setCapability("Seed", url); - - LLSD capabilityNames = LLSD::emptyArray(); - mImpl->buildCapabilityNames(capabilityNames); - - llinfos << "posting to seed " << url << llendl; - - S32 id = ++mImpl->mHttpResponderID; - LLHTTPClient::post(url, capabilityNames, - BaseCapabilitiesComplete::build(getHandle(), id), - LLSD(), CAP_REQUEST_TIMEOUT); -} - -S32 LLViewerRegion::getNumSeedCapRetries() -{ - return mImpl->mSeedCapAttempts; -} - -void LLViewerRegion::failedSeedCapability() -{ - // Should we retry asking for caps? - mImpl->mSeedCapAttempts++; - std::string url = getCapability("Seed"); - if ( url.empty() ) - { - LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL; - return; - } - // After a few attempts, continue login. We will keep trying once in-world: - if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin && - STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() ) - { - LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); - } - - if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts) - { - LLSD capabilityNames = LLSD::emptyArray(); - mImpl->buildCapabilityNames(capabilityNames); - - llinfos << "posting to seed " << url << " (retry " - << mImpl->mSeedCapAttempts << ")" << llendl; - - S32 id = ++mImpl->mHttpResponderID; - LLHTTPClient::post(url, capabilityNames, - BaseCapabilitiesComplete::build(getHandle(), id), - LLSD(), CAP_REQUEST_TIMEOUT); - } - else - { - // *TODO: Give a user pop-up about this error? - LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts. Giving up!" << LL_ENDL; - } -} - -class SimulatorFeaturesReceived : public LLHTTPClient::Responder -{ - LOG_CLASS(SimulatorFeaturesReceived); -public: - SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, - S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) - : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) - { } - - - void error(U32 statusNum, const std::string& reason) - { - LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; - retry(); - } - - void result(const LLSD& content) - { - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); - if(!regionp) //region is removed or responder is not created. - { - LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL; - return ; - } - - regionp->setSimulatorFeatures(content); - } - -private: - void retry() - { - if (mAttempt < mMaxAttempts) - { - mAttempt++; - LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; - LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); - } - } - - std::string mRetryURL; - U64 mRegionHandle; - S32 mAttempt; - S32 mMaxAttempts; -}; - - -void LLViewerRegion::setCapability(const std::string& name, const std::string& url) -{ - if(name == "EventQueueGet") - { - delete mImpl->mEventPoll; - mImpl->mEventPoll = NULL; - mImpl->mEventPoll = new LLEventPoll(url, getHost()); - } - else if(name == "UntrustedSimulatorMessage") - { - LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url)); - } - else if (name == "SimulatorFeatures") - { - // kick off a request for simulator features - LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT); - } - else - { - mImpl->mCapabilities[name] = url; - if(name == "GetTexture") - { - mHttpUrl = url ; - } - } -} - -bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) -{ - return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; -} - -std::string LLViewerRegion::getCapability(const std::string& name) const -{ - CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); - if(iter == mImpl->mCapabilities.end()) - { - return ""; - } - - return iter->second; -} - -bool LLViewerRegion::capabilitiesReceived() const -{ - return mCapabilitiesReceived; -} - -void LLViewerRegion::setCapabilitiesReceived(bool received) -{ - mCapabilitiesReceived = received; - - // Tell interested parties that we've received capabilities, - // so that they can safely use getCapability(). - if (received) - { - mCapabilitiesReceivedSignal(getRegionID()); - - // This is a single-shot signal. Forget callbacks to save resources. - mCapabilitiesReceivedSignal.disconnect_all_slots(); - } -} - -boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb) -{ - return mCapabilitiesReceivedSignal.connect(cb); -} - -void LLViewerRegion::logActiveCapabilities() const -{ - int count = 0; - CapabilityMap::const_iterator iter; - for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count) - { - if (!iter->second.empty()) - { - llinfos << iter->first << " URL is " << iter->second << llendl; - } - } - llinfos << "Dumped " << count << " entries." << llendl; -} - -LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) -{ - if (type < mImpl->mObjectPartition.size()) - { - return mImpl->mObjectPartition[type]; - } - return NULL; -} - -// the viewer can not yet distinquish between normal- and estate-owned objects -// so we collapse these two bits and enable the UI if either are set -const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT - | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; - -bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const -{ - return (mParcelOverlay != NULL) - && (mParcelOverlay->isOwnedSelf(pos) - || mParcelOverlay->isOwnedGroup(pos) - || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) - && mParcelOverlay->encroachesOwned(boxes)) ); -} - -bool LLViewerRegion::childrenObjectReturnable( const std::vector& boxes ) const -{ - bool result = false; - result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0; - return result; -} - -bool LLViewerRegion::objectsCrossParcel(const std::vector& boxes) const -{ - return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes); -} - -void LLViewerRegion::getNeighboringRegions( std::vector& uniqueRegions ) -{ - mImpl->mLandp->getNeighboringRegions( uniqueRegions ); -} -void LLViewerRegion::getNeighboringRegionsStatus( std::vector& regions ) -{ - mImpl->mLandp->getNeighboringRegionsStatus( regions ); -} -void LLViewerRegion::showReleaseNotes() -{ - std::string url = this->getCapability("ServerReleaseNotes"); - - if (url.empty()) { - // HACK haven't received the capability yet, we'll wait until - // it arives. - mReleaseNotesRequested = TRUE; - return; - } - - LLWeb::loadURL(url); - mReleaseNotesRequested = FALSE; -} - -std::string LLViewerRegion::getDescription() const -{ - return stringize(*this); -} - -bool LLViewerRegion::meshUploadEnabled() const -{ - return (mSimulatorFeatures.has("MeshUploadEnabled") && - mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); -} - -bool LLViewerRegion::meshRezEnabled() const -{ - return (mSimulatorFeatures.has("MeshRezEnabled") && - mSimulatorFeatures["MeshRezEnabled"].asBoolean()); -} - -bool LLViewerRegion::dynamicPathfindingEnabled() const -{ - return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") && - mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); -} - +/** + * @file llviewerregion.cpp + * @brief Implementation of the LLViewerRegion class. + * + * $LicenseInfo:firstyear=2000&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" + +#include "llviewerregion.h" + +// linden libraries +#include "indra_constants.h" +#include "llavatarnamecache.h" // name lookup cap url +#include "llfloaterreg.h" +#include "llmath.h" +#include "llhttpclient.h" +#include "llregionflags.h" +#include "llregionhandle.h" +#include "llsurface.h" +#include "message.h" +//#include "vmath.h" +#include "v3math.h" +#include "v4math.h" + +#include "llagent.h" +#include "llagentcamera.h" +#include "llcallingcard.h" +#include "llcaphttpsender.h" +#include "llcapabilitylistener.h" +#include "llcommandhandler.h" +#include "lldir.h" +#include "lleventpoll.h" +#include "llfloatergodtools.h" +#include "llfloaterreporter.h" +#include "llfloaterregioninfo.h" +#include "llhttpnode.h" +#include "llregioninfomodel.h" +#include "llsdutil.h" +#include "llstartup.h" +#include "lltrans.h" +#include "llurldispatcher.h" +#include "llviewerobjectlist.h" +#include "llviewerparceloverlay.h" +#include "llviewerstatsrecorder.h" +#include "llvlmanager.h" +#include "llvlcomposition.h" +#include "llvocache.h" +#include "llworld.h" +#include "llspatialpartition.h" +#include "stringize.h" +#include "llviewercontrol.h" +#include "llsdserialize.h" + +#ifdef LL_WINDOWS + #pragma warning(disable:4355) +#endif + +const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region +const S16 MAX_MAP_DIST = 10; +// The server only keeps our pending agent info for 60 seconds. +// We want to allow for seed cap retry, but its not useful after that 60 seconds. +// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up. +const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; +const F32 CAP_REQUEST_TIMEOUT = 18; +// Even though we gave up on login, keep trying for caps after we are logged in: +const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; + +typedef std::map CapabilityMap; + +class LLViewerRegionImpl { +public: + LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) + : mHost(host), + mCompositionp(NULL), + mEventPoll(NULL), + mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), + mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), + mSeedCapAttempts(0), + mHttpResponderID(0), + // I'd prefer to set the LLCapabilityListener name to match the region + // name -- it's disappointing that's not available at construction time. + // We could instead store an LLCapabilityListener*, making + // setRegionNameAndZone() replace the instance. Would that pose + // consistency problems? Can we even request a capability before calling + // setRegionNameAndZone()? + // For testability -- the new Michael Feathers paradigm -- + // LLCapabilityListener binds all the globals it expects to need at + // construction time. + mCapabilityListener(host.getString(), gMessageSystem, *region, + gAgent.getID(), gAgent.getSessionID()) + { + } + + void buildCapabilityNames(LLSD& capabilityNames); + + // The surfaces and other layers + LLSurface* mLandp; + + // Region geometry data + LLVector3d mOriginGlobal; // Location of southwest corner of region (meters) + LLVector3d mCenterGlobal; // Location of center in world space (meters) + LLHost mHost; + + // The unique ID for this region. + LLUUID mRegionID; + + // region/estate owner - usually null. + LLUUID mOwnerID; + + // Network statistics for the region's circuit... + LLTimer mLastNetUpdate; + + // Misc + LLVLComposition *mCompositionp; // Composition layer for the surface + + LLVOCacheEntry::vocache_entry_map_t mCacheMap; + // time? + // LRU info? + + // Cache ID is unique per-region, across renames, moving locations, + // etc. + LLUUID mCacheID; + + CapabilityMap mCapabilities; + + LLEventPoll* mEventPoll; + + S32 mSeedCapMaxAttempts; + S32 mSeedCapMaxAttemptsBeforeLogin; + S32 mSeedCapAttempts; + + S32 mHttpResponderID; + + /// Post an event to this LLCapabilityListener to invoke a capability message on + /// this LLViewerRegion's server + /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities) + LLCapabilityListener mCapabilityListener; + + //spatial partitions for objects in this region + std::vector mObjectPartition; +}; + +// support for secondlife:///app/region/{REGION} SLapps +// N.B. this is defined to work exactly like the classic secondlife://{REGION} +// However, the later syntax cannot support spaces in the region name because +// spaces (and %20 chars) are illegal in the hostname of an http URL. Some +// browsers let you get away with this, but some do not (such as Qt's Webkit). +// Hence we introduced the newer secondlife:///app/region alternative. +class LLRegionHandler : public LLCommandHandler +{ +public: + // requests will be throttled from a non-trusted browser + LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {} + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + // make sure that we at least have a region name + int num_params = params.size(); + if (num_params < 1) + { + return false; + } + + // build a secondlife://{PLACE} SLurl from this SLapp + std::string url = "secondlife://"; + for (int i = 0; i < num_params; i++) + { + if (i > 0) + { + url += "/"; + } + url += params[i].asString(); + } + + // Process the SLapp as if it was a secondlife://{PLACE} SLurl + LLURLDispatcher::dispatch(url, "clicked", web, true); + return true; + } +}; +LLRegionHandler gRegionHandler; + +class BaseCapabilitiesComplete : public LLHTTPClient::Responder +{ + LOG_CLASS(BaseCapabilitiesComplete); +public: + BaseCapabilitiesComplete(U64 region_handle, S32 id) + : mRegionHandle(region_handle), mID(id) + { } + virtual ~BaseCapabilitiesComplete() + { } + + void error(U32 statusNum, const std::string& reason) + { + LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL; + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if (regionp) + { + regionp->failedSeedCapability(); + } + } + + void result(const LLSD& content) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if(!regionp) //region was removed + { + LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; + return ; + } + if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder + { + LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL; + return ; + } + + LLSD::map_const_iterator iter; + for(iter = content.beginMap(); iter != content.endMap(); ++iter) + { + regionp->setCapability(iter->first, iter->second); + LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " + << iter->first << LL_ENDL; + + /* HACK we're waiting for the ServerReleaseNotes */ + if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested()) + { + regionp->showReleaseNotes(); + } + } + + regionp->setCapabilitiesReceived(true); + + if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) + { + LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); + } + } + + static boost::intrusive_ptr build( U64 region_handle, S32 id ) + { + return boost::intrusive_ptr( + new BaseCapabilitiesComplete(region_handle, id) ); + } + +private: + U64 mRegionHandle; + S32 mID; +}; + + +LLViewerRegion::LLViewerRegion(const U64 &handle, + const LLHost &host, + const U32 grids_per_region_edge, + const U32 grids_per_patch_edge, + const F32 region_width_meters) +: mImpl(new LLViewerRegionImpl(this, host)), + mHandle(handle), + mTimeDilation(1.0f), + mName(""), + mZoning(""), + mIsEstateManager(FALSE), + mRegionFlags( REGION_FLAGS_DEFAULT ), + mSimAccess( SIM_ACCESS_MIN ), + mBillableFactor(1.0), + mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), + mClassID(0), + mCPURatio(0), + mColoName("unknown"), + mProductSKU("unknown"), + mProductName("unknown"), + mHttpUrl(""), + mCacheLoaded(FALSE), + mCacheDirty(FALSE), + mReleaseNotesRequested(FALSE), + mCapabilitiesReceived(false) +{ + mWidth = region_width_meters; + mImpl->mOriginGlobal = from_region_handle(handle); + updateRenderMatrix(); + + mImpl->mLandp = new LLSurface('l', NULL); + + // Create the composition layer for the surface + mImpl->mCompositionp = + new LLVLComposition(mImpl->mLandp, + grids_per_region_edge, + region_width_meters / grids_per_region_edge); + mImpl->mCompositionp->setSurface(mImpl->mLandp); + + // Create the surfaces + mImpl->mLandp->setRegion(this); + mImpl->mLandp->create(grids_per_region_edge, + grids_per_patch_edge, + mImpl->mOriginGlobal, + mWidth); + + mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters); + + setOriginGlobal(from_region_handle(handle)); + calculateCenterGlobal(); + + // Create the object lists + initStats(); + + //create object partitions + //MUST MATCH declaration of eObjectPartitions + mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD + mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN + mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER + mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER + mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE + mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE + mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS + mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME + mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE + mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE + mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE +} + + +void LLViewerRegion::initStats() +{ + mImpl->mLastNetUpdate.reset(); + mPacketsIn = 0; + mBitsIn = 0; + mLastBitsIn = 0; + mLastPacketsIn = 0; + mPacketsOut = 0; + mLastPacketsOut = 0; + mPacketsLost = 0; + mLastPacketsLost = 0; + mPingDelay = 0; + mAlive = false; // can become false if circuit disconnects +} + +LLViewerRegion::~LLViewerRegion() +{ + gVLManager.cleanupData(this); + // Can't do this on destruction, because the neighbor pointers might be invalid. + // This should be reference counted... + disconnectAllNeighbors(); + LLViewerPartSim::getInstance()->cleanupRegion(this); + + gObjectList.killObjects(this); + + delete mImpl->mCompositionp; + delete mParcelOverlay; + delete mImpl->mLandp; + delete mImpl->mEventPoll; + LLHTTPSender::clearSender(mImpl->mHost); + + saveObjectCache(); + + std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); + + delete mImpl; + mImpl = NULL; +} + +LLEventPump& LLViewerRegion::getCapAPI() const +{ + return mImpl->mCapabilityListener.getCapAPI(); +} + +/*virtual*/ +const LLHost& LLViewerRegion::getHost() const +{ + return mImpl->mHost; +} + +LLSurface & LLViewerRegion::getLand() const +{ + return *mImpl->mLandp; +} + +const LLUUID& LLViewerRegion::getRegionID() const +{ + return mImpl->mRegionID; +} + +void LLViewerRegion::setRegionID(const LLUUID& region_id) +{ + mImpl->mRegionID = region_id; +} + +void LLViewerRegion::loadObjectCache() +{ + if (mCacheLoaded) + { + return; + } + + // Presume success. If it fails, we don't want to try again. + mCacheLoaded = TRUE; + + if(LLVOCache::hasInstance()) + { + LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ; + } +} + + +void LLViewerRegion::saveObjectCache() +{ + if (!mCacheLoaded) + { + return; + } + + if (mImpl->mCacheMap.empty()) + { + return; + } + + if(LLVOCache::hasInstance()) + { + LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ; + mCacheDirty = FALSE; + } + + for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) + { + delete iter->second; + } + mImpl->mCacheMap.clear(); +} + +void LLViewerRegion::sendMessage() +{ + gMessageSystem->sendMessage(mImpl->mHost); +} + +void LLViewerRegion::sendReliableMessage() +{ + gMessageSystem->sendReliable(mImpl->mHost); +} + +void LLViewerRegion::setFlags(BOOL b, U32 flags) +{ + if (b) + { + mRegionFlags |= flags; + } + else + { + mRegionFlags &= ~flags; + } +} + +void LLViewerRegion::setWaterHeight(F32 water_level) +{ + mImpl->mLandp->setWaterHeight(water_level); +} + +F32 LLViewerRegion::getWaterHeight() const +{ + return mImpl->mLandp->getWaterHeight(); +} + +BOOL LLViewerRegion::isVoiceEnabled() const +{ + return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE); +} + +void LLViewerRegion::setRegionFlags(U32 flags) +{ + mRegionFlags = flags; +} + + +void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) +{ + mImpl->mOriginGlobal = origin_global; + updateRenderMatrix(); + mImpl->mLandp->setOriginGlobal(origin_global); + mWind.setOriginGlobal(origin_global); + calculateCenterGlobal(); +} + +void LLViewerRegion::updateRenderMatrix() +{ + mRenderMatrix.setTranslation(getOriginAgent()); +} + +void LLViewerRegion::setTimeDilation(F32 time_dilation) +{ + mTimeDilation = time_dilation; +} + +const LLVector3d & LLViewerRegion::getOriginGlobal() const +{ + return mImpl->mOriginGlobal; +} + +LLVector3 LLViewerRegion::getOriginAgent() const +{ + return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal); +} + +const LLVector3d & LLViewerRegion::getCenterGlobal() const +{ + return mImpl->mCenterGlobal; +} + +LLVector3 LLViewerRegion::getCenterAgent() const +{ + return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal); +} + +void LLViewerRegion::setOwner(const LLUUID& owner_id) +{ + mImpl->mOwnerID = owner_id; +} + +const LLUUID& LLViewerRegion::getOwner() const +{ + return mImpl->mOwnerID; +} + +void LLViewerRegion::setRegionNameAndZone (const std::string& name_zone) +{ + std::string::size_type pipe_pos = name_zone.find('|'); + S32 length = name_zone.size(); + if (pipe_pos != std::string::npos) + { + mName = name_zone.substr(0, pipe_pos); + mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1)); + } + else + { + mName = name_zone; + mZoning = ""; + } + + LLStringUtil::stripNonprintable(mName); + LLStringUtil::stripNonprintable(mZoning); +} + +BOOL LLViewerRegion::canManageEstate() const +{ + return gAgent.isGodlike() + || isEstateManager() + || gAgent.getID() == getOwner(); +} + +const std::string LLViewerRegion::getSimAccessString() const +{ + return accessToString(mSimAccess); +} + +std::string LLViewerRegion::getLocalizedSimProductName() const +{ + std::string localized_spn; + return LLTrans::findString(localized_spn, mProductName) ? localized_spn : mProductName; +} + +// static +std::string LLViewerRegion::regionFlagsToString(U32 flags) +{ + std::string result; + + if (flags & REGION_FLAGS_SANDBOX) + { + result += "Sandbox"; + } + + if (flags & REGION_FLAGS_ALLOW_DAMAGE) + { + result += " Not Safe"; + } + + return result; +} + +// static +std::string LLViewerRegion::accessToString(U8 sim_access) +{ + switch(sim_access) + { + case SIM_ACCESS_PG: + return LLTrans::getString("SIM_ACCESS_PG"); + + case SIM_ACCESS_MATURE: + return LLTrans::getString("SIM_ACCESS_MATURE"); + + case SIM_ACCESS_ADULT: + return LLTrans::getString("SIM_ACCESS_ADULT"); + + case SIM_ACCESS_DOWN: + return LLTrans::getString("SIM_ACCESS_DOWN"); + + case SIM_ACCESS_MIN: + default: + return LLTrans::getString("SIM_ACCESS_MIN"); + } +} + +// static +std::string LLViewerRegion::getAccessIcon(U8 sim_access) +{ + switch(sim_access) + { + case SIM_ACCESS_MATURE: + return "Parcel_M_Dark"; + + case SIM_ACCESS_ADULT: + return "Parcel_R_Light"; + + case SIM_ACCESS_PG: + return "Parcel_PG_Light"; + + case SIM_ACCESS_MIN: + default: + return ""; + } +} + +// static +std::string LLViewerRegion::accessToShortString(U8 sim_access) +{ + switch(sim_access) /* Flawfinder: ignore */ + { + case SIM_ACCESS_PG: + return "PG"; + + case SIM_ACCESS_MATURE: + return "M"; + + case SIM_ACCESS_ADULT: + return "A"; + + case SIM_ACCESS_MIN: + default: + return "U"; + } +} + +// static +U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) +{ + U8 accessValue; + + if (LLStringUtil::compareStrings(sim_access, "PG") == 0) + { + accessValue = SIM_ACCESS_PG; + } + else if (LLStringUtil::compareStrings(sim_access, "M") == 0) + { + accessValue = SIM_ACCESS_MATURE; + } + else if (LLStringUtil::compareStrings(sim_access, "A") == 0) + { + accessValue = SIM_ACCESS_ADULT; + } + else + { + accessValue = SIM_ACCESS_MIN; + } + + return accessValue; +} + +// static +void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) +{ + // send it to 'observers' + // *TODO: switch the floaters to using LLRegionInfoModel + llinfos << "Processing region info" << llendl; + LLRegionInfoModel::instance().update(msg); + LLFloaterGodTools::processRegionInfo(msg); + LLFloaterRegionInfo::processRegionInfo(msg); + LLFloaterReporter::processRegionInfo(msg); +} + +void LLViewerRegion::setCacheID(const LLUUID& id) +{ + mImpl->mCacheID = id; +} + +S32 LLViewerRegion::renderPropertyLines() +{ + if (mParcelOverlay) + { + return mParcelOverlay->renderPropertyLines(); + } + else + { + return 0; + } +} + +// This gets called when the height field changes. +void LLViewerRegion::dirtyHeights() +{ + // Property lines need to be reconstructed when the land changes. + if (mParcelOverlay) + { + mParcelOverlay->setDirty(); + } +} + +BOOL LLViewerRegion::idleUpdate(F32 max_update_time) +{ + LLMemType mt_ivr(LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION); + // did_update returns TRUE if we did at least one significant update + BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time); + + if (mParcelOverlay) + { + // Hopefully not a significant time sink... + mParcelOverlay->idleUpdate(); + } + + return did_update; +} + + +// As above, but forcibly do the update. +void LLViewerRegion::forceUpdate() +{ + mImpl->mLandp->idleUpdate(0.f); + + if (mParcelOverlay) + { + mParcelOverlay->idleUpdate(true); + } +} + +void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction) +{ + mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); +} + + +void LLViewerRegion::disconnectAllNeighbors() +{ + mImpl->mLandp->disconnectAllNeighbors(); +} + +LLVLComposition * LLViewerRegion::getComposition() const +{ + return mImpl->mCompositionp; +} + +F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const +{ + if (x >= 256) + { + if (y >= 256) + { + LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled(255, 255); + F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + else + { + LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y); + F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + } + else if (y >= 256) + { + LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f); + F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + + return getComposition()->getValueScaled((F32)x, (F32)y); +} + +void LLViewerRegion::calculateCenterGlobal() +{ + mImpl->mCenterGlobal = mImpl->mOriginGlobal; + mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth; + mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth; + mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ(); +} + +void LLViewerRegion::calculateCameraDistance() +{ + mCameraDistanceSquared = (F32)(gAgentCamera.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared(); +} + +std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion) +{ + s << "{ "; + s << region.mImpl->mHost; + s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n"; + std::string name(region.getName()), zone(region.getZoning()); + if (! name.empty()) + { + s << " mName = " << name << '\n'; + } + if (! zone.empty()) + { + s << " mZoning = " << zone << '\n'; + } + s << "}"; + return s; +} + + +// ---------------- Protected Member Functions ---------------- + +void LLViewerRegion::updateNetStats() +{ + F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32(); + + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); + if (!cdp) + { + mAlive = false; + return; + } + + mAlive = true; + mDeltaTime = dt; + + mLastPacketsIn = mPacketsIn; + mLastBitsIn = mBitsIn; + mLastPacketsOut = mPacketsOut; + mLastPacketsLost = mPacketsLost; + + mPacketsIn = cdp->getPacketsIn(); + mBitsIn = 8 * cdp->getBytesIn(); + mPacketsOut = cdp->getPacketsOut(); + mPacketsLost = cdp->getPacketsLost(); + mPingDelay = cdp->getPingDelay(); + + mBitStat.addValue(mBitsIn - mLastBitsIn); + mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); + mPacketsLostStat.addValue(mPacketsLost); +} + + +U32 LLViewerRegion::getPacketsLost() const +{ + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); + if (!cdp) + { + llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << llendl; + return 0; + } + else + { + return cdp->getPacketsLost(); + } +} + +S32 LLViewerRegion::getHttpResponderID() const +{ + return mImpl->mHttpResponderID; +} + +BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const +{ + LLVector3 pos_region = getPosRegionFromGlobal(point_global); + + if (pos_region.mV[VX] < 0) + { + return FALSE; + } + if (pos_region.mV[VX] >= mWidth) + { + return FALSE; + } + if (pos_region.mV[VY] < 0) + { + return FALSE; + } + if (pos_region.mV[VY] >= mWidth) + { + return FALSE; + } + return TRUE; +} + +LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const +{ + LLVector3 pos_region; + pos_region.setVec(point_global - mImpl->mOriginGlobal); + return pos_region; +} + +LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) const +{ + LLVector3d pos_region_d; + pos_region_d.setVec(pos_region); + return pos_region_d + mImpl->mOriginGlobal; +} + +LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const +{ + LLVector3d pos_global = getPosGlobalFromRegion(pos_region); + + return gAgent.getPosAgentFromGlobal(pos_global); +} + +LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const +{ + return pos_agent - getOriginAgent(); +} + +F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos) +{ + return mImpl->mLandp->resolveHeightRegion( region_pos ); +} + +bool LLViewerRegion::isAlive() +{ + return mAlive; +} + +BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos) +{ + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedSelf(pos); + } else { + return FALSE; + } +} + +// Owned by a group you belong to? (officer or member) +BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos) +{ + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedGroup(pos); + } else { + return FALSE; + } +} + +// the new TCP coarse location handler node +class CoarseLocationUpdate : public LLHTTPNode +{ +public: + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + LLHost host(input["sender"].asString()); + LLViewerRegion* region = LLWorld::getInstance()->getRegion(host); + if( !region ) + { + return; + } + + S32 target_index = input["body"]["Index"][0]["Prey"].asInteger(); + S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); + + LLDynamicArray* avatar_locs = ®ion->mMapAvatars; + LLDynamicArray* avatar_ids = ®ion->mMapAvatarIDs; + avatar_locs->reset(); + avatar_ids->reset(); + + //llinfos << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << llendl; + //llinfos << "my agent id = " << gAgent.getID() << llendl; + //llinfos << ll_pretty_print_sd(input) << llendl; + + LLSD + locs = input["body"]["Location"], + agents = input["body"]["AgentData"]; + LLSD::array_iterator + locs_it = locs.beginArray(), + agents_it = agents.beginArray(); + BOOL has_agent_data = input["body"].has("AgentData"); + + for(int i=0; + locs_it != locs.endArray(); + i++, locs_it++) + { + U8 + x = locs_it->get("X").asInteger(), + y = locs_it->get("Y").asInteger(), + z = locs_it->get("Z").asInteger(); + // treat the target specially for the map, and don't add you or the target + if(i == target_index) + { + LLVector3d global_pos(region->getOriginGlobal()); + global_pos.mdV[VX] += (F64)x; + global_pos.mdV[VY] += (F64)y; + global_pos.mdV[VZ] += (F64)z * 4.0; + LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); + } + else if( i != you_index) + { + U32 loc = x << 16 | y << 8 | z; loc = loc; + U32 pos = 0x0; + pos |= x; + pos <<= 8; + pos |= y; + pos <<= 8; + pos |= z; + avatar_locs->put(pos); + //llinfos << "next pos: " << x << "," << y << "," << z << ": " << pos << llendl; + if(has_agent_data) // for backwards compatibility with old message format + { + LLUUID agent_id(agents_it->get("AgentID").asUUID()); + //llinfos << "next agent: " << agent_id.asString() << llendl; + avatar_ids->put(agent_id); + } + } + if (has_agent_data) + { + agents_it++; + } + } + } +}; + +// build the coarse location HTTP node under the "/message" URL +LLHTTPRegistration + gHTTPRegistrationCoarseLocationUpdate( + "/message/CoarseLocationUpdate"); + + +// the deprecated coarse location handler +void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg) +{ + //llinfos << "CoarseLocationUpdate" << llendl; + mMapAvatars.reset(); + mMapAvatarIDs.reset(); // only matters in a rare case but it's good to be safe. + + U8 x_pos = 0; + U8 y_pos = 0; + U8 z_pos = 0; + + U32 pos = 0x0; + + S16 agent_index; + S16 target_index; + msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index); + msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index); + + BOOL has_agent_data = msg->has(_PREHASH_AgentData); + S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location); + for(S32 i = 0; i < count; i++) + { + msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i); + msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i); + msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i); + LLUUID agent_id = LLUUID::null; + if(has_agent_data) + { + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id, i); + } + + //llinfos << " object X: " << (S32)x_pos << " Y: " << (S32)y_pos + // << " Z: " << (S32)(z_pos * 4) + // << llendl; + + // treat the target specially for the map + if(i == target_index) + { + LLVector3d global_pos(mImpl->mOriginGlobal); + global_pos.mdV[VX] += (F64)(x_pos); + global_pos.mdV[VY] += (F64)(y_pos); + global_pos.mdV[VZ] += (F64)(z_pos) * 4.0; + LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); + } + + //don't add you + if( i != agent_index) + { + pos = 0x0; + pos |= x_pos; + pos <<= 8; + pos |= y_pos; + pos <<= 8; + pos |= z_pos; + mMapAvatars.put(pos); + if(has_agent_data) + { + mMapAvatarIDs.put(agent_id); + } + } + } +} + +void LLViewerRegion::getInfo(LLSD& info) +{ + info["Region"]["Host"] = getHost().getIPandPort(); + info["Region"]["Name"] = getName(); + U32 x, y; + from_region_handle(getHandle(), &x, &y); + info["Region"]["Handle"]["x"] = (LLSD::Integer)x; + info["Region"]["Handle"]["y"] = (LLSD::Integer)y; +} + +void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) +{ + sim_features = mSimulatorFeatures; + +} + +void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) +{ + std::stringstream str; + + LLSDSerialize::toPrettyXML(sim_features, str); + llinfos << str.str() << llendl; + mSimulatorFeatures = sim_features; +} + +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) +{ + U32 local_id = objectp->getLocalID(); + U32 crc = objectp->getCRC(); + + LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); + + if (entry) + { + // we've seen this object before + if (entry->getCRC() == crc) + { + // Record a hit + entry->recordDupe(); + return CACHE_UPDATE_DUPE; + } + + // Update the cache entry + mImpl->mCacheMap.erase(local_id); + delete entry; + entry = new LLVOCacheEntry(local_id, crc, dp); + mImpl->mCacheMap[local_id] = entry; + return CACHE_UPDATE_CHANGED; + } + + // we haven't seen this object before + + // Create new entry and add to map + eCacheUpdateResult result = CACHE_UPDATE_ADDED; + if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) + { + delete mImpl->mCacheMap.begin()->second ; + mImpl->mCacheMap.erase(mImpl->mCacheMap.begin()); + result = CACHE_UPDATE_REPLACED; + + } + entry = new LLVOCacheEntry(local_id, crc, dp); + + mImpl->mCacheMap[local_id] = entry; + return result; +} + +// Get data packer for this object, if we have cached data +// AND the CRC matches. JC +LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type) +{ + //llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18 + + LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); + + if (entry) + { + // we've seen this object before + if (entry->getCRC() == crc) + { + // Record a hit + entry->recordHit(); + cache_miss_type = CACHE_MISS_TYPE_NONE; + return entry->getDP(crc); + } + else + { + // llinfos << "CRC miss for " << local_id << llendl; + cache_miss_type = CACHE_MISS_TYPE_CRC; + mCacheMissCRC.put(local_id); + } + } + else + { + // llinfos << "Cache miss for " << local_id << llendl; + cache_miss_type = CACHE_MISS_TYPE_FULL; + mCacheMissFull.put(local_id); + } + + return NULL; +} + +void LLViewerRegion::addCacheMissFull(const U32 local_id) +{ + mCacheMissFull.put(local_id); +} + +void LLViewerRegion::requestCacheMisses() +{ + S32 full_count = mCacheMissFull.count(); + S32 crc_count = mCacheMissCRC.count(); + if (full_count == 0 && crc_count == 0) return; + + LLMessageSystem* msg = gMessageSystem; + BOOL start_new_message = TRUE; + S32 blocks = 0; + S32 i; + + // Send full cache miss updates. For these, we KNOW we don't + // have a viewer object. + for (i = 0; i < full_count; i++) + { + if (start_new_message) + { + msg->newMessageFast(_PREHASH_RequestMultipleObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + start_new_message = FALSE; + } + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL); + msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]); + blocks++; + + if (blocks >= 255) + { + sendReliableMessage(); + start_new_message = TRUE; + blocks = 0; + } + } + + // Send CRC miss updates. For these, we _might_ have a viewer object, + // but probably not. + for (i = 0; i < crc_count; i++) + { + if (start_new_message) + { + msg->newMessageFast(_PREHASH_RequestMultipleObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + start_new_message = FALSE; + } + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC); + msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]); + blocks++; + + if (blocks >= 255) + { + sendReliableMessage(); + start_new_message = TRUE; + blocks = 0; + } + } + + // finish any pending message + if (!start_new_message) + { + sendReliableMessage(); + } + mCacheMissFull.reset(); + mCacheMissCRC.reset(); + + mCacheDirty = TRUE ; + // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; + #if LL_RECORD_VIEWER_STATS + LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); + LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count); + LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); + #endif +} + +void LLViewerRegion::dumpCache() +{ + const S32 BINS = 4; + S32 hit_bin[BINS]; + S32 change_bin[BINS]; + + S32 i; + for (i = 0; i < BINS; ++i) + { + hit_bin[i] = 0; + change_bin[i] = 0; + } + + LLVOCacheEntry *entry; + for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) + { + entry = iter->second ; + + S32 hits = entry->getHitCount(); + S32 changes = entry->getCRCChangeCount(); + + hits = llclamp(hits, 0, BINS-1); + changes = llclamp(changes, 0, BINS-1); + + hit_bin[hits]++; + change_bin[changes]++; + } + + llinfos << "Count " << mImpl->mCacheMap.size() << llendl; + for (i = 0; i < BINS; i++) + { + llinfos << "Hits " << i << " " << hit_bin[i] << llendl; + } + for (i = 0; i < BINS; i++) + { + llinfos << "Changes " << i << " " << change_bin[i] << llendl; + } +} + +void LLViewerRegion::unpackRegionHandshake() +{ + LLMessageSystem *msg = gMessageSystem; + + U32 region_flags; + U8 sim_access; + std::string sim_name; + LLUUID sim_owner; + BOOL is_estate_manager; + F32 water_height; + F32 billable_factor; + LLUUID cache_id; + + msg->getU32 ("RegionInfo", "RegionFlags", region_flags); + msg->getU8 ("RegionInfo", "SimAccess", sim_access); + msg->getString ("RegionInfo", "SimName", sim_name); + msg->getUUID ("RegionInfo", "SimOwner", sim_owner); + msg->getBOOL ("RegionInfo", "IsEstateManager", is_estate_manager); + msg->getF32 ("RegionInfo", "WaterHeight", water_height); + msg->getF32 ("RegionInfo", "BillableFactor", billable_factor); + msg->getUUID ("RegionInfo", "CacheID", cache_id ); + + setRegionFlags(region_flags); + setSimAccess(sim_access); + setRegionNameAndZone(sim_name); + setOwner(sim_owner); + setIsEstateManager(is_estate_manager); + setWaterHeight(water_height); + setBillableFactor(billable_factor); + setCacheID(cache_id); + + LLUUID region_id; + msg->getUUID("RegionInfo2", "RegionID", region_id); + setRegionID(region_id); + + // Retrieve the CR-53 (Homestead/Land SKU) information + S32 classID = 0; + S32 cpuRatio = 0; + std::string coloName; + std::string productSKU; + std::string productName; + + // the only reasonable way to decide if we actually have any data is to + // check to see if any of these fields have positive sizes + if (msg->getSize("RegionInfo3", "ColoName") > 0 || + msg->getSize("RegionInfo3", "ProductSKU") > 0 || + msg->getSize("RegionInfo3", "ProductName") > 0) + { + msg->getS32 ("RegionInfo3", "CPUClassID", classID); + msg->getS32 ("RegionInfo3", "CPURatio", cpuRatio); + msg->getString ("RegionInfo3", "ColoName", coloName); + msg->getString ("RegionInfo3", "ProductSKU", productSKU); + msg->getString ("RegionInfo3", "ProductName", productName); + + mClassID = classID; + mCPURatio = cpuRatio; + mColoName = coloName; + mProductSKU = productSKU; + mProductName = productName; + } + + LLVLComposition *compp = getComposition(); + if (compp) + { + LLUUID tmp_id; + + msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); + compp->setDetailTextureID(0, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); + compp->setDetailTextureID(1, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); + compp->setDetailTextureID(2, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); + compp->setDetailTextureID(3, tmp_id); + + F32 tmp_f32; + msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32); + compp->setStartHeight(0, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32); + compp->setStartHeight(1, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32); + compp->setStartHeight(2, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32); + compp->setStartHeight(3, tmp_f32); + + msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32); + compp->setHeightRange(0, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32); + compp->setHeightRange(1, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32); + compp->setHeightRange(2, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32); + compp->setHeightRange(3, tmp_f32); + + // If this is an UPDATE (params already ready, we need to regenerate + // all of our terrain stuff, by + if (compp->getParamsReady()) + { + //this line creates frame stalls on region crossing and removing it appears to have no effect + //getLand().dirtyAllPatches(); + } + else + { + compp->setParamsReady(); + } + } + + + // Now that we have the name, we can load the cache file + // off disk. + loadObjectCache(); + + // After loading cache, signal that simulator can start + // sending data. + // TODO: Send all upstream viewer->sim handshake info here. + LLHost host = msg->getSender(); + msg->newMessage("RegionHandshakeReply"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("RegionInfo"); + msg->addU32("Flags", 0x0 ); + msg->sendReliable(host); +} + +void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) +{ + capabilityNames.append("AgentState"); + capabilityNames.append("AttachmentResources"); + capabilityNames.append("AvatarPickerSearch"); + capabilityNames.append("CharacterProperties"); + capabilityNames.append("ChatSessionRequest"); + capabilityNames.append("CopyInventoryFromNotecard"); + capabilityNames.append("CreateInventoryCategory"); + capabilityNames.append("DispatchRegionInfo"); + capabilityNames.append("EnvironmentSettings"); + capabilityNames.append("EstateChangeInfo"); + capabilityNames.append("EventQueueGet"); + + if (gSavedSettings.getBOOL("UseHTTPInventory")) + { + capabilityNames.append("FetchLib2"); + capabilityNames.append("FetchLibDescendents2"); + capabilityNames.append("FetchInventory2"); + capabilityNames.append("FetchInventoryDescendents2"); + } + + capabilityNames.append("GetDisplayNames"); + capabilityNames.append("GetMesh"); + capabilityNames.append("GetObjectCost"); + capabilityNames.append("GetObjectPhysicsData"); + capabilityNames.append("GetTexture"); + capabilityNames.append("GroupMemberData"); + capabilityNames.append("GroupProposalBallot"); + capabilityNames.append("HomeLocation"); + capabilityNames.append("LandResources"); + capabilityNames.append("MapLayer"); + capabilityNames.append("MapLayerGod"); + capabilityNames.append("MeshUploadFlag"); + capabilityNames.append("NavMeshGenerationStatus"); + capabilityNames.append("NewFileAgentInventory"); + capabilityNames.append("ObjectMedia"); + capabilityNames.append("ObjectMediaNavigate"); + capabilityNames.append("ObjectNavMeshProperties"); + capabilityNames.append("ParcelPropertiesUpdate"); + capabilityNames.append("ParcelVoiceInfoRequest"); + capabilityNames.append("ProductInfoRequest"); + capabilityNames.append("ProvisionVoiceAccountRequest"); + capabilityNames.append("RemoteParcelRequest"); + capabilityNames.append("RequestTextureDownload"); + capabilityNames.append("ResourceCostSelected"); + capabilityNames.append("RetrieveNavMeshSrc"); + capabilityNames.append("SearchStatRequest"); + capabilityNames.append("SearchStatTracking"); + capabilityNames.append("SendPostcard"); + capabilityNames.append("SendUserReport"); + capabilityNames.append("SendUserReportWithScreenshot"); + capabilityNames.append("ServerReleaseNotes"); + capabilityNames.append("SetDisplayName"); + capabilityNames.append("SimConsoleAsync"); + capabilityNames.append("SimulatorFeatures"); + capabilityNames.append("StartGroupProposal"); + capabilityNames.append("TerrainNavMeshProperties"); + capabilityNames.append("TextureStats"); + capabilityNames.append("UntrustedSimulatorMessage"); + capabilityNames.append("UpdateAgentInformation"); + capabilityNames.append("UpdateAgentLanguage"); + capabilityNames.append("UpdateGestureAgentInventory"); + capabilityNames.append("UpdateGestureTaskInventory"); + capabilityNames.append("UpdateNotecardAgentInventory"); + capabilityNames.append("UpdateNotecardTaskInventory"); + capabilityNames.append("UpdateScriptAgent"); + capabilityNames.append("UpdateScriptTask"); + capabilityNames.append("UploadBakedTexture"); + capabilityNames.append("ViewerMetrics"); + capabilityNames.append("ViewerStartAuction"); + capabilityNames.append("ViewerStats"); + + // Please add new capabilities alphabetically to reduce + // merge conflicts. +} + +void LLViewerRegion::setSeedCapability(const std::string& url) +{ + if (getCapability("Seed") == url) + { + // llwarns << "Ignoring duplicate seed capability" << llendl; + return; + } + + delete mImpl->mEventPoll; + mImpl->mEventPoll = NULL; + + mImpl->mCapabilities.clear(); + setCapability("Seed", url); + + LLSD capabilityNames = LLSD::emptyArray(); + mImpl->buildCapabilityNames(capabilityNames); + + llinfos << "posting to seed " << url << llendl; + + S32 id = ++mImpl->mHttpResponderID; + LLHTTPClient::post(url, capabilityNames, + BaseCapabilitiesComplete::build(getHandle(), id), + LLSD(), CAP_REQUEST_TIMEOUT); +} + +S32 LLViewerRegion::getNumSeedCapRetries() +{ + return mImpl->mSeedCapAttempts; +} + +void LLViewerRegion::failedSeedCapability() +{ + // Should we retry asking for caps? + mImpl->mSeedCapAttempts++; + std::string url = getCapability("Seed"); + if ( url.empty() ) + { + LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL; + return; + } + // After a few attempts, continue login. We will keep trying once in-world: + if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin && + STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() ) + { + LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED ); + } + + if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts) + { + LLSD capabilityNames = LLSD::emptyArray(); + mImpl->buildCapabilityNames(capabilityNames); + + llinfos << "posting to seed " << url << " (retry " + << mImpl->mSeedCapAttempts << ")" << llendl; + + S32 id = ++mImpl->mHttpResponderID; + LLHTTPClient::post(url, capabilityNames, + BaseCapabilitiesComplete::build(getHandle(), id), + LLSD(), CAP_REQUEST_TIMEOUT); + } + else + { + // *TODO: Give a user pop-up about this error? + LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts. Giving up!" << LL_ENDL; + } +} + +class SimulatorFeaturesReceived : public LLHTTPClient::Responder +{ + LOG_CLASS(SimulatorFeaturesReceived); +public: + SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, + S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) + : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) + { } + + + void error(U32 statusNum, const std::string& reason) + { + LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; + retry(); + } + + void result(const LLSD& content) + { + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); + if(!regionp) //region is removed or responder is not created. + { + LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL; + return ; + } + + regionp->setSimulatorFeatures(content); + } + +private: + void retry() + { + if (mAttempt < mMaxAttempts) + { + mAttempt++; + LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; + LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); + } + } + + std::string mRetryURL; + U64 mRegionHandle; + S32 mAttempt; + S32 mMaxAttempts; +}; + + +void LLViewerRegion::setCapability(const std::string& name, const std::string& url) +{ + if(name == "EventQueueGet") + { + delete mImpl->mEventPoll; + mImpl->mEventPoll = NULL; + mImpl->mEventPoll = new LLEventPoll(url, getHost()); + } + else if(name == "UntrustedSimulatorMessage") + { + LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url)); + } + else if (name == "SimulatorFeatures") + { + // kick off a request for simulator features + LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT); + } + else + { + mImpl->mCapabilities[name] = url; + if(name == "GetTexture") + { + mHttpUrl = url ; + } + } +} + +bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) +{ + return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; +} + +std::string LLViewerRegion::getCapability(const std::string& name) const +{ + CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); + if(iter == mImpl->mCapabilities.end()) + { + return ""; + } + + return iter->second; +} + +bool LLViewerRegion::capabilitiesReceived() const +{ + return mCapabilitiesReceived; +} + +void LLViewerRegion::setCapabilitiesReceived(bool received) +{ + mCapabilitiesReceived = received; + + // Tell interested parties that we've received capabilities, + // so that they can safely use getCapability(). + if (received) + { + mCapabilitiesReceivedSignal(getRegionID()); + + // This is a single-shot signal. Forget callbacks to save resources. + mCapabilitiesReceivedSignal.disconnect_all_slots(); + } +} + +boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb) +{ + return mCapabilitiesReceivedSignal.connect(cb); +} + +void LLViewerRegion::logActiveCapabilities() const +{ + int count = 0; + CapabilityMap::const_iterator iter; + for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count) + { + if (!iter->second.empty()) + { + llinfos << iter->first << " URL is " << iter->second << llendl; + } + } + llinfos << "Dumped " << count << " entries." << llendl; +} + +LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) +{ + if (type < mImpl->mObjectPartition.size()) + { + return mImpl->mObjectPartition[type]; + } + return NULL; +} + +// the viewer can not yet distinquish between normal- and estate-owned objects +// so we collapse these two bits and enable the UI if either are set +const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT + | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + +bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const +{ + return (mParcelOverlay != NULL) + && (mParcelOverlay->isOwnedSelf(pos) + || mParcelOverlay->isOwnedGroup(pos) + || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) + && mParcelOverlay->encroachesOwned(boxes)) ); +} + +bool LLViewerRegion::childrenObjectReturnable( const std::vector& boxes ) const +{ + bool result = false; + result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0; + return result; +} + +bool LLViewerRegion::objectsCrossParcel(const std::vector& boxes) const +{ + return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes); +} + +void LLViewerRegion::getNeighboringRegions( std::vector& uniqueRegions ) +{ + mImpl->mLandp->getNeighboringRegions( uniqueRegions ); +} +void LLViewerRegion::getNeighboringRegionsStatus( std::vector& regions ) +{ + mImpl->mLandp->getNeighboringRegionsStatus( regions ); +} +void LLViewerRegion::showReleaseNotes() +{ + std::string url = this->getCapability("ServerReleaseNotes"); + + if (url.empty()) { + // HACK haven't received the capability yet, we'll wait until + // it arives. + mReleaseNotesRequested = TRUE; + return; + } + + LLWeb::loadURL(url); + mReleaseNotesRequested = FALSE; +} + +std::string LLViewerRegion::getDescription() const +{ + return stringize(*this); +} + +bool LLViewerRegion::meshUploadEnabled() const +{ + return (mSimulatorFeatures.has("MeshUploadEnabled") && + mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); +} + +bool LLViewerRegion::meshRezEnabled() const +{ + return (mSimulatorFeatures.has("MeshRezEnabled") && + mSimulatorFeatures["MeshRezEnabled"].asBoolean()); +} + +bool LLViewerRegion::dynamicPathfindingEnabled() const +{ + return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") && + mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); +} + -- cgit v1.2.3 From a905f7c74ee35ac16237311eb1d0fbda6577aadb Mon Sep 17 00:00:00 2001 From: Chris Baker Date: Wed, 3 Oct 2012 21:16:04 +0000 Subject: - Fixed an issue where group list wouldn't fall back to UDP if the region doesn't support the new GroupMemberData capabaility - Fixed a potential null pointer crash. Thanks to Ansariel from Firestorm for these! Reviewer: Myself --- indra/newview/llgroupmgr.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 9c0a30e689..6916cf813a 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1867,6 +1867,12 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) return; LLViewerRegion* currentRegion = gAgent.getRegion(); + // Thank you FS:Ansariel! + if(!currentRegion) + { + LL_WARNS("GrpMgr") << "Agent does not have a current region. Uh-oh!" << LL_ENDL; + return; + } // Check to make sure we have our capabilities if(!currentRegion->capabilitiesReceived()) @@ -1878,6 +1884,14 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) // Get our capability std::string cap_url = currentRegion->getCapability("GroupMemberData"); + // Thank you FS:Ansariel! + if(cap_url.empty()) + { + LL_INFOS("GrpMgr") << "Region has no GroupMemberData capability. Falling back to UDP fetch." << LL_ENDL; + sendGroupMembersRequest(group_id); + return; + } + // Post to our service. Add a body containing the group_id. LLSD body = LLSD::emptyMap(); body["group_id"] = group_id; -- cgit v1.2.3 From cdbfdfc351a51f4fe0c264110cf68a59f0859f04 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 11 Oct 2012 17:02:45 -0500 Subject: MAINT-1709 Factor out realloc Reviewed by VoidPointer --- indra/llmath/lloctree.h | 52 ++++++++----------- indra/newview/llspatialpartition.cpp | 98 +++++++++++++++++++----------------- indra/newview/llspatialpartition.h | 10 ++-- 3 files changed, 80 insertions(+), 80 deletions(-) diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index c3f6f7de2a..68d8110f1d 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -78,7 +78,7 @@ public: typedef LLOctreeTraveler oct_traveler; typedef LLTreeTraveler tree_traveler; - typedef LLPointer* element_list; + typedef std::vector> element_list; typedef LLPointer* element_iter; typedef const LLPointer* const_element_iter; typedef typename std::vector*>::iterator tree_listener_iter; @@ -106,8 +106,9 @@ public: : mParent((oct_node*)parent), mOctant(octant) { - mData = NULL; - mDataEnd = NULL; + //always keep a NULL terminated list to avoid out of bounds exceptions in debug builds + mData.push_back(NULL); + mDataEnd = &mData[0]; mCenter = center; mSize = size; @@ -133,9 +134,9 @@ public: mData[i] = NULL; } - free(mData); - mData = NULL; - mDataEnd = NULL; + mData.clear(); + mData.push_back(NULL); + mDataEnd = &mData[0]; for (U32 i = 0; i < getChildCount(); i++) { @@ -239,9 +240,9 @@ public: bool isEmpty() const { return mElementCount == 0; } element_list& getData() { return mData; } const element_list& getData() const { return mData; } - element_iter getDataBegin() { return mData; } + element_iter getDataBegin() { return &mData[0]; } element_iter getDataEnd() { return mDataEnd; } - const_element_iter getDataBegin() const { return mData; } + const_element_iter getDataBegin() const { return &mData[0]; } const_element_iter getDataEnd() const { return mDataEnd; } U32 getChildCount() const { return mChildCount; } @@ -321,14 +322,10 @@ public: if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here + mData.push_back(NULL); + mData[mElementCount] = data; mElementCount++; - mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); - - //avoid unref on uninitialized memory - memset(mData+mElementCount-1, 0, sizeof(LLPointer)); - - mData[mElementCount-1] = data; - mDataEnd = mData + mElementCount; + mDataEnd = &mData[mElementCount]; data->setBinIndex(mElementCount-1); BaseType::insert(data); return true; @@ -364,14 +361,10 @@ public: if( lt == 0x7 ) { + mData.push_back(NULL); + mData[mElementCount] = data; mElementCount++; - mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); - - //avoid unref on uninitialized memory - memset(mData+mElementCount-1, 0, sizeof(LLPointer)); - - mData[mElementCount-1] = data; - mDataEnd = mData + mElementCount; + mDataEnd = &mData[mElementCount]; data->setBinIndex(mElementCount-1); BaseType::insert(data); return true; @@ -436,16 +429,15 @@ public: mData[i]->setBinIndex(i); } - mData[mElementCount] = NULL; //needed for unref - mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); - mDataEnd = mData+mElementCount; + mData[mElementCount] = NULL; + mData.pop_back(); + mDataEnd = &mData[mElementCount]; } else { - mData[0] = NULL; //needed for unref - free(mData); - mData = NULL; - mDataEnd = NULL; + mData.clear(); + mData.push_back(NULL); + mDataEnd = &mData[0]; } notifyRemoval(data); @@ -491,7 +483,7 @@ public: } //node is now root - llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl; + llwarns << "!!! OCTREE REMOVING ELEMENT BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl; node->removeByAddress(data); llassert(data->getBinIndex() == -1); return true; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 7264ba3cab..3bb8e60787 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -4713,55 +4713,63 @@ LLCullResult::LLCullResult() mVisibleListAllocated = 0; mVisibleBridgeAllocated = 0; - mVisibleGroups = NULL; - mVisibleGroupsEnd = NULL; - mAlphaGroups = NULL; - mAlphaGroupsEnd = NULL; - mOcclusionGroups = NULL; - mOcclusionGroupsEnd = NULL; - mDrawableGroups = NULL; - mDrawableGroupsEnd = NULL; - mVisibleList = NULL; - mVisibleListEnd = NULL; - mVisibleBridge = NULL; - mVisibleBridgeEnd = NULL; + mVisibleGroups.clear(); + mVisibleGroups.push_back(NULL); + mVisibleGroupsEnd = &mVisibleGroups[0]; + mAlphaGroups.clear(); + mAlphaGroups.push_back(NULL); + mAlphaGroupsEnd = &mAlphaGroups[0]; + mOcclusionGroups.clear(); + mOcclusionGroups.push_back(NULL); + mOcclusionGroupsEnd = &mOcclusionGroups[0]; + mDrawableGroups.clear(); + mDrawableGroups.push_back(NULL); + mDrawableGroupsEnd = &mDrawableGroups[0]; + mVisibleList.clear(); + mVisibleList.push_back(NULL); + mVisibleListEnd = &mVisibleList[0]; + mVisibleBridge.clear(); + mVisibleBridge.push_back(NULL); + mVisibleBridgeEnd = &mVisibleBridge[0]; for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) { - mRenderMap[i] = NULL; - mRenderMapEnd[i] = NULL; + mRenderMap[i].clear(); + mRenderMap[i].push_back(NULL); + mRenderMapEnd[i] = &mRenderMap[i][0]; mRenderMapAllocated[i] = 0; } clear(); } -void LLCullResult::pushBack(void**& head, U32& count, void* val) +template +void LLCullResult::pushBack(T& head, U32& count, V* val) { + head[count] = val; + head.push_back(NULL); count++; - head = (void**) realloc((void*) head, sizeof(void*) * count); - head[count-1] = val; } void LLCullResult::clear() { mVisibleGroupsSize = 0; - mVisibleGroupsEnd = mVisibleGroups; + mVisibleGroupsEnd = &mVisibleGroups[0]; mAlphaGroupsSize = 0; - mAlphaGroupsEnd = mAlphaGroups; + mAlphaGroupsEnd = &mAlphaGroups[0]; mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = mOcclusionGroups; + mOcclusionGroupsEnd = &mOcclusionGroups[0]; mDrawableGroupsSize = 0; - mDrawableGroupsEnd = mDrawableGroups; + mDrawableGroupsEnd = &mDrawableGroups[0]; mVisibleListSize = 0; - mVisibleListEnd = mVisibleList; + mVisibleListEnd = &mVisibleList[0]; mVisibleBridgeSize = 0; - mVisibleBridgeEnd = mVisibleBridge; + mVisibleBridgeEnd = &mVisibleBridge[0]; for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) @@ -4771,13 +4779,13 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; - mRenderMapEnd[i] = mRenderMap[i]; + mRenderMapEnd[i] = &(mRenderMap[i][0]); } } LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() { - return mVisibleGroups; + return &mVisibleGroups[0]; } LLCullResult::sg_iterator LLCullResult::endVisibleGroups() @@ -4787,7 +4795,7 @@ LLCullResult::sg_iterator LLCullResult::endVisibleGroups() LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() { - return mAlphaGroups; + return &mAlphaGroups[0]; } LLCullResult::sg_iterator LLCullResult::endAlphaGroups() @@ -4797,7 +4805,7 @@ LLCullResult::sg_iterator LLCullResult::endAlphaGroups() LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { - return mOcclusionGroups; + return &mOcclusionGroups[0]; } LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() @@ -4807,7 +4815,7 @@ LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() { - return mDrawableGroups; + return &mDrawableGroups[0]; } LLCullResult::sg_iterator LLCullResult::endDrawableGroups() @@ -4817,7 +4825,7 @@ LLCullResult::sg_iterator LLCullResult::endDrawableGroups() LLCullResult::drawable_iterator LLCullResult::beginVisibleList() { - return mVisibleList; + return &mVisibleList[0]; } LLCullResult::drawable_iterator LLCullResult::endVisibleList() @@ -4827,7 +4835,7 @@ LLCullResult::drawable_iterator LLCullResult::endVisibleList() LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() { - return mVisibleBridge; + return &mVisibleBridge[0]; } LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() @@ -4837,7 +4845,7 @@ LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) { - return mRenderMap[type]; + return &mRenderMap[type][0]; } LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) @@ -4853,10 +4861,10 @@ void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) } else { - pushBack((void**&) mVisibleGroups, mVisibleGroupsAllocated, (void*) group); + pushBack(mVisibleGroups, mVisibleGroupsAllocated, group); } ++mVisibleGroupsSize; - mVisibleGroupsEnd = mVisibleGroups+mVisibleGroupsSize; + mVisibleGroupsEnd = &mVisibleGroups[mVisibleGroupsSize]; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) @@ -4867,10 +4875,10 @@ void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) } else { - pushBack((void**&) mAlphaGroups, mAlphaGroupsAllocated, (void*) group); + pushBack(mAlphaGroups, mAlphaGroupsAllocated, group); } ++mAlphaGroupsSize; - mAlphaGroupsEnd = mAlphaGroups+mAlphaGroupsSize; + mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) @@ -4881,10 +4889,10 @@ void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) } else { - pushBack((void**&) mOcclusionGroups, mOcclusionGroupsAllocated, (void*) group); + pushBack(mOcclusionGroups, mOcclusionGroupsAllocated, group); } ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = mOcclusionGroups+mOcclusionGroupsSize; + mOcclusionGroupsEnd = &mOcclusionGroups[mOcclusionGroupsSize]; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) @@ -4895,10 +4903,10 @@ void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) } else { - pushBack((void**&) mDrawableGroups, mDrawableGroupsAllocated, (void*) group); + pushBack(mDrawableGroups, mDrawableGroupsAllocated, group); } ++mDrawableGroupsSize; - mDrawableGroupsEnd = mDrawableGroups+mDrawableGroupsSize; + mDrawableGroupsEnd = &mDrawableGroups[mDrawableGroupsSize]; } void LLCullResult::pushDrawable(LLDrawable* drawable) @@ -4909,10 +4917,10 @@ void LLCullResult::pushDrawable(LLDrawable* drawable) } else { - pushBack((void**&) mVisibleList, mVisibleListAllocated, (void*) drawable); + pushBack(mVisibleList, mVisibleListAllocated, drawable); } ++mVisibleListSize; - mVisibleListEnd = mVisibleList+mVisibleListSize; + mVisibleListEnd = &mVisibleList[mVisibleListSize]; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) @@ -4923,10 +4931,10 @@ void LLCullResult::pushBridge(LLSpatialBridge* bridge) } else { - pushBack((void**&) mVisibleBridge, mVisibleBridgeAllocated, (void*) bridge); + pushBack(mVisibleBridge, mVisibleBridgeAllocated, bridge); } ++mVisibleBridgeSize; - mVisibleBridgeEnd = mVisibleBridge+mVisibleBridgeSize; + mVisibleBridgeEnd = &mVisibleBridge[mVisibleBridgeSize]; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) @@ -4937,10 +4945,10 @@ void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) } else { - pushBack((void**&) mRenderMap[type], mRenderMapAllocated[type], (void*) draw_info); + pushBack(mRenderMap[type], mRenderMapAllocated[type], draw_info); } ++mRenderMapSize[type]; - mRenderMapEnd[type] = mRenderMap[type] + mRenderMapSize[type]; + mRenderMapEnd[type] = &(mRenderMap[type][mRenderMapSize[type]]); } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index e63037b4a8..b1706d9d35 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -569,10 +569,10 @@ class LLCullResult public: LLCullResult(); - typedef LLSpatialGroup** sg_list_t; - typedef LLDrawable** drawable_list_t; - typedef LLSpatialBridge** bridge_list_t; - typedef LLDrawInfo** drawinfo_list_t; + typedef std::vector sg_list_t; + typedef std::vector drawable_list_t; + typedef std::vector bridge_list_t; + typedef std::vector drawinfo_list_t; typedef LLSpatialGroup** sg_iterator; typedef LLSpatialBridge** bridge_iterator; @@ -622,7 +622,7 @@ public: private: - void pushBack(void** &head, U32& count, void* val); + template void pushBack(T &head, U32& count, V* val); U32 mVisibleGroupsSize; U32 mAlphaGroupsSize; -- cgit v1.2.3 From 57e8f8f5e4f771d6fe6a7739db474ade24af71e8 Mon Sep 17 00:00:00 2001 From: callumprentice Date: Thu, 11 Oct 2012 16:51:56 -0700 Subject: point to new version of Google Breakpad and tweak function sig of GBP exception handler --- autobuild.xml | 4 ++-- indra/llcommon/llapp.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index b7a73f2c75..6a1aeb45f9 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -762,9 +762,9 @@ archive hash - 21babc394dbf8572830f2e85adec7b9f + 3ec313ddf607a5716f47d5b1ec0edf31 url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-darwin-20110202.tar.bz2 + https://viewer-source-downloads.s3.amazonaws.com/install_pkgs/google_breakpad-0.0.0-rev1099-darwin-20121011.tar.bz2 name darwin diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index ed192a9975..a93957bb6b 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -349,7 +349,12 @@ void LLApp::setupErrorHandling() if(installHandler && (mExceptionHandler == 0)) { std::string dumpPath = "/tmp/"; - mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); + mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, + 0, + &unix_post_minidump_callback, + 0, + true, + "port_name"); } #endif -- cgit v1.2.3 From a64e0b3e25a13fa8f8f5828da8f029dea2197e6f Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 15 Oct 2012 14:08:27 -0700 Subject: changed ctor param to use in-process crash generation --- indra/llcommon/llapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index a93957bb6b..95ea60b005 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -354,7 +354,7 @@ void LLApp::setupErrorHandling() &unix_post_minidump_callback, 0, true, - "port_name"); + NULL); } #endif -- cgit v1.2.3 From c8d58f8db33360a0610a6dabd29916b4081a73db Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 17 Oct 2012 13:51:53 -0700 Subject: Update script that generates Google Breakpad symbols to look in tghe right place first and default to the original location if not found. --- indra/newview/generate_breakpad_symbols.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index 5ebec1563e..ddc8a41136 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -75,7 +75,14 @@ def main(configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, vi def dump_module(m): print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) - child = subprocess.Popen([dump_syms_tool, m] , stdout=subprocess.PIPE) + dsym_full_path = m + if sys.platform in ['darwin']: + dsym_dir=os.path.join(m+".dSYM", 'Contents', 'Resources', 'DWARF') + if os.path.isdir(dsym_dir): + dsym_full_path=os.path.join(dsym_dir, os.path.basename(m)) + else: + dsym_full_path = m + child = subprocess.Popen([dump_syms_tool, dsym_full_path] , stdout=subprocess.PIPE) out, err = child.communicate() return (m,child.returncode, out, err) -- cgit v1.2.3 From 5a2f71b0bc30804c3ca40ac4fc49e1257ad43106 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 17 Oct 2012 18:18:06 -0500 Subject: MAINT-1527 Fix for crash on exit when VBO disabled --- indra/newview/pipeline.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 2edb5cf852..b42a84da47 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -695,6 +695,8 @@ void LLPipeline::cleanup() mInitialized = FALSE; mDeferredVB = NULL; + + mCubeVB = NULL; } //============================================================================ -- cgit v1.2.3 From 5bf755ba014cfd8f82b2b94f29ace98a8e887ed6 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Wed, 17 Oct 2012 17:11:13 -0700 Subject: Adding '-g' to mac builds --- indra/cmake/00-Common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 98eeed09b3..bc140d5f7c 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -195,7 +195,7 @@ if (DARWIN) # This is a known issue where getcontext(3) is writing past the end of the # ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ). # As a workaround, define _XOPEN_SOURCE before including ucontext.h. - add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE) + add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE -g) set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") set(DARWIN_extra_cstar_flags "-mlong-branch") -- cgit v1.2.3 From 4936ce7782a22ec27239bba27d6fd18ae0bfa1a0 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 18 Oct 2012 16:23:31 -0700 Subject: Removing -g flag from mac builds --- indra/cmake/00-Common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index bc140d5f7c..98eeed09b3 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -195,7 +195,7 @@ if (DARWIN) # This is a known issue where getcontext(3) is writing past the end of the # ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ). # As a workaround, define _XOPEN_SOURCE before including ucontext.h. - add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE -g) + add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE) set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") set(DARWIN_extra_cstar_flags "-mlong-branch") -- cgit v1.2.3 From 64912f9e4983f7a6eba56e411693d4a110f1c6ff Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 18 Oct 2012 16:31:24 -0700 Subject: Removing GCC_GENERATE_DEBUGGING_SYMBOLS=NO from xcode project --- build.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.sh b/build.sh index 15f0463aff..4ae146c578 100755 --- a/build.sh +++ b/build.sh @@ -76,6 +76,10 @@ pre_build() -DLL_TESTS:BOOL="$run_tests" \ -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url + mv ${build_dir}/SecondLife.xcodeproj/project.pbxproj ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate + grep -v GCC_GENERATE_DEBUGGING_SYMBOLS ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate > ${build_dir}/SecondLife.xcodeproj/project.pbxproj + rm ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate + check_for "After 'autobuild configure'" ${build_dir}/packages/dictionaries end_section "Pre$variant" -- cgit v1.2.3 From 11017315e6f0cdcc247a875e41d027beac8df764 Mon Sep 17 00:00:00 2001 From: William Todd Stinson Date: Thu, 18 Oct 2012 17:36:57 -0700 Subject: MAINT-1753: Correcting behavior of ll_aligned_realloc_16() on Linux to avoid memory corruption in the case that the new memory size requested is smaller than the old memory size. Also, adding check to ensure that the aligned malloc returns a non-null value before memcopying. --- indra/llcommon/llmemory.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 40cde485cf..10013e0f92 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -87,7 +87,11 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r void* ret = ll_aligned_malloc_16(size); if (ptr) { - memcpy(ret, ptr, old_size); + if (ret) + { + // Only copy the size of the smallest memory block to avoid memory corruption. + memcpy(ret, ptr, llmin(old_size, size)); + } ll_aligned_free_16(ptr); } return ret; -- cgit v1.2.3 From f71d2a649b62c115eca4d56d8800d2d6ae9f57a0 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 19 Oct 2012 10:31:11 -0400 Subject: tag merge of DRTVWR-231 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b9c59588e1..1c986e9772 100644 --- a/.hgtags +++ b/.hgtags @@ -323,3 +323,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 524da902713e8b60322640b9825101add4a7c497 3.4.1-beta7 173c2809f9873499c4b9d6bc044ec941c954d3fb DRTVWR-228 1dc94555582f52718834081e7659e973ae4521f7 3.4.1-beta8 +52c164c8023a5e65f3dc1b0bbb7fa1dd0c631b6b DRTVWR-231 -- cgit v1.2.3 From c8fcb6c798b46ffbffdfa3c04bdb2846a87a60d4 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 19 Oct 2012 11:33:24 -0400 Subject: Added tag 3.4.1-beta9 for changeset 9c4519aa5c70 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 1c986e9772..b53dd3ce9e 100644 --- a/.hgtags +++ b/.hgtags @@ -324,3 +324,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 173c2809f9873499c4b9d6bc044ec941c954d3fb DRTVWR-228 1dc94555582f52718834081e7659e973ae4521f7 3.4.1-beta8 52c164c8023a5e65f3dc1b0bbb7fa1dd0c631b6b DRTVWR-231 +9c4519aa5c70f7560111fb5c740d3a7dc20a845a 3.4.1-beta9 -- cgit v1.2.3 From 04a16d2836b3c8517d367861d3dea632a0d58fc1 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 19 Oct 2012 14:06:50 -0400 Subject: tag merge of DRTVWR-233 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b9c59588e1..4935499e24 100644 --- a/.hgtags +++ b/.hgtags @@ -323,3 +323,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 524da902713e8b60322640b9825101add4a7c497 3.4.1-beta7 173c2809f9873499c4b9d6bc044ec941c954d3fb DRTVWR-228 1dc94555582f52718834081e7659e973ae4521f7 3.4.1-beta8 +464cf7a63a9a2f95bc4972dc022ca765e93de7d3 DRTVWR-233 -- cgit v1.2.3 From f2a674274fc043e55ad3e78e05120d34ed2ff361 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 19 Oct 2012 14:07:05 -0400 Subject: Added tag 3.4.1-beta9 for changeset 637fe8bbee5e --- .hgtags | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgtags b/.hgtags index 3f70231561..dc7ca3db19 100644 --- a/.hgtags +++ b/.hgtags @@ -326,3 +326,5 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 52c164c8023a5e65f3dc1b0bbb7fa1dd0c631b6b DRTVWR-231 9c4519aa5c70f7560111fb5c740d3a7dc20a845a 3.4.1-beta9 464cf7a63a9a2f95bc4972dc022ca765e93de7d3 DRTVWR-233 +9c4519aa5c70f7560111fb5c740d3a7dc20a845a 3.4.1-beta9 +637fe8bbee5e24940448198c221d5ee0fa3247b4 3.4.1-beta9 -- cgit v1.2.3 From 2d7eb0885259702eaf348703dd62c54a7428a2a5 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 19 Oct 2012 12:13:18 -0700 Subject: Turn off cleaning up post build for testing --- BuildParams | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BuildParams b/BuildParams index ebfc640023..5a69d68074 100644 --- a/BuildParams +++ b/BuildParams @@ -20,6 +20,8 @@ email_status_this_is_os = true # Limit extent of codeticket updates to revisions after... codeticket_since = 3.3.0-release +build_clean_on_success = false + # ======================================== # Viewer Development # ======================================== -- cgit v1.2.3 From 15cde616b9b89bd27c3a8633ada33cb20d151e93 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 19 Oct 2012 16:14:11 -0700 Subject: Update to BuildParams var --- BuildParams | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BuildParams b/BuildParams index 5a69d68074..40ec94ceaa 100644 --- a/BuildParams +++ b/BuildParams @@ -20,7 +20,7 @@ email_status_this_is_os = true # Limit extent of codeticket updates to revisions after... codeticket_since = 3.3.0-release -build_clean_on_success = false +clean_on_success = false # ======================================== # Viewer Development -- cgit v1.2.3 From e18d97782f47c7ddb2b77a42c96116ba8dd5e9d3 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Fri, 19 Oct 2012 16:45:40 -0700 Subject: Turn off configs and tests for testingg --- BuildParams | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BuildParams b/BuildParams index 40ec94ceaa..f584c63d1a 100644 --- a/BuildParams +++ b/BuildParams @@ -21,6 +21,9 @@ email_status_this_is_os = true codeticket_since = 3.3.0-release clean_on_success = false +run_tests = false +build_Darwin_Debug = false +build_Darwin_RelWithDebInfo = false # ======================================== # Viewer Development -- cgit v1.2.3 From 6dee3e638af312b33516d2d731ff6df720b7dcfa Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Fri, 19 Oct 2012 23:54:41 +0000 Subject: Trying explicitly turning on debug symbols for all mac configurations --- build.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/build.sh b/build.sh index 4ae146c578..ea09a243cf 100755 --- a/build.sh +++ b/build.sh @@ -76,9 +76,14 @@ pre_build() -DLL_TESTS:BOOL="$run_tests" \ -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url - mv ${build_dir}/SecondLife.xcodeproj/project.pbxproj ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate - grep -v GCC_GENERATE_DEBUGGING_SYMBOLS ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate > ${build_dir}/SecondLife.xcodeproj/project.pbxproj - rm ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate + # *HACK - Fix debug symbol generation in xcode + case "$arch" in + Darwin) sed -i '' 's/GCC_GENERATE_DEBUGGING_SYMBOLS = NO/GCC_GENERATE_DEBUGGING_SYMBOLS = YES/' ${build_dir}/SecondLife.xcodeproj/project.pbxproj + #mv ${build_dir}/SecondLife.xcodeproj/project.pbxproj ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate + #grep -v GCC_GENERATE_DEBUGGING_SYMBOLS ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate > ${build_dir}/SecondLife.xcodeproj/project.pbxproj + #rm ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate + ;; + esac check_for "After 'autobuild configure'" ${build_dir}/packages/dictionaries -- cgit v1.2.3 From 73cc2c6a7ab853b79e12d215060936fec7bf036d Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sat, 20 Oct 2012 09:46:59 +0000 Subject: Adding expanded searching for symbols during google breakpad symbol scan --- indra/newview/CMakeLists.txt | 18 +++++++--- indra/newview/generate_breakpad_symbols.py | 54 +++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c0a252637f..6bdcf2df25 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1987,8 +1987,9 @@ if (INSTALL) endif (INSTALL) if (PACKAGE) + set(SYMBOL_SEARCH_DIRS "") if (WINDOWS) - set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows.tar.bz2") # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") @@ -1997,13 +1998,20 @@ if (PACKAGE) set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) endif (WINDOWS) if (DARWIN) - set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + # *TODO: Generate these search dirs in the cmake files related to each binary. + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_updater/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/webkit/${CMAKE_CFG_INTDIR}") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin.tar.bz2") - set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin") + set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin mac-updater mac-crash-logger") set(VIEWER_LIB_GLOB "*.dylib") endif (DARWIN) if (LINUX) - set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2") set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") @@ -2023,7 +2031,7 @@ if (PACKAGE) ARGS "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" "${LLBUILD_CONFIG}" - "${VIEWER_DIST_DIR}" + "${SYMBOL_SEARCH_DIRS}" "${VIEWER_EXE_GLOBS}" "${VIEWER_LIB_GLOB}" "${AUTOBUILD_INSTALL_DIR}/bin/dump_syms" diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index ddc8a41136..4181e4ebb3 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -39,17 +39,20 @@ import shlex import subprocess import tarfile import StringIO +import pprint + +DEBUG=False def usage(): - print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] + print >>sys.stderr, "usage: %s search_dirs viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] class MissingModuleError(Exception): def __init__(self, modules): Exception.__init__(self, "Failed to find required modules: %r" % modules) self.modules = modules -def main(configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): - print "generate_breakpad_symbols run with args: %s" % str((configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) +def main(configuration, search_dirs, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): + print "generate_breakpad_symbols run with args: %s" % str((configuration, search_dirs, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) if not re.match("release", configuration, re.IGNORECASE): print "skipping breakpad symbol generation for non-release build." @@ -67,28 +70,49 @@ def main(configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, vi return True return fnmatch.fnmatch(f, libs_suffix) + search_dirs = search_dirs.split(";") + def list_files(): - for (dirname, subdirs, filenames) in os.walk(viewer_dir): - #print "scanning '%s' for modules..." % dirname - for f in itertools.ifilter(matches, filenames): - yield os.path.join(dirname, f) + for search_dir in search_dirs: + for (dirname, subdirs, filenames) in os.walk(search_dir): + if DEBUG: + print "scanning '%s' for modules..." % dirname + for f in itertools.ifilter(matches, filenames): + yield os.path.join(dirname, f) def dump_module(m): print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) dsym_full_path = m - if sys.platform in ['darwin']: - dsym_dir=os.path.join(m+".dSYM", 'Contents', 'Resources', 'DWARF') - if os.path.isdir(dsym_dir): - dsym_full_path=os.path.join(dsym_dir, os.path.basename(m)) - else: - dsym_full_path = m child = subprocess.Popen([dump_syms_tool, dsym_full_path] , stdout=subprocess.PIPE) out, err = child.communicate() return (m,child.returncode, out, err) - out = tarfile.open(viewer_symbol_file, 'w:bz2') + + modules = {} + + for m in list_files(): + if DEBUG: + print "examining module '%s' ... " % m, + filename=os.path.basename(m) + if -1 != m.find("DWARF"): + # Just use this module; it has the symbols we want. + modules[filename] = m + if DEBUG: + print "found dSYM entry" + elif filename not in modules: + # Only use this if we don't already have a (possibly better) entry. + modules[filename] = m + if DEBUG: + print "found new entry" + elif DEBUG: + print "ignoring entry" + + + print "Found these following modules:" + pprint.pprint( modules ) - for (filename,status,symbols,err) in itertools.imap(dump_module, list_files()): + out = tarfile.open(viewer_symbol_file, 'w:bz2') + for (filename,status,symbols,err) in itertools.imap(dump_module, modules.values()): if status == 0: module_line = symbols[:symbols.index('\n')] module_line = module_line.split() -- cgit v1.2.3 From 486f80aae69ae3918c5243fdc95628071a73c4ee Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Sat, 20 Oct 2012 19:47:36 +0000 Subject: Removing build.sh darwin symbols hack. Adding '-g' to both CFLAGS and CXXFLAG to have cmake generation debug symbols in xcode. --- build.sh | 9 --------- indra/cmake/00-Common.cmake | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/build.sh b/build.sh index ea09a243cf..15f0463aff 100755 --- a/build.sh +++ b/build.sh @@ -76,15 +76,6 @@ pre_build() -DLL_TESTS:BOOL="$run_tests" \ -DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url - # *HACK - Fix debug symbol generation in xcode - case "$arch" in - Darwin) sed -i '' 's/GCC_GENERATE_DEBUGGING_SYMBOLS = NO/GCC_GENERATE_DEBUGGING_SYMBOLS = YES/' ${build_dir}/SecondLife.xcodeproj/project.pbxproj - #mv ${build_dir}/SecondLife.xcodeproj/project.pbxproj ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate - #grep -v GCC_GENERATE_DEBUGGING_SYMBOLS ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate > ${build_dir}/SecondLife.xcodeproj/project.pbxproj - #rm ${build_dir}/SecondLife.xcodeproj/project.pbxproj.intermediate - ;; - esac - check_for "After 'autobuild configure'" ${build_dir}/packages/dictionaries end_section "Pre$variant" diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 98eeed09b3..99880a14ca 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -198,7 +198,7 @@ if (DARWIN) add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE) set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") - set(DARWIN_extra_cstar_flags "-mlong-branch") + set(DARWIN_extra_cstar_flags "-mlong-branch -g") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}") # NOTE: it's critical that the optimization flag is put in front. -- cgit v1.2.3 From 08b7f100f6964464eeb26dcd5e454b4f949afb86 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 22 Oct 2012 11:03:34 -0700 Subject: Trying original version of GBP with new scripts/code --- autobuild.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 6a1aeb45f9..b7a73f2c75 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -762,9 +762,9 @@ archive hash - 3ec313ddf607a5716f47d5b1ec0edf31 + 21babc394dbf8572830f2e85adec7b9f url - https://viewer-source-downloads.s3.amazonaws.com/install_pkgs/google_breakpad-0.0.0-rev1099-darwin-20121011.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-darwin-20110202.tar.bz2 name darwin -- cgit v1.2.3 From ece80f722eaab4e3631094c923ee8dc5b80ab74a Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 22 Oct 2012 11:20:24 -0700 Subject: Trying original version of GBP with new scripts/code- revert corresponding cpp code --- indra/llcommon/llapp.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 95ea60b005..ed192a9975 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -349,12 +349,7 @@ void LLApp::setupErrorHandling() if(installHandler && (mExceptionHandler == 0)) { std::string dumpPath = "/tmp/"; - mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, - 0, - &unix_post_minidump_callback, - 0, - true, - NULL); + mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); } #endif -- cgit v1.2.3 From 4827b7160b7629b9e3ea530df1e28134280f5e34 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 22 Oct 2012 14:39:29 -0500 Subject: Enable tcmalloc --- indra/cmake/GooglePerfTools.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 73b3642ae6..09501e0406 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -3,7 +3,7 @@ include(Prebuilt) # If you want to enable or disable TCMALLOC in viewer builds, this is the place. # set ON or OFF as desired. -set (USE_TCMALLOC OFF) +set (USE_TCMALLOC ON) if (STANDALONE) include(FindGooglePerfTools) -- cgit v1.2.3 From 682d7355fdf467242a72f225927692dcc09c28a0 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 22 Oct 2012 15:51:07 -0700 Subject: whitespace change to force new build in TC --- BuildParams | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BuildParams b/BuildParams index f584c63d1a..908ef3ed0c 100644 --- a/BuildParams +++ b/BuildParams @@ -24,9 +24,9 @@ clean_on_success = false run_tests = false build_Darwin_Debug = false build_Darwin_RelWithDebInfo = false - + # ======================================== -# Viewer Development +# Viewer Development -- # ======================================== # Report changes since... -- cgit v1.2.3 From 1743e6a81330824021667000f8acdd6cf64dbf1b Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 24 Oct 2012 14:31:05 -0400 Subject: Added tag 3.4.1-beta10 for changeset 4e0d84e92132 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index dc7ca3db19..c1bd6a13f1 100644 --- a/.hgtags +++ b/.hgtags @@ -328,3 +328,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 464cf7a63a9a2f95bc4972dc022ca765e93de7d3 DRTVWR-233 9c4519aa5c70f7560111fb5c740d3a7dc20a845a 3.4.1-beta9 637fe8bbee5e24940448198c221d5ee0fa3247b4 3.4.1-beta9 +4e0d84e92132e9e95a1d52a1e49bad69c278ea05 3.4.1-beta10 -- cgit v1.2.3 From b8e14ad2b250ae8c4cae877035e38c485a841515 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 26 Oct 2012 15:55:58 -0500 Subject: MAINT-1709 Fix for >> that should have been > > --- indra/llmath/lloctree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 68d8110f1d..4ac1e55cfc 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -78,7 +78,7 @@ public: typedef LLOctreeTraveler oct_traveler; typedef LLTreeTraveler tree_traveler; - typedef std::vector> element_list; + typedef std::vector > element_list; typedef LLPointer* element_iter; typedef const LLPointer* const_element_iter; typedef typename std::vector*>::iterator tree_listener_iter; -- cgit v1.2.3 From e680af5e5df347edd08a5e441ffe06ae652c6232 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 30 Oct 2012 10:32:17 -0400 Subject: tag merge of DRTVWR-235 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 6d9234d3e8..0dbab285a6 100644 --- a/.hgtags +++ b/.hgtags @@ -309,3 +309,4 @@ ceed0b65a69f1eac20d523e0203320a32f9a3f3c DRTVWR-215 733ceac77583874f3626ef7a15c105b83ef0f5bb 3.4.0-beta7 d02759655d6b36d60f4a927e4bfce82844a82ef5 3.4.0-release 97977c67245f52db20eb15f1918cc0f24778cabc 3.4.0-release +f7cbd60a3f57ff1101157eeb79ea21e8898bedae DRTVWR-235 -- cgit v1.2.3 From d6e96021c8caeea736d1290db9b3898bb93f293a Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 30 Oct 2012 13:54:27 -0400 Subject: tag merge of DRTVWR-236 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c1bd6a13f1..5fdd8f8761 100644 --- a/.hgtags +++ b/.hgtags @@ -329,3 +329,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 9c4519aa5c70f7560111fb5c740d3a7dc20a845a 3.4.1-beta9 637fe8bbee5e24940448198c221d5ee0fa3247b4 3.4.1-beta9 4e0d84e92132e9e95a1d52a1e49bad69c278ea05 3.4.1-beta10 +baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236 -- cgit v1.2.3 From e4df3c1ca875d396240f75c1af8db20f4f7300bf Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 30 Oct 2012 14:02:49 -0400 Subject: Added tag 3.4.1-beta11 for changeset 18498afcdb83 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index f0ae285819..ce2c9d5b62 100644 --- a/.hgtags +++ b/.hgtags @@ -329,3 +329,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 4e0d84e92132e9e95a1d52a1e49bad69c278ea05 3.4.1-beta10 f7cbd60a3f57ff1101157eeb79ea21e8898bedae DRTVWR-235 baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236 +18498afcdb835d6fc4d36ed935347d3b65307bad 3.4.1-beta11 -- cgit v1.2.3 From 44a024d2f5d4467372d0d2082a83449696b22948 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 31 Oct 2012 16:00:56 -0500 Subject: MAINT-646 Fix for leak introduced by optimizations. --- indra/newview/llviewerobjectlist.cpp | 9 ++++++++- indra/newview/llviewerobjectlist.h | 1 + indra/newview/llviewerwindow.cpp | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index ea20950b36..b433484783 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1405,8 +1405,9 @@ void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) { mActiveObjects[idx] = mActiveObjects[last_index]; mActiveObjects[idx]->setListIndex(idx); - mActiveObjects.pop_back(); } + + mActiveObjects.pop_back(); } } @@ -1450,6 +1451,12 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) objectp->setOnActiveList(FALSE); } } + + //post condition: if object is active, it must be on the active list + llassert(!active || std::find(mActiveObjects.begin(), mActiveObjects.end(), objectp) != mActiveObjects.end()); + + //post condition: if object is not active, it must not be on the active list + llassert(active || std::find(mActiveObjects.begin(), mActiveObjects.end(), objectp) == mActiveObjects.end()); } void LLViewerObjectList::updateObjectCost(LLViewerObject* object) diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 9936432a71..449a4633ff 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -129,6 +129,7 @@ public: LLViewerObject *getSelectedObject(const U32 object_id); inline S32 getNumObjects() { return (S32) mObjects.size(); } + inline S32 getNumActiveObjects() { return (S32) mActiveObjects.size(); } void addToMap(LLViewerObject *objectp); void removeFromMap(LLViewerObject *objectp); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index af2eec9ba8..98ea923272 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -563,6 +563,9 @@ public: addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount)); ypos += y_inc; + addText(xpos, ypos, llformat("%d/%d Objects Active", gObjectList.getNumActiveObjects(), gObjectList.getNumObjects())); + ypos += y_inc; + addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount)); ypos += y_inc; -- cgit v1.2.3 From 6cd60fced27a9cf0e0389901d1d93a85376e93a4 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 1 Nov 2012 19:59:01 -0400 Subject: tag merge of DRTVWR-237 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index ce2c9d5b62..e60b2b5642 100644 --- a/.hgtags +++ b/.hgtags @@ -330,3 +330,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 f7cbd60a3f57ff1101157eeb79ea21e8898bedae DRTVWR-235 baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236 18498afcdb835d6fc4d36ed935347d3b65307bad 3.4.1-beta11 +b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 -- cgit v1.2.3 From fcb393f108fc5bee02f8164f828f40c6c543311b Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 1 Nov 2012 20:50:20 -0400 Subject: Added tag 3.4.1-beta12 for changeset 853a20242639 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index e60b2b5642..3e81884085 100644 --- a/.hgtags +++ b/.hgtags @@ -331,3 +331,4 @@ f7cbd60a3f57ff1101157eeb79ea21e8898bedae DRTVWR-235 baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236 18498afcdb835d6fc4d36ed935347d3b65307bad 3.4.1-beta11 b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 +853a202426398cb0b7676aa498603a25d8ad20fb 3.4.1-beta12 -- cgit v1.2.3 From e00d2c8744aabbdc5ad158b41a7b80db3ad6ce9a Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 2 Nov 2012 14:03:22 -0400 Subject: Added tag 3.4.1-beta12 for changeset b6b68f3c2c6d --- .hgtags | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgtags b/.hgtags index 3e81884085..48125a1a51 100644 --- a/.hgtags +++ b/.hgtags @@ -332,3 +332,5 @@ baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236 18498afcdb835d6fc4d36ed935347d3b65307bad 3.4.1-beta11 b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 853a202426398cb0b7676aa498603a25d8ad20fb 3.4.1-beta12 +853a202426398cb0b7676aa498603a25d8ad20fb 3.4.1-beta12 +b6b68f3c2c6dd04ad88bd0575aad67bf87a9c108 3.4.1-beta12 -- cgit v1.2.3 From dd55b600e54b48b0052f5cecf36c72dd6021fd77 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 2 Nov 2012 14:58:09 -0400 Subject: whitespace change to force new build number --- BuildParams | 1 + 1 file changed, 1 insertion(+) diff --git a/BuildParams b/BuildParams index 908ef3ed0c..8d529c63b9 100644 --- a/BuildParams +++ b/BuildParams @@ -3,6 +3,7 @@ # Please refer to: # https://wiki.secondlife.com/wiki/Automated_Build_System + # Global setting for now... Darwin.symbolfiles = "newview/Release/secondlife-symbols-darwin.tar.bz2" CYGWIN.symbolfiles = "newview/Release/secondlife-symbols-windows.tar.bz2" -- cgit v1.2.3 From 1f305e8624e130683fc5d8fceac7a8159515376b Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 2 Nov 2012 14:58:18 -0400 Subject: Added tag 3.4.1-beta12 for changeset 3f9be82de642 --- .hgtags | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgtags b/.hgtags index 48125a1a51..8d6197a0b5 100644 --- a/.hgtags +++ b/.hgtags @@ -334,3 +334,5 @@ b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 853a202426398cb0b7676aa498603a25d8ad20fb 3.4.1-beta12 853a202426398cb0b7676aa498603a25d8ad20fb 3.4.1-beta12 b6b68f3c2c6dd04ad88bd0575aad67bf87a9c108 3.4.1-beta12 +b6b68f3c2c6dd04ad88bd0575aad67bf87a9c108 3.4.1-beta12 +3f9be82de642d468c5fc272cb9d96b46b5498402 3.4.1-beta12 -- cgit v1.2.3 From f8749ec9bd03072cc5b50f4cb1a61289b2989c72 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 5 Nov 2012 14:46:38 -0500 Subject: Added tag 3.4.1-release for changeset e59ffd3fe083 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8d6197a0b5..e7be33a842 100644 --- a/.hgtags +++ b/.hgtags @@ -336,3 +336,4 @@ b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237 b6b68f3c2c6dd04ad88bd0575aad67bf87a9c108 3.4.1-beta12 b6b68f3c2c6dd04ad88bd0575aad67bf87a9c108 3.4.1-beta12 3f9be82de642d468c5fc272cb9d96b46b5498402 3.4.1-beta12 +e59ffd3fe0838ae6b09b242a6e9df71761b88f41 3.4.1-release -- cgit v1.2.3 From 21de2d948c86cd2ccc728f6165369e01ff09049e Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 5 Nov 2012 16:26:48 -0500 Subject: tag merge of DRTVWR-217 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c1bd6a13f1..7698982990 100755 --- a/.hgtags +++ b/.hgtags @@ -329,3 +329,4 @@ fba99f381b8d4ad1b7b42fa4993b29998d95be18 DRTVWR-179 9c4519aa5c70f7560111fb5c740d3a7dc20a845a 3.4.1-beta9 637fe8bbee5e24940448198c221d5ee0fa3247b4 3.4.1-beta9 4e0d84e92132e9e95a1d52a1e49bad69c278ea05 3.4.1-beta10 +32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217 -- cgit v1.2.3 From bfd6a0c6b9bb4b05d6705c722d330b49195d5b0c Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 5 Nov 2012 17:14:19 -0500 Subject: Added tag 3.4.2-beta1 for changeset 704bbae7b182 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 25bc400684..965770d483 100755 --- a/.hgtags +++ b/.hgtags @@ -345,3 +345,4 @@ de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202 7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206 b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219 32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217 +704bbae7b182a1f2811a47a054e680522966f54a 3.4.2-beta1 -- cgit v1.2.3