/indra/newview/llviewerregion.cpp

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