llparcel.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. /**
  2. * @file llparcel.cpp
  3. * @brief A land parcel.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include <iostream>
  34. #include <utility>
  35. #include "indra_constants.h"
  36. #include "llparcel.h"
  37. #include "llmath.h"
  38. #include "llregionflags.h"
  39. #include "llsd.h"
  40. #include "llsdutil.h"
  41. #include "llsdutil_math.h"
  42. #include "llstreamtools.h"
  43. #include "lltransactiontypes.h"
  44. #include "lltransactionflags.h"
  45. #include "llmessage.h"
  46. constexpr F32 SOME_BIG_NUMBER = 1000.f;
  47. constexpr F32 SOME_BIG_NEG_NUMBER = -1000.f;
  48. static const std::string PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT + 1] =
  49. {
  50. "leased",
  51. "lease_pending",
  52. "abandoned",
  53. "none"
  54. };
  55. // NOTE: Adding parcel categories also requires updating:
  56. // * floater_directory.xml category combobox
  57. // * floater_about_land.xml category combobox
  58. // * Web site "create event" tools
  59. // DO NOT DELETE ITEMS FROM THIS LIST WITHOUT DEEPLY UNDERSTANDING WHAT YOU ARE
  60. // DOING.
  61. //
  62. static const std::string PARCEL_CATEGORY_STRING[LLParcel::C_COUNT] =
  63. {
  64. "none",
  65. "linden",
  66. "adult",
  67. "arts",
  68. "store", // "business" legacy name
  69. "educational",
  70. "game", // "gaming" legacy name
  71. "gather", // "hangout" legacy name
  72. "newcomer",
  73. "park",
  74. "home", // "residential" legacy name
  75. "shopping",
  76. "stage",
  77. "other",
  78. "rental"
  79. };
  80. static const std::string PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] =
  81. {
  82. "None",
  83. "Linden location",
  84. "Adult",
  85. "Arts and culture",
  86. "Business",
  87. "Educational",
  88. "Gaming",
  89. "Hangout",
  90. "Newcomer friendly",
  91. "Parks and nature",
  92. "Residential",
  93. "Shopping",
  94. "Stage",
  95. "Other",
  96. "Rental",
  97. "Any", // valid string for parcel searches
  98. };
  99. static const std::string PARCEL_ACTION_STRING[LLParcel::A_COUNT + 1] =
  100. {
  101. "create",
  102. "release",
  103. "absorb",
  104. "absorbed",
  105. "divide",
  106. "division",
  107. "acquire",
  108. "relinquish",
  109. "confirm",
  110. "unknown"
  111. };
  112. const std::string& category_to_ui_string(LLParcel::ECategory category);
  113. LLParcel::ECategory category_ui_string_to_category(const std::string& s);
  114. LLParcel::LLParcel()
  115. {
  116. init(LLUUID::null, true, false, false, 0, 0, 0, 0, 0, 1.f, 0);
  117. }
  118. LLParcel::LLParcel(const LLUUID& owner_id,
  119. bool modify, bool terraform, bool damage,
  120. time_t claim_date, S32 claim_price_per_meter,
  121. S32 rent_price_per_meter, S32 area,
  122. S32 sim_object_limit, F32 parcel_object_bonus,
  123. bool is_group_owned)
  124. {
  125. init(owner_id, modify, terraform, damage, claim_date,
  126. claim_price_per_meter, rent_price_per_meter, area,
  127. sim_object_limit, parcel_object_bonus, is_group_owned);
  128. }
  129. void LLParcel::init(const LLUUID& owner_id,
  130. bool modify, bool terraform, bool damage,
  131. time_t claim_date, S32 claim_price_per_meter,
  132. S32 rent_price_per_meter, S32 area,
  133. S32 sim_object_limit, F32 parcel_object_bonus,
  134. bool is_group_owned)
  135. {
  136. mID.setNull();
  137. mOwnerID = owner_id;
  138. mGroupOwned = is_group_owned;
  139. mClaimDate = claim_date;
  140. mClaimPricePerMeter = claim_price_per_meter;
  141. mRentPricePerMeter = rent_price_per_meter;
  142. mArea = area;
  143. mDiscountRate = 1.f;
  144. mUserLookAt.set(0.f, 0.f, 0.f);
  145. // Default to using the parcel's landing point, if any.
  146. mLandingType = L_LANDING_POINT;
  147. // *FIX: if owner_id != null, should be owned or sale pending; investigate
  148. // init callers.
  149. mStatus = OS_NONE;
  150. mCategory = C_NONE;
  151. mAuthBuyerID.setNull();
  152. mGraceExtension = 0;
  153. mAuctionID = 0;
  154. mParcelFlags = PF_DEFAULT;
  155. setParcelFlag(PF_CREATE_OBJECTS, modify);
  156. setParcelFlag(PF_ALLOW_TERRAFORM, terraform);
  157. setParcelFlag(PF_ALLOW_DAMAGE, damage);
  158. mSalePrice = 10000;
  159. setName(LLStringUtil::null);
  160. setDesc(LLStringUtil::null);
  161. setMusicURL(LLStringUtil::null);
  162. setMediaURL(LLStringUtil::null);
  163. setMediaDesc(LLStringUtil::null);
  164. setMediaType(LLStringUtil::null);
  165. mMediaID.setNull();
  166. mMediaAutoScale = false;
  167. mMediaLoop = true;
  168. mMediaWidth = mMediaHeight = 0;
  169. setMediaCurrentURL(LLStringUtil::null);
  170. mMediaAllowNavigate = 1;
  171. mMediaPreventCameraZoom = 0;
  172. mMediaURLTimeout = 0.f;
  173. mGroupID.setNull();
  174. mPassPrice = PARCEL_PASS_PRICE_DEFAULT;
  175. mPassHours = PARCEL_PASS_HOURS_DEFAULT;
  176. mAABBMin.set(SOME_BIG_NUMBER, SOME_BIG_NUMBER, SOME_BIG_NUMBER);
  177. mAABBMax.set(SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER,
  178. SOME_BIG_NEG_NUMBER);
  179. mLocalID = INVALID_PARCEL_ID;
  180. setMaxPrimCapacity((S32)(sim_object_limit *
  181. area / (F32)(REGION_WIDTH_METERS *
  182. REGION_WIDTH_METERS)));
  183. mSimWideMaxPrimCapacity = mSimWidePrimCount = 0;
  184. mOwnerPrimCount = mGroupPrimCount = mOtherPrimCount = 0;
  185. mSelectedPrimCount = mTempPrimCount = 0;
  186. mCleanOtherTime = 0;
  187. mRegionPushOverride = mRegionDenyAnonymousOverride = false;
  188. mRegionDenyAgeUnverifiedOverride = false;
  189. mParcelPrimBonus = parcel_object_bonus;
  190. mPreviousOwnerID.setNull();
  191. mPreviouslyGroupOwned = false;
  192. mSeeAVs = mAllowGroupAVSounds = mAllowAnyAVSounds = true;
  193. mObscureMOAP = false;
  194. mHaveNewParcelLimitData = false;
  195. mRegionAllowEnvironmentOverride = false;
  196. mCurrentEnvironmentVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
  197. }
  198. void LLParcel::setName(const std::string& name)
  199. {
  200. // The escaping here must match the escaping in the database
  201. // abstraction layer.
  202. mName = name;
  203. LLStringFn::replace_nonprintable_in_ascii(mName, LL_UNKNOWN_CHAR);
  204. }
  205. void LLParcel::setDesc(const std::string& desc)
  206. {
  207. // The escaping here must match the escaping in the database
  208. // abstraction layer.
  209. mDesc = desc;
  210. mDesc = rawstr_to_utf8(mDesc);
  211. }
  212. void LLParcel::setMusicURL(const std::string& url)
  213. {
  214. mMusicURL = url;
  215. // The escaping here must match the escaping in the database
  216. // abstraction layer.
  217. // This should really filter the url in some way. Other than
  218. // simply requiring non-printable.
  219. LLStringFn::replace_nonprintable_in_ascii(mMusicURL, LL_UNKNOWN_CHAR);
  220. }
  221. void LLParcel::setMediaURL(const std::string& url)
  222. {
  223. mMediaURL = url;
  224. // The escaping here must match the escaping in the database
  225. // abstraction layer if it's ever added.
  226. // This should really filter the url in some way. Other than
  227. // simply requiring non-printable.
  228. LLStringFn::replace_nonprintable_in_ascii(mMediaURL, LL_UNKNOWN_CHAR);
  229. }
  230. void LLParcel::setMediaDesc(const std::string& desc)
  231. {
  232. // The escaping here must match the escaping in the database
  233. // abstraction layer.
  234. mMediaDesc = desc;
  235. mMediaDesc = rawstr_to_utf8(mMediaDesc);
  236. }
  237. void LLParcel::setMediaType(const std::string& type)
  238. {
  239. // The escaping here must match the escaping in the database
  240. // abstraction layer.
  241. mMediaType = type;
  242. mMediaType = rawstr_to_utf8(mMediaType);
  243. // This code attempts to preserve legacy movie functioning
  244. if (mMediaType.empty() && !mMediaURL.empty())
  245. {
  246. setMediaType(std::string("video/vnd.secondlife.qt.legacy"));
  247. }
  248. }
  249. void LLParcel::setMediaCurrentURL(const std::string& url)
  250. {
  251. mMediaCurrentURL = url;
  252. // The escaping here must match the escaping in the database abstraction
  253. // layer if it is ever added. This should really filter the url in some
  254. // way. Other than simply requiring non-printable.
  255. LLStringFn::replace_nonprintable_in_ascii(mMediaCurrentURL,
  256. LL_UNKNOWN_CHAR);
  257. }
  258. void LLParcel::setParcelFlag(U32 flag, bool b)
  259. {
  260. if (b)
  261. {
  262. mParcelFlags |= flag;
  263. }
  264. else
  265. {
  266. mParcelFlags &= ~flag;
  267. }
  268. }
  269. bool LLParcel::allowModifyBy(const LLUUID& agent_id,
  270. const LLUUID& group_id) const
  271. {
  272. if (agent_id.isNull())
  273. {
  274. // system always can enter
  275. return true;
  276. }
  277. else if (isPublic())
  278. {
  279. return true;
  280. }
  281. else if (agent_id == mOwnerID)
  282. {
  283. // owner can always perform operations
  284. return true;
  285. }
  286. else if (mParcelFlags & PF_CREATE_OBJECTS)
  287. {
  288. return true;
  289. }
  290. else if ((mParcelFlags & PF_CREATE_GROUP_OBJECTS) && group_id.notNull())
  291. {
  292. return (getGroupID() == group_id);
  293. }
  294. return false;
  295. }
  296. bool LLParcel::allowTerraformBy(const LLUUID& agent_id) const
  297. {
  298. if (agent_id.isNull())
  299. {
  300. // system always can enter
  301. return true;
  302. }
  303. else if (OS_LEASED == mStatus)
  304. {
  305. if (agent_id == mOwnerID)
  306. {
  307. // owner can modify leased land
  308. return true;
  309. }
  310. else
  311. {
  312. // otherwise check other people
  313. return mParcelFlags & PF_ALLOW_TERRAFORM;
  314. }
  315. }
  316. else
  317. {
  318. return false;
  319. }
  320. }
  321. //-----------------------------------------------------------
  322. // File input and output
  323. //-----------------------------------------------------------
  324. // Assumes we are in a block "ParcelData"
  325. void LLParcel::packMessage(LLMessageSystem* msg)
  326. {
  327. msg->addU32Fast(_PREHASH_ParcelFlags, mParcelFlags);
  328. msg->addS32Fast(_PREHASH_SalePrice, mSalePrice);
  329. msg->addStringFast(_PREHASH_Name, mName);
  330. msg->addStringFast(_PREHASH_Desc, mDesc);
  331. msg->addStringFast(_PREHASH_MusicURL, mMusicURL);
  332. msg->addStringFast(_PREHASH_MediaURL, mMediaURL);
  333. msg->addU8(_PREHASH_MediaAutoScale, U8(mMediaAutoScale));
  334. msg->addUUIDFast(_PREHASH_MediaID, getMediaID());
  335. msg->addUUIDFast(_PREHASH_GroupID, getGroupID());
  336. msg->addS32Fast(_PREHASH_PassPrice, mPassPrice);
  337. msg->addF32Fast(_PREHASH_PassHours, mPassHours);
  338. msg->addU8Fast(_PREHASH_Category, U8(mCategory));
  339. msg->addUUIDFast(_PREHASH_AuthBuyerID, mAuthBuyerID);
  340. msg->addUUIDFast(_PREHASH_SnapshotID, mSnapshotID);
  341. msg->addVector3Fast(_PREHASH_UserLocation, mUserLocation);
  342. msg->addVector3Fast(_PREHASH_UserLookAt, mUserLookAt);
  343. msg->addU8Fast(_PREHASH_LandingType, U8(mLandingType));
  344. }
  345. // Assumes we are in a block "ParcelData". Used in the viewer, the sim uses its
  346. // own packer.
  347. void LLParcel::packMessage(LLSD& msg)
  348. {
  349. msg["local_id"] = mLocalID;
  350. msg["parcel_flags"] = ll_sd_from_U32(mParcelFlags);
  351. msg["sale_price"] = mSalePrice;
  352. msg["name"] = mName;
  353. msg["description"] = mDesc;
  354. msg["music_url"] = mMusicURL;
  355. msg["media_url"] = mMediaURL;
  356. msg["media_desc"] = mMediaDesc;
  357. msg["media_type"] = mMediaType;
  358. msg["media_width"] = mMediaWidth;
  359. msg["media_height"] = mMediaHeight;
  360. msg["auto_scale"] = mMediaAutoScale;
  361. msg["media_loop"] = mMediaLoop;
  362. msg["media_current_url"] = mMediaCurrentURL;
  363. msg["obscure_media"] = false; // OBSOLETE - no longer used
  364. msg["obscure_music"] = false; // OBSOLETE - no longer used
  365. msg["media_id"] = mMediaID;
  366. msg["media_allow_navigate"] = mMediaAllowNavigate;
  367. msg["media_prevent_camera_zoom"] = mMediaPreventCameraZoom;
  368. msg["media_url_timeout"] = mMediaURLTimeout;
  369. msg["group_id"] = mGroupID;
  370. msg["pass_price"] = mPassPrice;
  371. msg["pass_hours"] = mPassHours;
  372. msg["category"] = (U8)mCategory;
  373. msg["auth_buyer_id"] = mAuthBuyerID;
  374. msg["snapshot_id"] = mSnapshotID;
  375. msg["user_location"] = ll_sd_from_vector3(mUserLocation);
  376. msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt);
  377. msg["landing_type"] = (U8)mLandingType;
  378. msg["see_avs"] = mSeeAVs;
  379. msg["group_av_sounds"] = mAllowGroupAVSounds;
  380. msg["any_av_sounds"] = mAllowAnyAVSounds;
  381. msg["obscure_moap"] = mObscureMOAP;
  382. }
  383. void LLParcel::unpackMessage(LLMessageSystem* msg)
  384. {
  385. std::string buffer;
  386. msg->getU32Fast(_PREHASH_ParcelData,_PREHASH_ParcelFlags, mParcelFlags);
  387. msg->getS32Fast(_PREHASH_ParcelData,_PREHASH_SalePrice, mSalePrice);
  388. msg->getStringFast(_PREHASH_ParcelData,_PREHASH_Name, buffer);
  389. setName(buffer);
  390. msg->getStringFast(_PREHASH_ParcelData,_PREHASH_Desc, buffer);
  391. setDesc(buffer);
  392. msg->getStringFast(_PREHASH_ParcelData,_PREHASH_MusicURL, buffer);
  393. setMusicURL(buffer);
  394. msg->getStringFast(_PREHASH_ParcelData,_PREHASH_MediaURL, buffer);
  395. setMediaURL(buffer);
  396. // All default to true for legacy server behavior:
  397. bool see_avs = true;
  398. bool any_av_sounds = true;
  399. bool group_av_sounds = true;
  400. // New version of server should send all 3 of these values:
  401. bool have_new_parcel_limit_data = msg->getSizeFast(_PREHASH_ParcelData,
  402. _PREHASH_SeeAVs) > 0;
  403. have_new_parcel_limit_data &= msg->getSizeFast(_PREHASH_ParcelData,
  404. _PREHASH_AnyAVSounds) > 0;
  405. have_new_parcel_limit_data &= msg->getSizeFast(_PREHASH_ParcelData,
  406. _PREHASH_GroupAVSounds) > 0;
  407. if (have_new_parcel_limit_data)
  408. {
  409. msg->getBoolFast(_PREHASH_ParcelData, _PREHASH_SeeAVs, see_avs);
  410. msg->getBoolFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds,
  411. any_av_sounds);
  412. msg->getBoolFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds,
  413. group_av_sounds);
  414. }
  415. setSeeAVs(see_avs);
  416. setAllowAnyAVSounds(any_av_sounds);
  417. setAllowGroupAVSounds(group_av_sounds);
  418. setHaveNewParcelLimitData(have_new_parcel_limit_data);
  419. // non-optimized version
  420. U8 temp;
  421. msg->getU8(_PREHASH_ParcelData, _PREHASH_MediaAutoScale, temp);
  422. mMediaAutoScale = (bool)temp;
  423. msg->getUUIDFast(_PREHASH_ParcelData,_PREHASH_MediaID, mMediaID);
  424. msg->getUUIDFast(_PREHASH_ParcelData,_PREHASH_GroupID, mGroupID);
  425. msg->getS32Fast(_PREHASH_ParcelData,_PREHASH_PassPrice, mPassPrice);
  426. msg->getF32Fast(_PREHASH_ParcelData,_PREHASH_PassHours, mPassHours);
  427. U8 category;
  428. msg->getU8Fast(_PREHASH_ParcelData,_PREHASH_Category, category);
  429. mCategory = (ECategory)category;
  430. msg->getUUIDFast(_PREHASH_ParcelData,_PREHASH_AuthBuyerID, mAuthBuyerID);
  431. msg->getUUIDFast(_PREHASH_ParcelData,_PREHASH_SnapshotID, mSnapshotID);
  432. msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLocation,
  433. mUserLocation);
  434. msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLookAt, mUserLookAt);
  435. U8 landing_type;
  436. msg->getU8Fast(_PREHASH_ParcelData,_PREHASH_LandingType, landing_type);
  437. mLandingType = (ELandingType)landing_type;
  438. // New Media Data
  439. // Note: the message has been converted to TCP
  440. if (msg->has(_PREHASH_MediaData))
  441. {
  442. msg->getString(_PREHASH_MediaData, _PREHASH_MediaDesc, buffer);
  443. setMediaDesc(buffer);
  444. msg->getString(_PREHASH_MediaData, _PREHASH_MediaType, buffer);
  445. setMediaType(buffer);
  446. msg->getS32(_PREHASH_MediaData, _PREHASH_MediaWidth, mMediaWidth);
  447. msg->getS32(_PREHASH_MediaData, _PREHASH_MediaHeight, mMediaHeight);
  448. U8 temp;
  449. msg->getU8(_PREHASH_MediaData, _PREHASH_MediaLoop, temp);
  450. mMediaLoop = (bool)temp;
  451. // The ObscureMedia and ObscureMusic flags previously set here are no
  452. // longer used
  453. }
  454. else
  455. {
  456. setMediaType(std::string("video/vnd.secondlife.qt.legacy"));
  457. setMediaDesc(std::string("No description available without server upgrade"));
  458. mMediaLoop = true;
  459. }
  460. if (msg->getNumberOfBlocks(_PREHASH_MediaLinkSharing) > 0)
  461. {
  462. msg->getString(_PREHASH_MediaLinkSharing, _PREHASH_MediaCurrentURL,
  463. buffer);
  464. setMediaCurrentURL(buffer);
  465. msg->getU8(_PREHASH_MediaLinkSharing, _PREHASH_MediaAllowNavigate,
  466. mMediaAllowNavigate);
  467. msg->getU8(_PREHASH_MediaLinkSharing, _PREHASH_MediaPreventCameraZoom,
  468. mMediaPreventCameraZoom);
  469. msg->getF32(_PREHASH_MediaLinkSharing, _PREHASH_MediaURLTimeout,
  470. mMediaURLTimeout);
  471. }
  472. else
  473. {
  474. setMediaCurrentURL(LLStringUtil::null);
  475. }
  476. }
  477. void LLParcel::unpackAccessEntries(LLMessageSystem* msg, access_map_t* list)
  478. {
  479. LLUUID id;
  480. S32 time;
  481. U32 flags;
  482. S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
  483. for (S32 i = 0; i < count; ++i)
  484. {
  485. msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
  486. msg->getS32Fast(_PREHASH_List, _PREHASH_Time, time, i);
  487. msg->getU32Fast(_PREHASH_List, _PREHASH_Flags, flags, i);
  488. if (id.notNull())
  489. {
  490. // C++11 is not the most limpid language... This whole
  491. // gymnastic with piecewise_construct and forward_as_tuple is
  492. // here to ensure LLAccessEntry is constructed emplace, and
  493. // not just the UUID key of the map.
  494. list->emplace(std::piecewise_construct,
  495. std::forward_as_tuple(id),
  496. std::forward_as_tuple(id, time, flags));
  497. }
  498. }
  499. }
  500. void LLParcel::unpackExperienceEntries(LLMessageSystem* msg, U32 type)
  501. {
  502. LLUUID id;
  503. for (S32 i = 0, count = msg->getNumberOfBlocksFast(_PREHASH_List);
  504. i < count; ++i)
  505. {
  506. msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
  507. if (id.notNull())
  508. {
  509. mExperienceKeys[id] = type;
  510. }
  511. }
  512. }
  513. access_map_t LLParcel::getExperienceKeysByType(U32 type) const
  514. {
  515. access_map_t access;
  516. LLAccessEntry entry;
  517. for (xp_type_map_t::const_iterator it = mExperienceKeys.begin(),
  518. end = mExperienceKeys.end();
  519. it != end; ++it)
  520. {
  521. if (it->second == type)
  522. {
  523. entry.mID = it->first;
  524. access.emplace(entry.mID, entry);
  525. }
  526. }
  527. return access;
  528. }
  529. void LLParcel::clearExperienceKeysByType(U32 type)
  530. {
  531. xp_type_map_t::iterator it = mExperienceKeys.begin();
  532. while (it != mExperienceKeys.end())
  533. {
  534. if (it->second == type)
  535. {
  536. mExperienceKeys.hmap_erase(it++);
  537. }
  538. else
  539. {
  540. ++it;
  541. }
  542. }
  543. }
  544. void LLParcel::setExperienceKeyType(const LLUUID& experience_key, U32 type)
  545. {
  546. if (type == EXPERIENCE_KEY_TYPE_NONE)
  547. {
  548. mExperienceKeys.erase(experience_key);
  549. }
  550. else if (countExperienceKeyType(type) < (U32)PARCEL_MAX_EXPERIENCE_LIST)
  551. {
  552. mExperienceKeys[experience_key] = type;
  553. }
  554. }
  555. U32 LLParcel::countExperienceKeyType(U32 type) const
  556. {
  557. U32 count = 0;
  558. for (xp_type_map_t::const_iterator it = mExperienceKeys.begin(),
  559. end = mExperienceKeys.end();
  560. it != end; ++it)
  561. {
  562. if (it->second == type)
  563. {
  564. ++count;
  565. }
  566. }
  567. return count;
  568. }
  569. bool LLParcel::operator==(const LLParcel& rhs) const
  570. {
  571. return mOwnerID == rhs.mOwnerID && mParcelFlags == rhs.mParcelFlags &&
  572. mClaimDate == rhs.mClaimDate &&
  573. mClaimPricePerMeter == rhs.mClaimPricePerMeter &&
  574. mRentPricePerMeter == rhs.mRentPricePerMeter;
  575. }
  576. // Calculates rent
  577. S32 LLParcel::getTotalRent() const
  578. {
  579. return (S32)floor(0.5f + (F32)mArea * (F32)mRentPricePerMeter *
  580. (1.f - mDiscountRate));
  581. }
  582. F32 LLParcel::getAdjustedRentPerMeter() const
  583. {
  584. return ((F32)mRentPricePerMeter * (1.f - mDiscountRate));
  585. }
  586. LLVector3 LLParcel::getCenterpoint() const
  587. {
  588. LLVector3 rv;
  589. rv.mV[VX] = (getAABBMin().mV[VX] + getAABBMax().mV[VX]) * 0.5f;
  590. rv.mV[VY] = (getAABBMin().mV[VY] + getAABBMax().mV[VY]) * 0.5f;
  591. rv.mV[VZ] = 0.f;
  592. return rv;
  593. }
  594. bool LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
  595. {
  596. if (mAccessList.size() >= (U32)PARCEL_MAX_ACCESS_LIST)
  597. {
  598. return false;
  599. }
  600. if (agent_id == getOwnerID())
  601. {
  602. // Cannot add owner to these lists
  603. return false;
  604. }
  605. access_map_t::iterator itor = mAccessList.begin();
  606. while (itor != mAccessList.end())
  607. {
  608. const LLAccessEntry& entry = itor->second;
  609. if (entry.mID == agent_id)
  610. {
  611. if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
  612. {
  613. mAccessList.hmap_erase(itor++);
  614. }
  615. else
  616. {
  617. LL_DEBUGS("ParcelAccess") << "Agent " << agent_id
  618. << " already in access list ("
  619. << (time ? "temporary" : "permanent")
  620. << " access)." << LL_ENDL;
  621. // Existing one expires later
  622. return false;
  623. }
  624. }
  625. else
  626. {
  627. ++itor;
  628. }
  629. }
  630. removeFromBanList(agent_id);
  631. LL_DEBUGS("ParcelAccess") << "Adding agent " << agent_id << " to access list ("
  632. << (time ? "temporary" : "permanent")
  633. << " access)." << LL_ENDL;
  634. LLAccessEntry new_entry;
  635. new_entry.mID = agent_id;
  636. new_entry.mTime = time;
  637. new_entry.mFlags = 0x0;
  638. mAccessList[agent_id] = new_entry;
  639. return true;
  640. }
  641. bool LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
  642. {
  643. if (mBanList.size() >= (U32)PARCEL_MAX_ACCESS_LIST)
  644. {
  645. // Not using ban list, so not a rational thing to do
  646. return false;
  647. }
  648. if (agent_id == getOwnerID())
  649. {
  650. // Cannot add owner to these lists
  651. return false;
  652. }
  653. access_map_t::iterator itor = mBanList.begin();
  654. while (itor != mBanList.end())
  655. {
  656. const LLAccessEntry& entry = itor->second;
  657. if (entry.mID == agent_id)
  658. {
  659. if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
  660. {
  661. mBanList.hmap_erase(itor++);
  662. }
  663. else
  664. {
  665. LL_DEBUGS("ParcelAccess") << "Agent " << agent_id
  666. << " already in ban list ("
  667. << (time ? "temporary" : "permanent")
  668. << " ban)." << LL_ENDL;
  669. // Existing one expires later
  670. return false;
  671. }
  672. }
  673. else
  674. {
  675. ++itor;
  676. }
  677. }
  678. removeFromAccessList(agent_id);
  679. LL_DEBUGS("ParcelAccess") << "Adding agent " << agent_id << " to ban list ("
  680. << (time ? "temporary" : "permanent") << " ban)."
  681. << LL_ENDL;
  682. LLAccessEntry new_entry;
  683. new_entry.mID = agent_id;
  684. new_entry.mTime = time;
  685. new_entry.mFlags = 0x0;
  686. mBanList[agent_id] = new_entry;
  687. return true;
  688. }
  689. bool remove_from_access_array(access_map_t* list, const LLUUID& agent_id)
  690. {
  691. bool removed = false;
  692. access_map_t::iterator it = list->begin();
  693. while (it != list->end())
  694. {
  695. const LLAccessEntry& entry = it->second;
  696. if (entry.mID == agent_id)
  697. {
  698. list->hmap_erase(it++);
  699. removed = true;
  700. }
  701. else
  702. {
  703. ++it;
  704. }
  705. }
  706. return removed;
  707. }
  708. bool LLParcel::removeFromAccessList(const LLUUID& agent_id)
  709. {
  710. return remove_from_access_array(&mAccessList, agent_id);
  711. }
  712. bool LLParcel::removeFromBanList(const LLUUID& agent_id)
  713. {
  714. return remove_from_access_array(&mBanList, agent_id);
  715. }
  716. //static
  717. const std::string& LLParcel::getOwnershipStatusString(EOwnershipStatus status)
  718. {
  719. return ownership_status_to_string(status);
  720. }
  721. //static
  722. const std::string& LLParcel::getCategoryString(ECategory category)
  723. {
  724. return category_to_string(category);
  725. }
  726. //static
  727. const std::string& LLParcel::getCategoryUIString(ECategory category)
  728. {
  729. return category_to_ui_string(category);
  730. }
  731. //static
  732. LLParcel::ECategory LLParcel::getCategoryFromString(const std::string& string)
  733. {
  734. return category_string_to_category(string);
  735. }
  736. //static
  737. LLParcel::ECategory LLParcel::getCategoryFromUIString(const std::string& string)
  738. {
  739. return category_ui_string_to_category(string);
  740. }
  741. //static
  742. const std::string& LLParcel::getActionString(LLParcel::EAction action)
  743. {
  744. S32 index = 0;
  745. if (action >= 0 && action < LLParcel::A_COUNT)
  746. {
  747. index = action;
  748. }
  749. else
  750. {
  751. index = A_COUNT;
  752. }
  753. return PARCEL_ACTION_STRING[index];
  754. }
  755. void LLParcel::dump()
  756. {
  757. llinfos << "Parcel: " << mLocalID << " - Area: " << mArea << " - Name: "
  758. << mName << " - Description: " << mDesc << llendl;
  759. }
  760. const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status)
  761. {
  762. if (status >= 0 && status < LLParcel::OS_COUNT)
  763. {
  764. return PARCEL_OWNERSHIP_STATUS_STRING[status];
  765. }
  766. return PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT];
  767. }
  768. LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s)
  769. {
  770. for (S32 i = 0; i < LLParcel::OS_COUNT; ++i)
  771. {
  772. if (s == PARCEL_OWNERSHIP_STATUS_STRING[i])
  773. {
  774. return (LLParcel::EOwnershipStatus)i;
  775. }
  776. }
  777. return LLParcel::OS_NONE;
  778. }
  779. const std::string& category_to_string(LLParcel::ECategory category)
  780. {
  781. S32 index = 0;
  782. if (category >= 0 && category < LLParcel::C_COUNT)
  783. {
  784. index = category;
  785. }
  786. return PARCEL_CATEGORY_STRING[index];
  787. }
  788. const std::string& category_to_ui_string(LLParcel::ECategory category)
  789. {
  790. S32 index = 0;
  791. if (category >= 0 && category < LLParcel::C_COUNT)
  792. {
  793. index = category;
  794. }
  795. else
  796. {
  797. // C_ANY = -1 , but the "Any" string is at the end of the list
  798. index = (S32)LLParcel::C_COUNT;
  799. }
  800. return PARCEL_CATEGORY_UI_STRING[index];
  801. }
  802. LLParcel::ECategory category_string_to_category(const std::string& s)
  803. {
  804. if (s.empty())
  805. {
  806. return LLParcel::C_NONE;
  807. }
  808. for (S32 i = 0; i < LLParcel::C_COUNT; ++i)
  809. {
  810. if (s == PARCEL_CATEGORY_STRING[i])
  811. {
  812. return (LLParcel::ECategory)i;
  813. }
  814. }
  815. llwarns << "Parcel category outside of possibilities: " << s << llendl;
  816. return LLParcel::C_NONE;
  817. }
  818. LLParcel::ECategory category_ui_string_to_category(const std::string& s)
  819. {
  820. for (S32 i = 0; i < LLParcel::C_COUNT; ++i)
  821. {
  822. if (s == PARCEL_CATEGORY_UI_STRING[i])
  823. {
  824. return (LLParcel::ECategory)i;
  825. }
  826. }
  827. // "Any" is a valid category for searches, and is a distinct option from
  828. // "None" and "Other"
  829. return LLParcel::C_ANY;
  830. }