LandObject.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  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 OpenSim 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 libsecondlife;
  31. using libsecondlife.Packets;
  32. using log4net;
  33. using OpenSim.Framework;
  34. using OpenSim.Region.Environment.Interfaces;
  35. using OpenSim.Region.Environment.Scenes;
  36. namespace OpenSim.Region.Environment.Modules.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 bool[,] m_landBitmap = new bool[64,64];
  46. protected LandData m_landData = new LandData();
  47. protected Scene m_scene;
  48. protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
  49. public bool[,] landBitmap
  50. {
  51. get { return m_landBitmap; }
  52. set { m_landBitmap = value; }
  53. }
  54. #endregion
  55. #region ILandObject Members
  56. public LandData landData
  57. {
  58. get { return m_landData; }
  59. set { m_landData = value; }
  60. }
  61. public LLUUID regionUUID
  62. {
  63. get { return m_scene.RegionInfo.RegionID; }
  64. }
  65. #region Constructors
  66. public LandObject(LLUUID owner_id, bool is_group_owned, Scene scene)
  67. {
  68. m_scene = scene;
  69. landData.ownerID = owner_id;
  70. landData.isGroupOwned = is_group_owned;
  71. }
  72. #endregion
  73. #region Member Functions
  74. #region General Functions
  75. /// <summary>
  76. /// Checks to see if this land object contains a point
  77. /// </summary>
  78. /// <param name="x"></param>
  79. /// <param name="y"></param>
  80. /// <returns>Returns true if the piece of land contains the specified point</returns>
  81. public bool containsPoint(int x, int y)
  82. {
  83. if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize)
  84. {
  85. return (landBitmap[x / 4, y / 4] == true);
  86. }
  87. else
  88. {
  89. return false;
  90. }
  91. }
  92. public ILandObject Copy()
  93. {
  94. ILandObject newLand = new LandObject(landData.ownerID, landData.isGroupOwned, m_scene);
  95. //Place all new variables here!
  96. newLand.landBitmap = (bool[,]) (landBitmap.Clone());
  97. newLand.landData = landData.Copy();
  98. return newLand;
  99. }
  100. #endregion
  101. #region Packet Request Handling
  102. /// <summary>
  103. /// Sends land properties as requested
  104. /// </summary>
  105. /// <param name="sequence_id">ID sent by client for them to keep track of</param>
  106. /// <param name="snap_selection">Bool sent by client for them to use</param>
  107. /// <param name="remote_client">Object representing the client</param>
  108. public void sendLandProperties(int sequence_id, bool snap_selection, int request_result,
  109. IClientAPI remote_client)
  110. {
  111. ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ParcelProperties);
  112. // TODO: don't create new blocks if recycling an old packet
  113. updatePacket.ParcelData.AABBMax = landData.AABBMax;
  114. updatePacket.ParcelData.AABBMin = landData.AABBMin;
  115. updatePacket.ParcelData.Area = landData.area;
  116. updatePacket.ParcelData.AuctionID = landData.auctionID;
  117. updatePacket.ParcelData.AuthBuyerID = landData.authBuyerID; //unemplemented
  118. updatePacket.ParcelData.Bitmap = landData.landBitmapByteArray;
  119. updatePacket.ParcelData.Desc = Helpers.StringToField(landData.landDesc);
  120. updatePacket.ParcelData.Category = (byte) landData.category;
  121. updatePacket.ParcelData.ClaimDate = landData.claimDate;
  122. updatePacket.ParcelData.ClaimPrice = landData.claimPrice;
  123. updatePacket.ParcelData.GroupID = landData.groupID;
  124. updatePacket.ParcelData.GroupPrims = landData.groupPrims;
  125. updatePacket.ParcelData.IsGroupOwned = landData.isGroupOwned;
  126. updatePacket.ParcelData.LandingType = (byte) landData.landingType;
  127. updatePacket.ParcelData.LocalID = landData.localID;
  128. if (landData.area > 0)
  129. {
  130. updatePacket.ParcelData.MaxPrims =
  131. Convert.ToInt32(
  132. Math.Round((Convert.ToDecimal(landData.area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity *
  133. Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor)));
  134. }
  135. else
  136. {
  137. updatePacket.ParcelData.MaxPrims = 0;
  138. }
  139. updatePacket.ParcelData.MediaAutoScale = landData.mediaAutoScale;
  140. updatePacket.ParcelData.MediaID = landData.mediaID;
  141. updatePacket.ParcelData.MediaURL = Helpers.StringToField(landData.mediaURL);
  142. updatePacket.ParcelData.MusicURL = Helpers.StringToField(landData.musicURL);
  143. updatePacket.ParcelData.Name = Helpers.StringToField(landData.landName);
  144. updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented
  145. updatePacket.ParcelData.OtherCount = 0; //unemplemented
  146. updatePacket.ParcelData.OtherPrims = landData.otherPrims;
  147. updatePacket.ParcelData.OwnerID = landData.ownerID;
  148. updatePacket.ParcelData.OwnerPrims = landData.ownerPrims;
  149. updatePacket.ParcelData.ParcelFlags = landData.landFlags;
  150. updatePacket.ParcelData.ParcelPrimBonus = m_scene.RegionInfo.EstateSettings.objectBonusFactor;
  151. updatePacket.ParcelData.PassHours = landData.passHours;
  152. updatePacket.ParcelData.PassPrice = landData.passPrice;
  153. updatePacket.ParcelData.PublicCount = 0; //unemplemented
  154. uint regionFlags = (uint) m_scene.RegionInfo.EstateSettings.regionFlags;
  155. updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint) Simulator.RegionFlags.DenyAnonymous) >
  156. 0);
  157. updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint) Simulator.RegionFlags.DenyIdentified) >
  158. 0);
  159. updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint) Simulator.RegionFlags.DenyTransacted) >
  160. 0);
  161. updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint) Simulator.RegionFlags.RestrictPushObject) >
  162. 0);
  163. updatePacket.ParcelData.RentPrice = 0;
  164. updatePacket.ParcelData.RequestResult = request_result;
  165. updatePacket.ParcelData.SalePrice = landData.salePrice;
  166. updatePacket.ParcelData.SelectedPrims = landData.selectedPrims;
  167. updatePacket.ParcelData.SelfCount = 0; //unemplemented
  168. updatePacket.ParcelData.SequenceID = sequence_id;
  169. if (landData.simwideArea > 0)
  170. {
  171. updatePacket.ParcelData.SimWideMaxPrims =
  172. Convert.ToInt32(
  173. Math.Round((Convert.ToDecimal(landData.simwideArea) / Convert.ToDecimal(65536)) * m_scene.objectCapacity *
  174. Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor)));
  175. }
  176. else
  177. {
  178. updatePacket.ParcelData.SimWideMaxPrims = 0;
  179. }
  180. updatePacket.ParcelData.SimWideTotalPrims = landData.simwidePrims;
  181. updatePacket.ParcelData.SnapSelection = snap_selection;
  182. updatePacket.ParcelData.SnapshotID = landData.snapshotID;
  183. updatePacket.ParcelData.Status = (byte) landData.landStatus;
  184. updatePacket.ParcelData.TotalPrims = landData.ownerPrims + landData.groupPrims + landData.otherPrims +
  185. landData.selectedPrims;
  186. updatePacket.ParcelData.UserLocation = landData.userLocation;
  187. updatePacket.ParcelData.UserLookAt = landData.userLookAt;
  188. remote_client.OutPacket((Packet) updatePacket, ThrottleOutPacketType.Task);
  189. }
  190. public void updateLandProperties(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client)
  191. {
  192. if (remote_client.AgentId == landData.ownerID)
  193. {
  194. //Needs later group support
  195. LandData newData = landData.Copy();
  196. newData.authBuyerID = packet.ParcelData.AuthBuyerID;
  197. newData.category = (Parcel.ParcelCategory) packet.ParcelData.Category;
  198. newData.landDesc = Helpers.FieldToUTF8String(packet.ParcelData.Desc);
  199. newData.groupID = packet.ParcelData.GroupID;
  200. newData.landingType = packet.ParcelData.LandingType;
  201. newData.mediaAutoScale = packet.ParcelData.MediaAutoScale;
  202. newData.mediaID = packet.ParcelData.MediaID;
  203. newData.mediaURL = Helpers.FieldToUTF8String(packet.ParcelData.MediaURL);
  204. newData.musicURL = Helpers.FieldToUTF8String(packet.ParcelData.MusicURL);
  205. newData.landName = Helpers.FieldToUTF8String(packet.ParcelData.Name);
  206. newData.landFlags = packet.ParcelData.ParcelFlags;
  207. newData.passHours = packet.ParcelData.PassHours;
  208. newData.passPrice = packet.ParcelData.PassPrice;
  209. newData.salePrice = packet.ParcelData.SalePrice;
  210. newData.snapshotID = packet.ParcelData.SnapshotID;
  211. newData.userLocation = packet.ParcelData.UserLocation;
  212. newData.userLookAt = packet.ParcelData.UserLookAt;
  213. m_scene.LandChannel.updateLandObject(landData.localID, newData);
  214. sendLandUpdateToAvatarsOverMe();
  215. }
  216. }
  217. public void updateLandSold(LLUUID avatarID, LLUUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
  218. {
  219. LandData newData = landData.Copy();
  220. newData.ownerID = avatarID;
  221. newData.groupID = groupID;
  222. newData.isGroupOwned = groupOwned;
  223. //newData.auctionID = AuctionID;
  224. newData.claimDate = Util.UnixTimeSinceEpoch();
  225. newData.claimPrice = claimprice;
  226. newData.salePrice = 0;
  227. newData.authBuyerID = LLUUID.Zero;
  228. newData.landFlags &= ~(uint) (Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects);
  229. m_scene.LandChannel.updateLandObject(landData.localID, newData);
  230. sendLandUpdateToAvatarsOverMe();
  231. }
  232. public bool isEitherBannedOrRestricted(LLUUID avatar)
  233. {
  234. if (isBannedFromLand(avatar))
  235. {
  236. return true;
  237. }
  238. else if (isRestrictedFromLand(avatar))
  239. {
  240. return true;
  241. }
  242. return false;
  243. }
  244. public bool isBannedFromLand(LLUUID avatar)
  245. {
  246. if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseBanList) > 0)
  247. {
  248. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  249. entry.AgentID = avatar;
  250. entry.Flags = ParcelManager.AccessList.Ban;
  251. entry.Time = new DateTime();
  252. if (landData.parcelAccessList.Contains(entry))
  253. {
  254. //They are banned, so lets send them a notice about this parcel
  255. return true;
  256. }
  257. }
  258. return false;
  259. }
  260. public bool isRestrictedFromLand(LLUUID avatar)
  261. {
  262. if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseAccessList) > 0)
  263. {
  264. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  265. entry.AgentID = avatar;
  266. entry.Flags = ParcelManager.AccessList.Access;
  267. entry.Time = new DateTime();
  268. if (!landData.parcelAccessList.Contains(entry))
  269. {
  270. //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel
  271. return true;
  272. }
  273. }
  274. return false;
  275. }
  276. public void sendLandUpdateToClient(IClientAPI remote_client)
  277. {
  278. sendLandProperties(0, false, 0, remote_client);
  279. }
  280. public void sendLandUpdateToAvatarsOverMe()
  281. {
  282. List<ScenePresence> avatars = m_scene.GetAvatars();
  283. ILandObject over = null;
  284. for (int i = 0; i < avatars.Count; i++)
  285. {
  286. try
  287. {
  288. over =
  289. m_scene.LandChannel.getLandObject((int) Math.Max(255, Math.Min(0, Math.Round(avatars[i].AbsolutePosition.X))),
  290. (int) Math.Max(255, Math.Min(0, Math.Round(avatars[i].AbsolutePosition.Y))));
  291. }
  292. catch (Exception)
  293. {
  294. m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatars[i].AbsolutePosition.X) + " y: " +
  295. Math.Round(avatars[i].AbsolutePosition.Y));
  296. }
  297. if (over != null)
  298. {
  299. if (over.landData.localID == landData.localID)
  300. {
  301. sendLandUpdateToClient(avatars[i].ControllingClient);
  302. }
  303. }
  304. }
  305. }
  306. #endregion
  307. #region AccessList Functions
  308. public ParcelAccessListReplyPacket.ListBlock[] createAccessListArrayByFlag(ParcelManager.AccessList flag)
  309. {
  310. List<ParcelAccessListReplyPacket.ListBlock> list = new List<ParcelAccessListReplyPacket.ListBlock>();
  311. foreach (ParcelManager.ParcelAccessEntry entry in landData.parcelAccessList)
  312. {
  313. if (entry.Flags == flag)
  314. {
  315. ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock();
  316. listBlock.Flags = (uint) 0;
  317. listBlock.ID = entry.AgentID;
  318. listBlock.Time = 0;
  319. list.Add(listBlock);
  320. }
  321. }
  322. if (list.Count == 0)
  323. {
  324. ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock();
  325. listBlock.Flags = (uint) 0;
  326. listBlock.ID = LLUUID.Zero;
  327. listBlock.Time = 0;
  328. list.Add(listBlock);
  329. }
  330. return list.ToArray();
  331. }
  332. public void sendAccessList(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID,
  333. IClientAPI remote_client)
  334. {
  335. ParcelAccessListReplyPacket replyPacket;
  336. if (flags == (uint) ParcelManager.AccessList.Access || flags == (uint) ParcelManager.AccessList.Both)
  337. {
  338. replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
  339. replyPacket.Data.AgentID = agentID;
  340. replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Access;
  341. replyPacket.Data.LocalID = landData.localID;
  342. replyPacket.Data.SequenceID = 0;
  343. replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Access);
  344. remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task);
  345. }
  346. if (flags == (uint) ParcelManager.AccessList.Ban || flags == (uint) ParcelManager.AccessList.Both)
  347. {
  348. replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
  349. replyPacket.Data.AgentID = agentID;
  350. replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Ban;
  351. replyPacket.Data.LocalID = landData.localID;
  352. replyPacket.Data.SequenceID = 0;
  353. replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Ban);
  354. remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task);
  355. }
  356. }
  357. public void updateAccessList(uint flags, List<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client)
  358. {
  359. LandData newData = landData.Copy();
  360. if (entries.Count == 1 && entries[0].AgentID == LLUUID.Zero)
  361. {
  362. entries.Clear();
  363. }
  364. List<ParcelManager.ParcelAccessEntry> toRemove = new List<ParcelManager.ParcelAccessEntry>();
  365. foreach (ParcelManager.ParcelAccessEntry entry in newData.parcelAccessList)
  366. {
  367. if (entry.Flags == (ParcelManager.AccessList) flags)
  368. {
  369. toRemove.Add(entry);
  370. }
  371. }
  372. foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
  373. {
  374. newData.parcelAccessList.Remove(entry);
  375. }
  376. foreach (ParcelManager.ParcelAccessEntry entry in entries)
  377. {
  378. ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry();
  379. temp.AgentID = entry.AgentID;
  380. temp.Time = new DateTime(); //Pointless? Yes.
  381. temp.Flags = (ParcelManager.AccessList) flags;
  382. if (!newData.parcelAccessList.Contains(temp))
  383. {
  384. newData.parcelAccessList.Add(temp);
  385. }
  386. }
  387. m_scene.LandChannel.updateLandObject(landData.localID, newData);
  388. }
  389. #endregion
  390. #region Update Functions
  391. public void updateLandBitmapByteArray()
  392. {
  393. landData.landBitmapByteArray = convertLandBitmapToBytes();
  394. }
  395. /// <summary>
  396. /// Update all settings in land such as area, bitmap byte array, etc
  397. /// </summary>
  398. public void forceUpdateLandInfo()
  399. {
  400. updateAABBAndAreaValues();
  401. updateLandBitmapByteArray();
  402. }
  403. public void setLandBitmapFromByteArray()
  404. {
  405. landBitmap = convertBytesToLandBitmap();
  406. }
  407. /// <summary>
  408. /// Updates the AABBMin and AABBMax values after area/shape modification of the land object
  409. /// </summary>
  410. private void updateAABBAndAreaValues()
  411. {
  412. int min_x = 64;
  413. int min_y = 64;
  414. int max_x = 0;
  415. int max_y = 0;
  416. int tempArea = 0;
  417. int x, y;
  418. for (x = 0; x < 64; x++)
  419. {
  420. for (y = 0; y < 64; y++)
  421. {
  422. if (landBitmap[x, y] == true)
  423. {
  424. if (min_x > x) min_x = x;
  425. if (min_y > y) min_y = y;
  426. if (max_x < x) max_x = x;
  427. if (max_y < y) max_y = y;
  428. tempArea += 16; //16sqm peice of land
  429. }
  430. }
  431. }
  432. int tx = min_x * 4;
  433. if (tx > 255)
  434. tx = 255;
  435. int ty = min_y * 4;
  436. if (ty > 255)
  437. ty = 255;
  438. landData.AABBMin =
  439. new LLVector3((float) (min_x * 4), (float) (min_y * 4),
  440. (float) m_scene.Heightmap[tx, ty]);
  441. tx = max_x * 4;
  442. if (tx > 255)
  443. tx = 255;
  444. ty = max_y * 4;
  445. if (ty > 255)
  446. ty = 255;
  447. landData.AABBMax =
  448. new LLVector3((float) (max_x * 4), (float) (max_y * 4),
  449. (float) m_scene.Heightmap[tx, ty]);
  450. landData.area = tempArea;
  451. }
  452. #endregion
  453. #region Land Bitmap Functions
  454. /// <summary>
  455. /// Sets the land's bitmap manually
  456. /// </summary>
  457. /// <param name="bitmap">64x64 block representing where this land is on a map</param>
  458. public void setLandBitmap(bool[,] bitmap)
  459. {
  460. if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
  461. {
  462. //Throw an exception - The bitmap is not 64x64
  463. //throw new Exception("Error: Invalid Parcel Bitmap");
  464. }
  465. else
  466. {
  467. //Valid: Lets set it
  468. landBitmap = bitmap;
  469. forceUpdateLandInfo();
  470. }
  471. }
  472. /// <summary>
  473. /// Gets the land's bitmap manually
  474. /// </summary>
  475. /// <returns></returns>
  476. public bool[,] getLandBitmap()
  477. {
  478. return landBitmap;
  479. }
  480. /// <summary>
  481. /// Full sim land object creation
  482. /// </summary>
  483. /// <returns></returns>
  484. public bool[,] basicFullRegionLandBitmap()
  485. {
  486. return getSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
  487. }
  488. /// <summary>
  489. /// Used to modify the bitmap between the x and y points. Points use 64 scale
  490. /// </summary>
  491. /// <param name="start_x"></param>
  492. /// <param name="start_y"></param>
  493. /// <param name="end_x"></param>
  494. /// <param name="end_y"></param>
  495. /// <returns></returns>
  496. public bool[,] getSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
  497. {
  498. bool[,] tempBitmap = new bool[64,64];
  499. tempBitmap.Initialize();
  500. tempBitmap = modifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
  501. return tempBitmap;
  502. }
  503. /// <summary>
  504. /// Change a land bitmap at within a square and set those points to a specific value
  505. /// </summary>
  506. /// <param name="land_bitmap"></param>
  507. /// <param name="start_x"></param>
  508. /// <param name="start_y"></param>
  509. /// <param name="end_x"></param>
  510. /// <param name="end_y"></param>
  511. /// <param name="set_value"></param>
  512. /// <returns></returns>
  513. public bool[,] modifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
  514. bool set_value)
  515. {
  516. if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
  517. {
  518. //Throw an exception - The bitmap is not 64x64
  519. //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
  520. }
  521. int x, y;
  522. for (y = 0; y < 64; y++)
  523. {
  524. for (x = 0; x < 64; x++)
  525. {
  526. if (x >= start_x / 4 && x < end_x / 4
  527. && y >= start_y / 4 && y < end_y / 4)
  528. {
  529. land_bitmap[x, y] = set_value;
  530. }
  531. }
  532. }
  533. return land_bitmap;
  534. }
  535. /// <summary>
  536. /// Join the true values of 2 bitmaps together
  537. /// </summary>
  538. /// <param name="bitmap_base"></param>
  539. /// <param name="bitmap_add"></param>
  540. /// <returns></returns>
  541. public bool[,] mergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
  542. {
  543. if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
  544. {
  545. //Throw an exception - The bitmap is not 64x64
  546. throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
  547. }
  548. if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
  549. {
  550. //Throw an exception - The bitmap is not 64x64
  551. throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
  552. }
  553. int x, y;
  554. for (y = 0; y < 64; y++)
  555. {
  556. for (x = 0; x < 64; x++)
  557. {
  558. if (bitmap_add[x, y])
  559. {
  560. bitmap_base[x, y] = true;
  561. }
  562. }
  563. }
  564. return bitmap_base;
  565. }
  566. /// <summary>
  567. /// Converts the land bitmap to a packet friendly byte array
  568. /// </summary>
  569. /// <returns></returns>
  570. private byte[] convertLandBitmapToBytes()
  571. {
  572. byte[] tempConvertArr = new byte[512];
  573. byte tempByte = 0;
  574. int x, y, i, byteNum = 0;
  575. i = 0;
  576. for (y = 0; y < 64; y++)
  577. {
  578. for (x = 0; x < 64; x++)
  579. {
  580. tempByte = Convert.ToByte(tempByte | Convert.ToByte(landBitmap[x, y]) << (i++ % 8));
  581. if (i % 8 == 0)
  582. {
  583. tempConvertArr[byteNum] = tempByte;
  584. tempByte = (byte) 0;
  585. i = 0;
  586. byteNum++;
  587. }
  588. }
  589. }
  590. return tempConvertArr;
  591. }
  592. private bool[,] convertBytesToLandBitmap()
  593. {
  594. bool[,] tempConvertMap = new bool[64,64];
  595. tempConvertMap.Initialize();
  596. byte tempByte = 0;
  597. int x = 0, y = 0, i = 0, bitNum = 0;
  598. for (i = 0; i < 512; i++)
  599. {
  600. tempByte = landData.landBitmapByteArray[i];
  601. for (bitNum = 0; bitNum < 8; bitNum++)
  602. {
  603. bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
  604. tempConvertMap[x, y] = bit;
  605. x++;
  606. if (x > 63)
  607. {
  608. x = 0;
  609. y++;
  610. }
  611. }
  612. }
  613. return tempConvertMap;
  614. }
  615. #endregion
  616. #region Object Select and Object Owner Listing
  617. public void sendForceObjectSelect(int local_id, int request_type, IClientAPI remote_client)
  618. {
  619. List<uint> resultLocalIDs = new List<uint>();
  620. foreach (SceneObjectGroup obj in primsOverMe)
  621. {
  622. if (obj.LocalId > 0)
  623. {
  624. if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == landData.ownerID)
  625. {
  626. resultLocalIDs.Add(obj.LocalId);
  627. }
  628. // else if (request_type == LandManager.LAND_SELECT_OBJECTS_GROUP && ...) // TODO: group support
  629. // {
  630. // }
  631. else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
  632. obj.OwnerID != remote_client.AgentId)
  633. {
  634. resultLocalIDs.Add(obj.LocalId);
  635. }
  636. }
  637. }
  638. bool firstCall = true;
  639. int MAX_OBJECTS_PER_PACKET = 251;
  640. ForceObjectSelectPacket pack = (ForceObjectSelectPacket) PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
  641. // TODO: don't create new blocks if recycling an old packet
  642. ForceObjectSelectPacket.DataBlock[] data;
  643. while (resultLocalIDs.Count > 0)
  644. {
  645. if (firstCall)
  646. {
  647. pack._Header.ResetList = true;
  648. firstCall = false;
  649. }
  650. else
  651. {
  652. pack._Header.ResetList = false;
  653. }
  654. if (resultLocalIDs.Count > MAX_OBJECTS_PER_PACKET)
  655. {
  656. data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET];
  657. }
  658. else
  659. {
  660. data = new ForceObjectSelectPacket.DataBlock[resultLocalIDs.Count];
  661. }
  662. int i;
  663. for (i = 0; i < MAX_OBJECTS_PER_PACKET && resultLocalIDs.Count > 0; i++)
  664. {
  665. data[i] = new ForceObjectSelectPacket.DataBlock();
  666. data[i].LocalID = Convert.ToUInt32(resultLocalIDs[0]);
  667. resultLocalIDs.RemoveAt(0);
  668. }
  669. pack.Data = data;
  670. remote_client.OutPacket((Packet) pack, ThrottleOutPacketType.Task);
  671. }
  672. }
  673. /// <summary>
  674. /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
  675. /// aggreagete details such as the number of prims.
  676. ///
  677. /// </summary>
  678. /// <param name="remote_client">
  679. /// A <see cref="IClientAPI"/>
  680. /// </param>
  681. public void sendLandObjectOwners(IClientAPI remote_client)
  682. {
  683. Dictionary<LLUUID, int> primCount = new Dictionary<LLUUID, int>();
  684. ParcelObjectOwnersReplyPacket pack
  685. = (ParcelObjectOwnersReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
  686. // TODO: don't create new blocks if recycling an old packet
  687. foreach (SceneObjectGroup obj in primsOverMe)
  688. {
  689. try
  690. {
  691. if (!primCount.ContainsKey(obj.OwnerID))
  692. {
  693. primCount.Add(obj.OwnerID, 0);
  694. }
  695. }
  696. catch (NullReferenceException)
  697. {
  698. m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
  699. }
  700. try
  701. {
  702. primCount[obj.OwnerID] += obj.PrimCount;
  703. }
  704. catch (KeyNotFoundException)
  705. {
  706. m_log.Error("[LAND]: Unable to match a prim with it's owner.");
  707. }
  708. }
  709. int notifyCount = primCount.Count;
  710. if (notifyCount > 0)
  711. {
  712. if (notifyCount > 32)
  713. {
  714. m_log.InfoFormat(
  715. "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
  716. + " - a developer might want to investigate whether this is a hard limit", 32);
  717. notifyCount = 32;
  718. }
  719. ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
  720. = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
  721. int num = 0;
  722. foreach (LLUUID owner in primCount.Keys)
  723. {
  724. dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock();
  725. dataBlock[num].Count = primCount[owner];
  726. dataBlock[num].IsGroupOwned = false; //TODO: fix me when group support is added
  727. dataBlock[num].OnlineStatus = true; //TODO: fix me later
  728. dataBlock[num].OwnerID = owner;
  729. num++;
  730. if (num >= notifyCount)
  731. {
  732. break;
  733. }
  734. }
  735. pack.Data = dataBlock;
  736. }
  737. remote_client.OutPacket(pack, ThrottleOutPacketType.Task);
  738. }
  739. public Dictionary<LLUUID, int> getLandObjectOwners()
  740. {
  741. Dictionary<LLUUID, int> ownersAndCount = new Dictionary<LLUUID, int>();
  742. foreach (SceneObjectGroup obj in primsOverMe)
  743. {
  744. if (!ownersAndCount.ContainsKey(obj.OwnerID))
  745. {
  746. ownersAndCount.Add(obj.OwnerID, 0);
  747. }
  748. ownersAndCount[obj.OwnerID] += obj.PrimCount;
  749. }
  750. return ownersAndCount;
  751. }
  752. #endregion
  753. #region Object Returning
  754. public void returnObject(SceneObjectGroup obj)
  755. {
  756. }
  757. public void returnLandObjects(int type, LLUUID owner)
  758. {
  759. }
  760. #endregion
  761. #region Object Adding/Removing from Parcel
  762. public void resetLandPrimCounts()
  763. {
  764. landData.groupPrims = 0;
  765. landData.ownerPrims = 0;
  766. landData.otherPrims = 0;
  767. landData.selectedPrims = 0;
  768. primsOverMe.Clear();
  769. }
  770. public void addPrimToCount(SceneObjectGroup obj)
  771. {
  772. LLUUID prim_owner = obj.OwnerID;
  773. int prim_count = obj.PrimCount;
  774. if (obj.IsSelected)
  775. {
  776. landData.selectedPrims += prim_count;
  777. }
  778. else
  779. {
  780. if (prim_owner == landData.ownerID)
  781. {
  782. landData.ownerPrims += prim_count;
  783. }
  784. else
  785. {
  786. landData.otherPrims += prim_count;
  787. }
  788. }
  789. primsOverMe.Add(obj);
  790. }
  791. public void removePrimFromCount(SceneObjectGroup obj)
  792. {
  793. if (primsOverMe.Contains(obj))
  794. {
  795. LLUUID prim_owner = obj.OwnerID;
  796. int prim_count = obj.PrimCount;
  797. if (prim_owner == landData.ownerID)
  798. {
  799. landData.ownerPrims -= prim_count;
  800. }
  801. else if (prim_owner == landData.groupID)
  802. {
  803. landData.groupPrims -= prim_count;
  804. }
  805. else
  806. {
  807. landData.otherPrims -= prim_count;
  808. }
  809. primsOverMe.Remove(obj);
  810. }
  811. }
  812. #endregion
  813. #endregion
  814. #endregion
  815. }
  816. }