PageRenderTime 128ms CodeModel.GetById 8ms app.highlight 107ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llviewerregion.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1830 lines | 1411 code | 259 blank | 160 comment | 138 complexity | 5fc4014d934e62cdb7e111c301fa49a3 MD5 | raw file
   1/** 
   2 * @file llviewerregion.cpp
   3 * @brief Implementation of the LLViewerRegion class.
   4 *
   5 * $LicenseInfo:firstyear=2000&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include "llviewerregion.h"
  30
  31// linden libraries
  32#include "indra_constants.h"
  33#include "llavatarnamecache.h"		// name lookup cap url
  34#include "llfloaterreg.h"
  35#include "llmath.h"
  36#include "llhttpclient.h"
  37#include "llregionflags.h"
  38#include "llregionhandle.h"
  39#include "llsurface.h"
  40#include "message.h"
  41//#include "vmath.h"
  42#include "v3math.h"
  43#include "v4math.h"
  44
  45#include "llagent.h"
  46#include "llagentcamera.h"
  47#include "llcallingcard.h"
  48#include "llcaphttpsender.h"
  49#include "llcapabilitylistener.h"
  50#include "llcommandhandler.h"
  51#include "lldir.h"
  52#include "lleventpoll.h"
  53#include "llfloatergodtools.h"
  54#include "llfloaterreporter.h"
  55#include "llfloaterregioninfo.h"
  56#include "llhttpnode.h"
  57#include "llregioninfomodel.h"
  58#include "llsdutil.h"
  59#include "llstartup.h"
  60#include "lltrans.h"
  61#include "llurldispatcher.h"
  62#include "llviewerobjectlist.h"
  63#include "llviewerparceloverlay.h"
  64#include "llviewerstatsrecorder.h"
  65#include "llvlmanager.h"
  66#include "llvlcomposition.h"
  67#include "llvocache.h"
  68#include "llworld.h"
  69#include "llspatialpartition.h"
  70#include "stringize.h"
  71#include "llviewercontrol.h"
  72#include "llsdserialize.h"
  73
  74#ifdef LL_WINDOWS
  75	#pragma warning(disable:4355)
  76#endif
  77
  78const F32 WATER_TEXTURE_SCALE = 8.f;			//  Number of times to repeat the water texture across a region
  79const S16 MAX_MAP_DIST = 10;
  80// The server only keeps our pending agent info for 60 seconds.
  81// We want to allow for seed cap retry, but its not useful after that 60 seconds.
  82// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up.
  83const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3;
  84const F32 CAP_REQUEST_TIMEOUT = 18;
  85// Even though we gave up on login, keep trying for caps after we are logged in:
  86const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
  87
  88typedef std::map<std::string, std::string> CapabilityMap;
  89
  90class LLViewerRegionImpl {
  91public:
  92	LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host)
  93		:	mHost(host),
  94			mCompositionp(NULL),
  95			mEventPoll(NULL),
  96			mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS),
  97			mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN),
  98			mSeedCapAttempts(0),
  99			mHttpResponderID(0),
 100		    // I'd prefer to set the LLCapabilityListener name to match the region
 101		    // name -- it's disappointing that's not available at construction time.
 102		    // We could instead store an LLCapabilityListener*, making
 103		    // setRegionNameAndZone() replace the instance. Would that pose
 104		    // consistency problems? Can we even request a capability before calling
 105		    // setRegionNameAndZone()?
 106		    // For testability -- the new Michael Feathers paradigm --
 107		    // LLCapabilityListener binds all the globals it expects to need at
 108		    // construction time.
 109		    mCapabilityListener(host.getString(), gMessageSystem, *region,
 110		                        gAgent.getID(), gAgent.getSessionID())
 111	{
 112	}
 113
 114	void buildCapabilityNames(LLSD& capabilityNames);
 115
 116	// The surfaces and other layers
 117	LLSurface*	mLandp;
 118
 119	// Region geometry data
 120	LLVector3d	mOriginGlobal;	// Location of southwest corner of region (meters)
 121	LLVector3d	mCenterGlobal;	// Location of center in world space (meters)
 122	LLHost		mHost;
 123
 124	// The unique ID for this region.
 125	LLUUID mRegionID;
 126
 127	// region/estate owner - usually null.
 128	LLUUID mOwnerID;
 129
 130	// Network statistics for the region's circuit...
 131	LLTimer mLastNetUpdate;
 132
 133	// Misc
 134	LLVLComposition *mCompositionp;		// Composition layer for the surface
 135
 136	LLVOCacheEntry::vocache_entry_map_t		mCacheMap;
 137	// time?
 138	// LRU info?
 139
 140	// Cache ID is unique per-region, across renames, moving locations,
 141	// etc.
 142	LLUUID mCacheID;
 143
 144	CapabilityMap mCapabilities;
 145	
 146	LLEventPoll* mEventPoll;
 147
 148	S32 mSeedCapMaxAttempts;
 149	S32 mSeedCapMaxAttemptsBeforeLogin;
 150	S32 mSeedCapAttempts;
 151
 152	S32 mHttpResponderID;
 153
 154	/// Post an event to this LLCapabilityListener to invoke a capability message on
 155	/// this LLViewerRegion's server
 156	/// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
 157	LLCapabilityListener mCapabilityListener;
 158
 159	//spatial partitions for objects in this region
 160	std::vector<LLSpatialPartition*> mObjectPartition;
 161};
 162
 163// support for secondlife:///app/region/{REGION} SLapps
 164// N.B. this is defined to work exactly like the classic secondlife://{REGION}
 165// However, the later syntax cannot support spaces in the region name because
 166// spaces (and %20 chars) are illegal in the hostname of an http URL. Some
 167// browsers let you get away with this, but some do not (such as Qt's Webkit).
 168// Hence we introduced the newer secondlife:///app/region alternative.
 169class LLRegionHandler : public LLCommandHandler
 170{
 171public:
 172	// requests will be throttled from a non-trusted browser
 173	LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {}
 174
 175	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
 176	{
 177		// make sure that we at least have a region name
 178		int num_params = params.size();
 179		if (num_params < 1)
 180		{
 181			return false;
 182		}
 183
 184		// build a secondlife://{PLACE} SLurl from this SLapp
 185		std::string url = "secondlife://";
 186		for (int i = 0; i < num_params; i++)
 187		{
 188			if (i > 0)
 189			{
 190				url += "/";
 191			}
 192			url += params[i].asString();
 193		}
 194
 195		// Process the SLapp as if it was a secondlife://{PLACE} SLurl
 196		LLURLDispatcher::dispatch(url, "clicked", web, true);
 197		return true;
 198	}
 199};
 200LLRegionHandler gRegionHandler;
 201
 202class BaseCapabilitiesComplete : public LLHTTPClient::Responder
 203{
 204	LOG_CLASS(BaseCapabilitiesComplete);
 205public:
 206    BaseCapabilitiesComplete(U64 region_handle, S32 id)
 207		: mRegionHandle(region_handle), mID(id)
 208    { }
 209	virtual ~BaseCapabilitiesComplete()
 210	{ }
 211
 212    void error(U32 statusNum, const std::string& reason)
 213    {
 214		LL_WARNS2("AppInit", "Capabilities") << statusNum << ": " << reason << LL_ENDL;
 215		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 216		if (regionp)
 217		{
 218			regionp->failedSeedCapability();
 219		}
 220    }
 221
 222    void result(const LLSD& content)
 223    {
 224		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
 225		if(!regionp) //region was removed
 226		{
 227			LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
 228			return ;
 229		}
 230		if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder
 231		{
 232			LL_WARNS2("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL;
 233			return ;
 234		}
 235
 236		LLSD::map_const_iterator iter;
 237		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
 238		{
 239			regionp->setCapability(iter->first, iter->second);
 240			LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " 
 241				<< iter->first << LL_ENDL;
 242
 243			/* HACK we're waiting for the ServerReleaseNotes */
 244			if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested())
 245			{
 246				regionp->showReleaseNotes();
 247			}
 248		}
 249
 250		regionp->setCapabilitiesReceived(true);
 251
 252		if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
 253		{
 254			LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
 255		}
 256	}
 257
 258    static boost::intrusive_ptr<BaseCapabilitiesComplete> build( U64 region_handle, S32 id )
 259    {
 260		return boost::intrusive_ptr<BaseCapabilitiesComplete>( 
 261				new BaseCapabilitiesComplete(region_handle, id) );
 262    }
 263
 264private:
 265	U64 mRegionHandle;
 266	S32 mID;
 267};
 268
 269
 270LLViewerRegion::LLViewerRegion(const U64 &handle,
 271							   const LLHost &host,
 272							   const U32 grids_per_region_edge, 
 273							   const U32 grids_per_patch_edge, 
 274							   const F32 region_width_meters)
 275:	mImpl(new LLViewerRegionImpl(this, host)),
 276	mHandle(handle),
 277	mTimeDilation(1.0f),
 278	mName(""),
 279	mZoning(""),
 280	mIsEstateManager(FALSE),
 281	mRegionFlags( REGION_FLAGS_DEFAULT ),
 282	mSimAccess( SIM_ACCESS_MIN ),
 283	mBillableFactor(1.0),
 284	mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT),
 285	mClassID(0),
 286	mCPURatio(0),
 287	mColoName("unknown"),
 288	mProductSKU("unknown"),
 289	mProductName("unknown"),
 290	mHttpUrl(""),
 291	mCacheLoaded(FALSE),
 292	mCacheDirty(FALSE),
 293	mReleaseNotesRequested(FALSE),
 294	mCapabilitiesReceived(false)
 295{
 296	mWidth = region_width_meters;
 297	mImpl->mOriginGlobal = from_region_handle(handle); 
 298	updateRenderMatrix();
 299
 300	mImpl->mLandp = new LLSurface('l', NULL);
 301
 302	// Create the composition layer for the surface
 303	mImpl->mCompositionp =
 304		new LLVLComposition(mImpl->mLandp,
 305							grids_per_region_edge,
 306							region_width_meters / grids_per_region_edge);
 307	mImpl->mCompositionp->setSurface(mImpl->mLandp);
 308
 309	// Create the surfaces
 310	mImpl->mLandp->setRegion(this);
 311	mImpl->mLandp->create(grids_per_region_edge,
 312					grids_per_patch_edge,
 313					mImpl->mOriginGlobal,
 314					mWidth);
 315
 316	mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters);
 317
 318	setOriginGlobal(from_region_handle(handle));
 319	calculateCenterGlobal();
 320
 321	// Create the object lists
 322	initStats();
 323
 324	//create object partitions
 325	//MUST MATCH declaration of eObjectPartitions
 326	mImpl->mObjectPartition.push_back(new LLHUDPartition());		//PARTITION_HUD
 327	mImpl->mObjectPartition.push_back(new LLTerrainPartition());	//PARTITION_TERRAIN
 328	mImpl->mObjectPartition.push_back(new LLVoidWaterPartition());	//PARTITION_VOIDWATER
 329	mImpl->mObjectPartition.push_back(new LLWaterPartition());		//PARTITION_WATER
 330	mImpl->mObjectPartition.push_back(new LLTreePartition());		//PARTITION_TREE
 331	mImpl->mObjectPartition.push_back(new LLParticlePartition());	//PARTITION_PARTICLE
 332	mImpl->mObjectPartition.push_back(new LLGrassPartition());		//PARTITION_GRASS
 333	mImpl->mObjectPartition.push_back(new LLVolumePartition());	//PARTITION_VOLUME
 334	mImpl->mObjectPartition.push_back(new LLBridgePartition());	//PARTITION_BRIDGE
 335	mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE
 336	mImpl->mObjectPartition.push_back(NULL);						//PARTITION_NONE
 337}
 338
 339
 340void LLViewerRegion::initStats()
 341{
 342	mImpl->mLastNetUpdate.reset();
 343	mPacketsIn = 0;
 344	mBitsIn = 0;
 345	mLastBitsIn = 0;
 346	mLastPacketsIn = 0;
 347	mPacketsOut = 0;
 348	mLastPacketsOut = 0;
 349	mPacketsLost = 0;
 350	mLastPacketsLost = 0;
 351	mPingDelay = 0;
 352	mAlive = false;					// can become false if circuit disconnects
 353}
 354
 355LLViewerRegion::~LLViewerRegion() 
 356{
 357	gVLManager.cleanupData(this);
 358	// Can't do this on destruction, because the neighbor pointers might be invalid.
 359	// This should be reference counted...
 360	disconnectAllNeighbors();
 361	LLViewerPartSim::getInstance()->cleanupRegion(this);
 362
 363	gObjectList.killObjects(this);
 364
 365	delete mImpl->mCompositionp;
 366	delete mParcelOverlay;
 367	delete mImpl->mLandp;
 368	delete mImpl->mEventPoll;
 369	LLHTTPSender::clearSender(mImpl->mHost);
 370	
 371	saveObjectCache();
 372
 373	std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
 374
 375	delete mImpl;
 376	mImpl = NULL;
 377}
 378
 379LLEventPump& LLViewerRegion::getCapAPI() const
 380{
 381	return mImpl->mCapabilityListener.getCapAPI();
 382}
 383
 384/*virtual*/ 
 385const LLHost&	LLViewerRegion::getHost() const				
 386{ 
 387	return mImpl->mHost; 
 388}
 389
 390LLSurface & LLViewerRegion::getLand() const
 391{
 392	return *mImpl->mLandp;
 393}
 394
 395const LLUUID& LLViewerRegion::getRegionID() const
 396{
 397	return mImpl->mRegionID;
 398}
 399
 400void LLViewerRegion::setRegionID(const LLUUID& region_id)
 401{
 402	mImpl->mRegionID = region_id;
 403}
 404
 405void LLViewerRegion::loadObjectCache()
 406{
 407	if (mCacheLoaded)
 408	{
 409		return;
 410	}
 411
 412	// Presume success.  If it fails, we don't want to try again.
 413	mCacheLoaded = TRUE;
 414
 415	if(LLVOCache::hasInstance())
 416	{
 417		LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ;
 418	}
 419}
 420
 421
 422void LLViewerRegion::saveObjectCache()
 423{
 424	if (!mCacheLoaded)
 425	{
 426		return;
 427	}
 428
 429	if (mImpl->mCacheMap.empty())
 430	{
 431		return;
 432	}
 433
 434	if(LLVOCache::hasInstance())
 435	{
 436		LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ;
 437		mCacheDirty = FALSE;
 438	}
 439
 440	for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter)
 441	{
 442		delete iter->second;
 443	}
 444	mImpl->mCacheMap.clear();
 445}
 446
 447void LLViewerRegion::sendMessage()
 448{
 449	gMessageSystem->sendMessage(mImpl->mHost);
 450}
 451
 452void LLViewerRegion::sendReliableMessage()
 453{
 454	gMessageSystem->sendReliable(mImpl->mHost);
 455}
 456
 457void LLViewerRegion::setFlags(BOOL b, U32 flags)
 458{
 459	if (b)
 460	{
 461		mRegionFlags |=  flags;
 462	}
 463	else
 464	{
 465		mRegionFlags &= ~flags;
 466	}
 467}
 468
 469void LLViewerRegion::setWaterHeight(F32 water_level)
 470{
 471	mImpl->mLandp->setWaterHeight(water_level);
 472}
 473
 474F32 LLViewerRegion::getWaterHeight() const
 475{
 476	return mImpl->mLandp->getWaterHeight();
 477}
 478
 479BOOL LLViewerRegion::isVoiceEnabled() const
 480{
 481	return (getRegionFlags() & REGION_FLAGS_ALLOW_VOICE);
 482}
 483
 484void LLViewerRegion::setRegionFlags(U32 flags)
 485{
 486	mRegionFlags = flags;
 487}
 488
 489
 490void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) 
 491{ 
 492	mImpl->mOriginGlobal = origin_global; 
 493	updateRenderMatrix();
 494	mImpl->mLandp->setOriginGlobal(origin_global);
 495	mWind.setOriginGlobal(origin_global);
 496	calculateCenterGlobal();
 497}
 498
 499void LLViewerRegion::updateRenderMatrix()
 500{
 501	mRenderMatrix.setTranslation(getOriginAgent());
 502}
 503
 504void LLViewerRegion::setTimeDilation(F32 time_dilation)
 505{
 506	mTimeDilation = time_dilation;
 507}
 508
 509const LLVector3d & LLViewerRegion::getOriginGlobal() const
 510{
 511	return mImpl->mOriginGlobal;
 512}
 513
 514LLVector3 LLViewerRegion::getOriginAgent() const
 515{
 516	return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal);
 517}
 518
 519const LLVector3d & LLViewerRegion::getCenterGlobal() const
 520{
 521	return mImpl->mCenterGlobal;
 522}
 523
 524LLVector3 LLViewerRegion::getCenterAgent() const
 525{
 526	return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal);
 527}
 528
 529void LLViewerRegion::setOwner(const LLUUID& owner_id)
 530{
 531	mImpl->mOwnerID = owner_id;
 532}
 533
 534const LLUUID& LLViewerRegion::getOwner() const
 535{
 536	return mImpl->mOwnerID;
 537}
 538
 539void LLViewerRegion::setRegionNameAndZone	(const std::string& name_zone)
 540{
 541	std::string::size_type pipe_pos = name_zone.find('|');
 542	S32 length   = name_zone.size();
 543	if (pipe_pos != std::string::npos)
 544	{
 545		mName   = name_zone.substr(0, pipe_pos);
 546		mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1));
 547	}
 548	else
 549	{
 550		mName   = name_zone;
 551		mZoning = "";
 552	}
 553
 554	LLStringUtil::stripNonprintable(mName);
 555	LLStringUtil::stripNonprintable(mZoning);
 556}
 557
 558BOOL LLViewerRegion::canManageEstate() const
 559{
 560	return gAgent.isGodlike()
 561		|| isEstateManager()
 562		|| gAgent.getID() == getOwner();
 563}
 564
 565const std::string LLViewerRegion::getSimAccessString() const
 566{
 567	return accessToString(mSimAccess);
 568}
 569
 570std::string LLViewerRegion::getLocalizedSimProductName() const
 571{
 572	std::string localized_spn;
 573	return LLTrans::findString(localized_spn, mProductName) ? localized_spn : mProductName;
 574}
 575
 576// static
 577std::string LLViewerRegion::regionFlagsToString(U32 flags)
 578{
 579	std::string result;
 580
 581	if (flags & REGION_FLAGS_SANDBOX)
 582	{
 583		result += "Sandbox";
 584	}
 585
 586	if (flags & REGION_FLAGS_ALLOW_DAMAGE)
 587	{
 588		result += " Not Safe";
 589	}
 590
 591	return result;
 592}
 593
 594// static
 595std::string LLViewerRegion::accessToString(U8 sim_access)
 596{
 597	switch(sim_access)
 598	{
 599	case SIM_ACCESS_PG:
 600		return LLTrans::getString("SIM_ACCESS_PG");
 601
 602	case SIM_ACCESS_MATURE:
 603		return LLTrans::getString("SIM_ACCESS_MATURE");
 604
 605	case SIM_ACCESS_ADULT:
 606		return LLTrans::getString("SIM_ACCESS_ADULT");
 607
 608	case SIM_ACCESS_DOWN:
 609		return LLTrans::getString("SIM_ACCESS_DOWN");
 610
 611	case SIM_ACCESS_MIN:
 612	default:
 613		return LLTrans::getString("SIM_ACCESS_MIN");
 614	}
 615}
 616
 617// static
 618std::string LLViewerRegion::getAccessIcon(U8 sim_access)
 619{
 620	switch(sim_access)
 621	{
 622	case SIM_ACCESS_MATURE:
 623		return "Parcel_M_Dark";
 624
 625	case SIM_ACCESS_ADULT:
 626		return "Parcel_R_Light";
 627
 628	case SIM_ACCESS_PG:
 629		return "Parcel_PG_Light";
 630
 631	case SIM_ACCESS_MIN:
 632	default:
 633		return "";
 634	}
 635}
 636
 637// static
 638std::string LLViewerRegion::accessToShortString(U8 sim_access)
 639{
 640	switch(sim_access)		/* Flawfinder: ignore */
 641	{
 642	case SIM_ACCESS_PG:
 643		return "PG";
 644
 645	case SIM_ACCESS_MATURE:
 646		return "M";
 647
 648	case SIM_ACCESS_ADULT:
 649		return "A";
 650
 651	case SIM_ACCESS_MIN:
 652	default:
 653		return "U";
 654	}
 655}
 656
 657// static
 658void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
 659{
 660	// send it to 'observers'
 661	// *TODO: switch the floaters to using LLRegionInfoModel
 662	llinfos << "Processing region info" << llendl;
 663	LLRegionInfoModel::instance().update(msg);
 664	LLFloaterGodTools::processRegionInfo(msg);
 665	LLFloaterRegionInfo::processRegionInfo(msg);
 666	LLFloaterReporter::processRegionInfo(msg);
 667}
 668
 669void LLViewerRegion::setCacheID(const LLUUID& id)
 670{
 671	mImpl->mCacheID = id;
 672}
 673
 674S32 LLViewerRegion::renderPropertyLines()
 675{
 676	if (mParcelOverlay)
 677	{
 678		return mParcelOverlay->renderPropertyLines();
 679	}
 680	else
 681	{
 682		return 0;
 683	}
 684}
 685
 686// This gets called when the height field changes.
 687void LLViewerRegion::dirtyHeights()
 688{
 689	// Property lines need to be reconstructed when the land changes.
 690	if (mParcelOverlay)
 691	{
 692		mParcelOverlay->setDirty();
 693	}
 694}
 695
 696BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
 697{
 698	LLMemType mt_ivr(LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION);
 699	// did_update returns TRUE if we did at least one significant update
 700	BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time);
 701	
 702	if (mParcelOverlay)
 703	{
 704		// Hopefully not a significant time sink...
 705		mParcelOverlay->idleUpdate();
 706	}
 707
 708	return did_update;
 709}
 710
 711
 712// As above, but forcibly do the update.
 713void LLViewerRegion::forceUpdate()
 714{
 715	mImpl->mLandp->idleUpdate(0.f);
 716
 717	if (mParcelOverlay)
 718	{
 719		mParcelOverlay->idleUpdate(true);
 720	}
 721}
 722
 723void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction)
 724{
 725	mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction);
 726}
 727
 728
 729void LLViewerRegion::disconnectAllNeighbors()
 730{
 731	mImpl->mLandp->disconnectAllNeighbors();
 732}
 733
 734LLVLComposition * LLViewerRegion::getComposition() const
 735{
 736	return mImpl->mCompositionp;
 737}
 738
 739F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const
 740{
 741	if (x >= 256)
 742	{
 743		if (y >= 256)
 744		{
 745			LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f);
 746			LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center);
 747			if (regionp)
 748			{
 749				// OK, we need to do some hackery here - different simulators no longer use
 750				// the same composition values, necessarily.
 751				// If we're attempting to blend, then we want to make the fractional part of
 752				// this region match the fractional of the adjacent.  For now, just minimize
 753				// the delta.
 754				F32 our_comp = getComposition()->getValueScaled(255, 255);
 755				F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f);
 756				while (llabs(our_comp - adj_comp) >= 1.f)
 757				{
 758					if (our_comp > adj_comp)
 759					{
 760						adj_comp += 1.f;
 761					}
 762					else
 763					{
 764						adj_comp -= 1.f;
 765					}
 766				}
 767				return adj_comp;
 768			}
 769		}
 770		else
 771		{
 772			LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f);
 773			LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center);
 774			if (regionp)
 775			{
 776				// OK, we need to do some hackery here - different simulators no longer use
 777				// the same composition values, necessarily.
 778				// If we're attempting to blend, then we want to make the fractional part of
 779				// this region match the fractional of the adjacent.  For now, just minimize
 780				// the delta.
 781				F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y);
 782				F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y);
 783				while (llabs(our_comp - adj_comp) >= 1.f)
 784				{
 785					if (our_comp > adj_comp)
 786					{
 787						adj_comp += 1.f;
 788					}
 789					else
 790					{
 791						adj_comp -= 1.f;
 792					}
 793				}
 794				return adj_comp;
 795			}
 796		}
 797	}
 798	else if (y >= 256)
 799	{
 800		LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f);
 801		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center);
 802		if (regionp)
 803		{
 804			// OK, we need to do some hackery here - different simulators no longer use
 805			// the same composition values, necessarily.
 806			// If we're attempting to blend, then we want to make the fractional part of
 807			// this region match the fractional of the adjacent.  For now, just minimize
 808			// the delta.
 809			F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f);
 810			F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f);
 811			while (llabs(our_comp - adj_comp) >= 1.f)
 812			{
 813				if (our_comp > adj_comp)
 814				{
 815					adj_comp += 1.f;
 816				}
 817				else
 818				{
 819					adj_comp -= 1.f;
 820				}
 821			}
 822			return adj_comp;
 823		}
 824	}
 825
 826	return getComposition()->getValueScaled((F32)x, (F32)y);
 827}
 828
 829void LLViewerRegion::calculateCenterGlobal() 
 830{
 831	mImpl->mCenterGlobal = mImpl->mOriginGlobal;
 832	mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth;
 833	mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth;
 834	mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ();
 835}
 836
 837void LLViewerRegion::calculateCameraDistance()
 838{
 839	mCameraDistanceSquared = (F32)(gAgentCamera.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared();
 840}
 841
 842std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region)
 843{
 844	s << "{ ";
 845	s << region.mImpl->mHost;
 846	s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n";
 847    std::string name(region.getName()), zone(region.getZoning());
 848    if (! name.empty())
 849    {
 850        s << " mName         = " << name << '\n';
 851    }
 852    if (! zone.empty())
 853    {
 854        s << " mZoning       = " << zone << '\n';
 855    }
 856	s << "}";
 857	return s;
 858}
 859
 860
 861// ---------------- Protected Member Functions ----------------
 862
 863void LLViewerRegion::updateNetStats()
 864{
 865	F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32();
 866
 867	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost);
 868	if (!cdp)
 869	{
 870		mAlive = false;
 871		return;
 872	}
 873
 874	mAlive = true;
 875	mDeltaTime = dt;
 876
 877	mLastPacketsIn =	mPacketsIn;
 878	mLastBitsIn =		mBitsIn;
 879	mLastPacketsOut =	mPacketsOut;
 880	mLastPacketsLost =	mPacketsLost;
 881
 882	mPacketsIn =				cdp->getPacketsIn();
 883	mBitsIn =					8 * cdp->getBytesIn();
 884	mPacketsOut =				cdp->getPacketsOut();
 885	mPacketsLost =				cdp->getPacketsLost();
 886	mPingDelay =				cdp->getPingDelay();
 887
 888	mBitStat.addValue(mBitsIn - mLastBitsIn);
 889	mPacketsStat.addValue(mPacketsIn - mLastPacketsIn);
 890	mPacketsLostStat.addValue(mPacketsLost);
 891}
 892
 893
 894U32 LLViewerRegion::getPacketsLost() const
 895{
 896	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost);
 897	if (!cdp)
 898	{
 899		llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << llendl;
 900		return 0;
 901	}
 902	else
 903	{
 904		return cdp->getPacketsLost();
 905	}
 906}
 907
 908S32 LLViewerRegion::getHttpResponderID() const
 909{
 910	return mImpl->mHttpResponderID;
 911}
 912
 913BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const
 914{
 915	LLVector3 pos_region = getPosRegionFromGlobal(point_global);
 916
 917	if (pos_region.mV[VX] < 0)
 918	{
 919		return FALSE;
 920	}
 921	if (pos_region.mV[VX] >= mWidth)
 922	{
 923		return FALSE;
 924	}
 925	if (pos_region.mV[VY] < 0)
 926	{
 927		return FALSE;
 928	}
 929	if (pos_region.mV[VY] >= mWidth)
 930	{
 931		return FALSE;
 932	}
 933	return TRUE;
 934}
 935
 936LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const
 937{
 938	LLVector3 pos_region;
 939	pos_region.setVec(point_global - mImpl->mOriginGlobal);
 940	return pos_region;
 941}
 942
 943LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) const
 944{
 945	LLVector3d pos_region_d;
 946	pos_region_d.setVec(pos_region);
 947	return pos_region_d + mImpl->mOriginGlobal;
 948}
 949
 950LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const
 951{
 952	LLVector3d pos_global = getPosGlobalFromRegion(pos_region);
 953
 954	return gAgent.getPosAgentFromGlobal(pos_global);
 955}
 956
 957LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const
 958{
 959	return pos_agent - getOriginAgent();
 960}
 961
 962F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos)
 963{
 964	return mImpl->mLandp->resolveHeightRegion( region_pos );
 965}
 966
 967bool LLViewerRegion::isAlive()
 968{
 969	return mAlive;
 970}
 971
 972BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos)
 973{
 974	if (mParcelOverlay)
 975	{
 976		return mParcelOverlay->isOwnedSelf(pos);
 977	} else {
 978		return FALSE;
 979	}
 980}
 981
 982// Owned by a group you belong to?  (officer or member)
 983BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos)
 984{
 985	if (mParcelOverlay)
 986	{
 987		return mParcelOverlay->isOwnedGroup(pos);
 988	} else {
 989		return FALSE;
 990	}
 991}
 992
 993// the new TCP coarse location handler node
 994class CoarseLocationUpdate : public LLHTTPNode
 995{
 996public:
 997	virtual void post(
 998		ResponsePtr responder,
 999		const LLSD& context,
1000		const LLSD& input) const
1001	{
1002		LLHost host(input["sender"].asString());
1003		LLViewerRegion* region = LLWorld::getInstance()->getRegion(host);
1004		if( !region )
1005		{
1006			return;
1007		}
1008
1009		S32 target_index = input["body"]["Index"][0]["Prey"].asInteger();
1010		S32 you_index    = input["body"]["Index"][0]["You" ].asInteger();
1011
1012		LLDynamicArray<U32>* avatar_locs = &region->mMapAvatars;
1013		LLDynamicArray<LLUUID>* avatar_ids = &region->mMapAvatarIDs;
1014		avatar_locs->reset();
1015		avatar_ids->reset();
1016
1017		//llinfos << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << llendl;
1018		//llinfos << "my agent id = " << gAgent.getID() << llendl;
1019		//llinfos << ll_pretty_print_sd(input) << llendl;
1020
1021		LLSD 
1022			locs   = input["body"]["Location"],
1023			agents = input["body"]["AgentData"];
1024		LLSD::array_iterator 
1025			locs_it = locs.beginArray(), 
1026			agents_it = agents.beginArray();
1027		BOOL has_agent_data = input["body"].has("AgentData");
1028
1029		for(int i=0; 
1030			locs_it != locs.endArray(); 
1031			i++, locs_it++)
1032		{
1033			U8 
1034				x = locs_it->get("X").asInteger(),
1035				y = locs_it->get("Y").asInteger(),
1036				z = locs_it->get("Z").asInteger();
1037			// treat the target specially for the map, and don't add you or the target
1038			if(i == target_index)
1039			{
1040				LLVector3d global_pos(region->getOriginGlobal());
1041				global_pos.mdV[VX] += (F64)x;
1042				global_pos.mdV[VY] += (F64)y;
1043				global_pos.mdV[VZ] += (F64)z * 4.0;
1044				LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos);
1045			}
1046			else if( i != you_index)
1047			{
1048				U32 loc = x << 16 | y << 8 | z; loc = loc;
1049				U32 pos = 0x0;
1050				pos |= x;
1051				pos <<= 8;
1052				pos |= y;
1053				pos <<= 8;
1054				pos |= z;
1055				avatar_locs->put(pos);
1056				//llinfos << "next pos: " << x << "," << y << "," << z << ": " << pos << llendl;
1057				if(has_agent_data) // for backwards compatibility with old message format
1058				{
1059					LLUUID agent_id(agents_it->get("AgentID").asUUID());
1060					//llinfos << "next agent: " << agent_id.asString() << llendl;
1061					avatar_ids->put(agent_id);
1062				}
1063			}
1064			if (has_agent_data)
1065			{
1066				agents_it++;
1067			}
1068		}
1069	}
1070};
1071
1072// build the coarse location HTTP node under the "/message" URL
1073LLHTTPRegistration<CoarseLocationUpdate>
1074   gHTTPRegistrationCoarseLocationUpdate(
1075	   "/message/CoarseLocationUpdate");
1076
1077
1078// the deprecated coarse location handler
1079void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
1080{
1081	//llinfos << "CoarseLocationUpdate" << llendl;
1082	mMapAvatars.reset();
1083	mMapAvatarIDs.reset(); // only matters in a rare case but it's good to be safe.
1084
1085	U8 x_pos = 0;
1086	U8 y_pos = 0;
1087	U8 z_pos = 0;
1088
1089	U32 pos = 0x0;
1090
1091	S16 agent_index;
1092	S16 target_index;
1093	msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index);
1094	msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index);
1095
1096	BOOL has_agent_data = msg->has(_PREHASH_AgentData);
1097	S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location);
1098	for(S32 i = 0; i < count; i++)
1099	{
1100		msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i);
1101		msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i);
1102		msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i);
1103		LLUUID agent_id = LLUUID::null;
1104		if(has_agent_data)
1105		{
1106			msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id, i);
1107		}
1108
1109		//llinfos << "  object X: " << (S32)x_pos << " Y: " << (S32)y_pos
1110		//		<< " Z: " << (S32)(z_pos * 4)
1111		//		<< llendl;
1112
1113		// treat the target specially for the map
1114		if(i == target_index)
1115		{
1116			LLVector3d global_pos(mImpl->mOriginGlobal);
1117			global_pos.mdV[VX] += (F64)(x_pos);
1118			global_pos.mdV[VY] += (F64)(y_pos);
1119			global_pos.mdV[VZ] += (F64)(z_pos) * 4.0;
1120			LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos);
1121		}
1122		
1123		//don't add you
1124		if( i != agent_index)
1125		{
1126			pos = 0x0;
1127			pos |= x_pos;
1128			pos <<= 8;
1129			pos |= y_pos;
1130			pos <<= 8;
1131			pos |= z_pos;
1132			mMapAvatars.put(pos);
1133			if(has_agent_data)
1134			{
1135				mMapAvatarIDs.put(agent_id);
1136			}
1137		}
1138	}
1139}
1140
1141void LLViewerRegion::getInfo(LLSD& info)
1142{
1143	info["Region"]["Host"] = getHost().getIPandPort();
1144	info["Region"]["Name"] = getName();
1145	U32 x, y;
1146	from_region_handle(getHandle(), &x, &y);
1147	info["Region"]["Handle"]["x"] = (LLSD::Integer)x;
1148	info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
1149}
1150
1151void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features)
1152{
1153	sim_features = mSimulatorFeatures;
1154}
1155
1156void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
1157{
1158	std::stringstream str;
1159	
1160	LLSDSerialize::toPrettyXML(sim_features, str);
1161	llinfos << str.str() << llendl;
1162	mSimulatorFeatures = sim_features;
1163}
1164
1165LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
1166{
1167	U32 local_id = objectp->getLocalID();
1168	U32 crc = objectp->getCRC();
1169
1170	LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
1171
1172	if (entry)
1173	{
1174		// we've seen this object before
1175		if (entry->getCRC() == crc)
1176		{
1177			// Record a hit
1178			entry->recordDupe();
1179			return CACHE_UPDATE_DUPE;
1180		}
1181
1182		// Update the cache entry
1183		mImpl->mCacheMap.erase(local_id);
1184		delete entry;
1185		entry = new LLVOCacheEntry(local_id, crc, dp);
1186		mImpl->mCacheMap[local_id] = entry;
1187		return CACHE_UPDATE_CHANGED;
1188	}
1189
1190	// we haven't seen this object before
1191
1192	// Create new entry and add to map
1193	eCacheUpdateResult result = CACHE_UPDATE_ADDED;
1194	if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
1195	{
1196		delete mImpl->mCacheMap.begin()->second ;
1197		mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());
1198		result = CACHE_UPDATE_REPLACED;
1199		
1200	}
1201	entry = new LLVOCacheEntry(local_id, crc, dp);
1202
1203	mImpl->mCacheMap[local_id] = entry;
1204	return result;
1205}
1206
1207// Get data packer for this object, if we have cached data
1208// AND the CRC matches. JC
1209LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)
1210{
1211	//llassert(mCacheLoaded);  This assert failes often, changing to early-out -- davep, 2010/10/18
1212
1213	LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
1214
1215	if (entry)
1216	{
1217		// we've seen this object before
1218		if (entry->getCRC() == crc)
1219		{
1220			// Record a hit
1221			entry->recordHit();
1222		cache_miss_type = CACHE_MISS_TYPE_NONE;
1223			return entry->getDP(crc);
1224		}
1225		else
1226		{
1227			// llinfos << "CRC miss for " << local_id << llendl;
1228		cache_miss_type = CACHE_MISS_TYPE_CRC;
1229			mCacheMissCRC.put(local_id);
1230		}
1231	}
1232	else
1233	{
1234		// llinfos << "Cache miss for " << local_id << llendl;
1235	cache_miss_type = CACHE_MISS_TYPE_FULL;
1236		mCacheMissFull.put(local_id);
1237	}
1238
1239	return NULL;
1240}
1241
1242void LLViewerRegion::addCacheMissFull(const U32 local_id)
1243{
1244	mCacheMissFull.put(local_id);
1245}
1246
1247void LLViewerRegion::requestCacheMisses()
1248{
1249	S32 full_count = mCacheMissFull.count();
1250	S32 crc_count = mCacheMissCRC.count();
1251	if (full_count == 0 && crc_count == 0) return;
1252
1253	LLMessageSystem* msg = gMessageSystem;
1254	BOOL start_new_message = TRUE;
1255	S32 blocks = 0;
1256	S32 i;
1257
1258	// Send full cache miss updates.  For these, we KNOW we don't
1259	// have a viewer object.
1260	for (i = 0; i < full_count; i++)
1261	{
1262		if (start_new_message)
1263		{
1264			msg->newMessageFast(_PREHASH_RequestMultipleObjects);
1265			msg->nextBlockFast(_PREHASH_AgentData);
1266			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
1267			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1268			start_new_message = FALSE;
1269		}
1270
1271		msg->nextBlockFast(_PREHASH_ObjectData);
1272		msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL);
1273		msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]);
1274		blocks++;
1275
1276		if (blocks >= 255)
1277		{
1278			sendReliableMessage();
1279			start_new_message = TRUE;
1280			blocks = 0;
1281		}
1282	}
1283
1284	// Send CRC miss updates.  For these, we _might_ have a viewer object,
1285	// but probably not.
1286	for (i = 0; i < crc_count; i++)
1287	{
1288		if (start_new_message)
1289		{
1290			msg->newMessageFast(_PREHASH_RequestMultipleObjects);
1291			msg->nextBlockFast(_PREHASH_AgentData);
1292			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
1293			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1294			start_new_message = FALSE;
1295		}
1296
1297		msg->nextBlockFast(_PREHASH_ObjectData);
1298		msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC);
1299		msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]);
1300		blocks++;
1301
1302		if (blocks >= 255)
1303		{
1304			sendReliableMessage();
1305			start_new_message = TRUE;
1306			blocks = 0;
1307		}
1308	}
1309
1310	// finish any pending message
1311	if (!start_new_message)
1312	{
1313		sendReliableMessage();
1314	}
1315	mCacheMissFull.reset();
1316	mCacheMissCRC.reset();
1317
1318	mCacheDirty = TRUE ;
1319	// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl;
1320	#if LL_RECORD_VIEWER_STATS
1321	LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this);
1322	LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count);
1323	LLViewerStatsRecorder::instance()->endObjectUpdateEvents();
1324	#endif
1325}
1326
1327void LLViewerRegion::dumpCache()
1328{
1329	const S32 BINS = 4;
1330	S32 hit_bin[BINS];
1331	S32 change_bin[BINS];
1332
1333	S32 i;
1334	for (i = 0; i < BINS; ++i)
1335	{
1336		hit_bin[i] = 0;
1337		change_bin[i] = 0;
1338	}
1339
1340	LLVOCacheEntry *entry;
1341	for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter)
1342	{
1343		entry = iter->second ;
1344
1345		S32 hits = entry->getHitCount();
1346		S32 changes = entry->getCRCChangeCount();
1347
1348		hits = llclamp(hits, 0, BINS-1);
1349		changes = llclamp(changes, 0, BINS-1);
1350
1351		hit_bin[hits]++;
1352		change_bin[changes]++;
1353	}
1354
1355	llinfos << "Count " << mImpl->mCacheMap.size() << llendl;
1356	for (i = 0; i < BINS; i++)
1357	{
1358		llinfos << "Hits " << i << " " << hit_bin[i] << llendl;
1359	}
1360	for (i = 0; i < BINS; i++)
1361	{
1362		llinfos << "Changes " << i << " " << change_bin[i] << llendl;
1363	}
1364}
1365
1366void LLViewerRegion::unpackRegionHandshake()
1367{
1368	LLMessageSystem *msg = gMessageSystem;
1369
1370	U32 region_flags;
1371	U8 sim_access;
1372	std::string sim_name;
1373	LLUUID sim_owner;
1374	BOOL is_estate_manager;
1375	F32 water_height;
1376	F32 billable_factor;
1377	LLUUID cache_id;
1378
1379	msg->getU32		("RegionInfo", "RegionFlags", region_flags);
1380	msg->getU8		("RegionInfo", "SimAccess", sim_access);
1381	msg->getString	("RegionInfo", "SimName", sim_name);
1382	msg->getUUID	("RegionInfo", "SimOwner", sim_owner);
1383	msg->getBOOL	("RegionInfo", "IsEstateManager", is_estate_manager);
1384	msg->getF32		("RegionInfo", "WaterHeight", water_height);
1385	msg->getF32		("RegionInfo", "BillableFactor", billable_factor);
1386	msg->getUUID	("RegionInfo", "CacheID", cache_id );
1387
1388	setRegionFlags(region_flags);
1389	setSimAccess(sim_access);
1390	setRegionNameAndZone(sim_name);
1391	setOwner(sim_owner);
1392	setIsEstateManager(is_estate_manager);
1393	setWaterHeight(water_height);
1394	setBillableFactor(billable_factor);
1395	setCacheID(cache_id);
1396
1397	LLUUID region_id;
1398	msg->getUUID("RegionInfo2", "RegionID", region_id);
1399	setRegionID(region_id);
1400	
1401	// Retrieve the CR-53 (Homestead/Land SKU) information
1402	S32 classID = 0;
1403	S32 cpuRatio = 0;
1404	std::string coloName;
1405	std::string productSKU;
1406	std::string productName;
1407
1408	// the only reasonable way to decide if we actually have any data is to
1409	// check to see if any of these fields have positive sizes
1410	if (msg->getSize("RegionInfo3", "ColoName") > 0 ||
1411	    msg->getSize("RegionInfo3", "ProductSKU") > 0 ||
1412	    msg->getSize("RegionInfo3", "ProductName") > 0)
1413	{
1414		msg->getS32     ("RegionInfo3", "CPUClassID",  classID);
1415		msg->getS32     ("RegionInfo3", "CPURatio",    cpuRatio);
1416		msg->getString  ("RegionInfo3", "ColoName",    coloName);
1417		msg->getString  ("RegionInfo3", "ProductSKU",  productSKU);
1418		msg->getString  ("RegionInfo3", "ProductName", productName);
1419		
1420		mClassID = classID;
1421		mCPURatio = cpuRatio;
1422		mColoName = coloName;
1423		mProductSKU = productSKU;
1424		mProductName = productName;
1425	}
1426
1427	LLVLComposition *compp = getComposition();
1428	if (compp)
1429	{
1430		LLUUID tmp_id;
1431
1432		msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id);
1433		compp->setDetailTextureID(0, tmp_id);
1434		msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id);
1435		compp->setDetailTextureID(1, tmp_id);
1436		msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id);
1437		compp->setDetailTextureID(2, tmp_id);
1438		msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id);
1439		compp->setDetailTextureID(3, tmp_id);
1440
1441		F32 tmp_f32;
1442		msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32);
1443		compp->setStartHeight(0, tmp_f32);
1444		msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32);
1445		compp->setStartHeight(1, tmp_f32);
1446		msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32);
1447		compp->setStartHeight(2, tmp_f32);
1448		msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32);
1449		compp->setStartHeight(3, tmp_f32);
1450
1451		msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32);
1452		compp->setHeightRange(0, tmp_f32);
1453		msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32);
1454		compp->setHeightRange(1, tmp_f32);
1455		msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32);
1456		compp->setHeightRange(2, tmp_f32);
1457		msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32);
1458		compp->setHeightRange(3, tmp_f32);
1459
1460		// If this is an UPDATE (params already ready, we need to regenerate
1461		// all of our terrain stuff, by
1462		if (compp->getParamsReady())
1463		{
1464			getLand().dirtyAllPatches();
1465		}
1466		else
1467		{
1468			compp->setParamsReady();
1469		}
1470	}
1471
1472
1473	// Now that we have the name, we can load the cache file
1474	// off disk.
1475	loadObjectCache();
1476
1477	// After loading cache, signal that simulator can start
1478	// sending data.
1479	// TODO: Send all upstream viewer->sim handshake info here.
1480	LLHost host = msg->getSender();
1481	msg->newMessage("RegionHandshakeReply");
1482	msg->nextBlock("AgentData");
1483	msg->addUUID("AgentID", gAgent.getID());
1484	msg->addUUID("SessionID", gAgent.getSessionID());
1485	msg->nextBlock("RegionInfo");
1486	msg->addU32("Flags", 0x0 );
1487	msg->sendReliable(host);
1488}
1489
1490void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
1491{
1492	capabilityNames.append("AttachmentResources");
1493	capabilityNames.append("AvatarPickerSearch");
1494	capabilityNames.append("ChatSessionRequest");
1495	capabilityNames.append("CopyInventoryFromNotecard");
1496	capabilityNames.append("CreateInventoryCategory");
1497	capabilityNames.append("DispatchRegionInfo");
1498	capabilityNames.append("EstateChangeInfo");
1499	capabilityNames.append("EventQueueGet");
1500	capabilityNames.append("EnvironmentSettings");
1501	capabilityNames.append("ObjectMedia");
1502	capabilityNames.append("ObjectMediaNavigate");
1503
1504	if (gSavedSettings.getBOOL("UseHTTPInventory"))
1505	{
1506		capabilityNames.append("FetchLib2");
1507		capabilityNames.append("FetchLibDescendents2");
1508		capabilityNames.append("FetchInventory2");
1509		capabilityNames.append("FetchInventoryDescendents2");
1510	}
1511
1512	capabilityNames.append("GetDisplayNames");
1513	capabilityNames.append("GetTexture");
1514	capabilityNames.append("GetMesh");
1515	capabilityNames.append("GetObjectCost");
1516	capabilityNames.append("GetObjectPhysicsData");
1517	capabilityNames.append("GroupProposalBallot");
1518	capabilityNames.append("HomeLocation");
1519	capabilityNames.append("LandResources");
1520	capabilityNames.append("MapLayer");
1521	capabilityNames.append("MapLayerGod");
1522	capabilityNames.append("MeshUploadFlag");
1523	capabilityNames.append("NewFileAgentInventory");
1524	capabilityNames.append("ParcelPropertiesUpdate");
1525	capabilityNames.append("ParcelMediaURLFilterList");
1526	capabilityNames.append("ParcelNavigateMedia");
1527	capabilityNames.append("ParcelVoiceInfoRequest");
1528	capabilityNames.append("ProductInfoRequest");
1529	capabilityNames.append("ProvisionVoiceAccountRequest");
1530	capabilityNames.append("RemoteParcelRequest");
1531	capabilityNames.append("RequestTextureDownload");
1532	capabilityNames.append("ResourceCostSelected");
1533	capabilityNames.append("SearchStatRequest");
1534	capabilityNames.append("SearchStatTracking");
1535	capabilityNames.append("SendPostcard");
1536	capabilityNames.append("SendUserReport");
1537	capabilityNames.append("SendUserReportWithScreenshot");
1538	capabilityNames.append("ServerReleaseNotes");
1539	capabilityNames.append("SimConsole");
1540	capabilityNames.append("SimulatorFeatures");
1541	capabilityNames.append("SetDisplayName");
1542	capabilityNames.append("SimConsoleAsync");
1543	capabilityNames.append("StartGroupProposal");
1544	capabilityNames.append("TextureStats");
1545	capabilityNames.append("UntrustedSimulatorMessage");
1546	capabilityNames.append("UpdateAgentInformation");
1547	capabilityNames.append("UpdateAgentLanguage");
1548	capabilityNames.append("UpdateGestureAgentInventory");
1549	capabilityNames.append("UpdateNotecardAgentInventory");
1550	capabilityNames.append("UpdateScriptAgent");
1551	capabilityNames.append("UpdateGestureTaskInventory");
1552	capabilityNames.append("UpdateNotecardTaskInventory");
1553	capabilityNames.append("UpdateScriptTask");
1554	capabilityNames.append("UploadBakedTexture");
1555	capabilityNames.append("ViewerMetrics");
1556	capabilityNames.append("ViewerStartAuction");
1557	capabilityNames.append("ViewerStats");
1558	
1559	// Please add new capabilities alphabetically to reduce
1560	// merge conflicts.
1561}
1562
1563void LLViewerRegion::setSeedCapability(const std::string& url)
1564{
1565	if (getCapability("Seed") == url)
1566    {
1567		// llwarns << "Ignoring duplicate seed capability" << llendl;
1568		return;
1569    }
1570	
1571	delete mImpl->mEventPoll;
1572	mImpl->mEventPoll = NULL;
1573	
1574	mImpl->mCapabilities.clear();
1575	setCapability("Seed", url);
1576
1577	LLSD capabilityNames = LLSD::emptyArray();
1578	mImpl->buildCapabilityNames(capabilityNames);
1579
1580	llinfos << "posting to seed " << url << llendl;
1581
1582	S32 id = ++mImpl->mHttpResponderID;
1583	LLHTTPClient::post(url, capabilityNames, 
1584						BaseCapabilitiesComplete::build(getHandle(), id),
1585						LLSD(), CAP_REQUEST_TIMEOUT);
1586}
1587
1588S32 LLViewerRegion::getNumSeedCapRetries()
1589{
1590	return mImpl->mSeedCapAttempts;
1591}
1592
1593void LLViewerRegion::failedSeedCapability()
1594{
1595	// Should we retry asking for caps?
1596	mImpl->mSeedCapAttempts++;
1597	std::string url = getCapability("Seed");
1598	if ( url.empty() )
1599	{
1600		LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL;
1601		return;
1602	}
1603	// After a few attempts, continue login.  We will keep trying once in-world:
1604	if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin &&
1605		 STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() )
1606	{
1607		LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
1608	}
1609
1610	if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts)
1611	{
1612		LLSD capabilityNames = LLSD::emptyArray();
1613		mImpl->buildCapabilityNames(capabilityNames);
1614
1615		llinfos << "posting to seed " << url << " (retry " 
1616				<< mImpl->mSeedCapAttempts << ")" << llendl;
1617
1618		S32 id = ++mImpl->mHttpResponderID;
1619		LLHTTPClient::post(url, capabilityNames, 
1620						BaseCapabilitiesComplete::build(getHandle(), id),
1621						LLSD(), CAP_REQUEST_TIMEOUT);
1622	}
1623	else
1624	{
1625		// *TODO: Give a user pop-up about this error?
1626		LL_WARNS2("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts.  Giving up!" << LL_ENDL;
1627	}
1628}
1629
1630class SimulatorFeaturesReceived : public LLHTTPClient::Responder
1631{
1632	LOG_CLASS(SimulatorFeaturesReceived);
1633public:
1634    SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, 
1635			S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
1636	: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
1637    { }
1638	
1639	
1640    void error(U32 statusNum, const std::string& reason)
1641    {
1642		LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL;
1643		retry();
1644    }
1645
1646    void result(const LLSD& content)
1647    {
1648		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
1649		if(!regionp) //region is removed or responder is not created.
1650		{
1651			LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL;
1652			return ;
1653		}
1654		
1655		regionp->setSimulatorFeatures(content);
1656	}
1657
1658private:
1659	void retry()
1660	{
1661		if (mAttempt < mMaxAttempts)
1662		{
1663			mAttempt++;
1664			LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'.  Retry #" << mAttempt << LL_ENDL;
1665			LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT);
1666		}
1667	}
1668	
1669	std::string mRetryURL;
1670	U64 mRegionHandle;
1671	S32 mAttempt;
1672	S32 mMaxAttempts;
1673};
1674
1675
1676void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
1677{
1678	if(name == "EventQueueGet")
1679	{
1680		delete mImpl->mEventPoll;
1681		mImpl->mEventPoll = NULL;
1682		mImpl->mEventPoll = new LLEventPoll(url, getHost());
1683	}
1684	else if(name == "UntrustedSimulatorMessage")
1685	{
1686		LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
1687	}
1688	else if (name == "SimulatorFeatures")
1689	{
1690		// kick off a request for simulator features
1691		LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT);
1692	}
1693	else
1694	{
1695		mImpl->mCapabilities[name] = url;
1696		if(name == "GetTexture")
1697		{
1698			mHttpUrl = url ;
1699		}
1700	}
1701}
1702
1703bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
1704{
1705	return name == "EventQueueGet" || name == "UntrustedSimulatorMessage";
1706}
1707
1708std::string LLViewerRegion::getCapability(const std::string& name) const
1709{
1710	CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name);
1711	if(iter == mImpl->mCapabilities.end())
1712	{
1713		return "";
1714	}
1715
1716	return iter->second;
1717}
1718
1719bool LLViewerRegion::capabilitiesReceived() const
1720{
1721	return mCapabilitiesReceived;
1722}
1723
1724void LLViewerRegion::setCapabilitiesReceived(bool received)
1725{
1726	mCapabilitiesReceived = received;
1727
1728	// Tell interested parties that we've received capabilities,
1729	// so that they can safely use getCapability().
1730	if (received)
1731	{
1732		mCapabilitiesReceivedSignal(getRegionID());
1733
1734		// This is a single-shot signal. Forget callbacks to save resources.
1735		mCapabilitiesReceivedSignal.disconnect_all_slots();
1736	}
1737}
1738
1739boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb)
1740{
1741	return mCapabilitiesReceivedSignal.connect(cb);
1742}
1743
1744void LLViewerRegion::logActiveCapabilities() const
1745{
1746	int count = 0;
1747	CapabilityMap::const_iterator iter;
1748	for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count)
1749	{
1750		if (!iter->second.empty())
1751		{
1752			llinfos << iter->first << " URL is " << iter->second << llendl;
1753		}
1754	}
1755	llinfos << "Dumped " << count << " entries." << llendl;
1756}
1757
1758LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
1759{
1760	if (type < mImpl->mObjectPartition.size())
1761	{
1762		return mImpl->mObjectPartition[type];
1763	}
1764	return NULL;
1765}
1766
1767// the viewer can not yet distinquish between normal- and estate-owned objects
1768// so we collapse these two bits and enable the UI if either are set
1769const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT
1770											| REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT;
1771
1772bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const
1773{
1774	return (mParcelOverlay != NULL)
1775		&& (mParcelOverlay->isOwnedSelf(pos)
1776			|| mParcelOverlay->isOwnedGroup(pos)
1777			|| ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT)
1778				&& mParcelOverlay->encroachesOwned(boxes)) );
1779}
1780
1781bool LLViewerRegion::childrenObjectReturnable( const std::vector<LLBBox>& boxes ) const
1782{
1783	bool result = false;
1784	result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0;
1785	return result;
1786}
1787
1788bool LLViewerRegion::objectsCrossParcel(const std::vector<LLBBox>& boxes) const
1789{
1790	return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes);
1791}
1792
1793void LLViewerRegion::getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions )
1794{
1795	mImpl->mLandp->getNeighboringRegions( uniqueRegions );
1796}
1797
1798void LLViewerRegion::showReleaseNotes()
1799{
1800	std::string url = this->getCapability("ServerReleaseNotes");
1801
1802	if (url.empty()) {
1803		// HACK haven't received the capability yet, we'll wait until
1804		// it arives.
1805		mReleaseNotesRequested = TRUE;
1806		return;
1807	}
1808
1809	LLWeb::loadURL(url);
1810	mReleaseNotesRequested = FALSE;
1811}
1812
1813std::string LLViewerRegion::getDescription() const
1814{
1815    return stringize(*this);
1816}
1817
1818bool LLViewerRegion::meshUploadEnabled() const
1819{
1820	return (mSimulatorFeatures.has("MeshUploadEnabled") &&
1821		mSimulatorFeatures["MeshUploadEnabled"].asBoolean());
1822}
1823
1824bool LLViewerRegion::meshRezEnabled() const
1825{
1826	return (mSimulatorFeatures.has("MeshRezEnabled") &&
1827				mSimulatorFeatures["MeshRezEnabled"].asBoolean());
1828}
1829
1830