LandObject.cs 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Reflection;
  30. using log4net;
  31. using OpenMetaverse;
  32. using OpenSim.Framework;
  33. using OpenSim.Region.Framework.Interfaces;
  34. using OpenSim.Region.Framework.Scenes;
  35. using RegionFlags = OpenMetaverse.RegionFlags;
  36. namespace OpenSim.Region.CoreModules.World.Land
  37. {
  38. /// <summary>
  39. /// Keeps track of a specific piece of land's information
  40. /// </summary>
  41. public class LandObject : ILandObject
  42. {
  43. #region Member Variables
  44. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  45. private static readonly string LogHeader = "[LAND OBJECT]";
  46. private readonly int landUnit = 4;
  47. private int m_lastSeqId = 0;
  48. protected Scene m_scene;
  49. protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
  50. protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
  51. protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
  52. protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
  53. public bool[,] LandBitmap { get; set; }
  54. #endregion
  55. public int GetPrimsFree()
  56. {
  57. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  58. int free = GetSimulatorMaxPrimCount() - LandData.SimwidePrims;
  59. return free;
  60. }
  61. public LandData LandData { get; set; }
  62. public IPrimCounts PrimCounts { get; set; }
  63. public UUID RegionUUID
  64. {
  65. get { return m_scene.RegionInfo.RegionID; }
  66. }
  67. public Vector3 StartPoint
  68. {
  69. get
  70. {
  71. for (int y = 0; y < LandBitmap.GetLength(1); y++)
  72. {
  73. for (int x = 0; x < LandBitmap.GetLength(0); x++)
  74. {
  75. if (LandBitmap[x, y])
  76. return new Vector3(x * landUnit, y * landUnit, 0);
  77. }
  78. }
  79. m_log.ErrorFormat("{0} StartPoint. No start point found. bitmapSize=<{1},{2}>",
  80. LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
  81. return new Vector3(-1, -1, -1);
  82. }
  83. }
  84. public Vector3 EndPoint
  85. {
  86. get
  87. {
  88. for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
  89. {
  90. for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
  91. {
  92. if (LandBitmap[x, y])
  93. {
  94. return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
  95. }
  96. }
  97. }
  98. m_log.ErrorFormat("{0} EndPoint. No end point found. bitmapSize=<{1},{2}>",
  99. LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
  100. return new Vector3(-1, -1, -1);
  101. }
  102. }
  103. #region Constructors
  104. public LandObject(LandData landData, Scene scene)
  105. {
  106. LandData = landData.Copy();
  107. m_scene = scene;
  108. }
  109. public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
  110. {
  111. m_scene = scene;
  112. if (m_scene == null)
  113. LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
  114. else
  115. LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
  116. LandData = new LandData();
  117. LandData.OwnerID = owner_id;
  118. if (is_group_owned)
  119. LandData.GroupID = owner_id;
  120. else
  121. LandData.GroupID = UUID.Zero;
  122. LandData.IsGroupOwned = is_group_owned;
  123. }
  124. #endregion
  125. #region Member Functions
  126. #region General Functions
  127. /// <summary>
  128. /// Checks to see if this land object contains a point
  129. /// </summary>
  130. /// <param name="x"></param>
  131. /// <param name="y"></param>
  132. /// <returns>Returns true if the piece of land contains the specified point</returns>
  133. public bool ContainsPoint(int x, int y)
  134. {
  135. if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
  136. {
  137. return LandBitmap[x / landUnit, y / landUnit];
  138. }
  139. else
  140. {
  141. return false;
  142. }
  143. }
  144. public ILandObject Copy()
  145. {
  146. ILandObject newLand = new LandObject(LandData, m_scene);
  147. newLand.LandBitmap = (bool[,]) (LandBitmap.Clone());
  148. return newLand;
  149. }
  150. static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
  151. static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
  152. public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
  153. {
  154. overrideParcelMaxPrimCount = overrideDel;
  155. }
  156. public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
  157. {
  158. overrideSimulatorMaxPrimCount = overrideDel;
  159. }
  160. public int GetParcelMaxPrimCount()
  161. {
  162. if (overrideParcelMaxPrimCount != null)
  163. {
  164. return overrideParcelMaxPrimCount(this);
  165. }
  166. else
  167. {
  168. // Normal Calculations
  169. int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
  170. * (float)m_scene.RegionInfo.ObjectCapacity
  171. * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
  172. // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL!
  173. return parcelMax;
  174. }
  175. }
  176. public int GetSimulatorMaxPrimCount()
  177. {
  178. if (overrideSimulatorMaxPrimCount != null)
  179. {
  180. return overrideSimulatorMaxPrimCount(this);
  181. }
  182. else
  183. {
  184. //Normal Calculations
  185. int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
  186. * (float)m_scene.RegionInfo.ObjectCapacity);
  187. return simMax;
  188. }
  189. }
  190. #endregion
  191. #region Packet Request Handling
  192. public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
  193. {
  194. IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
  195. // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
  196. uint regionFlags = (uint)(RegionFlags.PublicAllowed
  197. | RegionFlags.AllowDirectTeleport
  198. | RegionFlags.AllowParcelChanges
  199. | RegionFlags.AllowVoice );
  200. if (estateModule != null)
  201. regionFlags = estateModule.GetRegionFlags();
  202. int seq_id;
  203. if (snap_selection && (sequence_id == 0))
  204. {
  205. seq_id = m_lastSeqId;
  206. }
  207. else
  208. {
  209. seq_id = sequence_id;
  210. m_lastSeqId = seq_id;
  211. }
  212. remote_client.SendLandProperties(seq_id,
  213. snap_selection, request_result, this,
  214. (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
  215. GetParcelMaxPrimCount(),
  216. GetSimulatorMaxPrimCount(), regionFlags);
  217. }
  218. public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
  219. {
  220. //Needs later group support
  221. bool snap_selection = false;
  222. LandData newData = LandData.Copy();
  223. uint allowedDelta = 0;
  224. // These two are always blocked as no client can set them anyway
  225. // ParcelFlags.ForSaleObjects
  226. // ParcelFlags.LindenHome
  227. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
  228. {
  229. allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
  230. ParcelFlags.AllowTerraform |
  231. ParcelFlags.AllowDamage |
  232. ParcelFlags.CreateObjects |
  233. ParcelFlags.RestrictPushObject |
  234. ParcelFlags.AllowOtherScripts |
  235. ParcelFlags.AllowGroupScripts |
  236. ParcelFlags.CreateGroupObjects |
  237. ParcelFlags.AllowAPrimitiveEntry |
  238. ParcelFlags.AllowGroupObjectEntry |
  239. ParcelFlags.AllowFly);
  240. }
  241. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale))
  242. {
  243. if (args.AuthBuyerID != newData.AuthBuyerID ||
  244. args.SalePrice != newData.SalePrice)
  245. {
  246. snap_selection = true;
  247. }
  248. newData.AuthBuyerID = args.AuthBuyerID;
  249. newData.SalePrice = args.SalePrice;
  250. if (!LandData.IsGroupOwned)
  251. {
  252. newData.GroupID = args.GroupID;
  253. allowedDelta |= (uint)(ParcelFlags.AllowDeedToGroup |
  254. ParcelFlags.ContributeWithDeed |
  255. ParcelFlags.SellParcelObjects);
  256. }
  257. allowedDelta |= (uint)ParcelFlags.ForSale;
  258. }
  259. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces))
  260. {
  261. newData.Category = args.Category;
  262. allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
  263. ParcelFlags.AllowPublish |
  264. ParcelFlags.MaturePublish);
  265. }
  266. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity))
  267. {
  268. newData.Description = args.Desc;
  269. newData.Name = args.Name;
  270. newData.SnapshotID = args.SnapshotID;
  271. }
  272. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint))
  273. {
  274. newData.LandingType = args.LandingType;
  275. newData.UserLocation = args.UserLocation;
  276. newData.UserLookAt = args.UserLookAt;
  277. }
  278. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia))
  279. {
  280. newData.MediaAutoScale = args.MediaAutoScale;
  281. newData.MediaID = args.MediaID;
  282. newData.MediaURL = args.MediaURL;
  283. newData.MusicURL = args.MusicURL;
  284. newData.MediaType = args.MediaType;
  285. newData.MediaDescription = args.MediaDescription;
  286. newData.MediaWidth = args.MediaWidth;
  287. newData.MediaHeight = args.MediaHeight;
  288. newData.MediaLoop = args.MediaLoop;
  289. newData.ObscureMusic = args.ObscureMusic;
  290. newData.ObscureMedia = args.ObscureMedia;
  291. allowedDelta |= (uint)(ParcelFlags.SoundLocal |
  292. ParcelFlags.UrlWebPage |
  293. ParcelFlags.UrlRawHtml |
  294. ParcelFlags.AllowVoiceChat |
  295. ParcelFlags.UseEstateVoiceChan);
  296. }
  297. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses))
  298. {
  299. newData.PassHours = args.PassHours;
  300. newData.PassPrice = args.PassPrice;
  301. allowedDelta |= (uint)ParcelFlags.UsePassList;
  302. }
  303. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed))
  304. {
  305. allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
  306. ParcelFlags.UseAccessList);
  307. }
  308. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned))
  309. {
  310. allowedDelta |= (uint)(ParcelFlags.UseBanList |
  311. ParcelFlags.DenyAnonymous |
  312. ParcelFlags.DenyAgeUnverified);
  313. }
  314. if (allowedDelta != (uint)ParcelFlags.None)
  315. {
  316. uint preserve = LandData.Flags & ~allowedDelta;
  317. newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
  318. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  319. SendLandUpdateToAvatarsOverMe(snap_selection);
  320. }
  321. }
  322. public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
  323. {
  324. LandData newData = LandData.Copy();
  325. newData.OwnerID = avatarID;
  326. newData.GroupID = groupID;
  327. newData.IsGroupOwned = groupOwned;
  328. //newData.auctionID = AuctionID;
  329. newData.ClaimDate = Util.UnixTimeSinceEpoch();
  330. newData.ClaimPrice = claimprice;
  331. newData.SalePrice = 0;
  332. newData.AuthBuyerID = UUID.Zero;
  333. newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  334. bool sellObjects = (LandData.Flags & (uint)(ParcelFlags.SellParcelObjects)) != 0
  335. && !LandData.IsGroupOwned && !groupOwned;
  336. UUID previousOwner = LandData.OwnerID;
  337. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  338. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  339. SendLandUpdateToAvatarsOverMe(true);
  340. if (sellObjects) SellLandObjects(previousOwner);
  341. }
  342. public void DeedToGroup(UUID groupID)
  343. {
  344. LandData newData = LandData.Copy();
  345. newData.OwnerID = groupID;
  346. newData.GroupID = groupID;
  347. newData.IsGroupOwned = true;
  348. // Reset show in directory flag on deed
  349. newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  350. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  351. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  352. SendLandUpdateToAvatarsOverMe(true);
  353. }
  354. public bool IsEitherBannedOrRestricted(UUID avatar)
  355. {
  356. if (IsBannedFromLand(avatar))
  357. {
  358. return true;
  359. }
  360. else if (IsRestrictedFromLand(avatar))
  361. {
  362. return true;
  363. }
  364. return false;
  365. }
  366. public bool CanBeOnThisLand(UUID avatar, float posHeight)
  367. {
  368. if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar))
  369. {
  370. return false;
  371. }
  372. else if (IsRestrictedFromLand(avatar))
  373. {
  374. return false;
  375. }
  376. return true;
  377. }
  378. public bool HasGroupAccess(UUID avatar)
  379. {
  380. if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
  381. {
  382. ScenePresence sp;
  383. if (!m_scene.TryGetScenePresence(avatar, out sp))
  384. {
  385. bool isMember;
  386. if (m_groupMemberCache.TryGetValue(avatar, out isMember))
  387. {
  388. m_groupMemberCache.Update(avatar, isMember, m_groupMemberCacheTimeout);
  389. return isMember;
  390. }
  391. IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
  392. if (groupsModule == null)
  393. return false;
  394. GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar);
  395. if (membership == null || membership.Length == 0)
  396. {
  397. m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout);
  398. return false;
  399. }
  400. foreach (GroupMembershipData d in membership)
  401. {
  402. if (d.GroupID == LandData.GroupID)
  403. {
  404. m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout);
  405. return true;
  406. }
  407. }
  408. m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout);
  409. return false;
  410. }
  411. return sp.ControllingClient.IsGroupMember(LandData.GroupID);
  412. }
  413. return false;
  414. }
  415. public bool IsBannedFromLand(UUID avatar)
  416. {
  417. ExpireAccessList();
  418. if (m_scene.Permissions.IsAdministrator(avatar))
  419. return false;
  420. if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
  421. return false;
  422. if (avatar == LandData.OwnerID)
  423. return false;
  424. if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
  425. {
  426. if (LandData.ParcelAccessList.FindIndex(
  427. delegate(LandAccessEntry e)
  428. {
  429. if (e.AgentID == avatar && e.Flags == AccessList.Ban)
  430. return true;
  431. return false;
  432. }) != -1)
  433. {
  434. return true;
  435. }
  436. }
  437. return false;
  438. }
  439. public bool IsRestrictedFromLand(UUID avatar)
  440. {
  441. if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0)
  442. return false;
  443. if (m_scene.Permissions.IsAdministrator(avatar))
  444. return false;
  445. if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
  446. return false;
  447. if (avatar == LandData.OwnerID)
  448. return false;
  449. if (HasGroupAccess(avatar))
  450. return false;
  451. return !IsInLandAccessList(avatar);
  452. }
  453. public bool IsInLandAccessList(UUID avatar)
  454. {
  455. ExpireAccessList();
  456. if (LandData.ParcelAccessList.FindIndex(
  457. delegate(LandAccessEntry e)
  458. {
  459. if (e.AgentID == avatar && e.Flags == AccessList.Access)
  460. return true;
  461. return false;
  462. }) == -1)
  463. {
  464. return false;
  465. }
  466. return true;
  467. }
  468. public void SendLandUpdateToClient(IClientAPI remote_client)
  469. {
  470. SendLandProperties(0, false, 0, remote_client);
  471. }
  472. public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client)
  473. {
  474. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  475. SendLandProperties(0, snap_selection, 0, remote_client);
  476. }
  477. public void SendLandUpdateToAvatarsOverMe()
  478. {
  479. SendLandUpdateToAvatarsOverMe(false);
  480. }
  481. public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
  482. {
  483. m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
  484. {
  485. ILandObject over = null;
  486. try
  487. {
  488. over =
  489. m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
  490. Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
  491. }
  492. catch (Exception)
  493. {
  494. m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " +
  495. Math.Round(avatar.AbsolutePosition.Y));
  496. }
  497. if (over != null)
  498. {
  499. if (over.LandData.LocalID == LandData.LocalID)
  500. {
  501. if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) &&
  502. m_scene.RegionInfo.RegionSettings.AllowDamage)
  503. avatar.Invulnerable = false;
  504. else
  505. avatar.Invulnerable = true;
  506. SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
  507. }
  508. }
  509. });
  510. }
  511. #endregion
  512. #region AccessList Functions
  513. public List<LandAccessEntry> CreateAccessListArrayByFlag(AccessList flag)
  514. {
  515. ExpireAccessList();
  516. List<LandAccessEntry> list = new List<LandAccessEntry>();
  517. foreach (LandAccessEntry entry in LandData.ParcelAccessList)
  518. {
  519. if (entry.Flags == flag)
  520. list.Add(entry);
  521. }
  522. if (list.Count == 0)
  523. {
  524. LandAccessEntry e = new LandAccessEntry();
  525. e.AgentID = UUID.Zero;
  526. e.Flags = 0;
  527. e.Expires = 0;
  528. list.Add(e);
  529. }
  530. return list;
  531. }
  532. public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
  533. IClientAPI remote_client)
  534. {
  535. if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both)
  536. {
  537. List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access);
  538. remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID);
  539. }
  540. if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both)
  541. {
  542. List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban);
  543. remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID);
  544. }
  545. }
  546. public void UpdateAccessList(uint flags, UUID transactionID,
  547. int sequenceID, int sections,
  548. List<LandAccessEntry> entries,
  549. IClientAPI remote_client)
  550. {
  551. LandData newData = LandData.Copy();
  552. if ((!m_listTransactions.ContainsKey(flags)) ||
  553. m_listTransactions[flags] != transactionID)
  554. {
  555. m_listTransactions[flags] = transactionID;
  556. List<LandAccessEntry> toRemove =
  557. new List<LandAccessEntry>();
  558. foreach (LandAccessEntry entry in newData.ParcelAccessList)
  559. {
  560. if (entry.Flags == (AccessList)flags)
  561. toRemove.Add(entry);
  562. }
  563. foreach (LandAccessEntry entry in toRemove)
  564. {
  565. newData.ParcelAccessList.Remove(entry);
  566. }
  567. // Checked here because this will always be the first
  568. // and only packet in a transaction
  569. if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
  570. {
  571. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  572. return;
  573. }
  574. }
  575. foreach (LandAccessEntry entry in entries)
  576. {
  577. LandAccessEntry temp =
  578. new LandAccessEntry();
  579. temp.AgentID = entry.AgentID;
  580. temp.Expires = entry.Expires;
  581. temp.Flags = (AccessList)flags;
  582. newData.ParcelAccessList.Add(temp);
  583. }
  584. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  585. }
  586. #endregion
  587. #region Update Functions
  588. public void UpdateLandBitmapByteArray()
  589. {
  590. LandData.Bitmap = ConvertLandBitmapToBytes();
  591. }
  592. /// <summary>
  593. /// Update all settings in land such as area, bitmap byte array, etc
  594. /// </summary>
  595. public void ForceUpdateLandInfo()
  596. {
  597. UpdateAABBAndAreaValues();
  598. UpdateLandBitmapByteArray();
  599. }
  600. public void SetLandBitmapFromByteArray()
  601. {
  602. LandBitmap = ConvertBytesToLandBitmap();
  603. }
  604. /// <summary>
  605. /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
  606. /// </summary>
  607. private void UpdateAABBAndAreaValues()
  608. {
  609. int min_x = 10000;
  610. int min_y = 10000;
  611. int max_x = 0;
  612. int max_y = 0;
  613. int tempArea = 0;
  614. int x, y;
  615. for (x = 0; x < LandBitmap.GetLength(0); x++)
  616. {
  617. for (y = 0; y < LandBitmap.GetLength(1); y++)
  618. {
  619. if (LandBitmap[x, y] == true)
  620. {
  621. if (min_x > x) min_x = x;
  622. if (min_y > y) min_y = y;
  623. if (max_x < x) max_x = x;
  624. if (max_y < y) max_y = y;
  625. tempArea += landUnit * landUnit; //16sqm peice of land
  626. }
  627. }
  628. }
  629. int tx = min_x * landUnit;
  630. if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
  631. tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
  632. int ty = min_y * landUnit;
  633. if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
  634. ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
  635. LandData.AABBMin =
  636. new Vector3(
  637. (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
  638. tx = max_x * landUnit;
  639. if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
  640. tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
  641. ty = max_y * landUnit;
  642. if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
  643. ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
  644. LandData.AABBMax
  645. = new Vector3(
  646. (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
  647. LandData.Area = tempArea;
  648. }
  649. #endregion
  650. #region Land Bitmap Functions
  651. /// <summary>
  652. /// Sets the land's bitmap manually
  653. /// </summary>
  654. /// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
  655. public void SetLandBitmap(bool[,] bitmap)
  656. {
  657. LandBitmap = bitmap;
  658. // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
  659. ForceUpdateLandInfo();
  660. }
  661. /// <summary>
  662. /// Gets the land's bitmap manually
  663. /// </summary>
  664. /// <returns></returns>
  665. public bool[,] GetLandBitmap()
  666. {
  667. return LandBitmap;
  668. }
  669. public bool[,] BasicFullRegionLandBitmap()
  670. {
  671. return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
  672. }
  673. public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
  674. {
  675. // Empty bitmap for the whole region
  676. bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
  677. tempBitmap.Initialize();
  678. // Fill the bitmap square area specified by state and end
  679. tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
  680. // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>",
  681. // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1));
  682. return tempBitmap;
  683. }
  684. /// <summary>
  685. /// Change a land bitmap at within a square and set those points to a specific value
  686. /// </summary>
  687. /// <param name="land_bitmap"></param>
  688. /// <param name="start_x"></param>
  689. /// <param name="start_y"></param>
  690. /// <param name="end_x"></param>
  691. /// <param name="end_y"></param>
  692. /// <param name="set_value"></param>
  693. /// <returns></returns>
  694. public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
  695. bool set_value)
  696. {
  697. int x, y;
  698. for (y = 0; y < land_bitmap.GetLength(1); y++)
  699. {
  700. for (x = 0; x < land_bitmap.GetLength(0); x++)
  701. {
  702. if (x >= start_x / landUnit && x < end_x / landUnit
  703. && y >= start_y / landUnit && y < end_y / landUnit)
  704. {
  705. land_bitmap[x, y] = set_value;
  706. }
  707. }
  708. }
  709. // m_log.DebugFormat("{0} ModifyLandBitmapSquare. startXY=<{1},{2}>, endXY=<{3},{4}>, val={5}, landBitmapSize=<{6},{7}>",
  710. // LogHeader, start_x, start_y, end_x, end_y, set_value, land_bitmap.GetLength(0), land_bitmap.GetLength(1));
  711. return land_bitmap;
  712. }
  713. /// <summary>
  714. /// Join the true values of 2 bitmaps together
  715. /// </summary>
  716. /// <param name="bitmap_base"></param>
  717. /// <param name="bitmap_add"></param>
  718. /// <returns></returns>
  719. public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
  720. {
  721. if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
  722. || bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
  723. || bitmap_add.Rank != 2
  724. || bitmap_base.Rank != 2)
  725. {
  726. throw new Exception(
  727. String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
  728. LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
  729. );
  730. }
  731. int x, y;
  732. for (y = 0; y < bitmap_base.GetLength(1); y++)
  733. {
  734. for (x = 0; x < bitmap_add.GetLength(0); x++)
  735. {
  736. if (bitmap_add[x, y])
  737. {
  738. bitmap_base[x, y] = true;
  739. }
  740. }
  741. }
  742. return bitmap_base;
  743. }
  744. /// <summary>
  745. /// Converts the land bitmap to a packet friendly byte array
  746. /// </summary>
  747. /// <returns></returns>
  748. private byte[] ConvertLandBitmapToBytes()
  749. {
  750. byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
  751. byte tempByte = 0;
  752. int byteNum = 0;
  753. int i = 0;
  754. for (int y = 0; y < LandBitmap.GetLength(1); y++)
  755. {
  756. for (int x = 0; x < LandBitmap.GetLength(0); x++)
  757. {
  758. tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
  759. if (i % 8 == 0)
  760. {
  761. tempConvertArr[byteNum] = tempByte;
  762. tempByte = (byte) 0;
  763. i = 0;
  764. byteNum++;
  765. }
  766. }
  767. }
  768. // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>",
  769. // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
  770. return tempConvertArr;
  771. }
  772. private bool[,] ConvertBytesToLandBitmap()
  773. {
  774. bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
  775. tempConvertMap.Initialize();
  776. byte tempByte = 0;
  777. // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
  778. int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
  779. int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
  780. if (bitmapLen == 512)
  781. {
  782. // Legacy bitmap being passed in. Use the legacy region size
  783. // and only set the lower area of the larger region.
  784. xLen = (int)(Constants.RegionSize / landUnit);
  785. }
  786. // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
  787. int x = 0, y = 0;
  788. for (int i = 0; i < bitmapLen; i++)
  789. {
  790. tempByte = LandData.Bitmap[i];
  791. for (int bitNum = 0; bitNum < 8; bitNum++)
  792. {
  793. bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
  794. try
  795. {
  796. tempConvertMap[x, y] = bit;
  797. }
  798. catch (Exception)
  799. {
  800. m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
  801. }
  802. x++;
  803. if (x >= xLen)
  804. {
  805. x = 0;
  806. y++;
  807. }
  808. }
  809. }
  810. return tempConvertMap;
  811. }
  812. #endregion
  813. #region Object Select and Object Owner Listing
  814. public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
  815. {
  816. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
  817. {
  818. List<uint> resultLocalIDs = new List<uint>();
  819. try
  820. {
  821. lock (primsOverMe)
  822. {
  823. foreach (SceneObjectGroup obj in primsOverMe)
  824. {
  825. if (obj.LocalId > 0)
  826. {
  827. if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID)
  828. {
  829. resultLocalIDs.Add(obj.LocalId);
  830. }
  831. else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero)
  832. {
  833. resultLocalIDs.Add(obj.LocalId);
  834. }
  835. else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
  836. obj.OwnerID != remote_client.AgentId)
  837. {
  838. resultLocalIDs.Add(obj.LocalId);
  839. }
  840. else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
  841. {
  842. resultLocalIDs.Add(obj.LocalId);
  843. }
  844. }
  845. }
  846. }
  847. } catch (InvalidOperationException)
  848. {
  849. m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
  850. }
  851. remote_client.SendForceClientSelectObjects(resultLocalIDs);
  852. }
  853. }
  854. /// <summary>
  855. /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
  856. /// aggreagete details such as the number of prims.
  857. ///
  858. /// </summary>
  859. /// <param name="remote_client">
  860. /// A <see cref="IClientAPI"/>
  861. /// </param>
  862. public void SendLandObjectOwners(IClientAPI remote_client)
  863. {
  864. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
  865. {
  866. Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
  867. List<UUID> groups = new List<UUID>();
  868. lock (primsOverMe)
  869. {
  870. // m_log.DebugFormat(
  871. // "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region",
  872. // remote_client.Name, primsOverMe.Count);
  873. try
  874. {
  875. foreach (SceneObjectGroup obj in primsOverMe)
  876. {
  877. try
  878. {
  879. if (!primCount.ContainsKey(obj.OwnerID))
  880. {
  881. primCount.Add(obj.OwnerID, 0);
  882. }
  883. }
  884. catch (NullReferenceException)
  885. {
  886. m_log.Error("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
  887. }
  888. try
  889. {
  890. primCount[obj.OwnerID] += obj.PrimCount;
  891. }
  892. catch (KeyNotFoundException)
  893. {
  894. m_log.Error("[LAND]: Unable to match a prim with it's owner.");
  895. }
  896. if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID)))
  897. groups.Add(obj.OwnerID);
  898. }
  899. }
  900. catch (InvalidOperationException)
  901. {
  902. m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
  903. }
  904. }
  905. remote_client.SendLandObjectOwners(LandData, groups, primCount);
  906. }
  907. }
  908. public Dictionary<UUID, int> GetLandObjectOwners()
  909. {
  910. Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
  911. lock (primsOverMe)
  912. {
  913. try
  914. {
  915. foreach (SceneObjectGroup obj in primsOverMe)
  916. {
  917. if (!ownersAndCount.ContainsKey(obj.OwnerID))
  918. {
  919. ownersAndCount.Add(obj.OwnerID, 0);
  920. }
  921. ownersAndCount[obj.OwnerID] += obj.PrimCount;
  922. }
  923. }
  924. catch (InvalidOperationException)
  925. {
  926. m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
  927. }
  928. }
  929. return ownersAndCount;
  930. }
  931. #endregion
  932. #region Object Sales
  933. public void SellLandObjects(UUID previousOwner)
  934. {
  935. // m_log.DebugFormat(
  936. // "[LAND OBJECT]: Request to sell objects in {0} from {1}", LandData.Name, previousOwner);
  937. if (LandData.IsGroupOwned)
  938. return;
  939. IBuySellModule m_BuySellModule = m_scene.RequestModuleInterface<IBuySellModule>();
  940. if (m_BuySellModule == null)
  941. {
  942. m_log.Error("[LAND OBJECT]: BuySellModule not found");
  943. return;
  944. }
  945. ScenePresence sp;
  946. if (!m_scene.TryGetScenePresence(LandData.OwnerID, out sp))
  947. {
  948. m_log.Error("[LAND OBJECT]: New owner is not present in scene");
  949. return;
  950. }
  951. lock (primsOverMe)
  952. {
  953. foreach (SceneObjectGroup obj in primsOverMe)
  954. {
  955. if (obj.OwnerID == previousOwner && obj.GroupID == UUID.Zero &&
  956. (obj.GetEffectivePermissions() & (uint)(OpenSim.Framework.PermissionMask.Transfer)) != 0)
  957. m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0);
  958. }
  959. }
  960. }
  961. #endregion
  962. #region Object Returning
  963. public void ReturnObject(SceneObjectGroup obj)
  964. {
  965. SceneObjectGroup[] objs = new SceneObjectGroup[1];
  966. objs[0] = obj;
  967. m_scene.returnObjects(objs, obj.OwnerID);
  968. }
  969. public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
  970. {
  971. // m_log.DebugFormat(
  972. // "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name);
  973. Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>();
  974. lock (primsOverMe)
  975. {
  976. if (type == (uint)ObjectReturnType.Owner)
  977. {
  978. foreach (SceneObjectGroup obj in primsOverMe)
  979. {
  980. if (obj.OwnerID == LandData.OwnerID)
  981. {
  982. if (!returns.ContainsKey(obj.OwnerID))
  983. returns[obj.OwnerID] =
  984. new List<SceneObjectGroup>();
  985. returns[obj.OwnerID].Add(obj);
  986. }
  987. }
  988. }
  989. else if (type == (uint)ObjectReturnType.Group && LandData.GroupID != UUID.Zero)
  990. {
  991. foreach (SceneObjectGroup obj in primsOverMe)
  992. {
  993. if (obj.GroupID == LandData.GroupID)
  994. {
  995. if (!returns.ContainsKey(obj.OwnerID))
  996. returns[obj.OwnerID] =
  997. new List<SceneObjectGroup>();
  998. returns[obj.OwnerID].Add(obj);
  999. }
  1000. }
  1001. }
  1002. else if (type == (uint)ObjectReturnType.Other)
  1003. {
  1004. foreach (SceneObjectGroup obj in primsOverMe)
  1005. {
  1006. if (obj.OwnerID != LandData.OwnerID &&
  1007. (obj.GroupID != LandData.GroupID ||
  1008. LandData.GroupID == UUID.Zero))
  1009. {
  1010. if (!returns.ContainsKey(obj.OwnerID))
  1011. returns[obj.OwnerID] =
  1012. new List<SceneObjectGroup>();
  1013. returns[obj.OwnerID].Add(obj);
  1014. }
  1015. }
  1016. }
  1017. else if (type == (uint)ObjectReturnType.List)
  1018. {
  1019. List<UUID> ownerlist = new List<UUID>(owners);
  1020. foreach (SceneObjectGroup obj in primsOverMe)
  1021. {
  1022. if (ownerlist.Contains(obj.OwnerID))
  1023. {
  1024. if (!returns.ContainsKey(obj.OwnerID))
  1025. returns[obj.OwnerID] =
  1026. new List<SceneObjectGroup>();
  1027. returns[obj.OwnerID].Add(obj);
  1028. }
  1029. }
  1030. }
  1031. }
  1032. foreach (List<SceneObjectGroup> ol in returns.Values)
  1033. {
  1034. if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol))
  1035. m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
  1036. }
  1037. }
  1038. #endregion
  1039. #region Object Adding/Removing from Parcel
  1040. public void ResetOverMeRecord()
  1041. {
  1042. lock (primsOverMe)
  1043. primsOverMe.Clear();
  1044. }
  1045. public void AddPrimOverMe(SceneObjectGroup obj)
  1046. {
  1047. // m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name);
  1048. lock (primsOverMe)
  1049. primsOverMe.Add(obj);
  1050. }
  1051. public void RemovePrimFromOverMe(SceneObjectGroup obj)
  1052. {
  1053. // m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name);
  1054. lock (primsOverMe)
  1055. primsOverMe.Remove(obj);
  1056. }
  1057. #endregion
  1058. /// <summary>
  1059. /// Set the media url for this land parcel
  1060. /// </summary>
  1061. /// <param name="url"></param>
  1062. public void SetMediaUrl(string url)
  1063. {
  1064. LandData.MediaURL = url;
  1065. SendLandUpdateToAvatarsOverMe();
  1066. }
  1067. /// <summary>
  1068. /// Set the music url for this land parcel
  1069. /// </summary>
  1070. /// <param name="url"></param>
  1071. public void SetMusicUrl(string url)
  1072. {
  1073. LandData.MusicURL = url;
  1074. SendLandUpdateToAvatarsOverMe();
  1075. }
  1076. /// <summary>
  1077. /// Get the music url for this land parcel
  1078. /// </summary>
  1079. /// <returns>The music url.</returns>
  1080. public string GetMusicUrl()
  1081. {
  1082. return LandData.MusicURL;
  1083. }
  1084. #endregion
  1085. private void ExpireAccessList()
  1086. {
  1087. List<LandAccessEntry> delete = new List<LandAccessEntry>();
  1088. foreach (LandAccessEntry entry in LandData.ParcelAccessList)
  1089. {
  1090. if (entry.Expires != 0 && entry.Expires < Util.UnixTimeSinceEpoch())
  1091. delete.Add(entry);
  1092. }
  1093. foreach (LandAccessEntry entry in delete)
  1094. LandData.ParcelAccessList.Remove(entry);
  1095. if (delete.Count > 0)
  1096. m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this);
  1097. }
  1098. }
  1099. }