PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llviewerparcelmgr.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2332 lines | 1763 code | 354 blank | 215 comment | 269 complexity | 68823a547156306d4d5b6d9238b3b96e MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /**
  2. * @file llviewerparcelmgr.cpp
  3. * @brief Viewer-side representation of owned land
  4. *
  5. * $LicenseInfo:firstyear=2002&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 "llviewerparcelmgr.h"
  28. // Library includes
  29. #include "llaudioengine.h"
  30. #include "indra_constants.h"
  31. #include "llcachename.h"
  32. #include "llgl.h"
  33. #include "llnotifications.h"
  34. #include "llnotificationsutil.h"
  35. #include "llparcel.h"
  36. #include "llsecondlifeurls.h"
  37. #include "message.h"
  38. #include "llfloaterreg.h"
  39. // Viewer includes
  40. #include "llagent.h"
  41. #include "llagentaccess.h"
  42. #include "llviewerwindow.h"
  43. #include "llviewercontrol.h"
  44. //#include "llfirstuse.h"
  45. #include "llfloaterbuyland.h"
  46. #include "llfloatergroups.h"
  47. #include "llpanelnearbymedia.h"
  48. #include "llfloatersellland.h"
  49. #include "llfloatertools.h"
  50. #include "llparcelselection.h"
  51. #include "llresmgr.h"
  52. #include "llsdutil.h"
  53. #include "llsdutil_math.h"
  54. #include "llslurl.h"
  55. #include "llstatusbar.h"
  56. #include "llui.h"
  57. #include "llviewertexture.h"
  58. #include "llviewertexturelist.h"
  59. #include "llviewermenu.h"
  60. #include "llviewerparcelmedia.h"
  61. #include "llviewerparceloverlay.h"
  62. #include "llviewerregion.h"
  63. #include "llworld.h"
  64. #include "roles_constants.h"
  65. #include "llweb.h"
  66. #include "llvieweraudio.h"
  67. const F32 PARCEL_COLLISION_DRAW_SECS = 1.f;
  68. // Globals
  69. U8* LLViewerParcelMgr::sPackedOverlay = NULL;
  70. LLUUID gCurrentMovieID = LLUUID::null;
  71. LLPointer<LLViewerTexture> sBlockedImage;
  72. LLPointer<LLViewerTexture> sPassImage;
  73. // Local functions
  74. void optionally_start_music(const std::string& music_url);
  75. void callback_start_music(S32 option, void* data);
  76. void optionally_prepare_video(const LLParcel *parcelp);
  77. void callback_prepare_video(S32 option, void* data);
  78. void prepare_video(const LLParcel *parcelp);
  79. void start_video(const LLParcel *parcelp);
  80. void stop_video();
  81. bool callback_god_force_owner(const LLSD&, const LLSD&);
  82. struct LLGodForceOwnerData
  83. {
  84. LLUUID mOwnerID;
  85. S32 mLocalID;
  86. LLHost mHost;
  87. LLGodForceOwnerData(
  88. const LLUUID& owner_id,
  89. S32 local_parcel_id,
  90. const LLHost& host) :
  91. mOwnerID(owner_id),
  92. mLocalID(local_parcel_id),
  93. mHost(host) {}
  94. };
  95. //
  96. // Methods
  97. //
  98. LLViewerParcelMgr::LLViewerParcelMgr()
  99. : mSelected(FALSE),
  100. mRequestResult(0),
  101. mWestSouth(),
  102. mEastNorth(),
  103. mSelectedDwell(DWELL_NAN),
  104. mAgentParcelSequenceID(-1),
  105. mHoverRequestResult(0),
  106. mHoverWestSouth(),
  107. mHoverEastNorth(),
  108. mRenderCollision(FALSE),
  109. mRenderSelection(TRUE),
  110. mCollisionBanned(0),
  111. mCollisionTimer(),
  112. mMediaParcelId(0),
  113. mMediaRegionId(0)
  114. {
  115. mCurrentParcel = new LLParcel();
  116. mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
  117. mFloatingParcelSelection = new LLParcelSelection(mCurrentParcel);
  118. mAgentParcel = new LLParcel();
  119. mHoverParcel = new LLParcel();
  120. mCollisionParcel = new LLParcel();
  121. mParcelsPerEdge = S32( REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS );
  122. mHighlightSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
  123. resetSegments(mHighlightSegments);
  124. mCollisionSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
  125. resetSegments(mCollisionSegments);
  126. // JC: Resolved a merge conflict here, eliminated
  127. // mBlockedImage->setAddressMode(LLTexUnit::TAM_WRAP);
  128. // because it is done in llviewertexturelist.cpp
  129. mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png");
  130. mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png");
  131. S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / PARCEL_OVERLAY_CHUNKS;
  132. sPackedOverlay = new U8[overlay_size];
  133. mAgentParcelOverlay = new U8[mParcelsPerEdge * mParcelsPerEdge];
  134. S32 i;
  135. for (i = 0; i < mParcelsPerEdge * mParcelsPerEdge; i++)
  136. {
  137. mAgentParcelOverlay[i] = 0;
  138. }
  139. mTeleportInProgress = TRUE; // the initial parcel update is treated like teleport
  140. }
  141. LLViewerParcelMgr::~LLViewerParcelMgr()
  142. {
  143. mCurrentParcelSelection->setParcel(NULL);
  144. mCurrentParcelSelection = NULL;
  145. mFloatingParcelSelection->setParcel(NULL);
  146. mFloatingParcelSelection = NULL;
  147. delete mCurrentParcel;
  148. mCurrentParcel = NULL;
  149. delete mAgentParcel;
  150. mAgentParcel = NULL;
  151. delete mCollisionParcel;
  152. mCollisionParcel = NULL;
  153. delete mHoverParcel;
  154. mHoverParcel = NULL;
  155. delete[] mHighlightSegments;
  156. mHighlightSegments = NULL;
  157. delete[] mCollisionSegments;
  158. mCollisionSegments = NULL;
  159. delete[] sPackedOverlay;
  160. sPackedOverlay = NULL;
  161. delete[] mAgentParcelOverlay;
  162. mAgentParcelOverlay = NULL;
  163. sBlockedImage = NULL;
  164. sPassImage = NULL;
  165. }
  166. void LLViewerParcelMgr::dump()
  167. {
  168. llinfos << "Parcel Manager Dump" << llendl;
  169. llinfos << "mSelected " << S32(mSelected) << llendl;
  170. llinfos << "Selected parcel: " << llendl;
  171. llinfos << mWestSouth << " to " << mEastNorth << llendl;
  172. mCurrentParcel->dump();
  173. llinfos << "banning " << mCurrentParcel->mBanList.size() << llendl;
  174. access_map_const_iterator cit = mCurrentParcel->mBanList.begin();
  175. access_map_const_iterator end = mCurrentParcel->mBanList.end();
  176. for ( ; cit != end; ++cit)
  177. {
  178. llinfos << "ban id " << (*cit).first << llendl;
  179. }
  180. llinfos << "Hover parcel:" << llendl;
  181. mHoverParcel->dump();
  182. llinfos << "Agent parcel:" << llendl;
  183. mAgentParcel->dump();
  184. }
  185. LLViewerRegion* LLViewerParcelMgr::getSelectionRegion()
  186. {
  187. return LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  188. }
  189. void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out,
  190. S32* rent_out,
  191. BOOL* for_sale_out,
  192. F32* dwell_out)
  193. {
  194. S32 area = 0;
  195. S32 price = 0;
  196. S32 rent = 0;
  197. BOOL for_sale = FALSE;
  198. F32 dwell = DWELL_NAN;
  199. if (mSelected)
  200. {
  201. if (mCurrentParcelSelection->mSelectedMultipleOwners)
  202. {
  203. area = mCurrentParcelSelection->getClaimableArea();
  204. }
  205. else
  206. {
  207. area = getSelectedArea();
  208. }
  209. if (mCurrentParcel->getForSale())
  210. {
  211. price = mCurrentParcel->getSalePrice();
  212. for_sale = TRUE;
  213. }
  214. else
  215. {
  216. price = area * mCurrentParcel->getClaimPricePerMeter();
  217. for_sale = FALSE;
  218. }
  219. rent = mCurrentParcel->getTotalRent();
  220. dwell = mSelectedDwell;
  221. }
  222. *area_out = area;
  223. *claim_out = price;
  224. *rent_out = rent;
  225. *for_sale_out = for_sale;
  226. *dwell_out = dwell;
  227. }
  228. S32 LLViewerParcelMgr::getSelectedArea() const
  229. {
  230. S32 rv = 0;
  231. if(mSelected && mCurrentParcel && mCurrentParcelSelection->mWholeParcelSelected)
  232. {
  233. rv = mCurrentParcel->getArea();
  234. }
  235. else if(mSelected)
  236. {
  237. F64 width = mEastNorth.mdV[VX] - mWestSouth.mdV[VX];
  238. F64 height = mEastNorth.mdV[VY] - mWestSouth.mdV[VY];
  239. F32 area = (F32)(width * height);
  240. rv = llround(area);
  241. }
  242. return rv;
  243. }
  244. void LLViewerParcelMgr::resetSegments(U8* segments)
  245. {
  246. S32 i;
  247. S32 count = (mParcelsPerEdge+1)*(mParcelsPerEdge+1);
  248. for (i = 0; i < count; i++)
  249. {
  250. segments[i] = 0x0;
  251. }
  252. }
  253. void LLViewerParcelMgr::writeHighlightSegments(F32 west, F32 south, F32 east,
  254. F32 north)
  255. {
  256. S32 x, y;
  257. S32 min_x = llround( west / PARCEL_GRID_STEP_METERS );
  258. S32 max_x = llround( east / PARCEL_GRID_STEP_METERS );
  259. S32 min_y = llround( south / PARCEL_GRID_STEP_METERS );
  260. S32 max_y = llround( north / PARCEL_GRID_STEP_METERS );
  261. const S32 STRIDE = mParcelsPerEdge+1;
  262. // south edge
  263. y = min_y;
  264. for (x = min_x; x < max_x; x++)
  265. {
  266. // exclusive OR means that writing to this segment twice
  267. // will turn it off
  268. mHighlightSegments[x + y*STRIDE] ^= SOUTH_MASK;
  269. }
  270. // west edge
  271. x = min_x;
  272. for (y = min_y; y < max_y; y++)
  273. {
  274. mHighlightSegments[x + y*STRIDE] ^= WEST_MASK;
  275. }
  276. // north edge - draw the south border on the y+1'th cell,
  277. // which given C-style arrays, is item foo[max_y]
  278. y = max_y;
  279. for (x = min_x; x < max_x; x++)
  280. {
  281. mHighlightSegments[x + y*STRIDE] ^= SOUTH_MASK;
  282. }
  283. // east edge - draw west border on x+1'th cell
  284. x = max_x;
  285. for (y = min_y; y < max_y; y++)
  286. {
  287. mHighlightSegments[x + y*STRIDE] ^= WEST_MASK;
  288. }
  289. }
  290. void LLViewerParcelMgr::writeSegmentsFromBitmap(U8* bitmap, U8* segments)
  291. {
  292. S32 x;
  293. S32 y;
  294. const S32 IN_STRIDE = mParcelsPerEdge;
  295. const S32 OUT_STRIDE = mParcelsPerEdge+1;
  296. for (y = 0; y < IN_STRIDE; y++)
  297. {
  298. x = 0;
  299. while( x < IN_STRIDE )
  300. {
  301. U8 byte = bitmap[ (x + y*IN_STRIDE) / 8 ];
  302. S32 bit;
  303. for (bit = 0; bit < 8; bit++)
  304. {
  305. if (byte & (1 << bit) )
  306. {
  307. S32 out = x+y*OUT_STRIDE;
  308. // This and one above it
  309. segments[out] ^= SOUTH_MASK;
  310. segments[out+OUT_STRIDE] ^= SOUTH_MASK;
  311. // This and one to the right
  312. segments[out] ^= WEST_MASK;
  313. segments[out+1] ^= WEST_MASK;
  314. }
  315. x++;
  316. }
  317. }
  318. }
  319. }
  320. void LLViewerParcelMgr::writeAgentParcelFromBitmap(U8* bitmap)
  321. {
  322. S32 x;
  323. S32 y;
  324. const S32 IN_STRIDE = mParcelsPerEdge;
  325. for (y = 0; y < IN_STRIDE; y++)
  326. {
  327. x = 0;
  328. while( x < IN_STRIDE )
  329. {
  330. U8 byte = bitmap[ (x + y*IN_STRIDE) / 8 ];
  331. S32 bit;
  332. for (bit = 0; bit < 8; bit++)
  333. {
  334. if (byte & (1 << bit) )
  335. {
  336. mAgentParcelOverlay[x+y*IN_STRIDE] = 1;
  337. }
  338. else
  339. {
  340. mAgentParcelOverlay[x+y*IN_STRIDE] = 0;
  341. }
  342. x++;
  343. }
  344. }
  345. }
  346. }
  347. // Given a point, find the PARCEL_GRID_STEP x PARCEL_GRID_STEP block
  348. // containing it and select that.
  349. LLParcelSelectionHandle LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global)
  350. {
  351. LLVector3d southwest = pos_global;
  352. LLVector3d northeast = pos_global;
  353. southwest -= LLVector3d( PARCEL_GRID_STEP_METERS/2, PARCEL_GRID_STEP_METERS/2, 0 );
  354. southwest.mdV[VX] = llround( southwest.mdV[VX], (F64)PARCEL_GRID_STEP_METERS );
  355. southwest.mdV[VY] = llround( southwest.mdV[VY], (F64)PARCEL_GRID_STEP_METERS );
  356. northeast += LLVector3d( PARCEL_GRID_STEP_METERS/2, PARCEL_GRID_STEP_METERS/2, 0 );
  357. northeast.mdV[VX] = llround( northeast.mdV[VX], (F64)PARCEL_GRID_STEP_METERS );
  358. northeast.mdV[VY] = llround( northeast.mdV[VY], (F64)PARCEL_GRID_STEP_METERS );
  359. // Snap to parcel
  360. return selectLand( southwest, northeast, TRUE );
  361. }
  362. // Tries to select the parcel inside the rectangle
  363. LLParcelSelectionHandle LLViewerParcelMgr::selectParcelInRectangle()
  364. {
  365. return selectLand(mWestSouth, mEastNorth, TRUE);
  366. }
  367. void LLViewerParcelMgr::selectCollisionParcel()
  368. {
  369. // BUG: Claim to be in the agent's region
  370. mWestSouth = gAgent.getRegion()->getOriginGlobal();
  371. mEastNorth = mWestSouth;
  372. mEastNorth += LLVector3d(PARCEL_GRID_STEP_METERS, PARCEL_GRID_STEP_METERS, 0.0);
  373. // BUG: must be in the sim you are in
  374. LLMessageSystem *msg = gMessageSystem;
  375. msg->newMessageFast(_PREHASH_ParcelPropertiesRequestByID);
  376. msg->nextBlockFast(_PREHASH_AgentID);
  377. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  378. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
  379. msg->nextBlockFast(_PREHASH_ParcelData);
  380. msg->addS32Fast(_PREHASH_SequenceID, SELECTED_PARCEL_SEQ_ID );
  381. msg->addS32Fast(_PREHASH_LocalID, mCollisionParcel->getLocalID() );
  382. gAgent.sendReliableMessage();
  383. mRequestResult = PARCEL_RESULT_NO_DATA;
  384. // Hack: Copy some data over temporarily
  385. mCurrentParcel->setName( mCollisionParcel->getName() );
  386. mCurrentParcel->setDesc( mCollisionParcel->getDesc() );
  387. mCurrentParcel->setPassPrice(mCollisionParcel->getPassPrice());
  388. mCurrentParcel->setPassHours(mCollisionParcel->getPassHours());
  389. // clear the list of segments to prevent flashing
  390. resetSegments(mHighlightSegments);
  391. mFloatingParcelSelection->setParcel(mCurrentParcel);
  392. mCurrentParcelSelection->setParcel(NULL);
  393. mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
  394. mSelected = TRUE;
  395. mCurrentParcelSelection->mWholeParcelSelected = TRUE;
  396. notifyObservers();
  397. return;
  398. }
  399. // snap_selection = auto-select the hit parcel, if there is exactly one
  400. LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &corner2,
  401. BOOL snap_selection)
  402. {
  403. sanitize_corners( corner1, corner2, mWestSouth, mEastNorth );
  404. // ...x isn't more than one meter away
  405. F32 delta_x = getSelectionWidth();
  406. if (delta_x * delta_x <= 1.f * 1.f)
  407. {
  408. mSelected = FALSE;
  409. notifyObservers();
  410. return NULL;
  411. }
  412. // ...y isn't more than one meter away
  413. F32 delta_y = getSelectionHeight();
  414. if (delta_y * delta_y <= 1.f * 1.f)
  415. {
  416. mSelected = FALSE;
  417. notifyObservers();
  418. return NULL;
  419. }
  420. // Can't select across region boundary
  421. // We need to pull in the upper right corner by a little bit to allow
  422. // selection up to the x = 256 or y = 256 edge.
  423. LLVector3d east_north_region_check( mEastNorth );
  424. east_north_region_check.mdV[VX] -= 0.5;
  425. east_north_region_check.mdV[VY] -= 0.5;
  426. LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mWestSouth);
  427. LLViewerRegion *region_other = LLWorld::getInstance()->getRegionFromPosGlobal( east_north_region_check );
  428. if(!region)
  429. {
  430. // just in case they somehow selected no land.
  431. mSelected = FALSE;
  432. return NULL;
  433. }
  434. if (region != region_other)
  435. {
  436. LLNotificationsUtil::add("CantSelectLandFromMultipleRegions");
  437. mSelected = FALSE;
  438. notifyObservers();
  439. return NULL;
  440. }
  441. // Build region global copies of corners
  442. LLVector3 wsb_region = region->getPosRegionFromGlobal( mWestSouth );
  443. LLVector3 ent_region = region->getPosRegionFromGlobal( mEastNorth );
  444. // Send request message
  445. LLMessageSystem *msg = gMessageSystem;
  446. msg->newMessageFast(_PREHASH_ParcelPropertiesRequest);
  447. msg->nextBlockFast(_PREHASH_AgentData);
  448. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  449. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
  450. msg->nextBlockFast(_PREHASH_ParcelData);
  451. msg->addS32Fast(_PREHASH_SequenceID, SELECTED_PARCEL_SEQ_ID );
  452. msg->addF32Fast(_PREHASH_West, wsb_region.mV[VX] );
  453. msg->addF32Fast(_PREHASH_South, wsb_region.mV[VY] );
  454. msg->addF32Fast(_PREHASH_East, ent_region.mV[VX] );
  455. msg->addF32Fast(_PREHASH_North, ent_region.mV[VY] );
  456. msg->addBOOL("SnapSelection", snap_selection);
  457. msg->sendReliable( region->getHost() );
  458. mRequestResult = PARCEL_RESULT_NO_DATA;
  459. // clear the list of segments to prevent flashing
  460. resetSegments(mHighlightSegments);
  461. mFloatingParcelSelection->setParcel(mCurrentParcel);
  462. mCurrentParcelSelection->setParcel(NULL);
  463. mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
  464. mSelected = TRUE;
  465. mCurrentParcelSelection->mWholeParcelSelected = snap_selection;
  466. notifyObservers();
  467. return mCurrentParcelSelection;
  468. }
  469. void LLViewerParcelMgr::deselectUnused()
  470. {
  471. // no more outstanding references to this selection, other than our own
  472. if (mCurrentParcelSelection->getNumRefs() == 1 && mFloatingParcelSelection->getNumRefs() == 1)
  473. {
  474. deselectLand();
  475. }
  476. }
  477. void LLViewerParcelMgr::deselectLand()
  478. {
  479. if (mSelected)
  480. {
  481. mSelected = FALSE;
  482. // Invalidate the selected parcel
  483. mCurrentParcel->setLocalID(-1);
  484. mCurrentParcel->mAccessList.clear();
  485. mCurrentParcel->mBanList.clear();
  486. //mCurrentParcel->mRenterList.reset();
  487. mSelectedDwell = DWELL_NAN;
  488. // invalidate parcel selection so that existing users of this selection can clean up
  489. mCurrentParcelSelection->setParcel(NULL);
  490. mFloatingParcelSelection->setParcel(NULL);
  491. // create new parcel selection
  492. mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
  493. notifyObservers(); // Notify observers *after* changing the parcel selection
  494. }
  495. }
  496. void LLViewerParcelMgr::addObserver(LLParcelObserver* observer)
  497. {
  498. mObservers.put(observer);
  499. }
  500. void LLViewerParcelMgr::removeObserver(LLParcelObserver* observer)
  501. {
  502. mObservers.removeObj(observer);
  503. }
  504. // Call this method when it's time to update everyone on a new state.
  505. // Copy the list because an observer could respond by removing itself
  506. // from the list.
  507. void LLViewerParcelMgr::notifyObservers()
  508. {
  509. LLDynamicArray<LLParcelObserver*> observers;
  510. S32 count = mObservers.count();
  511. S32 i;
  512. for(i = 0; i < count; ++i)
  513. {
  514. observers.put(mObservers.get(i));
  515. }
  516. for(i = 0; i < count; ++i)
  517. {
  518. observers.get(i)->changed();
  519. }
  520. }
  521. //
  522. // ACCESSORS
  523. //
  524. BOOL LLViewerParcelMgr::selectionEmpty() const
  525. {
  526. return !mSelected;
  527. }
  528. LLParcelSelectionHandle LLViewerParcelMgr::getParcelSelection() const
  529. {
  530. return mCurrentParcelSelection;
  531. }
  532. LLParcelSelectionHandle LLViewerParcelMgr::getFloatingParcelSelection() const
  533. {
  534. return mFloatingParcelSelection;
  535. }
  536. LLParcel *LLViewerParcelMgr::getAgentParcel() const
  537. {
  538. return mAgentParcel;
  539. }
  540. // Return whether the agent can build on the land they are on
  541. bool LLViewerParcelMgr::allowAgentBuild() const
  542. {
  543. if (mAgentParcel)
  544. {
  545. return (gAgent.isGodlike() ||
  546. (mAgentParcel->allowModifyBy(gAgent.getID(), gAgent.getGroupID())) ||
  547. (isParcelOwnedByAgent(mAgentParcel, GP_LAND_ALLOW_CREATE)));
  548. }
  549. else
  550. {
  551. return gAgent.isGodlike();
  552. }
  553. }
  554. // Return whether anyone can build on the given parcel
  555. bool LLViewerParcelMgr::allowAgentBuild(const LLParcel* parcel) const
  556. {
  557. return parcel->getAllowModify();
  558. }
  559. bool LLViewerParcelMgr::allowAgentVoice() const
  560. {
  561. return allowAgentVoice(gAgent.getRegion(), mAgentParcel);
  562. }
  563. bool LLViewerParcelMgr::allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const
  564. {
  565. return region && region->isVoiceEnabled()
  566. && parcel && parcel->getParcelFlagAllowVoice();
  567. }
  568. bool LLViewerParcelMgr::allowAgentFly(const LLViewerRegion* region, const LLParcel* parcel) const
  569. {
  570. return region && !region->getBlockFly()
  571. && parcel && parcel->getAllowFly();
  572. }
  573. // Can the agent be pushed around by LLPushObject?
  574. bool LLViewerParcelMgr::allowAgentPush(const LLViewerRegion* region, const LLParcel* parcel) const
  575. {
  576. return region && !region->getRestrictPushObject()
  577. && parcel && !parcel->getRestrictPushObject();
  578. }
  579. bool LLViewerParcelMgr::allowAgentScripts(const LLViewerRegion* region, const LLParcel* parcel) const
  580. {
  581. // *NOTE: This code does not take into account group-owned parcels
  582. // and the flag to allow group-owned scripted objects to run.
  583. // This mirrors the traditional menu bar parcel icon code, but is not
  584. // technically correct.
  585. return region
  586. && !(region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
  587. && !(region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
  588. && parcel
  589. && parcel->getAllowOtherScripts();
  590. }
  591. bool LLViewerParcelMgr::allowAgentDamage(const LLViewerRegion* region, const LLParcel* parcel) const
  592. {
  593. return (region && region->getAllowDamage())
  594. || (parcel && parcel->getAllowDamage());
  595. }
  596. BOOL LLViewerParcelMgr::isOwnedAt(const LLVector3d& pos_global) const
  597. {
  598. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos_global );
  599. if (!region) return FALSE;
  600. LLViewerParcelOverlay* overlay = region->getParcelOverlay();
  601. if (!overlay) return FALSE;
  602. LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
  603. return overlay->isOwned( pos_region );
  604. }
  605. BOOL LLViewerParcelMgr::isOwnedSelfAt(const LLVector3d& pos_global) const
  606. {
  607. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos_global );
  608. if (!region) return FALSE;
  609. LLViewerParcelOverlay* overlay = region->getParcelOverlay();
  610. if (!overlay) return FALSE;
  611. LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
  612. return overlay->isOwnedSelf( pos_region );
  613. }
  614. BOOL LLViewerParcelMgr::isOwnedOtherAt(const LLVector3d& pos_global) const
  615. {
  616. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos_global );
  617. if (!region) return FALSE;
  618. LLViewerParcelOverlay* overlay = region->getParcelOverlay();
  619. if (!overlay) return FALSE;
  620. LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
  621. return overlay->isOwnedOther( pos_region );
  622. }
  623. BOOL LLViewerParcelMgr::isSoundLocal(const LLVector3d& pos_global) const
  624. {
  625. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos_global );
  626. if (!region) return FALSE;
  627. LLViewerParcelOverlay* overlay = region->getParcelOverlay();
  628. if (!overlay) return FALSE;
  629. LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
  630. return overlay->isSoundLocal( pos_region );
  631. }
  632. BOOL LLViewerParcelMgr::canHearSound(const LLVector3d &pos_global) const
  633. {
  634. BOOL in_agent_parcel = inAgentParcel(pos_global);
  635. if (in_agent_parcel)
  636. {
  637. // In same parcel as the agent
  638. return TRUE;
  639. }
  640. else
  641. {
  642. if (LLViewerParcelMgr::getInstance()->getAgentParcel()->getSoundLocal())
  643. {
  644. // Not in same parcel, and agent parcel only has local sound
  645. return FALSE;
  646. }
  647. else if (LLViewerParcelMgr::getInstance()->isSoundLocal(pos_global))
  648. {
  649. // Not in same parcel, and target parcel only has local sound
  650. return FALSE;
  651. }
  652. else
  653. {
  654. // Not in same parcel, but neither are local sound
  655. return TRUE;
  656. }
  657. }
  658. }
  659. BOOL LLViewerParcelMgr::inAgentParcel(const LLVector3d &pos_global) const
  660. {
  661. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(pos_global);
  662. LLViewerRegion* agent_region = gAgent.getRegion();
  663. if (!region || !agent_region)
  664. return FALSE;
  665. if (region != agent_region)
  666. {
  667. // Can't be in the agent parcel if you're not in the same region.
  668. return FALSE;
  669. }
  670. LLVector3 pos_region = agent_region->getPosRegionFromGlobal(pos_global);
  671. S32 row = S32(pos_region.mV[VY] / PARCEL_GRID_STEP_METERS);
  672. S32 column = S32(pos_region.mV[VX] / PARCEL_GRID_STEP_METERS);
  673. if (mAgentParcelOverlay[row*mParcelsPerEdge + column])
  674. {
  675. return TRUE;
  676. }
  677. else
  678. {
  679. return FALSE;
  680. }
  681. }
  682. // Returns NULL when there is no valid data.
  683. LLParcel* LLViewerParcelMgr::getHoverParcel() const
  684. {
  685. if (mHoverRequestResult == PARCEL_RESULT_SUCCESS)
  686. {
  687. return mHoverParcel;
  688. }
  689. else
  690. {
  691. return NULL;
  692. }
  693. }
  694. // Returns NULL when there is no valid data.
  695. LLParcel* LLViewerParcelMgr::getCollisionParcel() const
  696. {
  697. if (mRenderCollision)
  698. {
  699. return mCollisionParcel;
  700. }
  701. else
  702. {
  703. return NULL;
  704. }
  705. }
  706. //
  707. // UTILITIES
  708. //
  709. void LLViewerParcelMgr::render()
  710. {
  711. if (mSelected && mRenderSelection && gSavedSettings.getBOOL("RenderParcelSelection"))
  712. {
  713. // Rendering is done in agent-coordinates, so need to supply
  714. // an appropriate offset to the render code.
  715. LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(mWestSouth);
  716. if (!regionp) return;
  717. renderHighlightSegments(mHighlightSegments, regionp);
  718. }
  719. }
  720. void LLViewerParcelMgr::renderParcelCollision()
  721. {
  722. // check for expiration
  723. if (mCollisionTimer.getElapsedTimeF32() > PARCEL_COLLISION_DRAW_SECS)
  724. {
  725. mRenderCollision = FALSE;
  726. }
  727. if (mRenderCollision && gSavedSettings.getBOOL("ShowBanLines"))
  728. {
  729. LLViewerRegion* regionp = gAgent.getRegion();
  730. if (regionp)
  731. {
  732. BOOL use_pass = mCollisionParcel->getParcelFlag(PF_USE_PASS_LIST);
  733. renderCollisionSegments(mCollisionSegments, use_pass, regionp);
  734. }
  735. }
  736. }
  737. void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
  738. {
  739. if (!mSelected)
  740. {
  741. return;
  742. }
  743. LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  744. if (!region) return;
  745. LLMessageSystem *msg = gMessageSystem;
  746. if (flags & AL_BAN)
  747. {
  748. mCurrentParcel->mBanList.clear();
  749. }
  750. if (flags & AL_ACCESS)
  751. {
  752. mCurrentParcel->mAccessList.clear();
  753. }
  754. // Only the headers differ
  755. msg->newMessageFast(_PREHASH_ParcelAccessListRequest);
  756. msg->nextBlockFast(_PREHASH_AgentData);
  757. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  758. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  759. msg->nextBlockFast(_PREHASH_Data);
  760. msg->addS32Fast(_PREHASH_SequenceID, 0);
  761. msg->addU32Fast(_PREHASH_Flags, flags);
  762. msg->addS32("LocalID", mCurrentParcel->getLocalID() );
  763. msg->sendReliable( region->getHost() );
  764. }
  765. void LLViewerParcelMgr::sendParcelDwellRequest()
  766. {
  767. if (!mSelected)
  768. {
  769. return;
  770. }
  771. LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  772. if (!region) return;
  773. LLMessageSystem *msg = gMessageSystem;
  774. // Only the headers differ
  775. msg->newMessage("ParcelDwellRequest");
  776. msg->nextBlock("AgentData");
  777. msg->addUUID("AgentID", gAgent.getID() );
  778. msg->addUUID("SessionID", gAgent.getSessionID());
  779. msg->nextBlock("Data");
  780. msg->addS32("LocalID", mCurrentParcel->getLocalID());
  781. msg->addUUID("ParcelID", LLUUID::null); // filled in on simulator
  782. msg->sendReliable( region->getHost() );
  783. }
  784. void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
  785. {
  786. if (!mSelected)
  787. {
  788. LLNotificationsUtil::add("CannotSetLandOwnerNothingSelected");
  789. return;
  790. }
  791. llinfos << "Claiming " << mWestSouth << " to " << mEastNorth << llendl;
  792. // BUG: Only works for the region containing mWestSouthBottom
  793. LLVector3d east_north_region_check( mEastNorth );
  794. east_north_region_check.mdV[VX] -= 0.5;
  795. east_north_region_check.mdV[VY] -= 0.5;
  796. LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  797. if (!region)
  798. {
  799. // TODO: Add a force owner version of this alert.
  800. LLNotificationsUtil::add("CannotContentifyNoRegion");
  801. return;
  802. }
  803. // BUG: Make work for cross-region selections
  804. LLViewerRegion *region2 = LLWorld::getInstance()->getRegionFromPosGlobal( east_north_region_check );
  805. if (region != region2)
  806. {
  807. LLNotificationsUtil::add("CannotSetLandOwnerMultipleRegions");
  808. return;
  809. }
  810. llinfos << "Region " << region->getOriginGlobal() << llendl;
  811. LLSD payload;
  812. payload["owner_id"] = owner_id;
  813. payload["parcel_local_id"] = mCurrentParcel->getLocalID();
  814. payload["region_host"] = region->getHost().getIPandPort();
  815. LLNotification::Params params("ForceOwnerAuctionWarning");
  816. params.payload(payload).functor.function(callback_god_force_owner);
  817. if(mCurrentParcel->getAuctionID())
  818. {
  819. LLNotifications::instance().add(params);
  820. }
  821. else
  822. {
  823. LLNotifications::instance().forceResponse(params, 0);
  824. }
  825. }
  826. bool callback_god_force_owner(const LLSD& notification, const LLSD& response)
  827. {
  828. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  829. if(0 == option)
  830. {
  831. LLMessageSystem* msg = gMessageSystem;
  832. msg->newMessage("ParcelGodForceOwner");
  833. msg->nextBlock("AgentData");
  834. msg->addUUID("AgentID", gAgent.getID());
  835. msg->addUUID("SessionID", gAgent.getSessionID());
  836. msg->nextBlock("Data");
  837. msg->addUUID("OwnerID", notification["payload"]["owner_id"].asUUID());
  838. msg->addS32( "LocalID", notification["payload"]["parcel_local_id"].asInteger());
  839. msg->sendReliable(LLHost(notification["payload"]["region_host"].asString()));
  840. }
  841. return false;
  842. }
  843. void LLViewerParcelMgr::sendParcelGodForceToContent()
  844. {
  845. if (!mSelected)
  846. {
  847. LLNotificationsUtil::add("CannotContentifyNothingSelected");
  848. return;
  849. }
  850. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  851. if (!region)
  852. {
  853. LLNotificationsUtil::add("CannotContentifyNoRegion");
  854. return;
  855. }
  856. LLMessageSystem* msg = gMessageSystem;
  857. msg->newMessage("ParcelGodMarkAsContent");
  858. msg->nextBlock("AgentData");
  859. msg->addUUID("AgentID", gAgent.getID());
  860. msg->addUUID("SessionID", gAgent.getSessionID());
  861. msg->nextBlock("ParcelData");
  862. msg->addS32("LocalID", mCurrentParcel->getLocalID());
  863. msg->sendReliable(region->getHost());
  864. }
  865. void LLViewerParcelMgr::sendParcelRelease()
  866. {
  867. if (!mSelected)
  868. {
  869. LLNotificationsUtil::add("CannotReleaseLandNothingSelected");
  870. return;
  871. }
  872. LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  873. if (!region)
  874. {
  875. LLNotificationsUtil::add("CannotReleaseLandNoRegion");
  876. return;
  877. }
  878. //U32 flags = PR_NONE;
  879. //if (god_force) flags |= PR_GOD_FORCE;
  880. LLMessageSystem* msg = gMessageSystem;
  881. msg->newMessage("ParcelRelease");
  882. msg->nextBlock("AgentData");
  883. msg->addUUID("AgentID", gAgent.getID() );
  884. msg->addUUID("SessionID", gAgent.getSessionID() );
  885. msg->nextBlock("Data");
  886. msg->addS32("LocalID", mCurrentParcel->getLocalID() );
  887. //msg->addU32("Flags", flags);
  888. msg->sendReliable( region->getHost() );
  889. // Blitz selection, since the parcel might be non-rectangular, and
  890. // we won't have appropriate parcel information.
  891. deselectLand();
  892. }
  893. class LLViewerParcelMgr::ParcelBuyInfo
  894. {
  895. public:
  896. LLUUID mAgent;
  897. LLUUID mSession;
  898. LLUUID mGroup;
  899. BOOL mIsGroupOwned;
  900. BOOL mRemoveContribution;
  901. BOOL mIsClaim;
  902. LLHost mHost;
  903. // for parcel buys
  904. S32 mParcelID;
  905. S32 mPrice;
  906. S32 mArea;
  907. // for land claims
  908. F32 mWest;
  909. F32 mSouth;
  910. F32 mEast;
  911. F32 mNorth;
  912. };
  913. LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
  914. const LLUUID& agent_id,
  915. const LLUUID& session_id,
  916. const LLUUID& group_id,
  917. BOOL is_group_owned,
  918. BOOL is_claim,
  919. BOOL remove_contribution)
  920. {
  921. if (!mSelected || !mCurrentParcel)
  922. {
  923. LLNotificationsUtil::add("CannotBuyLandNothingSelected");
  924. return NULL;
  925. }
  926. LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  927. if (!region)
  928. {
  929. LLNotificationsUtil::add("CannotBuyLandNoRegion");
  930. return NULL;
  931. }
  932. if (is_claim)
  933. {
  934. llinfos << "Claiming " << mWestSouth << " to " << mEastNorth << llendl;
  935. llinfos << "Region " << region->getOriginGlobal() << llendl;
  936. // BUG: Only works for the region containing mWestSouthBottom
  937. LLVector3d east_north_region_check( mEastNorth );
  938. east_north_region_check.mdV[VX] -= 0.5;
  939. east_north_region_check.mdV[VY] -= 0.5;
  940. LLViewerRegion *region2 = LLWorld::getInstance()->getRegionFromPosGlobal( east_north_region_check );
  941. if (region != region2)
  942. {
  943. LLNotificationsUtil::add("CantBuyLandAcrossMultipleRegions");
  944. return NULL;
  945. }
  946. }
  947. ParcelBuyInfo* info = new ParcelBuyInfo;
  948. info->mAgent = agent_id;
  949. info->mSession = session_id;
  950. info->mGroup = group_id;
  951. info->mIsGroupOwned = is_group_owned;
  952. info->mIsClaim = is_claim;
  953. info->mRemoveContribution = remove_contribution;
  954. info->mHost = region->getHost();
  955. info->mPrice = mCurrentParcel->getSalePrice();
  956. info->mArea = mCurrentParcel->getArea();
  957. if (!is_claim)
  958. {
  959. info->mParcelID = mCurrentParcel->getLocalID();
  960. }
  961. else
  962. {
  963. // BUG: Make work for cross-region selections
  964. LLVector3 west_south_bottom_region = region->getPosRegionFromGlobal( mWestSouth );
  965. LLVector3 east_north_top_region = region->getPosRegionFromGlobal( mEastNorth );
  966. info->mWest = west_south_bottom_region.mV[VX];
  967. info->mSouth = west_south_bottom_region.mV[VY];
  968. info->mEast = east_north_top_region.mV[VX];
  969. info->mNorth = east_north_top_region.mV[VY];
  970. }
  971. return info;
  972. }
  973. void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info)
  974. {
  975. // send the message
  976. LLMessageSystem* msg = gMessageSystem;
  977. msg->newMessage(info->mIsClaim ? "ParcelClaim" : "ParcelBuy");
  978. msg->nextBlock("AgentData");
  979. msg->addUUID("AgentID", info->mAgent);
  980. msg->addUUID("SessionID", info->mSession);
  981. msg->nextBlock("Data");
  982. msg->addUUID("GroupID", info->mGroup);
  983. msg->addBOOL("IsGroupOwned", info->mIsGroupOwned);
  984. if (!info->mIsClaim)
  985. {
  986. msg->addBOOL("RemoveContribution", info->mRemoveContribution);
  987. msg->addS32("LocalID", info->mParcelID);
  988. }
  989. msg->addBOOL("Final", TRUE); // don't allow escrow buys
  990. if (info->mIsClaim)
  991. {
  992. msg->nextBlock("ParcelData");
  993. msg->addF32("West", info->mWest);
  994. msg->addF32("South", info->mSouth);
  995. msg->addF32("East", info->mEast);
  996. msg->addF32("North", info->mNorth);
  997. }
  998. else // ParcelBuy
  999. {
  1000. msg->nextBlock("ParcelData");
  1001. msg->addS32("Price",info->mPrice);
  1002. msg->addS32("Area",info->mArea);
  1003. }
  1004. msg->sendReliable(info->mHost);
  1005. }
  1006. void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo* *info)
  1007. {
  1008. // Must be here because ParcelBuyInfo is local to this .cpp file
  1009. delete *info;
  1010. *info = NULL;
  1011. }
  1012. void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
  1013. {
  1014. if (!mSelected || !mCurrentParcel)
  1015. {
  1016. LLNotificationsUtil::add("CannotDeedLandNothingSelected");
  1017. return;
  1018. }
  1019. if(group_id.isNull())
  1020. {
  1021. LLNotificationsUtil::add("CannotDeedLandNoGroup");
  1022. return;
  1023. }
  1024. LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  1025. if (!region)
  1026. {
  1027. LLNotificationsUtil::add("CannotDeedLandNoRegion");
  1028. return;
  1029. }
  1030. LLMessageSystem* msg = gMessageSystem;
  1031. msg->newMessage("ParcelDeedToGroup");
  1032. msg->nextBlock("AgentData");
  1033. msg->addUUID("AgentID", gAgent.getID() );
  1034. msg->addUUID("SessionID", gAgent.getSessionID() );
  1035. msg->nextBlock("Data");
  1036. msg->addUUID("GroupID", group_id );
  1037. msg->addS32("LocalID", mCurrentParcel->getLocalID() );
  1038. //msg->addU32("JoinNeighbors", join);
  1039. msg->sendReliable( region->getHost() );
  1040. }
  1041. /*
  1042. // *NOTE: We cannot easily make landmarks at global positions because
  1043. // global positions probably refer to a sim/local combination which
  1044. // can move over time. We could implement this by looking up the
  1045. // region global x,y, but it's easier to take it out for now.
  1046. void LLViewerParcelMgr::makeLandmarkAtSelection()
  1047. {
  1048. // Don't create for parcels you don't own
  1049. if (gAgent.getID() != mCurrentParcel->getOwnerID())
  1050. {
  1051. return;
  1052. }
  1053. LLVector3d global_center(mWestSouth);
  1054. global_center += mEastNorth;
  1055. global_center *= 0.5f;
  1056. LLViewerRegion* region;
  1057. region = LLWorld::getInstance()->getRegionFromPosGlobal(global_center);
  1058. LLVector3 west_south_bottom_region = region->getPosRegionFromGlobal( mWestSouth );
  1059. LLVector3 east_north_top_region = region->getPosRegionFromGlobal( mEastNorth );
  1060. std::string name("My Land");
  1061. std::string buffer;
  1062. S32 pos_x = (S32)floor((west_south_bottom_region.mV[VX] + east_north_top_region.mV[VX]) / 2.0f);
  1063. S32 pos_y = (S32)floor((west_south_bottom_region.mV[VY] + east_north_top_region.mV[VY]) / 2.0f);
  1064. buffer = llformat("%s in %s (%d, %d)",
  1065. name.c_str(),
  1066. region->getName().c_str(),
  1067. pos_x, pos_y);
  1068. name.assign(buffer);
  1069. create_landmark(name, "Claimed land", global_center);
  1070. }
  1071. */
  1072. const std::string& LLViewerParcelMgr::getAgentParcelName() const
  1073. {
  1074. return mAgentParcel->getName();
  1075. }
  1076. void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region)
  1077. {
  1078. if(!parcel) return;
  1079. LLViewerRegion *region = use_agent_region ? gAgent.getRegion() : LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  1080. if (!region) return;
  1081. //llinfos << "found region: " << region->getName() << llendl;
  1082. LLSD body;
  1083. std::string url = region->getCapability("ParcelPropertiesUpdate");
  1084. if (!url.empty())
  1085. {
  1086. // request new properties update from simulator
  1087. U32 message_flags = 0x01;
  1088. body["flags"] = ll_sd_from_U32(message_flags);
  1089. parcel->packMessage(body);
  1090. llinfos << "Sending parcel properties update via capability to: "
  1091. << url << llendl;
  1092. LLHTTPClient::post(url, body, new LLHTTPClient::Responder());
  1093. }
  1094. else
  1095. {
  1096. LLMessageSystem* msg = gMessageSystem;
  1097. msg->newMessageFast(_PREHASH_ParcelPropertiesUpdate);
  1098. msg->nextBlockFast(_PREHASH_AgentData);
  1099. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  1100. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  1101. msg->nextBlockFast(_PREHASH_ParcelData);
  1102. msg->addS32Fast(_PREHASH_LocalID, parcel->getLocalID() );
  1103. U32 message_flags = 0x01;
  1104. msg->addU32("Flags", message_flags);
  1105. parcel->packMessage(msg);
  1106. msg->sendReliable( region->getHost() );
  1107. }
  1108. }
  1109. void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos)
  1110. {
  1111. static U32 last_west, last_south;
  1112. // only request parcel info when tooltip is shown
  1113. if (!gSavedSettings.getBOOL("ShowLandHoverTip"))
  1114. {
  1115. return;
  1116. }
  1117. // only request parcel info if position has changed outside of the
  1118. // last parcel grid step
  1119. U32 west_parcel_step = (U32) floor( pos.mdV[VX] / PARCEL_GRID_STEP_METERS );
  1120. U32 south_parcel_step = (U32) floor( pos.mdV[VY] / PARCEL_GRID_STEP_METERS );
  1121. if ((west_parcel_step == last_west) && (south_parcel_step == last_south))
  1122. {
  1123. return;
  1124. }
  1125. else
  1126. {
  1127. last_west = west_parcel_step;
  1128. last_south = south_parcel_step;
  1129. }
  1130. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos );
  1131. if (!region)
  1132. {
  1133. return;
  1134. }
  1135. // Send a rectangle around the point.
  1136. // This means the parcel sent back is at least a rectangle around the point,
  1137. // which is more efficient for public land. Fewer requests are sent. JC
  1138. LLVector3 wsb_region = region->getPosRegionFromGlobal( pos );
  1139. F32 west = PARCEL_GRID_STEP_METERS * floor( wsb_region.mV[VX] / PARCEL_GRID_STEP_METERS );
  1140. F32 south = PARCEL_GRID_STEP_METERS * floor( wsb_region.mV[VY] / PARCEL_GRID_STEP_METERS );
  1141. F32 east = west + PARCEL_GRID_STEP_METERS;
  1142. F32 north = south + PARCEL_GRID_STEP_METERS;
  1143. // Send request message
  1144. LLMessageSystem *msg = gMessageSystem;
  1145. msg->newMessageFast(_PREHASH_ParcelPropertiesRequest);
  1146. msg->nextBlockFast(_PREHASH_AgentData);
  1147. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  1148. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
  1149. msg->nextBlockFast(_PREHASH_ParcelData);
  1150. msg->addS32Fast(_PREHASH_SequenceID, HOVERED_PARCEL_SEQ_ID );
  1151. msg->addF32Fast(_PREHASH_West, west );
  1152. msg->addF32Fast(_PREHASH_South, south );
  1153. msg->addF32Fast(_PREHASH_East, east );
  1154. msg->addF32Fast(_PREHASH_North, north );
  1155. msg->addBOOL("SnapSelection", FALSE );
  1156. msg->sendReliable( region->getHost() );
  1157. mHoverRequestResult = PARCEL_RESULT_NO_DATA;
  1158. }
  1159. // static
  1160. void LLViewerParcelMgr::processParcelOverlay(LLMessageSystem *msg, void **user)
  1161. {
  1162. // Extract the packed overlay information
  1163. S32 packed_overlay_size = msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_Data);
  1164. if (packed_overlay_size <= 0)
  1165. {
  1166. llwarns << "Overlay size " << packed_overlay_size << llendl;
  1167. return;
  1168. }
  1169. S32 parcels_per_edge = LLViewerParcelMgr::getInstance()->mParcelsPerEdge;
  1170. S32 expected_size = parcels_per_edge * parcels_per_edge / PARCEL_OVERLAY_CHUNKS;
  1171. if (packed_overlay_size != expected_size)
  1172. {
  1173. llwarns << "Got parcel overlay size " << packed_overlay_size
  1174. << " expecting " << expected_size << llendl;
  1175. return;
  1176. }
  1177. S32 sequence_id;
  1178. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id);
  1179. msg->getBinaryDataFast(
  1180. _PREHASH_ParcelData,
  1181. _PREHASH_Data,
  1182. sPackedOverlay,
  1183. expected_size);
  1184. LLHost host = msg->getSender();
  1185. LLViewerRegion *region = LLWorld::getInstance()->getRegion(host);
  1186. if (region)
  1187. {
  1188. region->mParcelOverlay->uncompressLandOverlay( sequence_id, sPackedOverlay );
  1189. }
  1190. }
  1191. // static
  1192. void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **user)
  1193. {
  1194. S32 request_result;
  1195. S32 sequence_id;
  1196. BOOL snap_selection = FALSE;
  1197. S32 self_count = 0;
  1198. S32 other_count = 0;
  1199. S32 public_count = 0;
  1200. S32 local_id;
  1201. LLUUID owner_id;
  1202. BOOL is_group_owned;
  1203. U32 auction_id = 0;
  1204. S32 claim_price_per_meter = 0;
  1205. S32 rent_price_per_meter = 0;
  1206. S32 claim_date = 0;
  1207. LLVector3 aabb_min;
  1208. LLVector3 aabb_max;
  1209. S32 area = 0;
  1210. S32 sw_max_prims = 0;
  1211. S32 sw_total_prims = 0;
  1212. //LLUUID buyer_id;
  1213. U8 status = 0;
  1214. S32 max_prims = 0;
  1215. S32 total_prims = 0;
  1216. S32 owner_prims = 0;
  1217. S32 group_prims = 0;
  1218. S32 other_prims = 0;
  1219. S32 selected_prims = 0;
  1220. F32 parcel_prim_bonus = 1.f;
  1221. BOOL region_push_override = false;
  1222. BOOL region_deny_anonymous_override = false;
  1223. BOOL region_deny_identified_override = false; // Deprecated
  1224. BOOL region_deny_transacted_override = false; // Deprecated
  1225. BOOL region_deny_age_unverified_override = false;
  1226. S32 other_clean_time = 0;
  1227. LLViewerParcelMgr& parcel_mgr = LLViewerParcelMgr::instance();
  1228. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_RequestResult, request_result );
  1229. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id );
  1230. if (request_result == PARCEL_RESULT_NO_DATA)
  1231. {
  1232. // no valid parcel data
  1233. llinfos << "no valid parcel data" << llendl;
  1234. return;
  1235. }
  1236. // Decide where the data will go.
  1237. LLParcel* parcel = NULL;
  1238. if (sequence_id == SELECTED_PARCEL_SEQ_ID)
  1239. {
  1240. // ...selected parcels report this sequence id
  1241. parcel_mgr.mRequestResult = PARCEL_RESULT_SUCCESS;
  1242. parcel = parcel_mgr.mCurrentParcel;
  1243. }
  1244. else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
  1245. {
  1246. parcel_mgr.mHoverRequestResult = PARCEL_RESULT_SUCCESS;
  1247. parcel = parcel_mgr.mHoverParcel;
  1248. }
  1249. else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID ||
  1250. sequence_id == COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID ||
  1251. sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
  1252. {
  1253. parcel_mgr.mHoverRequestResult = PARCEL_RESULT_SUCCESS;
  1254. parcel = parcel_mgr.mCollisionParcel;
  1255. }
  1256. else if (sequence_id == 0 || sequence_id > parcel_mgr.mAgentParcelSequenceID)
  1257. {
  1258. // new agent parcel
  1259. parcel_mgr.mAgentParcelSequenceID = sequence_id;
  1260. parcel = parcel_mgr.mAgentParcel;
  1261. }
  1262. else
  1263. {
  1264. llinfos << "out of order agent parcel sequence id " << sequence_id
  1265. << " last good " << parcel_mgr.mAgentParcelSequenceID
  1266. << llendl;
  1267. return;
  1268. }
  1269. msg->getBOOL("ParcelData", "SnapSelection", snap_selection);
  1270. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SelfCount, self_count);
  1271. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OtherCount, other_count);
  1272. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_PublicCount, public_count);
  1273. msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_LocalID, local_id );
  1274. msg->getUUIDFast(_PREHASH_ParcelData, _PREHASH_OwnerID, owner_id);
  1275. msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_IsGroupOwned, is_group_owned);
  1276. msg->getU32Fast(_PREHASH_ParcelData, _PREHASH_AuctionID, auction_id);
  1277. msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimDate, claim_date);
  1278. msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimPrice, claim_price_per_meter);
  1279. msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_RentPrice, rent_price_per_meter);
  1280. msg->getVector3Fast(_PREHASH_ParcelData, _PREHASH_AABBMin, aabb_min);
  1281. msg->getVector3Fast(_PREHASH_ParcelData, _PREHASH_AABBMax, aabb_max);
  1282. msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_Area, area );
  1283. //msg->getUUIDFast( _PREHASH_ParcelData, _PREHASH_BuyerID, buyer_id);
  1284. msg->getU8("ParcelData", "Status", status);
  1285. msg->getS32("ParcelData", "SimWideMaxPrims", sw_max_prims );
  1286. msg->getS32("ParcelData", "SimWideTotalPrims", sw_total_prims );
  1287. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_MaxPrims, max_prims );
  1288. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_TotalPrims, total_prims );
  1289. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OwnerPrims, owner_prims );
  1290. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_GroupPrims, group_prims );
  1291. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OtherPrims, other_prims );
  1292. msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SelectedPrims, selected_prims );
  1293. msg->getF32Fast(_PREHASH_ParcelData, _PREHASH_ParcelPrimBonus, parcel_prim_bonus );
  1294. msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionPushOverride, region_push_override );
  1295. msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyAnonymous, region_deny_anonymous_override );
  1296. msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyIdentified, region_deny_identified_override ); // Deprecated
  1297. msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyTransacted, region_deny_transacted_override ); // Deprecated
  1298. if (msg->getNumberOfBlocksFast(_PREHASH_AgeVerificationBlock))
  1299. {
  1300. // this block was added later and may not be on older sims, so we have to test its existence first
  1301. msg->getBOOLFast(_PREHASH_AgeVerificationBlock, _PREHASH_RegionDenyAgeUnverified, region_deny_age_unverified_override );
  1302. }
  1303. msg->getS32("ParcelData", "OtherCleanTime", other_clean_time );
  1304. // Actually extract the data.
  1305. if (parcel)
  1306. {
  1307. parcel->init(owner_id,
  1308. FALSE, FALSE, FALSE,
  1309. claim_date, claim_price_per_meter, rent_price_per_meter,
  1310. area, other_prims, parcel_prim_bonus, is_group_owned);
  1311. parcel->setLocalID(local_id);
  1312. parcel->setAABBMin(aabb_min);
  1313. parcel->setAABBMax(aabb_max);
  1314. parcel->setAuctionID(auction_id);
  1315. parcel->setOwnershipStatus((LLParcel::EOwnershipStatus)status);
  1316. parcel->setSimWideMaxPrimCapacity(sw_max_prims);
  1317. parcel->setSimWidePrimCount(sw_total_prims);
  1318. parcel->setMaxPrimCapacity(max_prims);
  1319. parcel->setOwnerPrimCount(owner_prims);
  1320. parcel->setGroupPrimCount(group_prims);
  1321. parcel->setOtherPrimCount(other_prims);
  1322. parcel->setSelectedPrimCount(selected_prims);
  1323. parcel->setParcelPrimBonus(parcel_prim_bonus);
  1324. parcel->setCleanOtherTime(other_clean_time);
  1325. parcel->setRegionPushOverride(region_push_override);
  1326. parcel->setRegionDenyAnonymousOverride(region_deny_anonymous_override);
  1327. parcel->setRegionDenyAgeUnverifiedOverride(region_deny_age_unverified_override);
  1328. parcel->unpackMessage(msg);
  1329. if (parcel == parcel_mgr.mAgentParcel)
  1330. {
  1331. S32 bitmap_size = parcel_mgr.mParcelsPerEdge
  1332. * parcel_mgr.mParcelsPerEdge
  1333. / 8;
  1334. U8* bitmap = new U8[ bitmap_size ];
  1335. msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
  1336. parcel_mgr.writeAgentParcelFromBitmap(bitmap);
  1337. delete[] bitmap;
  1338. // Let interesting parties know about agent parcel change.
  1339. LLViewerParcelMgr* instance = LLViewerParcelMgr::getInstance();
  1340. instance->mAgentParcelChangedSignal();
  1341. if (instance->mTeleportInProgress)
  1342. {
  1343. instance->mTeleportInProgress = FALSE;
  1344. instance->mTeleportFinishedSignal(gAgent.getPositionGlobal());
  1345. }
  1346. }
  1347. }
  1348. // Handle updating selections, if necessary.
  1349. if (sequence_id == SELECTED_PARCEL_SEQ_ID)
  1350. {
  1351. // Update selected counts
  1352. parcel_mgr.mCurrentParcelSelection->mSelectedSelfCount = self_count;
  1353. parcel_mgr.mCurrentParcelSelection->mSelectedOtherCount = other_count;
  1354. parcel_mgr.mCurrentParcelSelection->mSelectedPublicCount = public_count;
  1355. parcel_mgr.mCurrentParcelSelection->mSelectedMultipleOwners =
  1356. (request_result == PARCEL_RESULT_MULTIPLE);
  1357. // Select the whole parcel
  1358. LLViewerRegion* region = LLWorld::getInstance()->getRegion( msg->getSender() );
  1359. if (region)
  1360. {
  1361. if (!snap_selection)
  1362. {
  1363. // don't muck with the westsouth and eastnorth.
  1364. // just highlight it
  1365. LLVector3 west_south = region->getPosRegionFromGlobal(parcel_mgr.mWestSouth);
  1366. LLVector3 east_north = region->getPosRegionFromGlobal(parcel_mgr.mEastNorth);
  1367. parcel_mgr.resetSegments(parcel_mgr.mHighlightSegments);
  1368. parcel_mgr.writeHighlightSegments(
  1369. west_south.mV[VX],
  1370. west_south.mV[VY],
  1371. east_north.mV[VX],
  1372. east_north.mV[VY] );
  1373. parcel_mgr.mCurrentParcelSelection->mWholeParcelSelected = FALSE;
  1374. }
  1375. else if (0 == local_id)
  1376. {
  1377. // this is public land, just highlight the selection
  1378. parcel_mgr.mWestSouth = region->getPosGlobalFromRegion( aabb_min );
  1379. parcel_mgr.mEastNorth = region->getPosGlobalFromRegion( aabb_max );
  1380. parcel_mgr.resetSegments(parcel_mgr.mHighlightSegments);
  1381. parcel_mgr.writeHighlightSegments(
  1382. aabb_min.mV[VX],
  1383. aabb_min.mV[VY],
  1384. aabb_max.mV[VX],
  1385. aabb_max.mV[VY] );
  1386. parcel_mgr.mCurrentParcelSelection->mWholeParcelSelected = TRUE;
  1387. }
  1388. else
  1389. {
  1390. parcel_mgr.mWestSouth = region->getPosGlobalFromRegion( aabb_min );
  1391. parcel_mgr.mEastNorth = region->getPosGlobalFromRegion( aabb_max );
  1392. // Owned land, highlight the boundaries
  1393. S32 bitmap_size = parcel_mgr.mParcelsPerEdge
  1394. * parcel_mgr.mParcelsPerEdge
  1395. / 8;
  1396. U8* bitmap = new U8[ bitmap_size ];
  1397. msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
  1398. parcel_mgr.resetSegments(parcel_mgr.mHighlightSegments);
  1399. parcel_mgr.writeSegmentsFromBitmap( bitmap, parcel_mgr.mHighlightSegments );
  1400. delete[] bitmap;
  1401. bitmap = NULL;
  1402. parcel_mgr.mCurrentParcelSelection->mWholeParcelSelected = TRUE;
  1403. }
  1404. // Request access list information for this land
  1405. parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN);
  1406. // Request the media url filter list for this land
  1407. parcel_mgr.requestParcelMediaURLFilter();
  1408. // Request dwell for this land, if it's not public land.
  1409. parcel_mgr.mSelectedDwell = DWELL_NAN;
  1410. if (0 != local_id)
  1411. {
  1412. parcel_mgr.sendParcelDwellRequest();
  1413. }
  1414. parcel_mgr.mSelected = TRUE;
  1415. parcel_mgr.notifyObservers();
  1416. }
  1417. }
  1418. else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID ||
  1419. sequence_id == COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID ||
  1420. sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
  1421. {
  1422. // We're about to collide with this parcel
  1423. parcel_mgr.mRenderCollision = TRUE;
  1424. parcel_mgr.mCollisionTimer.reset();
  1425. // Differentiate this parcel if we are banned from it.
  1426. if (sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
  1427. {
  1428. parcel_mgr.mCollisionBanned = BA_BANNED;
  1429. }
  1430. else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID)
  1431. {
  1432. parcel_mgr.mCollisionBanned = BA_NOT_IN_GROUP;
  1433. }
  1434. else
  1435. {
  1436. parcel_mgr.mCollisionBanned = BA_NOT_ON_LIST;
  1437. }
  1438. S32 bitmap_size = parcel_mgr.mParcelsPerEdge
  1439. * parcel_mgr.mParcelsPerEdge
  1440. / 8;
  1441. U8* bitmap = new U8[ bitmap_size ];
  1442. msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
  1443. parcel_mgr.resetSegments(parcel_mgr.mCollisionSegments);
  1444. parcel_mgr.writeSegmentsFromBitmap( bitmap, parcel_mgr.mCollisionSegments );
  1445. delete[] bitmap;
  1446. bitmap = NULL;
  1447. }
  1448. else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
  1449. {
  1450. LLViewerRegion *region = LLWorld::getInstance()->getRegion( msg->getSender() );
  1451. if (region)
  1452. {
  1453. parcel_mgr.mHoverWestSouth = region->getPosGlobalFromRegion( aabb_min );
  1454. parcel_mgr.mHoverEastNorth = region->getPosGlobalFromRegion( aabb_max );
  1455. }
  1456. else
  1457. {
  1458. parcel_mgr.mHoverWestSouth.clearVec();
  1459. parcel_mgr.mHoverEastNorth.clearVec();
  1460. }
  1461. }
  1462. else
  1463. {
  1464. // Check for video
  1465. LLViewerParcelMedia::update(parcel);
  1466. // Then check for music
  1467. if (gAudiop)
  1468. {
  1469. if (parcel)
  1470. {
  1471. std::string music_url_raw = parcel->getMusicURL();
  1472. // Trim off whitespace from front and back
  1473. std::string music_url = music_url_raw;
  1474. LLStringUtil::trim(music_url);
  1475. // If there is a new music URL and it's valid, play it.
  1476. if (music_url.size() > 12)
  1477. {
  1478. if (music_url.substr(0,7) == "http://")
  1479. {
  1480. optionally_start_music(music_url);
  1481. }
  1482. else
  1483. {
  1484. llinfos << "Stopping parcel music (invalid audio stream URL)" << llendl;
  1485. // clears the URL
  1486. // null value causes fade out
  1487. LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
  1488. }
  1489. }
  1490. else if (!gAudiop->getInternetStreamURL().empty())
  1491. {
  1492. llinfos << "Stopping parcel music (parcel stream URL is empty)" << llendl;
  1493. // null value causes fade out
  1494. LLV

Large files files are truncated, but you can click here to view the full file