Land.cs 31 KB

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