/indra/newview/llviewerparcelmgr.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 2332 lines · 1763 code · 354 blank · 215 comment · 271 complexity · 68823a547156306d4d5b6d9238b3b96e MD5 · raw 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. LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
  1495. }
  1496. }
  1497. else
  1498. {
  1499. // Public land has no music
  1500. LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
  1501. }
  1502. }//if gAudiop
  1503. };
  1504. }
  1505. void optionally_start_music(const std::string& music_url)
  1506. {
  1507. if (gSavedSettings.getBOOL("AudioStreamingMusic"))
  1508. {
  1509. // only play music when you enter a new parcel if the UI control for this
  1510. // was not *explicitly* stopped by the user. (part of SL-4878)
  1511. LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();;
  1512. if ((nearby_media_panel &&
  1513. nearby_media_panel->getParcelAudioAutoStart()) ||
  1514. // or they have expressed no opinion in the UI, but have autoplay on...
  1515. (!nearby_media_panel &&
  1516. gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
  1517. gSavedSettings.getBOOL("MediaTentativeAutoPlay")))
  1518. {
  1519. llinfos << "Starting parcel music " << music_url << llendl;
  1520. LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(music_url);
  1521. }
  1522. else
  1523. {
  1524. LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
  1525. }
  1526. }
  1527. }
  1528. // static
  1529. void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void **user)
  1530. {
  1531. LLUUID agent_id;
  1532. S32 sequence_id = 0;
  1533. U32 message_flags = 0x0;
  1534. S32 parcel_id = -1;
  1535. msg->getUUIDFast(_PREHASH_Data, _PREHASH_AgentID, agent_id);
  1536. msg->getS32Fast( _PREHASH_Data, _PREHASH_SequenceID, sequence_id ); //ignored
  1537. msg->getU32Fast( _PREHASH_Data, _PREHASH_Flags, message_flags);
  1538. msg->getS32Fast( _PREHASH_Data, _PREHASH_LocalID, parcel_id);
  1539. LLParcel* parcel = LLViewerParcelMgr::getInstance()->mCurrentParcel;
  1540. if (!parcel) return;
  1541. if (parcel_id != parcel->getLocalID())
  1542. {
  1543. LL_WARNS_ONCE("") << "processParcelAccessListReply for parcel " << parcel_id
  1544. << " which isn't the selected parcel " << parcel->getLocalID()<< llendl;
  1545. return;
  1546. }
  1547. if (message_flags & AL_ACCESS)
  1548. {
  1549. parcel->unpackAccessEntries(msg, &(parcel->mAccessList) );
  1550. }
  1551. else if (message_flags & AL_BAN)
  1552. {
  1553. parcel->unpackAccessEntries(msg, &(parcel->mBanList) );
  1554. }
  1555. /*else if (message_flags & AL_RENTER)
  1556. {
  1557. parcel->unpackAccessEntries(msg, &(parcel->mRenterList) );
  1558. }*/
  1559. LLViewerParcelMgr::getInstance()->notifyObservers();
  1560. }
  1561. // static
  1562. void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**)
  1563. {
  1564. LLUUID agent_id;
  1565. msg->getUUID("AgentData", "AgentID", agent_id);
  1566. S32 local_id;
  1567. msg->getS32("Data", "LocalID", local_id);
  1568. LLUUID parcel_id;
  1569. msg->getUUID("Data", "ParcelID", parcel_id);
  1570. F32 dwell;
  1571. msg->getF32("Data", "Dwell", dwell);
  1572. if (local_id == LLViewerParcelMgr::getInstance()->mCurrentParcel->getLocalID())
  1573. {
  1574. LLViewerParcelMgr::getInstance()->mSelectedDwell = dwell;
  1575. LLViewerParcelMgr::getInstance()->notifyObservers();
  1576. }
  1577. }
  1578. void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
  1579. {
  1580. LLUUID transactionUUID;
  1581. transactionUUID.generate();
  1582. if (!mSelected)
  1583. {
  1584. return;
  1585. }
  1586. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  1587. if (!region) return;
  1588. LLMessageSystem* msg = gMessageSystem;
  1589. LLParcel* parcel = mCurrentParcel;
  1590. if (!parcel) return;
  1591. if (which & AL_ACCESS)
  1592. {
  1593. S32 count = parcel->mAccessList.size();
  1594. S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
  1595. S32 sequence_id = 1;
  1596. BOOL start_message = TRUE;
  1597. BOOL initial = TRUE;
  1598. access_map_const_iterator cit = parcel->mAccessList.begin();
  1599. access_map_const_iterator end = parcel->mAccessList.end();
  1600. while ( (cit != end) || initial )
  1601. {
  1602. if (start_message)
  1603. {
  1604. msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
  1605. msg->nextBlockFast(_PREHASH_AgentData);
  1606. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  1607. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
  1608. msg->nextBlockFast(_PREHASH_Data);
  1609. msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
  1610. msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
  1611. msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
  1612. msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
  1613. msg->addS32Fast(_PREHASH_Sections, num_sections);
  1614. start_message = FALSE;
  1615. if (initial && (cit == end))
  1616. {
  1617. // pack an empty block if there will be no data
  1618. msg->nextBlockFast(_PREHASH_List);
  1619. msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
  1620. msg->addS32Fast(_PREHASH_Time, 0 );
  1621. msg->addU32Fast(_PREHASH_Flags, 0 );
  1622. }
  1623. initial = FALSE;
  1624. sequence_id++;
  1625. }
  1626. while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES))
  1627. {
  1628. const LLAccessEntry& entry = (*cit).second;
  1629. msg->nextBlockFast(_PREHASH_List);
  1630. msg->addUUIDFast(_PREHASH_ID, entry.mID );
  1631. msg->addS32Fast(_PREHASH_Time, entry.mTime );
  1632. msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
  1633. ++cit;
  1634. }
  1635. start_message = TRUE;
  1636. msg->sendReliable( region->getHost() );
  1637. }
  1638. }
  1639. if (which & AL_BAN)
  1640. {
  1641. S32 count = parcel->mBanList.size();
  1642. S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
  1643. S32 sequence_id = 1;
  1644. BOOL start_message = TRUE;
  1645. BOOL initial = TRUE;
  1646. access_map_const_iterator cit = parcel->mBanList.begin();
  1647. access_map_const_iterator end = parcel->mBanList.end();
  1648. while ( (cit != end) || initial )
  1649. {
  1650. if (start_message)
  1651. {
  1652. msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
  1653. msg->nextBlockFast(_PREHASH_AgentData);
  1654. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  1655. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
  1656. msg->nextBlockFast(_PREHASH_Data);
  1657. msg->addU32Fast(_PREHASH_Flags, AL_BAN);
  1658. msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
  1659. msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
  1660. msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
  1661. msg->addS32Fast(_PREHASH_Sections, num_sections);
  1662. start_message = FALSE;
  1663. if (initial && (cit == end))
  1664. {
  1665. // pack an empty block if there will be no data
  1666. msg->nextBlockFast(_PREHASH_List);
  1667. msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
  1668. msg->addS32Fast(_PREHASH_Time, 0 );
  1669. msg->addU32Fast(_PREHASH_Flags, 0 );
  1670. }
  1671. initial = FALSE;
  1672. sequence_id++;
  1673. }
  1674. while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES))
  1675. {
  1676. const LLAccessEntry& entry = (*cit).second;
  1677. msg->nextBlockFast(_PREHASH_List);
  1678. msg->addUUIDFast(_PREHASH_ID, entry.mID );
  1679. msg->addS32Fast(_PREHASH_Time, entry.mTime );
  1680. msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
  1681. ++cit;
  1682. }
  1683. start_message = TRUE;
  1684. msg->sendReliable( region->getHost() );
  1685. }
  1686. }
  1687. }
  1688. class LLParcelMediaURLFilterResponder : public LLHTTPClient::Responder
  1689. {
  1690. virtual void result(const LLSD& content)
  1691. {
  1692. LLViewerParcelMgr::getInstance()->receiveParcelMediaURLFilter(content);
  1693. }
  1694. };
  1695. void LLViewerParcelMgr::requestParcelMediaURLFilter()
  1696. {
  1697. if (!mSelected)
  1698. {
  1699. return;
  1700. }
  1701. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
  1702. if (!region)
  1703. {
  1704. return;
  1705. }
  1706. LLParcel* parcel = mCurrentParcel;
  1707. if (!parcel)
  1708. {
  1709. llwarns << "no parcel" << llendl;
  1710. return;
  1711. }
  1712. LLSD body;
  1713. body["local-id"] = parcel->getLocalID();
  1714. body["list"] = parcel->getMediaURLFilterList();
  1715. std::string url = region->getCapability("ParcelMediaURLFilterList");
  1716. if (!url.empty())
  1717. {
  1718. LLHTTPClient::post(url, body, new LLParcelMediaURLFilterResponder);
  1719. }
  1720. else
  1721. {
  1722. llwarns << "can't get ParcelMediaURLFilterList cap" << llendl;
  1723. }
  1724. }
  1725. void LLViewerParcelMgr::receiveParcelMediaURLFilter(const LLSD &content)
  1726. {
  1727. if (content.has("list"))
  1728. {
  1729. LLParcel* parcel = LLViewerParcelMgr::getInstance()->mCurrentParcel;
  1730. if (!parcel) return;
  1731. if (content["local-id"].asInteger() == parcel->getLocalID())
  1732. {
  1733. parcel->setMediaURLFilterList(content["list"]);
  1734. LLViewerParcelMgr::getInstance()->notifyObservers();
  1735. }
  1736. }
  1737. }
  1738. void LLViewerParcelMgr::deedLandToGroup()
  1739. {
  1740. std::string group_name;
  1741. gCacheName->getGroupName(mCurrentParcel->getGroupID(), group_name);
  1742. LLSD args;
  1743. args["AREA"] = llformat("%d", mCurrentParcel->getArea());
  1744. args["GROUP_NAME"] = group_name;
  1745. if(mCurrentParcel->getContributeWithDeed())
  1746. {
  1747. args["NAME"] = LLSLURL("agent", mCurrentParcel->getOwnerID(), "completename").getSLURLString();
  1748. LLNotificationsUtil::add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB);
  1749. }
  1750. else
  1751. {
  1752. LLNotificationsUtil::add("DeedLandToGroup",args, LLSD(), deedAlertCB);
  1753. }
  1754. }
  1755. // static
  1756. bool LLViewerParcelMgr::deedAlertCB(const LLSD& notification, const LLSD& response)
  1757. {
  1758. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1759. if (option == 0)
  1760. {
  1761. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
  1762. LLUUID group_id;
  1763. if(parcel)
  1764. {
  1765. group_id = parcel->getGroupID();
  1766. }
  1767. LLViewerParcelMgr::getInstance()->sendParcelDeed(group_id);
  1768. }
  1769. return false;
  1770. }
  1771. void LLViewerParcelMgr::startReleaseLand()
  1772. {
  1773. if (!mSelected)
  1774. {
  1775. LLNotificationsUtil::add("CannotReleaseLandNothingSelected");
  1776. return;
  1777. }
  1778. if (mRequestResult == PARCEL_RESULT_NO_DATA)
  1779. {
  1780. LLNotificationsUtil::add("CannotReleaseLandWatingForServer");
  1781. return;
  1782. }
  1783. if (mRequestResult == PARCEL_RESULT_MULTIPLE)
  1784. {
  1785. LLNotificationsUtil::add("CannotReleaseLandSelected");
  1786. return;
  1787. }
  1788. if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE)
  1789. && !(gAgent.canManageEstate()))
  1790. {
  1791. LLNotificationsUtil::add("CannotReleaseLandDontOwn");
  1792. return;
  1793. }
  1794. LLVector3d parcel_center = (mWestSouth + mEastNorth) / 2.0;
  1795. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
  1796. if (!region)
  1797. {
  1798. LLNotificationsUtil::add("CannotReleaseLandRegionNotFound");
  1799. return;
  1800. }
  1801. /*
  1802. if ((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
  1803. && !gAgent.isGodlike())
  1804. {
  1805. LLSD args;
  1806. args["REGION"] = region->getName();
  1807. LLNotificationsUtil::add("CannotReleaseLandNoTransfer", args);
  1808. return;
  1809. }
  1810. */
  1811. if (!mCurrentParcelSelection->mWholeParcelSelected)
  1812. {
  1813. LLNotificationsUtil::add("CannotReleaseLandPartialSelection");
  1814. return;
  1815. }
  1816. // Compute claim price
  1817. LLSD args;
  1818. args["AREA"] = llformat("%d",mCurrentParcel->getArea());
  1819. LLNotificationsUtil::add("ReleaseLandWarning", args, LLSD(), releaseAlertCB);
  1820. }
  1821. bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
  1822. {
  1823. if (!parcel)
  1824. {
  1825. return false;
  1826. }
  1827. if (mSelected && parcel == mCurrentParcel)
  1828. {
  1829. if (mRequestResult == PARCEL_RESULT_NO_DATA)
  1830. {
  1831. return false;
  1832. }
  1833. }
  1834. const LLUUID& parcelOwner = parcel->getOwnerID();
  1835. const LLUUID& authorizeBuyer = parcel->getAuthorizedBuyerID();
  1836. if (parcel->isPublic())
  1837. {
  1838. return true; // change this if want to make it gods only
  1839. }
  1840. LLVector3 parcel_coord = parcel->getCenterpoint();
  1841. LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosAgent(parcel_coord);
  1842. if (regionp)
  1843. {
  1844. U8 sim_access = regionp->getSimAccess();
  1845. const LLAgentAccess& agent_access = gAgent.getAgentAccess();
  1846. // if the region is PG, we're happy already, so do nothing
  1847. // but if we're set to avoid either mature or adult, get us outta here
  1848. if ((sim_access == SIM_ACCESS_MATURE) &&
  1849. !agent_access.canAccessMature())
  1850. {
  1851. return false;
  1852. }
  1853. else if ((sim_access == SIM_ACCESS_ADULT) &&
  1854. !agent_access.canAccessAdult())
  1855. {
  1856. return false;
  1857. }
  1858. }
  1859. bool isForSale = parcel->getForSale()
  1860. && ((parcel->getSalePrice() > 0) || (authorizeBuyer.notNull()));
  1861. bool isEmpowered
  1862. = forGroup ? gAgent.hasPowerInActiveGroup(GP_LAND_DEED) == TRUE : true;
  1863. bool isOwner
  1864. = parcelOwner == (forGroup ? gAgent.getGroupID() : gAgent.getID());
  1865. bool isAuthorized
  1866. = (authorizeBuyer.isNull()
  1867. || (gAgent.getID() == authorizeBuyer)
  1868. || (gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_DEED)
  1869. && gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_SET_SALE_INFO)));
  1870. return isForSale && !isOwner && isAuthorized && isEmpowered;
  1871. }
  1872. void LLViewerParcelMgr::startBuyLand(BOOL is_for_group)
  1873. {
  1874. LLFloaterBuyLand::buyLand(getSelectionRegion(), mCurrentParcelSelection, is_for_group == TRUE);
  1875. }
  1876. void LLViewerParcelMgr::startSellLand()
  1877. {
  1878. LLFloaterSellLand::sellLand(getSelectionRegion(), mCurrentParcelSelection);
  1879. }
  1880. void LLViewerParcelMgr::startDivideLand()
  1881. {
  1882. if (!mSelected)
  1883. {
  1884. LLNotificationsUtil::add("CannotDivideLandNothingSelected");
  1885. return;
  1886. }
  1887. if (mCurrentParcelSelection->mWholeParcelSelected)
  1888. {
  1889. LLNotificationsUtil::add("CannotDivideLandPartialSelection");
  1890. return;
  1891. }
  1892. LLSD payload;
  1893. payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth);
  1894. payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth);
  1895. LLNotificationsUtil::add("LandDivideWarning", LLSD(), payload, callbackDivideLand);
  1896. }
  1897. // static
  1898. bool LLViewerParcelMgr::callbackDivideLand(const LLSD& notification, const LLSD& response)
  1899. {
  1900. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1901. LLVector3d west_south_d = ll_vector3d_from_sd(notification["payload"]["west_south_border"]);
  1902. LLVector3d east_north_d = ll_vector3d_from_sd(notification["payload"]["east_north_border"]);
  1903. LLVector3d parcel_center = (west_south_d + east_north_d) / 2.0;
  1904. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
  1905. if (!region)
  1906. {
  1907. LLNotificationsUtil::add("CannotDivideLandNoRegion");
  1908. return false;
  1909. }
  1910. if (0 == option)
  1911. {
  1912. LLVector3 west_south = region->getPosRegionFromGlobal(west_south_d);
  1913. LLVector3 east_north = region->getPosRegionFromGlobal(east_north_d);
  1914. LLMessageSystem* msg = gMessageSystem;
  1915. msg->newMessage("ParcelDivide");
  1916. msg->nextBlock("AgentData");
  1917. msg->addUUID("AgentID", gAgent.getID());
  1918. msg->addUUID("SessionID", gAgent.getSessionID());
  1919. msg->nextBlock("ParcelData");
  1920. msg->addF32("West", west_south.mV[VX]);
  1921. msg->addF32("South", west_south.mV[VY]);
  1922. msg->addF32("East", east_north.mV[VX]);
  1923. msg->addF32("North", east_north.mV[VY]);
  1924. msg->sendReliable(region->getHost());
  1925. }
  1926. return false;
  1927. }
  1928. void LLViewerParcelMgr::startJoinLand()
  1929. {
  1930. if (!mSelected)
  1931. {
  1932. LLNotificationsUtil::add("CannotJoinLandNothingSelected");
  1933. return;
  1934. }
  1935. if (mCurrentParcelSelection->mWholeParcelSelected)
  1936. {
  1937. LLNotificationsUtil::add("CannotJoinLandEntireParcelSelected");
  1938. return;
  1939. }
  1940. if (!mCurrentParcelSelection->mSelectedMultipleOwners)
  1941. {
  1942. LLNotificationsUtil::add("CannotJoinLandSelection");
  1943. return;
  1944. }
  1945. LLSD payload;
  1946. payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth);
  1947. payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth);
  1948. LLNotificationsUtil::add("JoinLandWarning", LLSD(), payload, callbackJoinLand);
  1949. }
  1950. // static
  1951. bool LLViewerParcelMgr::callbackJoinLand(const LLSD& notification, const LLSD& response)
  1952. {
  1953. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1954. LLVector3d west_south_d = ll_vector3d_from_sd(notification["payload"]["west_south_border"]);
  1955. LLVector3d east_north_d = ll_vector3d_from_sd(notification["payload"]["east_north_border"]);
  1956. LLVector3d parcel_center = (west_south_d + east_north_d) / 2.0;
  1957. LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
  1958. if (!region)
  1959. {
  1960. LLNotificationsUtil::add("CannotJoinLandNoRegion");
  1961. return false;
  1962. }
  1963. if (0 == option)
  1964. {
  1965. LLVector3 west_south = region->getPosRegionFromGlobal(west_south_d);
  1966. LLVector3 east_north = region->getPosRegionFromGlobal(east_north_d);
  1967. LLMessageSystem* msg = gMessageSystem;
  1968. msg->newMessage("ParcelJoin");
  1969. msg->nextBlock("AgentData");
  1970. msg->addUUID("AgentID", gAgent.getID());
  1971. msg->addUUID("SessionID", gAgent.getSessionID());
  1972. msg->nextBlock("ParcelData");
  1973. msg->add