LandManager.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  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 Axiom.Math;
  31. using libsecondlife;
  32. using libsecondlife.Packets;
  33. using OpenSim.Framework;
  34. using OpenSim.Framework.Console;
  35. using OpenSim.Region.Environment.Scenes;
  36. using OpenSim.Region.Environment.Interfaces;
  37. using OpenSim.Region.Physics.Manager;
  38. namespace OpenSim.Region.Environment.LandManagement
  39. {
  40. #region LandManager Class
  41. /// <summary>
  42. /// Handles Land objects and operations requiring information from other Land objects (divide, join, etc)
  43. /// </summary>
  44. public class LandManager
  45. {
  46. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  47. #region Constants
  48. //Land types set with flags in ParcelOverlay.
  49. //Only one of these can be used.
  50. public const byte LAND_TYPE_PUBLIC = (byte) 0; //Equals 00000000
  51. public const byte LAND_TYPE_OWNED_BY_OTHER = (byte) 1; //Equals 00000001
  52. public const byte LAND_TYPE_OWNED_BY_GROUP = (byte) 2; //Equals 00000010
  53. public const byte LAND_TYPE_OWNED_BY_REQUESTER = (byte) 3; //Equals 00000011
  54. public const byte LAND_TYPE_IS_FOR_SALE = (byte) 4; //Equals 00000100
  55. public const byte LAND_TYPE_IS_BEING_AUCTIONED = (byte) 5; //Equals 00000101
  56. //Flags that when set, a border on the given side will be placed
  57. //NOTE: North and East is assumable by the west and south sides (if land to east has a west border, then I have an east border; etc)
  58. //This took forever to figure out -- jeesh. /blame LL for even having to send these
  59. public const byte LAND_FLAG_PROPERTY_BORDER_WEST = (byte) 64; //Equals 01000000
  60. public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = (byte) 128; //Equals 10000000
  61. //RequestResults (I think these are right, they seem to work):
  62. public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
  63. public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
  64. //ParcelSelectObjects
  65. public const int LAND_SELECT_OBJECTS_OWNER = 2;
  66. public const int LAND_SELECT_OBJECTS_GROUP = 4;
  67. public const int LAND_SELECT_OBJECTS_OTHER = 8;
  68. //These are other constants. Yay!
  69. public const int START_LAND_LOCAL_ID = 1;
  70. public const float BAN_LINE_SAFETY_HIEGHT = 100;
  71. #endregion
  72. #region Member Variables
  73. public Dictionary<int, Land> landList = new Dictionary<int, Land>();
  74. private int lastLandLocalID = START_LAND_LOCAL_ID - 1;
  75. private int[,] landIDList = new int[64,64];
  76. /// <summary>
  77. /// Set to true when a prim is moved, created, added. Performs a prim count update
  78. /// </summary>
  79. public bool landPrimCountTainted = false;
  80. private readonly Scene m_scene;
  81. private readonly RegionInfo m_regInfo;
  82. public bool allowedForcefulBans = true;
  83. #endregion
  84. #region Constructors
  85. public LandManager(Scene scene, RegionInfo reginfo)
  86. {
  87. m_scene = scene;
  88. m_regInfo = reginfo;
  89. landIDList.Initialize();
  90. scene.EventManager.OnAvatarEnteringNewParcel +=
  91. new EventManager.AvatarEnteringNewParcel(handleAvatarChangingParcel);
  92. scene.EventManager.OnClientMovement += new EventManager.ClientMovement(handleAnyClientMovement);
  93. }
  94. #endregion
  95. #region Member Functions
  96. #region Land Object From Storage Functions
  97. public void IncomingLandObjectsFromStorage(List<LandData> data)
  98. {
  99. for (int i = 0; i < data.Count; i++)
  100. {
  101. //try
  102. //{
  103. IncomingLandObjectFromStorage(data[i]);
  104. //}
  105. //catch (Exception ex)
  106. //{
  107. //m_log.Error("[LandManager]: IncomingLandObjectsFromStorage: Exception: " + ex.ToString());
  108. //throw ex;
  109. //}
  110. }
  111. //foreach (LandData parcel in data)
  112. //{
  113. // IncomingLandObjectFromStorage(parcel);
  114. //}
  115. }
  116. public void IncomingLandObjectFromStorage(LandData data)
  117. {
  118. Land new_land = new Land(data.ownerID, data.isGroupOwned, m_scene);
  119. new_land.landData = data.Copy();
  120. new_land.setLandBitmapFromByteArray();
  121. addLandObject(new_land);
  122. }
  123. public void NoLandDataFromStorage()
  124. {
  125. Console.WriteLine("No LandData in storage! Loading a single, flat parcel instead");
  126. resetSimLandObjects();
  127. }
  128. #endregion
  129. #region Parcel Add/Remove/Get/Create
  130. /// <summary>
  131. /// Creates a basic Parcel object without an owner (a zeroed key)
  132. /// </summary>
  133. /// <returns></returns>
  134. public Land createBaseLand()
  135. {
  136. return new Land(LLUUID.Zero, false, m_scene);
  137. }
  138. /// <summary>
  139. /// Adds a land object to the stored list and adds them to the landIDList to what they own
  140. /// </summary>
  141. /// <param name="new_land">The land object being added</param>
  142. public Land addLandObject(Land new_land)
  143. {
  144. lastLandLocalID++;
  145. new_land.landData.localID = lastLandLocalID;
  146. landList.Add(lastLandLocalID, new_land.Copy());
  147. bool[,] landBitmap = new_land.getLandBitmap();
  148. int x, y;
  149. for (x = 0; x < 64; x++)
  150. {
  151. for (y = 0; y < 64; y++)
  152. {
  153. if (landBitmap[x, y])
  154. {
  155. landIDList[x, y] = lastLandLocalID;
  156. }
  157. }
  158. }
  159. landList[lastLandLocalID].forceUpdateLandInfo();
  160. m_scene.EventManager.TriggerLandObjectAdded(new_land, m_scene.RegionInfo.RegionID);
  161. return new_land;
  162. }
  163. /// <summary>
  164. /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
  165. /// </summary>
  166. /// <param name="local_id">Land.localID of the peice of land to remove.</param>
  167. public void removeLandObject(int local_id)
  168. {
  169. int x, y;
  170. for (x = 0; x < 64; x++)
  171. {
  172. for (y = 0; y < 64; y++)
  173. {
  174. if (landIDList[x, y] == local_id)
  175. {
  176. return;
  177. //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
  178. }
  179. }
  180. }
  181. m_scene.EventManager.TriggerLandObjectRemoved(landList[local_id].landData.globalID);
  182. landList.Remove(local_id);
  183. }
  184. public void updateLandObject(int local_id, LandData newData)
  185. {
  186. if (landList.ContainsKey(local_id))
  187. {
  188. landList[local_id].landData = newData.Copy();
  189. m_scene.EventManager.TriggerLandObjectUpdated((uint) local_id, landList[local_id]);
  190. }
  191. else
  192. {
  193. //throw new Exception("Could not update land object. Local ID '" + local_id + "' does not exist");
  194. }
  195. }
  196. private void performFinalLandJoin(Land master, Land slave)
  197. {
  198. int x, y;
  199. bool[,] landBitmapSlave = slave.getLandBitmap();
  200. for (x = 0; x < 64; x++)
  201. {
  202. for (y = 0; y < 64; y++)
  203. {
  204. if (landBitmapSlave[x, y])
  205. {
  206. landIDList[x, y] = master.landData.localID;
  207. }
  208. }
  209. }
  210. removeLandObject(slave.landData.localID);
  211. updateLandObject(master.landData.localID, master.landData);
  212. }
  213. /// <summary>
  214. /// Get the land object at the specified point
  215. /// </summary>
  216. /// <param name="x">Value between 0 - 256 on the x axis of the point</param>
  217. /// <param name="y">Value between 0 - 256 on the y axis of the point</param>
  218. /// <returns>Land object at the point supplied</returns>
  219. public Land getLandObject(float x_float, float y_float)
  220. {
  221. int x;
  222. int y;
  223. try
  224. {
  225. x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / Convert.ToDouble(4.0)));
  226. y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / Convert.ToDouble(4.0)));
  227. }
  228. catch (System.OverflowException)
  229. {
  230. return null;
  231. }
  232. if (x >= 64 || y >= 64 || x < 0 || y < 0)
  233. {
  234. return null;
  235. }
  236. else
  237. {
  238. // Console.WriteLine("Point (" + x + ", " + y + ") determined from point (" + x_float + ", " + y_float + ")");
  239. return landList[landIDList[x, y]];
  240. }
  241. }
  242. public Land getLandObject(int x, int y)
  243. {
  244. if (x >= Constants.RegionSize || y >= Constants.RegionSize || x < 0 || y < 0)
  245. {
  246. // These exceptions here will cause a lot of complaints from the users specifically because
  247. // they happen every time at border crossings
  248. throw new Exception("Error: Parcel not found at point " + x + ", " + y);
  249. }
  250. else
  251. {
  252. return landList[landIDList[x/4, y/4]];
  253. }
  254. }
  255. #endregion
  256. #region Parcel Modification
  257. /// <summary>
  258. /// Subdivides a piece of land
  259. /// </summary>
  260. /// <param name="start_x">West Point</param>
  261. /// <param name="start_y">South Point</param>
  262. /// <param name="end_x">East Point</param>
  263. /// <param name="end_y">North Point</param>
  264. /// <param name="attempting_user_id">LLUUID of user who is trying to subdivide</param>
  265. /// <returns>Returns true if successful</returns>
  266. private bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
  267. {
  268. //First, lets loop through the points and make sure they are all in the same peice of land
  269. //Get the land object at start
  270. Land startLandObject = getLandObject(start_x, start_y);
  271. if (startLandObject == null) return false; //No such land object at the beginning
  272. //Loop through the points
  273. try
  274. {
  275. int totalX = end_x - start_x;
  276. int totalY = end_y - start_y;
  277. int x, y;
  278. for (y = 0; y < totalY; y++)
  279. {
  280. for (x = 0; x < totalX; x++)
  281. {
  282. Land tempLandObject = getLandObject(start_x + x, start_y + y);
  283. if (tempLandObject == null) return false; //No such land object at that point
  284. if (tempLandObject != startLandObject) return false; //Subdividing over 2 land objects; no-no
  285. }
  286. }
  287. }
  288. catch (Exception)
  289. {
  290. return false; //Exception. For now, lets skip subdivision
  291. }
  292. //If we are still here, then they are subdividing within one piece of land
  293. //Check owner
  294. if (startLandObject.landData.ownerID != attempting_user_id)
  295. {
  296. return false; //They cant do this!
  297. }
  298. //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
  299. Land newLand = startLandObject.Copy();
  300. newLand.landData.landName = "Subdivision of " + newLand.landData.landName;
  301. newLand.landData.globalID = LLUUID.Random();
  302. newLand.setLandBitmap(Land.getSquareLandBitmap(start_x, start_y, end_x, end_y));
  303. //Now, lets set the subdivision area of the original to false
  304. int startLandObjectIndex = startLandObject.landData.localID;
  305. landList[startLandObjectIndex].setLandBitmap(
  306. Land.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false));
  307. landList[startLandObjectIndex].forceUpdateLandInfo();
  308. setPrimsTainted();
  309. //Now add the new land object
  310. Land result = addLandObject(newLand);
  311. updateLandObject(startLandObject.landData.localID, startLandObject.landData);
  312. result.sendLandUpdateToAvatarsOverMe();
  313. return true;
  314. }
  315. /// <summary>
  316. /// Join 2 land objects together
  317. /// </summary>
  318. /// <param name="start_x">x value in first piece of land</param>
  319. /// <param name="start_y">y value in first piece of land</param>
  320. /// <param name="end_x">x value in second peice of land</param>
  321. /// <param name="end_y">y value in second peice of land</param>
  322. /// <param name="attempting_user_id">LLUUID of the avatar trying to join the land objects</param>
  323. /// <returns>Returns true if successful</returns>
  324. private bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
  325. {
  326. end_x -= 4;
  327. end_y -= 4;
  328. List<Land> selectedLandObjects = new List<Land>();
  329. int stepXSelected = 0;
  330. int stepYSelected = 0;
  331. for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
  332. {
  333. for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
  334. {
  335. Land p = getLandObject(stepXSelected, stepYSelected);
  336. if (p != null)
  337. {
  338. if (!selectedLandObjects.Contains(p))
  339. {
  340. selectedLandObjects.Add(p);
  341. }
  342. }
  343. }
  344. }
  345. Land masterLandObject = selectedLandObjects[0];
  346. selectedLandObjects.RemoveAt(0);
  347. if (selectedLandObjects.Count < 1)
  348. {
  349. return false; //Only one piece of land selected
  350. }
  351. if (masterLandObject.landData.ownerID != attempting_user_id)
  352. {
  353. return false; //Not the same owner
  354. }
  355. foreach (Land p in selectedLandObjects)
  356. {
  357. if (p.landData.ownerID != masterLandObject.landData.ownerID)
  358. {
  359. return false; //Over multiple users. TODO: make this just ignore this piece of land?
  360. }
  361. }
  362. foreach (Land slaveLandObject in selectedLandObjects)
  363. {
  364. landList[masterLandObject.landData.localID].setLandBitmap(
  365. Land.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap()));
  366. performFinalLandJoin(masterLandObject, slaveLandObject);
  367. }
  368. setPrimsTainted();
  369. masterLandObject.sendLandUpdateToAvatarsOverMe();
  370. return true;
  371. }
  372. #endregion
  373. #region Parcel Updating
  374. /// <summary>
  375. /// Where we send the ParcelOverlay packet to the client
  376. /// </summary>
  377. /// <param name="remote_client">The object representing the client</param>
  378. public void sendParcelOverlay(IClientAPI remote_client)
  379. {
  380. const int LAND_BLOCKS_PER_PACKET = 1024;
  381. int x, y = 0;
  382. byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  383. int byteArrayCount = 0;
  384. int sequenceID = 0;
  385. ParcelOverlayPacket packet;
  386. for (y = 0; y < 64; y++)
  387. {
  388. for (x = 0; x < 64; x++)
  389. {
  390. byte tempByte = (byte) 0; //This represents the byte for the current 4x4
  391. Land currentParcelBlock = getLandObject(x*4, y*4);
  392. if (currentParcelBlock != null)
  393. {
  394. if (currentParcelBlock.landData.ownerID == remote_client.AgentId)
  395. {
  396. //Owner Flag
  397. tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_REQUESTER);
  398. }
  399. else if (currentParcelBlock.landData.salePrice > 0 &&
  400. (currentParcelBlock.landData.authBuyerID == LLUUID.Zero ||
  401. currentParcelBlock.landData.authBuyerID == remote_client.AgentId))
  402. {
  403. //Sale Flag
  404. tempByte = Convert.ToByte(tempByte | LAND_TYPE_IS_FOR_SALE);
  405. }
  406. else if (currentParcelBlock.landData.ownerID == LLUUID.Zero)
  407. {
  408. //Public Flag
  409. tempByte = Convert.ToByte(tempByte | LAND_TYPE_PUBLIC);
  410. }
  411. else
  412. {
  413. //Other Flag
  414. tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_OTHER);
  415. }
  416. //Now for border control
  417. try
  418. {
  419. Land westParcel = null;
  420. Land southParcel = null;
  421. if (x > 0)
  422. {
  423. westParcel = getLandObject((x - 1)*4, y*4);
  424. }
  425. if (y > 0)
  426. {
  427. southParcel = getLandObject(x*4, (y - 1)*4);
  428. }
  429. if (x == 0)
  430. {
  431. tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST);
  432. }
  433. else if (westParcel != null && westParcel != currentParcelBlock)
  434. {
  435. tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST);
  436. }
  437. if (y == 0)
  438. {
  439. tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH);
  440. }
  441. else if (southParcel != null && southParcel != currentParcelBlock)
  442. {
  443. tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH);
  444. }
  445. byteArray[byteArrayCount] = tempByte;
  446. byteArrayCount++;
  447. if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
  448. {
  449. byteArrayCount = 0;
  450. packet = (ParcelOverlayPacket) PacketPool.Instance.GetPacket(PacketType.ParcelOverlay);
  451. packet.ParcelData.Data = byteArray;
  452. packet.ParcelData.SequenceID = sequenceID;
  453. remote_client.OutPacket((Packet) packet, ThrottleOutPacketType.Task);
  454. sequenceID++;
  455. byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  456. }
  457. }
  458. catch (Exception e)
  459. {
  460. m_log.Debug("[LAND]: Skipped Land checks because avatar is out of bounds: " + e.Message);
  461. }
  462. }
  463. }
  464. }
  465. }
  466. public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
  467. bool snap_selection, IClientAPI remote_client)
  468. {
  469. //Get the land objects within the bounds
  470. List<Land> temp = new List<Land>();
  471. int x, y, i;
  472. int inc_x = end_x - start_x;
  473. int inc_y = end_y - start_y;
  474. for (x = 0; x < inc_x; x++)
  475. {
  476. for (y = 0; y < inc_y; y++)
  477. {
  478. Land currentParcel = getLandObject(start_x + x, start_y + y);
  479. if (currentParcel != null)
  480. {
  481. if (!temp.Contains(currentParcel))
  482. {
  483. currentParcel.forceUpdateLandInfo();
  484. temp.Add(currentParcel);
  485. }
  486. }
  487. }
  488. }
  489. int requestResult = LAND_RESULT_SINGLE;
  490. if (temp.Count > 1)
  491. {
  492. requestResult = LAND_RESULT_MULTIPLE;
  493. }
  494. for (i = 0; i < temp.Count; i++)
  495. {
  496. temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
  497. }
  498. sendParcelOverlay(remote_client);
  499. }
  500. public void handleParcelPropertiesUpdateRequest(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client)
  501. {
  502. if (landList.ContainsKey(packet.ParcelData.LocalID))
  503. {
  504. landList[packet.ParcelData.LocalID].updateLandProperties(packet, remote_client);
  505. }
  506. }
  507. public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
  508. {
  509. subdivide(west, south, east, north, remote_client.AgentId);
  510. }
  511. public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
  512. {
  513. join(west, south, east, north, remote_client.AgentId);
  514. }
  515. public void handleParcelSelectObjectsRequest(int local_id, int request_type, IClientAPI remote_client)
  516. {
  517. landList[local_id].sendForceObjectSelect(local_id, request_type, remote_client);
  518. }
  519. public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client)
  520. {
  521. landList[local_id].sendLandObjectOwners(remote_client);
  522. }
  523. #endregion
  524. /// <summary>
  525. /// Resets the sim to the default land object (full sim piece of land owned by the default user)
  526. /// </summary>
  527. public void resetSimLandObjects()
  528. {
  529. //Remove all the land objects in the sim and add a blank, full sim land object set to public
  530. landList.Clear();
  531. lastLandLocalID = START_LAND_LOCAL_ID - 1;
  532. landIDList.Initialize();
  533. Land fullSimParcel = new Land(LLUUID.Zero, false, m_scene);
  534. fullSimParcel.setLandBitmap(Land.getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
  535. fullSimParcel.landData.ownerID = m_regInfo.MasterAvatarAssignedUUID;
  536. addLandObject(fullSimParcel);
  537. }
  538. public List<Land> parcelsNearPoint(LLVector3 position)
  539. {
  540. List<Land> parcelsNear = new List<Land>();
  541. int x, y;
  542. for (x = -4; x <= 4; x += 4)
  543. {
  544. for (y = -4; y <= 4; y += 4)
  545. {
  546. Land check = getLandObject(position.X + x, position.Y + y);
  547. if (check != null)
  548. {
  549. if (!parcelsNear.Contains(check))
  550. {
  551. parcelsNear.Add(check);
  552. }
  553. }
  554. }
  555. }
  556. return parcelsNear;
  557. }
  558. public void sendYouAreBannedNotice(ScenePresence avatar)
  559. {
  560. if (allowedForcefulBans)
  561. {
  562. avatar.ControllingClient.SendAlertMessage(
  563. "You are not allowed on this parcel because you are banned. Please go away. <3 OpenSim Developers");
  564. avatar.PhysicsActor.Position =
  565. new PhysicsVector(avatar.lastKnownAllowedPosition.x, avatar.lastKnownAllowedPosition.y,
  566. avatar.lastKnownAllowedPosition.z);
  567. avatar.PhysicsActor.Velocity = new PhysicsVector(0, 0, 0);
  568. }
  569. else
  570. {
  571. avatar.ControllingClient.SendAlertMessage(
  572. "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim! <3 OpenSim Developers");
  573. }
  574. }
  575. public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
  576. {
  577. if (m_scene.RegionInfo.RegionID == regionID)
  578. {
  579. if (landList[localLandID] != null)
  580. {
  581. Land parcelAvatarIsEntering = landList[localLandID];
  582. if (avatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT)
  583. {
  584. if (parcelAvatarIsEntering.isBannedFromLand(avatar.UUID))
  585. {
  586. sendYouAreBannedNotice(avatar);
  587. }
  588. else if (parcelAvatarIsEntering.isRestrictedFromLand(avatar.UUID))
  589. {
  590. avatar.ControllingClient.SendAlertMessage(
  591. "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!). <3 OpenSim Developers");
  592. }
  593. else
  594. {
  595. avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
  596. }
  597. }
  598. else
  599. {
  600. avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
  601. }
  602. }
  603. }
  604. }
  605. public void sendOutNearestBanLine(IClientAPI avatar)
  606. {
  607. List<ScenePresence> avatars = m_scene.GetAvatars();
  608. foreach (ScenePresence presence in avatars)
  609. {
  610. if (presence.UUID == avatar.AgentId)
  611. {
  612. List<Land> checkLandParcels = parcelsNearPoint(presence.AbsolutePosition);
  613. foreach (Land checkBan in checkLandParcels)
  614. {
  615. if (checkBan.isBannedFromLand(avatar.AgentId))
  616. {
  617. checkBan.sendLandProperties(-30000, false, (int) ParcelManager.ParcelResult.Single, avatar);
  618. return; //Only send one
  619. }
  620. else if (checkBan.isRestrictedFromLand(avatar.AgentId))
  621. {
  622. checkBan.sendLandProperties(-40000, false, (int) ParcelManager.ParcelResult.Single, avatar);
  623. return; //Only send one
  624. }
  625. }
  626. return;
  627. }
  628. }
  629. }
  630. public void sendLandUpdate(ScenePresence avatar, bool force)
  631. {
  632. Land over = getLandObject((int) Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
  633. (int) Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
  634. if (over != null)
  635. {
  636. if (force)
  637. {
  638. if (!avatar.IsChildAgent)
  639. {
  640. over.sendLandUpdateToClient(avatar.ControllingClient);
  641. }
  642. }
  643. if (avatar.currentParcelUUID != over.landData.globalID)
  644. {
  645. if (!avatar.IsChildAgent)
  646. {
  647. over.sendLandUpdateToClient(avatar.ControllingClient);
  648. avatar.currentParcelUUID = over.landData.globalID;
  649. m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.localID,
  650. m_scene.RegionInfo.RegionID);
  651. }
  652. }
  653. }
  654. }
  655. public void sendLandUpdate(ScenePresence avatar)
  656. {
  657. sendLandUpdate(avatar, false);
  658. }
  659. public void handleSignificantClientMovement(IClientAPI remote_client)
  660. {
  661. ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId);
  662. if (clientAvatar != null)
  663. {
  664. sendLandUpdate(clientAvatar);
  665. sendOutNearestBanLine(remote_client);
  666. Land parcel = getLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y);
  667. if (parcel != null)
  668. {
  669. if (clientAvatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT &&
  670. clientAvatar.sentMessageAboutRestrictedParcelFlyingDown)
  671. {
  672. handleAvatarChangingParcel(clientAvatar, parcel.landData.localID, m_scene.RegionInfo.RegionID);
  673. //They are going below the safety line!
  674. if (!parcel.isBannedFromLand(clientAvatar.UUID))
  675. {
  676. clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false;
  677. }
  678. }
  679. else if (clientAvatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT &&
  680. parcel.isBannedFromLand(clientAvatar.UUID))
  681. {
  682. sendYouAreBannedNotice(clientAvatar);
  683. }
  684. }
  685. }
  686. }
  687. public void handleAnyClientMovement(ScenePresence avatar)
  688. //Like handleSignificantClientMovement, but called with an AgentUpdate regardless of distance.
  689. {
  690. Land over = getLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
  691. if (over != null)
  692. {
  693. if (!over.isBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= BAN_LINE_SAFETY_HIEGHT)
  694. {
  695. avatar.lastKnownAllowedPosition =
  696. new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
  697. }
  698. }
  699. }
  700. public void handleParcelAccessRequest(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID,
  701. int landLocalID, IClientAPI remote_client)
  702. {
  703. if (landList.ContainsKey(landLocalID))
  704. {
  705. landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client);
  706. }
  707. }
  708. public void handleParcelAccessUpdateRequest(LLUUID agentID, LLUUID sessionID, uint flags, int landLocalID,
  709. List<ParcelManager.ParcelAccessEntry> entries,
  710. IClientAPI remote_client)
  711. {
  712. if (landList.ContainsKey(landLocalID))
  713. {
  714. if (agentID == landList[landLocalID].landData.ownerID)
  715. {
  716. landList[landLocalID].updateAccessList(flags, entries, remote_client);
  717. }
  718. }
  719. else
  720. {
  721. Console.WriteLine("INVALID LOCAL LAND ID");
  722. }
  723. }
  724. public void resetAllLandPrimCounts()
  725. {
  726. foreach (Land p in landList.Values)
  727. {
  728. p.resetLandPrimCounts();
  729. }
  730. }
  731. public void setPrimsTainted()
  732. {
  733. landPrimCountTainted = true;
  734. }
  735. public void addPrimToLandPrimCounts(SceneObjectGroup obj)
  736. {
  737. LLVector3 position = obj.AbsolutePosition;
  738. Land landUnderPrim = getLandObject(position.X, position.Y);
  739. if (landUnderPrim != null)
  740. {
  741. landUnderPrim.addPrimToCount(obj);
  742. }
  743. }
  744. public void removePrimFromLandPrimCounts(SceneObjectGroup obj)
  745. {
  746. foreach (Land p in landList.Values)
  747. {
  748. p.removePrimFromCount(obj);
  749. }
  750. }
  751. public void finalizeLandPrimCountUpdate()
  752. {
  753. //Get Simwide prim count for owner
  754. Dictionary<LLUUID, List<Land>> landOwnersAndParcels = new Dictionary<LLUUID, List<Land>>();
  755. foreach (Land p in landList.Values)
  756. {
  757. if (!landOwnersAndParcels.ContainsKey(p.landData.ownerID))
  758. {
  759. List<Land> tempList = new List<Land>();
  760. tempList.Add(p);
  761. landOwnersAndParcels.Add(p.landData.ownerID, tempList);
  762. }
  763. else
  764. {
  765. landOwnersAndParcels[p.landData.ownerID].Add(p);
  766. }
  767. }
  768. foreach (LLUUID owner in landOwnersAndParcels.Keys)
  769. {
  770. int simArea = 0;
  771. int simPrims = 0;
  772. foreach (Land p in landOwnersAndParcels[owner])
  773. {
  774. simArea += p.landData.area;
  775. simPrims += p.landData.ownerPrims + p.landData.otherPrims + p.landData.groupPrims +
  776. p.landData.selectedPrims;
  777. }
  778. foreach (Land p in landOwnersAndParcels[owner])
  779. {
  780. p.landData.simwideArea = simArea;
  781. p.landData.simwidePrims = simPrims;
  782. }
  783. }
  784. }
  785. #endregion
  786. }
  787. #endregion
  788. }