LandObject.cs 36 KB

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