LandObject.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  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. namespace OpenSim.Region.CoreModules.World.Land
  36. {
  37. /// <summary>
  38. /// Keeps track of a specific piece of land's information
  39. /// </summary>
  40. public class LandObject : ILandObject
  41. {
  42. #region Member Variables
  43. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  44. #pragma warning disable 0429
  45. private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
  46. #pragma warning restore 0429
  47. private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
  48. private int m_lastSeqId = 0;
  49. protected LandData m_landData = new LandData();
  50. protected Scene m_scene;
  51. protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
  52. protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
  53. public bool[,] LandBitmap
  54. {
  55. get { return m_landBitmap; }
  56. set { m_landBitmap = value; }
  57. }
  58. #endregion
  59. public int GetPrimsFree()
  60. {
  61. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  62. int free = GetSimulatorMaxPrimCount() - m_landData.SimwidePrims;
  63. return free;
  64. }
  65. public LandData LandData
  66. {
  67. get { return m_landData; }
  68. set { m_landData = value; }
  69. }
  70. public IPrimCounts PrimCounts { get; set; }
  71. public UUID RegionUUID
  72. {
  73. get { return m_scene.RegionInfo.RegionID; }
  74. }
  75. public Vector3 StartPoint
  76. {
  77. get
  78. {
  79. for (int y = 0; y < landArrayMax; y++)
  80. {
  81. for (int x = 0; x < landArrayMax; x++)
  82. {
  83. if (LandBitmap[x, y])
  84. return new Vector3(x * 4, y * 4, 0);
  85. }
  86. }
  87. return new Vector3(-1, -1, -1);
  88. }
  89. }
  90. public Vector3 EndPoint
  91. {
  92. get
  93. {
  94. for (int y = landArrayMax - 1; y >= 0; y--)
  95. {
  96. for (int x = landArrayMax - 1; x >= 0; x--)
  97. {
  98. if (LandBitmap[x, y])
  99. {
  100. return new Vector3(x * 4, y * 4, 0);
  101. }
  102. }
  103. }
  104. return new Vector3(-1, -1, -1);
  105. }
  106. }
  107. #region Constructors
  108. public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
  109. {
  110. m_scene = scene;
  111. LandData.OwnerID = owner_id;
  112. if (is_group_owned)
  113. LandData.GroupID = owner_id;
  114. else
  115. LandData.GroupID = UUID.Zero;
  116. LandData.IsGroupOwned = is_group_owned;
  117. }
  118. #endregion
  119. #region Member Functions
  120. #region General Functions
  121. /// <summary>
  122. /// Checks to see if this land object contains a point
  123. /// </summary>
  124. /// <param name="x"></param>
  125. /// <param name="y"></param>
  126. /// <returns>Returns true if the piece of land contains the specified point</returns>
  127. public bool ContainsPoint(int x, int y)
  128. {
  129. if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize)
  130. {
  131. return (LandBitmap[x / 4, y / 4] == true);
  132. }
  133. else
  134. {
  135. return false;
  136. }
  137. }
  138. public ILandObject Copy()
  139. {
  140. ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene);
  141. //Place all new variables here!
  142. newLand.LandBitmap = (bool[,]) (LandBitmap.Clone());
  143. newLand.LandData = LandData.Copy();
  144. return newLand;
  145. }
  146. static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
  147. static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
  148. public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
  149. {
  150. overrideParcelMaxPrimCount = overrideDel;
  151. }
  152. public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
  153. {
  154. overrideSimulatorMaxPrimCount = overrideDel;
  155. }
  156. public int GetParcelMaxPrimCount()
  157. {
  158. if (overrideParcelMaxPrimCount != null)
  159. {
  160. return overrideParcelMaxPrimCount(this);
  161. }
  162. else
  163. {
  164. // Normal Calculations
  165. int parcelMax = (int)(((float)LandData.Area / 65536.0f)
  166. * (float)m_scene.RegionInfo.ObjectCapacity
  167. * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
  168. // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL!
  169. return parcelMax;
  170. }
  171. }
  172. public int GetSimulatorMaxPrimCount()
  173. {
  174. if (overrideSimulatorMaxPrimCount != null)
  175. {
  176. return overrideSimulatorMaxPrimCount(this);
  177. }
  178. else
  179. {
  180. //Normal Calculations
  181. int simMax = (int)(((float)LandData.SimwideArea / 65536.0f)
  182. * (float)m_scene.RegionInfo.ObjectCapacity);
  183. return simMax;
  184. }
  185. }
  186. #endregion
  187. #region Packet Request Handling
  188. public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
  189. {
  190. IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
  191. uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
  192. if (estateModule != null)
  193. regionFlags = estateModule.GetRegionFlags();
  194. // In a perfect world, this would have worked.
  195. //
  196. // if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0)
  197. // regionFlags |= (uint)RegionFlags.AllowLandmark;
  198. // if (landData.OwnerID == remote_client.AgentId)
  199. // regionFlags |= (uint)RegionFlags.AllowSetHome;
  200. int seq_id;
  201. if (snap_selection && (sequence_id == 0))
  202. {
  203. seq_id = m_lastSeqId;
  204. }
  205. else
  206. {
  207. seq_id = sequence_id;
  208. m_lastSeqId = seq_id;
  209. }
  210. remote_client.SendLandProperties(seq_id,
  211. snap_selection, request_result, this,
  212. (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
  213. GetParcelMaxPrimCount(),
  214. GetSimulatorMaxPrimCount(), regionFlags);
  215. }
  216. public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
  217. {
  218. //Needs later group support
  219. bool snap_selection = false;
  220. LandData newData = LandData.Copy();
  221. uint allowedDelta = 0;
  222. // These two are always blocked as no client can set them anyway
  223. // ParcelFlags.ForSaleObjects
  224. // ParcelFlags.LindenHome
  225. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
  226. {
  227. allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
  228. ParcelFlags.AllowTerraform |
  229. ParcelFlags.AllowDamage |
  230. ParcelFlags.CreateObjects |
  231. ParcelFlags.RestrictPushObject |
  232. ParcelFlags.AllowOtherScripts |
  233. ParcelFlags.AllowGroupScripts |
  234. ParcelFlags.CreateGroupObjects |
  235. ParcelFlags.AllowAPrimitiveEntry |
  236. ParcelFlags.AllowGroupObjectEntry);
  237. }
  238. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale))
  239. {
  240. if (args.AuthBuyerID != newData.AuthBuyerID ||
  241. args.SalePrice != newData.SalePrice)
  242. {
  243. snap_selection = true;
  244. }
  245. newData.AuthBuyerID = args.AuthBuyerID;
  246. newData.SalePrice = args.SalePrice;
  247. if (!LandData.IsGroupOwned)
  248. {
  249. newData.GroupID = args.GroupID;
  250. allowedDelta |= (uint)(ParcelFlags.AllowDeedToGroup |
  251. ParcelFlags.ContributeWithDeed |
  252. ParcelFlags.SellParcelObjects);
  253. }
  254. allowedDelta |= (uint)ParcelFlags.ForSale;
  255. }
  256. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces))
  257. {
  258. newData.Category = args.Category;
  259. allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
  260. ParcelFlags.AllowPublish |
  261. ParcelFlags.MaturePublish);
  262. }
  263. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity))
  264. {
  265. newData.Description = args.Desc;
  266. newData.Name = args.Name;
  267. newData.SnapshotID = args.SnapshotID;
  268. }
  269. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint))
  270. {
  271. newData.LandingType = args.LandingType;
  272. newData.UserLocation = args.UserLocation;
  273. newData.UserLookAt = args.UserLookAt;
  274. }
  275. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia))
  276. {
  277. newData.MediaAutoScale = args.MediaAutoScale;
  278. newData.MediaID = args.MediaID;
  279. newData.MediaURL = args.MediaURL;
  280. newData.MusicURL = args.MusicURL;
  281. newData.MediaType = args.MediaType;
  282. newData.MediaDescription = args.MediaDescription;
  283. newData.MediaWidth = args.MediaWidth;
  284. newData.MediaHeight = args.MediaHeight;
  285. newData.MediaLoop = args.MediaLoop;
  286. newData.ObscureMusic = args.ObscureMusic;
  287. newData.ObscureMedia = args.ObscureMedia;
  288. allowedDelta |= (uint)(ParcelFlags.SoundLocal |
  289. ParcelFlags.UrlWebPage |
  290. ParcelFlags.UrlRawHtml |
  291. ParcelFlags.AllowVoiceChat |
  292. ParcelFlags.UseEstateVoiceChan);
  293. }
  294. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses))
  295. {
  296. newData.PassHours = args.PassHours;
  297. newData.PassPrice = args.PassPrice;
  298. allowedDelta |= (uint)ParcelFlags.UsePassList;
  299. }
  300. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed))
  301. {
  302. allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
  303. ParcelFlags.UseAccessList);
  304. }
  305. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned))
  306. {
  307. allowedDelta |= (uint)(ParcelFlags.UseBanList |
  308. ParcelFlags.DenyAnonymous |
  309. ParcelFlags.DenyAgeUnverified);
  310. }
  311. uint preserve = LandData.Flags & ~allowedDelta;
  312. newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
  313. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  314. SendLandUpdateToAvatarsOverMe(snap_selection);
  315. }
  316. public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
  317. {
  318. LandData newData = LandData.Copy();
  319. newData.OwnerID = avatarID;
  320. newData.GroupID = groupID;
  321. newData.IsGroupOwned = groupOwned;
  322. //newData.auctionID = AuctionID;
  323. newData.ClaimDate = Util.UnixTimeSinceEpoch();
  324. newData.ClaimPrice = claimprice;
  325. newData.SalePrice = 0;
  326. newData.AuthBuyerID = UUID.Zero;
  327. newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  328. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  329. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  330. SendLandUpdateToAvatarsOverMe(true);
  331. }
  332. public void DeedToGroup(UUID groupID)
  333. {
  334. LandData newData = LandData.Copy();
  335. newData.OwnerID = groupID;
  336. newData.GroupID = groupID;
  337. newData.IsGroupOwned = true;
  338. // Reset show in directory flag on deed
  339. newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  340. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  341. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  342. SendLandUpdateToAvatarsOverMe(true);
  343. }
  344. public bool IsEitherBannedOrRestricted(UUID avatar)
  345. {
  346. if (IsBannedFromLand(avatar))
  347. {
  348. return true;
  349. }
  350. else if (IsRestrictedFromLand(avatar))
  351. {
  352. return true;
  353. }
  354. return false;
  355. }
  356. public bool IsBannedFromLand(UUID avatar)
  357. {
  358. if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
  359. return false;
  360. if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
  361. {
  362. if (LandData.ParcelAccessList.FindIndex(
  363. delegate(ParcelManager.ParcelAccessEntry e)
  364. {
  365. if (e.AgentID == avatar && e.Flags == AccessList.Ban)
  366. return true;
  367. return false;
  368. }) != -1)
  369. {
  370. return true;
  371. }
  372. }
  373. return false;
  374. }
  375. public bool IsRestrictedFromLand(UUID avatar)
  376. {
  377. if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
  378. return false;
  379. if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0)
  380. {
  381. if (LandData.ParcelAccessList.FindIndex(
  382. delegate(ParcelManager.ParcelAccessEntry e)
  383. {
  384. if (e.AgentID == avatar && e.Flags == AccessList.Access)
  385. return true;
  386. return false;
  387. }) == -1)
  388. {
  389. return true;
  390. }
  391. }
  392. return false;
  393. }
  394. public void SendLandUpdateToClient(IClientAPI remote_client)
  395. {
  396. SendLandProperties(0, false, 0, remote_client);
  397. }
  398. public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client)
  399. {
  400. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  401. SendLandProperties(0, snap_selection, 0, remote_client);
  402. }
  403. public void SendLandUpdateToAvatarsOverMe()
  404. {
  405. SendLandUpdateToAvatarsOverMe(false);
  406. }
  407. public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
  408. {
  409. m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
  410. {
  411. if (avatar.IsChildAgent)
  412. return;
  413. ILandObject over = null;
  414. try
  415. {
  416. over =
  417. m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)),
  418. Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1)));
  419. }
  420. catch (Exception)
  421. {
  422. m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " +
  423. Math.Round(avatar.AbsolutePosition.Y));
  424. }
  425. if (over != null)
  426. {
  427. if (over.LandData.LocalID == LandData.LocalID)
  428. {
  429. if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) &&
  430. m_scene.RegionInfo.RegionSettings.AllowDamage)
  431. avatar.Invulnerable = false;
  432. else
  433. avatar.Invulnerable = true;
  434. SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
  435. }
  436. }
  437. });
  438. }
  439. #endregion
  440. #region AccessList Functions
  441. public List<UUID> CreateAccessListArrayByFlag(AccessList flag)
  442. {
  443. List<UUID> list = new List<UUID>();
  444. foreach (ParcelManager.ParcelAccessEntry entry in LandData.ParcelAccessList)
  445. {
  446. if (entry.Flags == flag)
  447. {
  448. list.Add(entry.AgentID);
  449. }
  450. }
  451. if (list.Count == 0)
  452. {
  453. list.Add(UUID.Zero);
  454. }
  455. return list;
  456. }
  457. public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
  458. IClientAPI remote_client)
  459. {
  460. if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both)
  461. {
  462. List<UUID> avatars = CreateAccessListArrayByFlag(AccessList.Access);
  463. remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,LandData.LocalID);
  464. }
  465. if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both)
  466. {
  467. List<UUID> avatars = CreateAccessListArrayByFlag(AccessList.Ban);
  468. remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, LandData.LocalID);
  469. }
  470. }
  471. public void UpdateAccessList(uint flags, UUID transactionID,
  472. int sequenceID, int sections,
  473. List<ParcelManager.ParcelAccessEntry> entries,
  474. IClientAPI remote_client)
  475. {
  476. LandData newData = LandData.Copy();
  477. if ((!m_listTransactions.ContainsKey(flags)) ||
  478. m_listTransactions[flags] != transactionID)
  479. {
  480. m_listTransactions[flags] = transactionID;
  481. List<ParcelManager.ParcelAccessEntry> toRemove =
  482. new List<ParcelManager.ParcelAccessEntry>();
  483. foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList)
  484. {
  485. if (entry.Flags == (AccessList)flags)
  486. toRemove.Add(entry);
  487. }
  488. foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
  489. {
  490. newData.ParcelAccessList.Remove(entry);
  491. }
  492. // Checked here because this will always be the first
  493. // and only packet in a transaction
  494. if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
  495. {
  496. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  497. return;
  498. }
  499. }
  500. foreach (ParcelManager.ParcelAccessEntry entry in entries)
  501. {
  502. ParcelManager.ParcelAccessEntry temp =
  503. new ParcelManager.ParcelAccessEntry();
  504. temp.AgentID = entry.AgentID;
  505. temp.Time = entry.Time;
  506. temp.Flags = (AccessList)flags;
  507. newData.ParcelAccessList.Add(temp);
  508. }
  509. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  510. }
  511. #endregion
  512. #region Update Functions
  513. public void UpdateLandBitmapByteArray()
  514. {
  515. LandData.Bitmap = ConvertLandBitmapToBytes();
  516. }
  517. /// <summary>
  518. /// Update all settings in land such as area, bitmap byte array, etc
  519. /// </summary>
  520. public void ForceUpdateLandInfo()
  521. {
  522. UpdateAABBAndAreaValues();
  523. UpdateLandBitmapByteArray();
  524. }
  525. public void SetLandBitmapFromByteArray()
  526. {
  527. LandBitmap = ConvertBytesToLandBitmap();
  528. }
  529. /// <summary>
  530. /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
  531. /// </summary>
  532. private void UpdateAABBAndAreaValues()
  533. {
  534. int min_x = 64;
  535. int min_y = 64;
  536. int max_x = 0;
  537. int max_y = 0;
  538. int tempArea = 0;
  539. int x, y;
  540. for (x = 0; x < 64; x++)
  541. {
  542. for (y = 0; y < 64; y++)
  543. {
  544. if (LandBitmap[x, y] == true)
  545. {
  546. if (min_x > x) min_x = x;
  547. if (min_y > y) min_y = y;
  548. if (max_x < x) max_x = x;
  549. if (max_y < y) max_y = y;
  550. tempArea += 16; //16sqm peice of land
  551. }
  552. }
  553. }
  554. int tx = min_x * 4;
  555. if (tx > ((int)Constants.RegionSize - 1))
  556. tx = ((int)Constants.RegionSize - 1);
  557. int ty = min_y * 4;
  558. if (ty > ((int)Constants.RegionSize - 1))
  559. ty = ((int)Constants.RegionSize - 1);
  560. LandData.AABBMin =
  561. new Vector3((float) (min_x * 4), (float) (min_y * 4),
  562. (float) m_scene.Heightmap[tx, ty]);
  563. tx = max_x * 4;
  564. if (tx > ((int)Constants.RegionSize - 1))
  565. tx = ((int)Constants.RegionSize - 1);
  566. ty = max_y * 4;
  567. if (ty > ((int)Constants.RegionSize - 1))
  568. ty = ((int)Constants.RegionSize - 1);
  569. LandData.AABBMax =
  570. new Vector3((float) (max_x * 4), (float) (max_y * 4),
  571. (float) m_scene.Heightmap[tx, ty]);
  572. LandData.Area = tempArea;
  573. }
  574. #endregion
  575. #region Land Bitmap Functions
  576. /// <summary>
  577. /// Sets the land's bitmap manually
  578. /// </summary>
  579. /// <param name="bitmap">64x64 block representing where this land is on a map</param>
  580. public void SetLandBitmap(bool[,] bitmap)
  581. {
  582. if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
  583. {
  584. //Throw an exception - The bitmap is not 64x64
  585. //throw new Exception("Error: Invalid Parcel Bitmap");
  586. }
  587. else
  588. {
  589. //Valid: Lets set it
  590. LandBitmap = bitmap;
  591. ForceUpdateLandInfo();
  592. }
  593. }
  594. /// <summary>
  595. /// Gets the land's bitmap manually
  596. /// </summary>
  597. /// <returns></returns>
  598. public bool[,] GetLandBitmap()
  599. {
  600. return LandBitmap;
  601. }
  602. public bool[,] BasicFullRegionLandBitmap()
  603. {
  604. return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
  605. }
  606. public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
  607. {
  608. bool[,] tempBitmap = new bool[64,64];
  609. tempBitmap.Initialize();
  610. tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
  611. return tempBitmap;
  612. }
  613. /// <summary>
  614. /// Change a land bitmap at within a square and set those points to a specific value
  615. /// </summary>
  616. /// <param name="land_bitmap"></param>
  617. /// <param name="start_x"></param>
  618. /// <param name="start_y"></param>
  619. /// <param name="end_x"></param>
  620. /// <param name="end_y"></param>
  621. /// <param name="set_value"></param>
  622. /// <returns></returns>
  623. public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
  624. bool set_value)
  625. {
  626. if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
  627. {
  628. //Throw an exception - The bitmap is not 64x64
  629. //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
  630. }
  631. int x, y;
  632. for (y = 0; y < 64; y++)
  633. {
  634. for (x = 0; x < 64; x++)
  635. {
  636. if (x >= start_x / 4 && x < end_x / 4
  637. && y >= start_y / 4 && y < end_y / 4)
  638. {
  639. land_bitmap[x, y] = set_value;
  640. }
  641. }
  642. }
  643. return land_bitmap;
  644. }
  645. /// <summary>
  646. /// Join the true values of 2 bitmaps together
  647. /// </summary>
  648. /// <param name="bitmap_base"></param>
  649. /// <param name="bitmap_add"></param>
  650. /// <returns></returns>
  651. public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
  652. {
  653. if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
  654. {
  655. //Throw an exception - The bitmap is not 64x64
  656. throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
  657. }
  658. if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
  659. {
  660. //Throw an exception - The bitmap is not 64x64
  661. throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
  662. }
  663. int x, y;
  664. for (y = 0; y < 64; y++)
  665. {
  666. for (x = 0; x < 64; x++)
  667. {
  668. if (bitmap_add[x, y])
  669. {
  670. bitmap_base[x, y] = true;
  671. }
  672. }
  673. }
  674. return bitmap_base;
  675. }
  676. /// <summary>
  677. /// Converts the land bitmap to a packet friendly byte array
  678. /// </summary>
  679. /// <returns></returns>
  680. private byte[] ConvertLandBitmapToBytes()
  681. {
  682. byte[] tempConvertArr = new byte[512];
  683. byte tempByte = 0;
  684. int x, y, i, byteNum = 0;
  685. i = 0;
  686. for (y = 0; y < 64; y++)
  687. {
  688. for (x = 0; x < 64; x++)
  689. {
  690. tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
  691. if (i % 8 == 0)
  692. {
  693. tempConvertArr[byteNum] = tempByte;
  694. tempByte = (byte) 0;
  695. i = 0;
  696. byteNum++;
  697. }
  698. }
  699. }
  700. return tempConvertArr;
  701. }
  702. private bool[,] ConvertBytesToLandBitmap()
  703. {
  704. bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax];
  705. tempConvertMap.Initialize();
  706. byte tempByte = 0;
  707. int x = 0, y = 0, i = 0, bitNum = 0;
  708. for (i = 0; i < 512; i++)
  709. {
  710. tempByte = LandData.Bitmap[i];
  711. for (bitNum = 0; bitNum < 8; bitNum++)
  712. {
  713. bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
  714. tempConvertMap[x, y] = bit;
  715. x++;
  716. if (x > 63)
  717. {
  718. x = 0;
  719. y++;
  720. }
  721. }
  722. }
  723. return tempConvertMap;
  724. }
  725. #endregion
  726. #region Object Select and Object Owner Listing
  727. public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
  728. {
  729. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
  730. {
  731. List<uint> resultLocalIDs = new List<uint>();
  732. try
  733. {
  734. lock (primsOverMe)
  735. {
  736. foreach (SceneObjectGroup obj in primsOverMe)
  737. {
  738. if (obj.LocalId > 0)
  739. {
  740. if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID)
  741. {
  742. resultLocalIDs.Add(obj.LocalId);
  743. }
  744. else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero)
  745. {
  746. resultLocalIDs.Add(obj.LocalId);
  747. }
  748. else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
  749. obj.OwnerID != remote_client.AgentId)
  750. {
  751. resultLocalIDs.Add(obj.LocalId);
  752. }
  753. else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
  754. {
  755. resultLocalIDs.Add(obj.LocalId);
  756. }
  757. }
  758. }
  759. }
  760. } catch (InvalidOperationException)
  761. {
  762. m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
  763. }
  764. remote_client.SendForceClientSelectObjects(resultLocalIDs);
  765. }
  766. }
  767. /// <summary>
  768. /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
  769. /// aggreagete details such as the number of prims.
  770. ///
  771. /// </summary>
  772. /// <param name="remote_client">
  773. /// A <see cref="IClientAPI"/>
  774. /// </param>
  775. public void SendLandObjectOwners(IClientAPI remote_client)
  776. {
  777. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
  778. {
  779. Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
  780. List<UUID> groups = new List<UUID>();
  781. lock (primsOverMe)
  782. {
  783. // m_log.DebugFormat(
  784. // "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region",
  785. // remote_client.Name, primsOverMe.Count);
  786. try
  787. {
  788. foreach (SceneObjectGroup obj in primsOverMe)
  789. {
  790. try
  791. {
  792. if (!primCount.ContainsKey(obj.OwnerID))
  793. {
  794. primCount.Add(obj.OwnerID, 0);
  795. }
  796. }
  797. catch (NullReferenceException)
  798. {
  799. m_log.Error("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
  800. }
  801. try
  802. {
  803. primCount[obj.OwnerID] += obj.PrimCount;
  804. }
  805. catch (KeyNotFoundException)
  806. {
  807. m_log.Error("[LAND]: Unable to match a prim with it's owner.");
  808. }
  809. if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID)))
  810. groups.Add(obj.OwnerID);
  811. }
  812. }
  813. catch (InvalidOperationException)
  814. {
  815. m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
  816. }
  817. }
  818. remote_client.SendLandObjectOwners(LandData, groups, primCount);
  819. }
  820. }
  821. public Dictionary<UUID, int> GetLandObjectOwners()
  822. {
  823. Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
  824. lock (primsOverMe)
  825. {
  826. try
  827. {
  828. foreach (SceneObjectGroup obj in primsOverMe)
  829. {
  830. if (!ownersAndCount.ContainsKey(obj.OwnerID))
  831. {
  832. ownersAndCount.Add(obj.OwnerID, 0);
  833. }
  834. ownersAndCount[obj.OwnerID] += obj.PrimCount;
  835. }
  836. }
  837. catch (InvalidOperationException)
  838. {
  839. m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
  840. }
  841. }
  842. return ownersAndCount;
  843. }
  844. #endregion
  845. #region Object Returning
  846. public void ReturnObject(SceneObjectGroup obj)
  847. {
  848. SceneObjectGroup[] objs = new SceneObjectGroup[1];
  849. objs[0] = obj;
  850. m_scene.returnObjects(objs, obj.OwnerID);
  851. }
  852. public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
  853. {
  854. // m_log.DebugFormat(
  855. // "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name);
  856. Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>();
  857. lock (primsOverMe)
  858. {
  859. if (type == (uint)ObjectReturnType.Owner)
  860. {
  861. foreach (SceneObjectGroup obj in primsOverMe)
  862. {
  863. if (obj.OwnerID == m_landData.OwnerID)
  864. {
  865. if (!returns.ContainsKey(obj.OwnerID))
  866. returns[obj.OwnerID] =
  867. new List<SceneObjectGroup>();
  868. returns[obj.OwnerID].Add(obj);
  869. }
  870. }
  871. }
  872. else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero)
  873. {
  874. foreach (SceneObjectGroup obj in primsOverMe)
  875. {
  876. if (obj.GroupID == m_landData.GroupID)
  877. {
  878. if (!returns.ContainsKey(obj.OwnerID))
  879. returns[obj.OwnerID] =
  880. new List<SceneObjectGroup>();
  881. returns[obj.OwnerID].Add(obj);
  882. }
  883. }
  884. }
  885. else if (type == (uint)ObjectReturnType.Other)
  886. {
  887. foreach (SceneObjectGroup obj in primsOverMe)
  888. {
  889. if (obj.OwnerID != m_landData.OwnerID &&
  890. (obj.GroupID != m_landData.GroupID ||
  891. m_landData.GroupID == UUID.Zero))
  892. {
  893. if (!returns.ContainsKey(obj.OwnerID))
  894. returns[obj.OwnerID] =
  895. new List<SceneObjectGroup>();
  896. returns[obj.OwnerID].Add(obj);
  897. }
  898. }
  899. }
  900. else if (type == (uint)ObjectReturnType.List)
  901. {
  902. List<UUID> ownerlist = new List<UUID>(owners);
  903. foreach (SceneObjectGroup obj in primsOverMe)
  904. {
  905. if (ownerlist.Contains(obj.OwnerID))
  906. {
  907. if (!returns.ContainsKey(obj.OwnerID))
  908. returns[obj.OwnerID] =
  909. new List<SceneObjectGroup>();
  910. returns[obj.OwnerID].Add(obj);
  911. }
  912. }
  913. }
  914. }
  915. foreach (List<SceneObjectGroup> ol in returns.Values)
  916. {
  917. if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol))
  918. m_scene.returnObjects(ol.ToArray(), remote_client.AgentId);
  919. }
  920. }
  921. #endregion
  922. #region Object Adding/Removing from Parcel
  923. public void ResetOverMeRecord()
  924. {
  925. lock (primsOverMe)
  926. primsOverMe.Clear();
  927. }
  928. public void AddPrimOverMe(SceneObjectGroup obj)
  929. {
  930. // m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name);
  931. lock (primsOverMe)
  932. primsOverMe.Add(obj);
  933. }
  934. public void RemovePrimFromOverMe(SceneObjectGroup obj)
  935. {
  936. // m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name);
  937. lock (primsOverMe)
  938. primsOverMe.Remove(obj);
  939. }
  940. #endregion
  941. /// <summary>
  942. /// Set the media url for this land parcel
  943. /// </summary>
  944. /// <param name="url"></param>
  945. public void SetMediaUrl(string url)
  946. {
  947. LandData.MediaURL = url;
  948. SendLandUpdateToAvatarsOverMe();
  949. }
  950. /// <summary>
  951. /// Set the music url for this land parcel
  952. /// </summary>
  953. /// <param name="url"></param>
  954. public void SetMusicUrl(string url)
  955. {
  956. LandData.MusicURL = url;
  957. SendLandUpdateToAvatarsOverMe();
  958. }
  959. #endregion
  960. }
  961. }