PageRenderTime 67ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Modules/World/Land/ParcelManagementModule.cs

https://bitbucket.org/VirtualReality/async-sim-testing
C# | 2423 lines | 1961 code | 256 blank | 206 comment | 371 complexity | 807f802677270bd1e7d9342a0c190f90 MD5 | raw file
  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/, 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 Aurora-Sim 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 Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.DatabaseInterfaces;
  31. using Aurora.Framework.Modules;
  32. using Aurora.Framework.PresenceInfo;
  33. using Aurora.Framework.SceneInfo;
  34. using Aurora.Framework.SceneInfo.Entities;
  35. using Aurora.Framework.Servers.HttpServer;
  36. using Aurora.Framework.Servers.HttpServer.Implementation;
  37. using Aurora.Framework.Servers.HttpServer.Interfaces;
  38. using Aurora.Framework.Services;
  39. using Aurora.Framework.Utilities;
  40. using Nini.Config;
  41. using OpenMetaverse;
  42. using OpenMetaverse.Messages.Linden;
  43. using OpenMetaverse.StructuredData;
  44. using System;
  45. using System.Collections.Generic;
  46. using System.IO;
  47. using System.Linq;
  48. using System.Timers;
  49. using GridRegion = Aurora.Framework.Services.GridRegion;
  50. namespace Aurora.Modules.Land
  51. {
  52. public class ParcelManagementModule : INonSharedRegionModule, IParcelManagementModule
  53. {
  54. #region Constants
  55. //Land types set with flags in ParcelOverlay.
  56. //Only one of these can be used.
  57. public const float BAN_LINE_SAFETY_HEIGHT = 100;
  58. public const int LAND_RESULT_NO_DATA = -1; // The request they made had no data
  59. public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
  60. public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
  61. //ParcelSelectObjects
  62. public const int LAND_SELECT_OBJECTS_GROUP = 4;
  63. public const int LAND_SELECT_OBJECTS_OTHER = 8;
  64. public const int LAND_SELECT_OBJECTS_OWNER = 2;
  65. public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
  66. public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
  67. public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
  68. public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
  69. public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
  70. public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
  71. public const int LAND_OVERLAY_CHUNKS = 4; //The number of land chunks to send to the client
  72. public const int LAND_MAX_ENTRIES_PER_PACKET = 48; //Max number of access/ban entry updates
  73. //These are other constants. Yay!
  74. public const int START_LAND_LOCAL_ID = 0;
  75. #endregion
  76. #region Declares
  77. private static readonly string remoteParcelRequestPath = "0009/";
  78. private readonly List<UUID> m_hasSentParcelOverLay = new List<UUID>();
  79. /// <value>
  80. /// Land objects keyed by local id
  81. /// </value>
  82. private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
  83. private readonly object m_landListLock = new object();
  84. private bool UseDwell = true;
  85. private bool m_TaintedLandData;
  86. private bool m_UpdateDirectoryOnTimer = true;
  87. private bool m_UpdateDirectoryOnUpdate;
  88. private Timer m_UpdateDirectoryTimer = new Timer();
  89. public UUID GodParcelOwner { get; set; }
  90. private string _godParcelOwner = "";
  91. /// <value>
  92. /// Local land ids at specified region co-ordinates (region size / 4)
  93. /// </value>
  94. private int[,] m_landIDList;
  95. private int m_lastLandLocalID = START_LAND_LOCAL_ID;
  96. private int m_minutesBeforeTimer = 1;
  97. protected Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
  98. private IScene m_scene;
  99. private int m_update_land = 200;
  100. //Check whether we need to rebuild the parcel prim count and other land related functions
  101. public int[,] LandIDList
  102. {
  103. get { return m_landIDList; }
  104. }
  105. #endregion
  106. #region INonSharedRegionModule Members
  107. public Type ReplaceableInterface
  108. {
  109. get { return null; }
  110. }
  111. public void Initialise(IConfigSource source)
  112. {
  113. IConfig config = source.Configs["LandManagement"];
  114. if (config != null)
  115. {
  116. m_UpdateDirectoryOnTimer = config.GetBoolean("UpdateOnTimer", m_UpdateDirectoryOnTimer);
  117. m_UpdateDirectoryOnUpdate = config.GetBoolean("UpdateOnUpdate", m_UpdateDirectoryOnUpdate);
  118. m_minutesBeforeTimer = config.GetInt("MinutesBeforeTimerUpdate", m_minutesBeforeTimer);
  119. _godParcelOwner = config.GetString("GodParcelOwner", "");
  120. UseDwell = config.GetBoolean("AllowDwell", true);
  121. }
  122. }
  123. public void AddRegion(IScene scene)
  124. {
  125. m_scene = scene;
  126. m_landIDList = new int[m_scene.RegionInfo.RegionSizeX/4,m_scene.RegionInfo.RegionSizeY/4];
  127. if (m_UpdateDirectoryOnTimer)
  128. {
  129. m_UpdateDirectoryTimer.Interval = 1000*60*m_minutesBeforeTimer;
  130. m_UpdateDirectoryTimer.Elapsed += UpdateDirectoryTimerElapsed;
  131. m_UpdateDirectoryTimer.Start();
  132. }
  133. UUID godParcelOwner = UUID.Zero;
  134. if (_godParcelOwner != "")
  135. {
  136. UserAccount acc = m_scene.UserAccountService.GetUserAccount(null, _godParcelOwner);
  137. if (acc != null)
  138. godParcelOwner = acc.PrincipalID;
  139. }
  140. GodParcelOwner = godParcelOwner;
  141. m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel;
  142. m_scene.EventManager.OnValidateBuyLand += EventManagerOnValidateLandBuy;
  143. m_scene.EventManager.OnNewClient += EventManagerOnNewClient;
  144. m_scene.EventManager.OnMakeRootAgent += CheckEnteringNewParcel;
  145. m_scene.EventManager.OnClientMovement += EventManagerOnSignificantClientMovement;
  146. m_scene.EventManager.OnSignificantObjectMovement += EventManagerOnSignificantObjectMovement;
  147. m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
  148. m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
  149. m_scene.EventManager.OnClosingClient += OnClosingClient;
  150. m_scene.EventManager.OnFrame += EventManager_OnFrame;
  151. m_scene.AuroraEventManager.RegisterEventHandler("ObjectAddedFlag", AuroraEventManager_OnGenericEvent);
  152. m_scene.AuroraEventManager.RegisterEventHandler("ObjectRemovedFlag", AuroraEventManager_OnGenericEvent);
  153. if (m_UpdateDirectoryOnTimer)
  154. m_scene.EventManager.OnStartupComplete += EventManager_OnStartupComplete;
  155. m_scene.RegisterModuleInterface<IParcelManagementModule>(this);
  156. }
  157. public void RegionLoaded(IScene scene)
  158. {
  159. IScheduledMoneyModule moneyModule = m_scene.RequestModuleInterface<IScheduledMoneyModule>();
  160. if (moneyModule != null)
  161. {
  162. moneyModule.OnUserDidNotPay += moneyModule_OnUserDidNotPay;
  163. moneyModule.OnCheckWhetherUserShouldPay += moneyModule_OnCheckWhetherUserShouldPay;
  164. }
  165. }
  166. public void RemoveRegion(IScene scene)
  167. {
  168. List<ILandObject> parcels = AllParcels();
  169. foreach (ILandObject land in parcels)
  170. {
  171. UpdateLandObject(land);
  172. }
  173. if (m_UpdateDirectoryOnTimer)
  174. {
  175. m_UpdateDirectoryTimer.Stop();
  176. m_UpdateDirectoryTimer = null;
  177. }
  178. m_scene.EventManager.OnAvatarEnteringNewParcel -= EventManagerOnAvatarEnteringNewParcel;
  179. m_scene.EventManager.OnValidateBuyLand -= EventManagerOnValidateLandBuy;
  180. m_scene.EventManager.OnNewClient -= EventManagerOnNewClient;
  181. m_scene.EventManager.OnMakeRootAgent -= CheckEnteringNewParcel;
  182. m_scene.EventManager.OnSignificantClientMovement -= EventManagerOnSignificantClientMovement;
  183. m_scene.EventManager.OnSignificantObjectMovement -= EventManagerOnSignificantObjectMovement;
  184. m_scene.EventManager.OnIncomingLandDataFromStorage -= EventManagerOnIncomingLandDataFromStorage;
  185. m_scene.EventManager.OnRegisterCaps -= EventManagerOnRegisterCaps;
  186. m_scene.EventManager.OnClosingClient -= OnClosingClient;
  187. m_scene.UnregisterModuleInterface<IParcelManagementModule>(this);
  188. }
  189. public void Close()
  190. {
  191. }
  192. public string Name
  193. {
  194. get { return "LandManagementModule"; }
  195. }
  196. #endregion
  197. #region MoneyModule pieces (for parcel directory payment)
  198. private bool moneyModule_OnCheckWhetherUserShouldPay(UUID agentID, string paymentTextThatFailed)
  199. {
  200. if (paymentTextThatFailed.StartsWith("Parcel Show in Search Fee - "))
  201. {
  202. UUID parcelGlobalID = UUID.Parse(paymentTextThatFailed.Substring("Parcel Show in Search Fee - ".Length));
  203. //Only charge if the parcel still exists
  204. return GetLandObject(parcelGlobalID) != null;
  205. }
  206. return true;
  207. }
  208. private void moneyModule_OnUserDidNotPay(UUID agentID, string paymentTextThatFailed)
  209. {
  210. UUID parcelGlobalID = UUID.Parse(paymentTextThatFailed.Substring("Parcel Show in Search Fee - ".Length));
  211. ILandObject parcel;
  212. if ((parcel = GetLandObject(parcelGlobalID)) != null)
  213. parcel.LandData.Flags &= (uint) ParcelFlags.ShowDirectory;
  214. }
  215. #endregion
  216. #region Heartbeat Tick, Parcel Returns, Clean temp objects
  217. private readonly HashSet<ISceneEntity> m_entitiesInAutoReturnQueue = new HashSet<ISceneEntity>();
  218. /// <summary>
  219. /// Return object to avatar Message
  220. /// </summary>
  221. /// <param name="agentID">Avatar Unique Id</param>
  222. /// <param name="objectName">Name of object returned</param>
  223. /// <param name="location">Location of object returned</param>
  224. /// <param name="reason">Reasion for object return</param>
  225. /// <param name="groups">The objects to return</param>
  226. public void AddReturns(UUID agentID, string objectName, Vector3 location, string reason,
  227. List<ISceneEntity> groups)
  228. {
  229. lock (m_returns)
  230. {
  231. if (m_returns.ContainsKey(agentID))
  232. {
  233. ReturnInfo info = m_returns[agentID];
  234. info.count += groups.Count;
  235. info.Groups.AddRange(groups);
  236. m_returns[agentID] = info;
  237. }
  238. else
  239. {
  240. ReturnInfo info = new ReturnInfo
  241. {
  242. count = groups.Count,
  243. objectName = objectName,
  244. location = location,
  245. reason = reason,
  246. Groups = groups
  247. };
  248. m_returns[agentID] = info;
  249. }
  250. }
  251. }
  252. private void EventManager_OnFrame()
  253. {
  254. if (m_scene.Frame%m_update_land == 0)
  255. {
  256. //It's time, check the parts we have
  257. CheckFrameEvents();
  258. }
  259. }
  260. private object AuroraEventManager_OnGenericEvent(string FunctionName, object parameters)
  261. {
  262. if (FunctionName == "ObjectAddedFlag")
  263. {
  264. object[] param = (object[]) parameters;
  265. ISceneChildEntity child = (ISceneChildEntity) param[0];
  266. PrimFlags flag = (PrimFlags) param[1];
  267. if (flag == PrimFlags.TemporaryOnRez)
  268. m_entitiesInAutoReturnQueue.Add(child.ParentEntity);
  269. }
  270. else if (FunctionName == "ObjectRemovedFlag")
  271. {
  272. object[] param = (object[]) parameters;
  273. ISceneChildEntity child = (ISceneChildEntity) param[0];
  274. PrimFlags flag = (PrimFlags) param[1];
  275. if (flag == PrimFlags.TemporaryOnRez)
  276. m_entitiesInAutoReturnQueue.Remove(child.ParentEntity);
  277. }
  278. return null;
  279. }
  280. /// <summary>
  281. /// This deals with sending the return IMs as well as actually returning the objects
  282. /// </summary>
  283. protected internal void CheckFrameEvents()
  284. {
  285. // Go through all updates and check for temp and auto return
  286. CheckPrimForAutoReturn();
  287. CheckPrimForTemperary();
  288. lock (m_returns)
  289. {
  290. foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
  291. {
  292. if (ret.Value.reason != "")
  293. {
  294. UUID transaction = UUID.Random();
  295. GridInstantMessage msg = new GridInstantMessage
  296. {
  297. fromAgentID = UUID.Zero,
  298. toAgentID = ret.Key,
  299. imSessionID = transaction,
  300. timestamp = (uint) Util.UnixTimeSinceEpoch(),
  301. fromAgentName = "Server",
  302. dialog = 19,
  303. fromGroup = false,
  304. offline = 1,
  305. ParentEstateID =
  306. m_scene.RegionInfo.EstateSettings.ParentEstateID,
  307. Position = Vector3.Zero,
  308. RegionID = m_scene.RegionInfo.RegionID,
  309. binaryBucket = Util.StringToBytes256("\0")
  310. };
  311. // From server
  312. // Object msg
  313. // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
  314. if (ret.Value.count > 1)
  315. msg.message =
  316. string.Format("Your {0} objects were returned from {1} in region {2} due to {3}",
  317. ret.Value.count, ret.Value.location.ToString(),
  318. m_scene.RegionInfo.RegionName, ret.Value.reason);
  319. else
  320. msg.message = string.Format(
  321. "Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName,
  322. ret.Value.location.ToString(), m_scene.RegionInfo.RegionName, ret.Value.reason);
  323. IMessageTransferModule tr = m_scene.RequestModuleInterface<IMessageTransferModule>();
  324. if (tr != null)
  325. tr.SendInstantMessage(msg);
  326. if (ret.Value.Groups.Count > 1)
  327. MainConsole.Instance.InfoFormat(
  328. "[LandManagement]: Returning {0} objects due to parcel auto return.",
  329. ret.Value.Groups.Count);
  330. else
  331. MainConsole.Instance.Info("[LandManagement]: Returning 1 object due to parcel auto return.");
  332. }
  333. IAsyncSceneObjectGroupDeleter asyncDelete =
  334. m_scene.RequestModuleInterface<IAsyncSceneObjectGroupDeleter>();
  335. if (asyncDelete != null)
  336. {
  337. asyncDelete.DeleteToInventory(
  338. DeRezAction.Return, ret.Value.Groups[0].RootChild.OwnerID, ret.Value.Groups,
  339. ret.Value.Groups[0].RootChild.OwnerID,
  340. true, true);
  341. }
  342. }
  343. m_returns.Clear();
  344. }
  345. }
  346. protected void CheckPrimForTemperary()
  347. {
  348. HashSet<ISceneEntity> entitiesToRemove = new HashSet<ISceneEntity>();
  349. foreach (
  350. ISceneEntity entity in
  351. m_entitiesInAutoReturnQueue.Where(entity => entity.RootChild.Expires <= DateTime.Now))
  352. {
  353. entitiesToRemove.Add(entity);
  354. //Temporary objects don't get a reason, they return quietly
  355. AddReturns(entity.OwnerID, entity.Name, entity.AbsolutePosition, "", new List<ISceneEntity> {entity});
  356. }
  357. foreach (ISceneEntity entity in entitiesToRemove)
  358. {
  359. m_entitiesInAutoReturnQueue.Remove(entity);
  360. }
  361. }
  362. protected void CheckPrimForAutoReturn()
  363. {
  364. // Don't abort the whole thing if one entity happens to give us an exception.
  365. try
  366. {
  367. IPrimCountModule primCount = m_scene.RequestModuleInterface<IPrimCountModule>();
  368. if (primCount == null)
  369. return;
  370. List<ISceneEntity> entities = new List<ISceneEntity>();
  371. foreach (ISceneEntity sog in from parcel in AllParcels()
  372. where parcel != null && parcel.LandData != null &&
  373. parcel.LandData.OtherCleanTime != 0
  374. from sog in primCount.GetPrimCounts(parcel.LandData.GlobalID).Objects
  375. where parcel.LandData.OwnerID != sog.OwnerID &&
  376. ((parcel.LandData.GroupID == UUID.Zero) ||
  377. //If there is no group, don't check the groups part
  378. ((parcel.LandData.GroupID != UUID.Zero) &&
  379. //If there is a group, check for group rezzed prims and group owned prims
  380. (parcel.LandData.GroupID != sog.GroupID &&
  381. //Allow prims set to the group
  382. parcel.LandData.GroupID != sog.OwnerID &&
  383. //Allow group deeded prims!
  384. parcel.LandData.OwnerID != sog.GroupID)
  385. //Allow group deeded prims!
  386. )) &&
  387. !m_scene.Permissions.IsAdministrator(sog.OwnerID)
  388. where (DateTime.UtcNow - sog.RootChild.Rezzed).TotalSeconds >
  389. parcel.LandData.OtherCleanTime*60
  390. select sog)
  391. {
  392. entities.Add(sog);
  393. }
  394. if (entities.Count > 0)
  395. AddReturns(entities[0].OwnerID, entities[0].Name, entities[0].AbsolutePosition, "Auto Parcel Return",
  396. entities);
  397. }
  398. catch (Exception e)
  399. {
  400. MainConsole.Instance.ErrorFormat(
  401. "[LandManagement]: Failed to check for parcel returns: {0}", e);
  402. }
  403. }
  404. #endregion
  405. #region Parcel Add/Remove/Get/Create
  406. private readonly Dictionary<UUID, ParcelResult> m_lastDataResults = new Dictionary<UUID, ParcelResult>();
  407. private readonly Dictionary<UUID, ILandObject> m_lastLandObject = new Dictionary<UUID, ILandObject>();
  408. private readonly Dictionary<UUID, int> m_lastResults = new Dictionary<UUID, int>();
  409. public void UpdateLandObject(ILandObject lo)
  410. {
  411. AddLandObjectToSearch(lo);
  412. m_scene.EventManager.TriggerLandObjectAdded(lo.LandData);
  413. foreach (IScenePresence sp in m_scene.GetScenePresences())
  414. {
  415. if (sp.CurrentParcelUUID == lo.LandData.GlobalID)
  416. {
  417. if (lo.IsEitherBannedOrRestricted(sp.UUID))
  418. {
  419. SendYouAreRestrictedNotice(sp);
  420. Vector3 pos = GetNearestAllowedPosition(sp);
  421. pos.Z -= sp.PhysicsActor.Size.Z;
  422. sp.Teleport(pos);
  423. }
  424. }
  425. }
  426. }
  427. /// <summary>
  428. /// Resets the sim to have no land objects
  429. /// </summary>
  430. public void ClearAllParcels()
  431. {
  432. //Remove all the land objects in the sim and add a blank, full sim land object set to public
  433. List<ILandObject> parcels = new List<ILandObject>(m_landList.Values);
  434. foreach (ILandObject land in parcels)
  435. {
  436. m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.RegionID, land.LandData.GlobalID);
  437. }
  438. lock (m_landListLock)
  439. {
  440. m_landList.Clear();
  441. m_lastLandLocalID = START_LAND_LOCAL_ID;
  442. }
  443. }
  444. /// <summary>
  445. /// Resets the sim to the default land object (full sim piece of land owned by the default user)
  446. /// </summary>
  447. public ILandObject ResetSimLandObjects()
  448. {
  449. ClearAllParcels();
  450. ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
  451. if (fullSimParcel.LandData.OwnerID == UUID.Zero)
  452. fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  453. UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.AllScopeIDs,
  454. fullSimParcel.LandData.OwnerID);
  455. while (fullSimParcel.LandData.OwnerID == UUID.Zero || account == null)
  456. {
  457. MainConsole.Instance.Warn(
  458. "[ParcelManagement]: Could not find user for parcel, please give a valid user to make the owner");
  459. string userName = MainConsole.Instance.Prompt("User Name:", "");
  460. if (userName == "")
  461. {
  462. MainConsole.Instance.Warn("Put in a valid username.");
  463. continue;
  464. }
  465. account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.AllScopeIDs, userName);
  466. if (account != null)
  467. fullSimParcel.LandData.OwnerID = account.PrincipalID;
  468. else
  469. MainConsole.Instance.Warn("Could not find the user.");
  470. }
  471. MainConsole.Instance.Info("[ParcelManagement]: No land found for region " + m_scene.RegionInfo.RegionName +
  472. ", setting owner to " + fullSimParcel.LandData.OwnerID);
  473. fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
  474. fullSimParcel.SetInfoID();
  475. fullSimParcel.LandData.Bitmap =
  476. new byte[(m_scene.RegionInfo.RegionSizeX/4)*(m_scene.RegionInfo.RegionSizeY/4)/8];
  477. fullSimParcel = AddLandObject(fullSimParcel);
  478. ModifyLandBitmapSquare(0, 0,
  479. m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY,
  480. fullSimParcel);
  481. return fullSimParcel;
  482. }
  483. public List<ILandObject> AllParcels()
  484. {
  485. lock (m_landListLock)
  486. return new List<ILandObject>(m_landList.Values);
  487. }
  488. public List<ILandObject> ParcelsNearPoint(Vector3 position)
  489. {
  490. List<ILandObject> parcelsNear = new List<ILandObject>();
  491. for (int x = -4; x <= 4; x += 4)
  492. {
  493. for (int y = -4; y <= 4; y += 4)
  494. {
  495. ILandObject check = GetLandObject((int) (position.X + x), (int) (position.Y + y));
  496. if (check != null)
  497. {
  498. if (!parcelsNear.Contains(check))
  499. {
  500. parcelsNear.Add(check);
  501. }
  502. }
  503. }
  504. }
  505. return parcelsNear;
  506. }
  507. public ILandObject GetLandObject(int parcelLocalID)
  508. {
  509. lock (m_landListLock)
  510. {
  511. ILandObject land = null;
  512. m_landList.TryGetValue(parcelLocalID, out land);
  513. return land;
  514. }
  515. }
  516. public ILandObject GetLandObject(UUID GlobalID)
  517. {
  518. return AllParcels().FirstOrDefault(land => land.LandData.GlobalID == GlobalID);
  519. }
  520. public ILandObject GetLandObject(float x, float y)
  521. {
  522. return GetLandObject((int) x, (int) y);
  523. }
  524. public ILandObject GetLandObject(int x, int y)
  525. {
  526. RegionInfo r = m_scene.RegionInfo;
  527. if (x >= r.RegionSizeX || y >= r.RegionSizeY || x < 0 || y < 0)
  528. {
  529. if (x >= r.RegionSizeX)
  530. x = r.RegionSizeX - 1;
  531. if (x < 0)
  532. x = 1;
  533. if (y >= r.RegionSizeY)
  534. y = r.RegionSizeY - 1;
  535. if (y < 0)
  536. y = 1;
  537. }
  538. lock (m_landListLock)
  539. {
  540. try
  541. {
  542. return m_landList[m_landIDList[x/4, y/4]];
  543. }
  544. catch (IndexOutOfRangeException)
  545. {
  546. return null;
  547. }
  548. catch (KeyNotFoundException)
  549. {
  550. return null;
  551. }
  552. }
  553. }
  554. protected void AddLandObjectToSearch(ILandObject parcel)
  555. {
  556. IDirectoryServiceConnector DSC = Framework.Utilities.DataManager.RequestPlugin<IDirectoryServiceConnector>();
  557. if (DSC != null)
  558. {
  559. if (m_UpdateDirectoryOnUpdate)
  560. //Update search database
  561. DoSearchUpdate();
  562. else if (m_UpdateDirectoryOnTimer)
  563. m_TaintedLandData = true;
  564. }
  565. }
  566. private void RemoveLandObjectFromSearch(ILandObject iLandObject)
  567. {
  568. IDirectoryServiceConnector DSC = Framework.Utilities.DataManager.RequestPlugin<IDirectoryServiceConnector>();
  569. if (DSC != null)
  570. {
  571. if (m_UpdateDirectoryOnUpdate)
  572. //Update search database
  573. DoSearchUpdate();
  574. else if (m_UpdateDirectoryOnTimer)
  575. m_TaintedLandData = true;
  576. }
  577. }
  578. /// <summary>
  579. /// Adds a land object to the stored list and adds them to the landIDList to what they own
  580. /// </summary>
  581. /// <param name="land">The land object being added</param>
  582. public ILandObject AddLandObject(ILandObject land)
  583. {
  584. return AddLandObject(land, false);
  585. }
  586. protected ILandObject AddLandObject(ILandObject land, bool incomingFromDatabase)
  587. {
  588. //Don't make a copy unless necessary
  589. ILandObject new_land = incomingFromDatabase ? land : land.Copy();
  590. new_land.LandData.RegionID = m_scene.RegionInfo.RegionID;
  591. new_land.LandData.RegionHandle = m_scene.RegionInfo.RegionHandle;
  592. lock (m_landListLock)
  593. {
  594. //Update the localID
  595. int newLandLocalID = ++m_lastLandLocalID;
  596. new_land.LandData.LocalID = newLandLocalID;
  597. //Add it to the list of land in this region
  598. m_landList.Add(newLandLocalID, new_land);
  599. }
  600. new_land.ForceUpdateLandInfo();
  601. //If it isn't coming in from the database, make sure to save the new parcel and add it to search
  602. if (!incomingFromDatabase)
  603. {
  604. AddLandObjectToSearch(new_land);
  605. }
  606. //Trigger the event for any interested listeners
  607. m_scene.EventManager.TriggerLandObjectAdded(new_land.LandData);
  608. return new_land;
  609. }
  610. public void SendYouAreBannedNotice(IScenePresence avatar)
  611. {
  612. avatar.ControllingClient.SendAlertMessage(
  613. "You are not allowed on this parcel because you are banned.");
  614. }
  615. public void SendYouAreRestrictedNotice(IScenePresence avatar)
  616. {
  617. avatar.ControllingClient.SendAlertMessage(
  618. "You are not allowed on this parcel because the land owner has restricted access.");
  619. }
  620. public void EventManagerOnAvatarEnteringNewParcel(IScenePresence avatar, ILandObject oldParcel)
  621. {
  622. if (avatar.CurrentParcel != null)
  623. {
  624. //Tell the clint about it
  625. avatar.CurrentParcel.SendLandUpdateToClient(avatar.ControllingClient);
  626. //Gotta kill all avatars outside the parcel
  627. foreach (
  628. IScenePresence sp in
  629. avatar.Scene.Entities.GetPresences()
  630. .Where(sp => sp.UUID != avatar.UUID)
  631. .Where(sp => sp.CurrentParcel != null))
  632. {
  633. if (sp.CurrentParcelUUID == avatar.CurrentParcelUUID) //Send full updates for those in the sim
  634. {
  635. if (avatar.CurrentParcel.LandData.Private || (oldParcel != null && oldParcel.LandData.Private))
  636. //Either one, we gotta send an update
  637. {
  638. sp.SceneViewer.RemoveAvatarFromView(avatar);
  639. avatar.SceneViewer.RemoveAvatarFromView(sp);
  640. sp.SceneViewer.QueuePresenceForFullUpdate(avatar, true);
  641. avatar.SceneViewer.QueuePresenceForFullUpdate(sp, true);
  642. }
  643. }
  644. else //Kill those outside the parcel
  645. {
  646. if (sp.CurrentParcel.LandData.Private || avatar.CurrentParcel.LandData.Private)
  647. {
  648. sp.ControllingClient.SendKillObject(sp.Scene.RegionInfo.RegionHandle,
  649. new IEntity[1] {avatar});
  650. avatar.ControllingClient.SendKillObject(sp.Scene.RegionInfo.RegionHandle,
  651. new IEntity[1] {sp});
  652. sp.SceneViewer.RemoveAvatarFromView(avatar);
  653. avatar.SceneViewer.RemoveAvatarFromView(sp);
  654. }
  655. }
  656. }
  657. if (UseDwell)
  658. avatar.CurrentParcel.LandData.Dwell += 1;
  659. if (avatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HEIGHT)
  660. {
  661. if (avatar.CurrentParcel.IsBannedFromLand(avatar.UUID))
  662. {
  663. SendYouAreBannedNotice(avatar);
  664. Vector3 pos = GetNearestAllowedPosition(avatar);
  665. pos.Z -= avatar.PhysicsActor.Size.Z;
  666. avatar.Teleport(pos);
  667. }
  668. else if (avatar.CurrentParcel.IsRestrictedFromLand(avatar.UUID))
  669. {
  670. SendYouAreRestrictedNotice(avatar);
  671. Vector3 pos = GetNearestAllowedPosition(avatar);
  672. pos.Z -= avatar.PhysicsActor.Size.Z;
  673. avatar.Teleport(pos);
  674. }
  675. }
  676. }
  677. }
  678. private void SendOutNearestBanLine(IScenePresence sp, ILandObject ourLandObject)
  679. {
  680. int multiple = 0;
  681. int result = 0;
  682. Vector3 spAbs = sp.AbsolutePosition;
  683. foreach (ILandObject parcel in from parcel in AllParcels()
  684. let aamax = parcel.LandData.AABBMax
  685. let aamin = parcel.LandData.AABBMin
  686. where Math.Abs(aamax.X - spAbs.X) < 4 ||
  687. Math.Abs(aamax.Y - spAbs.Y) < 4 ||
  688. Math.Abs(aamin.X - spAbs.X) < 4 ||
  689. Math.Abs(aamin.Y - spAbs.Y) < 4
  690. select parcel)
  691. {
  692. //Do the & since we don't need to check again if we have already set the ban flag
  693. if ((result & (int) ParcelPropertiesStatus.CollisionBanned) !=
  694. (int) ParcelPropertiesStatus.CollisionBanned &&
  695. parcel.IsBannedFromLand(sp.UUID))
  696. {
  697. multiple++;
  698. result |= (int) ParcelPropertiesStatus.CollisionBanned;
  699. continue; //Only send one
  700. }
  701. else if ((result & (int) ParcelPropertiesStatus.CollisionNotOnAccessList) !=
  702. (int) ParcelPropertiesStatus.CollisionNotOnAccessList &&
  703. parcel.IsRestrictedFromLand(sp.UUID))
  704. {
  705. multiple++;
  706. result |= (int) ParcelPropertiesStatus.CollisionNotOnAccessList;
  707. continue; //Only send one
  708. }
  709. }
  710. ParcelResult dataResult = ParcelResult.NoData;
  711. if (multiple > 1)
  712. dataResult = ParcelResult.Multiple;
  713. else if (multiple == 1)
  714. dataResult = ParcelResult.Single;
  715. m_lastDataResults[sp.UUID] = dataResult;
  716. m_lastResults[sp.UUID] = result;
  717. m_lastLandObject[sp.UUID] = ourLandObject;
  718. if (multiple == 0) //If there is no result, don't send anything
  719. return;
  720. ourLandObject.SendLandProperties(result, false, (int) dataResult, sp.ControllingClient);
  721. }
  722. private void CheckEnteringNewParcel(IScenePresence avatar)
  723. {
  724. ILandObject over = GetLandObject((int) avatar.AbsolutePosition.X,
  725. (int) avatar.AbsolutePosition.Y);
  726. CheckEnteringNewParcel(avatar, over);
  727. }
  728. private void CheckEnteringNewParcel(IScenePresence avatar, ILandObject over)
  729. {
  730. if (over != null)
  731. {
  732. if (avatar.CurrentParcelUUID != over.LandData.GlobalID)
  733. {
  734. if (!avatar.IsChildAgent)
  735. {
  736. ILandObject oldParcel = avatar.CurrentParcel;
  737. avatar.CurrentParcelUUID = over.LandData.GlobalID;
  738. avatar.CurrentParcel = over;
  739. m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, oldParcel);
  740. }
  741. }
  742. }
  743. }
  744. public void EventManagerOnSignificantClientMovement(IScenePresence sp)
  745. {
  746. IScenePresence clientAvatar = m_scene.GetScenePresence(sp.UUID);
  747. if (clientAvatar != null)
  748. {
  749. ILandObject over = GetLandObject((int) clientAvatar.AbsolutePosition.X,
  750. (int) clientAvatar.AbsolutePosition.Y);
  751. if (over != null)
  752. {
  753. if (!over.IsRestrictedFromLand(clientAvatar.UUID) &&
  754. (!over.IsBannedFromLand(clientAvatar.UUID) ||
  755. clientAvatar.AbsolutePosition.Z >= BAN_LINE_SAFETY_HEIGHT))
  756. //Allow for the flying over of ban lines
  757. {
  758. clientAvatar.LastKnownAllowedPosition =
  759. new Vector3(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y,
  760. clientAvatar.AbsolutePosition.Z);
  761. }
  762. else
  763. {
  764. //Kick them out
  765. Vector3 pos = clientAvatar.LastKnownAllowedPosition == Vector3.Zero
  766. ? GetNearestAllowedPosition(clientAvatar)
  767. : clientAvatar.LastKnownAllowedPosition;
  768. pos.Z = clientAvatar.AbsolutePosition.Z - clientAvatar.PhysicsActor.Size.Z;
  769. clientAvatar.Teleport(pos);
  770. }
  771. CheckEnteringNewParcel(clientAvatar, over);
  772. SendOutNearestBanLine(clientAvatar, over);
  773. }
  774. }
  775. }
  776. //Like handleEventManagerOnSignificantClientMovement, but for objects for parcel incoming object permissions
  777. public void EventManagerOnSignificantObjectMovement(ISceneEntity group)
  778. {
  779. ILandObject over = GetLandObject((int) group.AbsolutePosition.X, (int) group.AbsolutePosition.Y);
  780. if (over != null)
  781. {
  782. //Entered this new parcel
  783. if (over.LandData.GlobalID != group.LastParcelUUID)
  784. {
  785. if (!m_scene.Permissions.CanObjectEntry(group.UUID,
  786. false, group.AbsolutePosition, group.OwnerID))
  787. {
  788. //Revert the position and do not update the parcel ID
  789. group.AbsolutePosition = group.LastSignificantPosition;
  790. //If the object has physics, stop it from moving
  791. if ((group.RootChild.Flags & PrimFlags.Physics) == PrimFlags.Physics)
  792. {
  793. bool wasTemporary = ((group.RootChild.Flags & PrimFlags.TemporaryOnRez) != 0);
  794. bool wasPhantom = ((group.RootChild.Flags & PrimFlags.Phantom) != 0);
  795. bool wasVD = group.RootChild.VolumeDetectActive;
  796. bool needsPhysicalRebuild = group.RootChild.UpdatePrimFlags(false,
  797. wasTemporary,
  798. wasPhantom,
  799. wasVD, null);
  800. if (needsPhysicalRebuild)
  801. group.RebuildPhysicalRepresentation(true);
  802. }
  803. //Send an update so that all clients see it
  804. group.ScheduleGroupTerseUpdate();
  805. }
  806. else
  807. {
  808. UUID oldParcelUUID = group.LastParcelUUID;
  809. //Update the UUID then
  810. group.LastParcelUUID = over.LandData.GlobalID;
  811. //Trigger the event
  812. object[] param = new object[3];
  813. param[0] = group;
  814. param[1] = over.LandData.GlobalID;
  815. param[2] = oldParcelUUID;
  816. m_scene.AuroraEventManager.FireGenericEventHandler("ObjectEnteringNewParcel", param);
  817. }
  818. }
  819. }
  820. }
  821. public void ClientOnParcelAccessListRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID,
  822. int landLocalID, IClientAPI remote_client)
  823. {
  824. ILandObject land = GetLandObject(landLocalID);
  825. if (land != null)
  826. {
  827. land.SendAccessList(agentID, sessionID, flags, sequenceID, remote_client);
  828. }
  829. }
  830. public void ClientOnParcelAccessUpdateListRequest(UUID agentID, UUID sessionID, uint flags, int landLocalID,
  831. List<ParcelManager.ParcelAccessEntry> entries,
  832. IClientAPI remote_client)
  833. {
  834. ILandObject land = GetLandObject(landLocalID);
  835. if (land != null)
  836. {
  837. if (m_scene.Permissions.CanEditParcelAccessList(remote_client.AgentId, land, flags))
  838. {
  839. land.UpdateAccessList(flags, entries, remote_client);
  840. }
  841. }
  842. else
  843. {
  844. MainConsole.Instance.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID);
  845. }
  846. }
  847. /// <summary>
  848. /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
  849. /// </summary>
  850. /// <param name="local_id">Land.localID of the peice of land to remove.</param>
  851. public void removeLandObject(int local_id)
  852. {
  853. lock (m_landListLock)
  854. {
  855. for (int x = 0; x < m_scene.RegionInfo.RegionSizeX/4; x++)
  856. {
  857. for (int y = 0; y < m_scene.RegionInfo.RegionSizeY/4; y++)
  858. {
  859. if (m_landIDList[x, y] == local_id)
  860. {
  861. MainConsole.Instance.WarnFormat(
  862. "[LAND]: Not removing land object {0}; still being used at {1}, {2}",
  863. local_id, x, y);
  864. return;
  865. //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
  866. }
  867. }
  868. }
  869. ILandObject land = m_landList[local_id];
  870. m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.RegionID, land.LandData.GlobalID);
  871. m_landList.Remove(local_id);
  872. RemoveLandObjectFromSearch(land);
  873. }
  874. }
  875. public void ParcelBuyPass(IClientAPI client, UUID agentID, int ParcelLocalID)
  876. {
  877. ILandObject landObject = GetLandObject(ParcelLocalID);
  878. if (landObject == null)
  879. {
  880. client.SendAlertMessage("Could not find the parcel you are currently on.");
  881. return;
  882. }
  883. if (landObject.IsBannedFromLand(agentID))
  884. {
  885. client.SendAlertMessage("You cannot buy a pass as you are banned from this parcel.");
  886. return;
  887. }
  888. IMoneyModule module = m_scene.RequestModuleInterface<IMoneyModule>();
  889. if (module != null)
  890. if (
  891. !module.Transfer(landObject.LandData.OwnerID, client.AgentId, landObject.LandData.PassPrice,
  892. "Parcel Pass"))
  893. {
  894. client.SendAlertMessage("You do not have enough funds to complete this transaction.");
  895. return;
  896. }
  897. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry
  898. {
  899. AgentID = agentID,
  900. Flags = AccessList.Access,
  901. Time = DateTime.Now.AddHours(landObject.LandData.PassHours)
  902. };
  903. landObject.LandData.ParcelAccessList.Add(entry);
  904. client.SendAgentAlertMessage("You have been added to the parcel access list.", false);
  905. }
  906. #endregion
  907. #region Parcel Modification
  908. public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  909. {
  910. join(start_x, start_y, end_x, end_y, attempting_user_id);
  911. }
  912. public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  913. {
  914. subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
  915. }
  916. /// <summary>
  917. /// Subdivides a piece of land
  918. /// </summary>
  919. /// <param name="start_x">West Point</param>
  920. /// <param name="start_y">South Point</param>
  921. /// <param name="end_x">East Point</param>
  922. /// <param name="end_y">North Point</param>
  923. /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param>
  924. /// <returns>Returns true if successful</returns>
  925. private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  926. {
  927. //First, lets loop through the points and make sure they are all in the same peice of land
  928. //Get the land object at start
  929. ILandObject startLandObject = GetLandObject(start_x, start_y);
  930. if (startLandObject == null) return;
  931. //Loop through the points
  932. try
  933. {
  934. int totalX = end_x - start_x;
  935. int totalY = end_y - start_y;
  936. for (int y = 0; y < totalY; y += 2)
  937. {
  938. for (int x = 0; x < totalX; x += 2)
  939. {
  940. ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y);
  941. if (tempLandObject == null) return;
  942. if (tempLandObject != startLandObject) return;
  943. }
  944. }
  945. }
  946. catch (Exception)
  947. {
  948. return;
  949. }
  950. //If we are still here, then they are subdividing within one piece of land
  951. //Check owner
  952. IClientAPI client;
  953. m_scene.ClientManager.TryGetValue(attempting_user_id, out client);
  954. if (!m_scene.Permissions.CanSubdivideParcel(attempting_user_id, startLandObject) &&
  955. (!(m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide &&
  956. m_scene.Permissions.IsGod(attempting_user_id))))
  957. {
  958. client.SendAlertMessage("Permissions: you cannot split this parcel.");
  959. return;
  960. }
  961. //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
  962. ILandObject newLand = startLandObject.Copy();
  963. newLand.LandData.GlobalID = UUID.Random();
  964. newLand.LandData.Dwell = 0; //Reset dwell info when splitting
  965. startLandObject.ForceUpdateLandInfo();
  966. IPrimCountModule primCountsModule = m_scene.RequestModuleInterface<IPrimCountModule>();
  967. //Taint both land objects
  968. if (primCountsModule != null)
  969. {
  970. primCountsModule.TaintPrimCount(newLand);
  971. primCountsModule.TaintPrimCount(startLandObject);
  972. }
  973. //Now add the new land object
  974. ILandObject result = AddLandObject(newLand);
  975. ModifyLandBitmapSquare(start_x, start_y, end_x, end_y, result.LandData.LocalID);
  976. result.SetInfoID();
  977. //Fix the old land object as well
  978. UpdateLandObject(startLandObject);
  979. result.SendLandUpdateToAvatarsOverMe();
  980. //Update the parcel overlay for ALL clients
  981. m_hasSentParcelOverLay.Clear(); //Clear everyone out
  982. m_scene.ForEachClient(SendParcelOverlay);
  983. }
  984. /// <summary>
  985. /// Change a land bitmap at within a square and set those points to a specific value
  986. /// </summary>
  987. /// <param name="start_x"></param>
  988. /// <param name="start_y"></param>
  989. /// <param name="end_x"></param>
  990. /// <param name="end_y"></param>
  991. /// <param name="localIDToSet"></param>
  992. /// <returns></returns>
  993. public void ModifyLandBitmapSquare(int start_x, int start_y, int end_x, int end_y, int localIDToSet)
  994. {
  995. int x, y;
  996. for (y = 0; y < m_scene.RegionInfo.RegionSizeY/4; y++)
  997. {
  998. for (x = 0; x < m_scene.RegionInfo.RegionSizeX/4; x++)
  999. {
  1000. if (x >= start_x/4 && x < end_x/4
  1001. && y >= start_y/4 && y < end_y/4)
  1002. {
  1003. m_landIDList[x, y] = localIDToSet;
  1004. }
  1005. }
  1006. }
  1007. UpdateAllParcelBitmaps();
  1008. }
  1009. public void ModifyLandBitmapSquare(int start_x, int start_y, int end_x, int end_y, ILandObject landObject)
  1010. {
  1011. int x, y;
  1012. for (y = 0; y < m_scene.RegionInfo.RegionSizeY/4; y++)
  1013. {
  1014. for (x = 0; x < m_scene.RegionInfo.RegionSizeX/4; x++)
  1015. {
  1016. if (x >= start_x/4 && x < end_x/4
  1017. && y >= start_y/4 && y < end_y/4)
  1018. {
  1019. m_landIDList[x, y] = landObject.LandData.LocalID;
  1020. }
  1021. }
  1022. }
  1023. UpdateParcelBitmap(landObject);
  1024. }
  1025. /// <summary>
  1026. /// Rebuilds all of the parcel's bitmaps so that they are correct for saving and sending to clients
  1027. /// </summary>
  1028. private void UpdateAllParcelBitmaps()
  1029. {
  1030. foreach (ILandObject lo in AllParcels())
  1031. {
  1032. UpdateParcelBitmap(lo);
  1033. }
  1034. }
  1035. private void UpdateParcelBitmap(ILandObject lo)
  1036. {
  1037. int y, x, i = 0, byteNum = 0;
  1038. byte tempByte = 0;
  1039. for (y = 0; y < m_scene.RegionInfo.RegionSizeY/4; y++)
  1040. {
  1041. for (x = 0; x < m_scene.RegionInfo.RegionSizeX/4; x++)
  1042. {
  1043. tempByte = Convert.ToByte(tempByte |
  1044. Convert.ToByte(m_landIDList[x, y] == lo.LandData.LocalID) << (i++%8));
  1045. if (i%8 == 0)
  1046. {
  1047. lo.LandData.Bitmap[byteNum] = tempByte;
  1048. tempByte = 0;
  1049. i = 0;
  1050. byteNum++;
  1051. }
  1052. }
  1053. }
  1054. }
  1055. private void MergeLandBitmaps(int masterLocalID, int slaveLocalID)
  1056. {
  1057. int x, y;
  1058. for (y = 0; y < m_scene.RegionInfo.RegionSizeY/4; y++)
  1059. {
  1060. for (x = 0; x < m_scene.RegionInfo.RegionSizeX/4; x++)
  1061. {
  1062. if (m_landIDList[x, y] == slaveLocalID)
  1063. m_landIDList[x, y] = masterLocalID;
  1064. }
  1065. }
  1066. UpdateAllParcelBitmaps();
  1067. }
  1068. /// <summary>
  1069. /// Join 2 land objects together
  1070. /// </summary>
  1071. /// <param name="start_x">x value in first piece of land</param>
  1072. /// <param name="start_y">y value in first piece of land</param>
  1073. /// <param name="end_x">x value in second peice of land</param>
  1074. /// <param name="end_y">y value in second peice of land</param>
  1075. /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param>
  1076. /// <returns>Returns true if successful</returns>
  1077. private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  1078. {
  1079. IClientAPI client;
  1080. m_scene.ClientManager.TryGetValue(attempting_user_id, out client);
  1081. if (client == null)
  1082. return;
  1083. end_x -= 4;
  1084. end_y -= 4;
  1085. List<ILandObject> selectedLandObjects = new List<ILandObject>();
  1086. int stepYSelected;
  1087. for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
  1088. {
  1089. int stepXSelected;
  1090. for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
  1091. {
  1092. ILandObject p = GetLandObject(stepXSelected, stepYSelected);
  1093. if (p != null)
  1094. {
  1095. if (!selectedLandObjects.Contains(p))
  1096. {
  1097. selectedLandObjects.Add(p);
  1098. }
  1099. }
  1100. }
  1101. }
  1102. ILandObject masterLandObject = selectedLandObjects[0];
  1103. if (selectedLandObjects.Any(p => !m_scene.Permissions.CanSubdivideParcel(attempting_user_id, p) ||
  1104. (!m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide &&
  1105. !m_scene.Permissions.CanIssueEstateCommand(attempting_user_id, false))))
  1106. {
  1107. client.SendAlertMessage("Permissions: you cannot join these parcels");
  1108. return;
  1109. }
  1110. m_hasSentParcelOverLay.Clear(); //Clear everyone out
  1111. selectedLandObjects.RemoveAt(0);
  1112. if (selectedLandObjects.Count < 1)
  1113. {
  1114. client.SendAlertMessage("Permissions: select more than one parcel before joining");
  1115. return;
  1116. }
  1117. foreach (ILandObject slaveLandObject in selectedLandObjects)
  1118. {
  1119. MergeLandBitmaps(masterLandObject.LandData.LocalID, slaveLandObject.LandData.LocalID);
  1120. removeLandObject(slaveLandObject.LandData.LocalID);
  1121. }
  1122. masterLandObject.LandData.OwnerID = attempting_user_id;
  1123. IPrimCountModule primCountsModule = m_scene.RequestModuleInterface<IPrimCountModule>();
  1124. //Taint both land objects
  1125. if (primCountsModule != null)
  1126. {
  1127. foreach (ILandObject slaveLandObject in selectedLandObjects)
  1128. primCountsModule.TaintPrimCount(slaveLandObject);
  1129. primCountsModule.TaintPrimCount(masterLandObject);
  1130. }
  1131. masterLandObject.SendLandUpdateToAvatarsOverMe();
  1132. UpdateLandObject(masterLandObject);
  1133. }
  1134. #endregion
  1135. #region Parcel Updating
  1136. /// <summary>
  1137. /// Where we send the ParcelOverlay packet to the client
  1138. /// </summary>
  1139. /// <param name="remote_client">The object representing the client</param>
  1140. public void SendParcelOverlay(IClientAPI remote_client)
  1141. {
  1142. if (m_hasSentParcelOverLay.Contains(remote_client.AgentId))
  1143. return; //Already sent
  1144. m_hasSentParcelOverLay.Add(remote_client.AgentId);
  1145. Util.FireAndForget(delegate
  1146. {
  1147. const int LAND_BLOCKS_PER_PACKET = 1024;
  1148. byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  1149. int byteArrayCount = 0;
  1150. int sequenceID = 0;
  1151. for (int y = 0;
  1152. y <
  1153. (LAND_OVERLAY_CHUNKS*m_scene.RegionInfo.RegionSizeY/
  1154. Constants.TerrainPatchSize);
  1155. y++)
  1156. {
  1157. for (int x = 0;
  1158. x <
  1159. (LAND_OVERLAY_CHUNKS*m_scene.RegionInfo.RegionSizeX/
  1160. Constants.TerrainPatchSize);
  1161. x++)
  1162. {
  1163. byte tempByte = 0; //This represents the byte for the current 4x4
  1164. ILandObject currentParcelBlock = GetLandObject(x*LAND_OVERLAY_CHUNKS,
  1165. y*LAND_OVERLAY_CHUNKS);
  1166. if (currentParcelBlock != null)
  1167. {
  1168. if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
  1169. {
  1170. //Owner Flag
  1171. tempByte =
  1172. Convert.ToByte(tempByte |
  1173. (byte) ParcelOverlayType.OwnedBySelf);
  1174. }
  1175. else if (currentParcelBlock.LandData.SalePrice > 0 &&
  1176. (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
  1177. currentParcelBlock.LandData.AuthBuyerID ==
  1178. remote_client.AgentId))
  1179. {
  1180. //Sale Flag
  1181. tempByte =
  1182. Convert.ToByte(tempByte | (byte) ParcelOverlayType.ForSale);
  1183. }
  1184. else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
  1185. {
  1186. //Public Flag
  1187. tempByte =
  1188. Convert.ToByte(tempByte | (byte) ParcelOverlayType.Public);
  1189. }
  1190. else if (currentParcelBlock.LandData.GroupID != UUID.Zero &&
  1191. m_scene.Permissions.IsInGroup(remote_client.AgentId,
  1192. currentParcelBlock.LandData.
  1193. GroupID))
  1194. {
  1195. tempByte =
  1196. Convert.ToByte(tempByte |
  1197. (byte) ParcelOverlayType.OwnedByGroup);
  1198. }
  1199. else
  1200. {
  1201. //Other Flag
  1202. tempByte =
  1203. Convert.ToByte(tempByte |
  1204. (byte) ParcelOverlayType.OwnedByOther);
  1205. }
  1206. if (currentParcelBlock.LandData.Private)
  1207. {
  1208. //Public Flag
  1209. tempByte =
  1210. Convert.ToByte(tempByte | (byte) ParcelOverlayType.Private);
  1211. }
  1212. //Now for border control
  1213. ILandObject westParcel = null;
  1214. ILandObject southParcel = null;
  1215. if (x > 0)
  1216. {
  1217. if (currentParcelBlock.ContainsPoint(
  1218. (x - 1)*LAND_OVERLAY_CHUNKS, y*LAND_OVERLAY_CHUNKS))
  1219. westParcel = currentParcelBlock;
  1220. else
  1221. westParcel = GetLandObject((x - 1)*LAND_OVERLAY_CHUNKS,
  1222. y*LAND_OVERLAY_CHUNKS);
  1223. }
  1224. if (y > 0)
  1225. {
  1226. if (currentParcelBlock.ContainsPoint(x*LAND_OVERLAY_CHUNKS,
  1227. (y - 1)*LAND_OVERLAY_CHUNKS))
  1228. southParcel = currentParcelBlock;
  1229. else
  1230. southParcel = GetLandObject(x*LAND_OVERLAY_CHUNKS,
  1231. (y - 1)*LAND_OVERLAY_CHUNKS);
  1232. }
  1233. if (x == 0)
  1234. {
  1235. tempByte =
  1236. Convert.ToByte(tempByte | (byte) ParcelOverlayType.BorderWest);
  1237. }
  1238. else if (westParcel != null && westParcel != currentParcelBlock)
  1239. {
  1240. tempByte =
  1241. Convert.ToByte(tempByte | (byte) ParcelOverlayType.BorderWest);
  1242. }
  1243. if (y == 0)
  1244. {
  1245. tempByte =
  1246. Convert.ToByte(tempByte |
  1247. (byte) ParcelOverlayType.BorderSouth);
  1248. }
  1249. else if (southParcel != null && southParcel != currentParcelBlock)
  1250. {
  1251. tempByte =
  1252. Convert.ToByte(tempByte |
  1253. (byte) ParcelOverlayType.BorderSouth);
  1254. }
  1255. byteArray[byteArrayCount] = tempByte;
  1256. byteArrayCount++;
  1257. if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
  1258. {
  1259. remote_client.SendLandParcelOverlay(byteArray, sequenceID);
  1260. byteArrayCount = 0;
  1261. sequenceID++;
  1262. }
  1263. }
  1264. }
  1265. }
  1266. byteArray = null;
  1267. }
  1268. );
  1269. }
  1270. public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
  1271. bool snap_selection, IClientAPI remote_client)
  1272. {
  1273. //Get the land objects within the bounds
  1274. List<ILandObject> temp = new List<ILandObject>();
  1275. int inc_x = end_x - start_x;
  1276. int inc_y = end_y - start_y;
  1277. for (int x = 0; x < inc_x; x++)
  1278. {
  1279. for (int y = 0; y < inc_y; y++)
  1280. {
  1281. ILandObject currentParcel = GetLandObject(start_x + x, start_y + y);
  1282. if (currentParcel != null)
  1283. {
  1284. if (!temp.Contains(currentParcel))
  1285. {
  1286. currentParcel.ForceUpdateLandInfo();
  1287. temp.Add(currentParcel);
  1288. }
  1289. }
  1290. }
  1291. }
  1292. int requestResult = LAND_RESULT_SINGLE;
  1293. if (temp.Count > 1)
  1294. {
  1295. requestResult = LAND_RESULT_MULTIPLE;
  1296. }
  1297. foreach (ILandObject t in temp)
  1298. {
  1299. t.SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
  1300. }
  1301. SendParcelOverlay(remote_client);
  1302. }
  1303. public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
  1304. {
  1305. if (localID == -1) //Bad request
  1306. return;
  1307. ILandObject land = GetLandObject(localID);
  1308. if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, land))
  1309. if (land != null)
  1310. land.UpdateLandProperties(args, remote_client);
  1311. }
  1312. public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
  1313. {
  1314. subdivide(west, south, east, north, remote_client.AgentId);
  1315. }
  1316. public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
  1317. {
  1318. join(west, south, east, north, remote_client.AgentId);
  1319. }
  1320. public void ClientOnParcelSelectObjects(int local_id, int request_type,
  1321. List<UUID> returnIDs, IClientAPI remote_client)
  1322. {
  1323. lock (m_landListLock)
  1324. m_landList[local_id].SendForceObjectSelect(local_id, request_type, returnIDs, remote_client);
  1325. }
  1326. public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client)
  1327. {
  1328. ILandObject land = GetLandObject(local_id);
  1329. if (land != null)
  1330. {
  1331. land.SendLandObjectOwners(remote_client);
  1332. }
  1333. else
  1334. {
  1335. MainConsole.Instance.WarnFormat(
  1336. "[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id);
  1337. }
  1338. }
  1339. public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client)
  1340. {
  1341. ILandObject land = GetLandObject(local_id);
  1342. if (land != null)
  1343. {
  1344. if (m_scene.Permissions.IsGod(remote_client.AgentId))
  1345. {
  1346. land.LandData.OwnerID = ownerID;
  1347. land.LandData.AuctionID = 0; //This must be reset!
  1348. land.LandData.GroupID = UUID.Zero;
  1349. land.LandData.IsGroupOwned = false;
  1350. land.LandData.SalePrice = 0;
  1351. land.LandData.AuthBuyerID = UUID.Zero;
  1352. land.LandData.Flags &=
  1353. ~(uint)
  1354. (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects |
  1355. ParcelFlags.ShowDirectory | ParcelFlags.AllowDeedToGroup | ParcelFlags.ContributeWithDeed);
  1356. m_hasSentParcelOverLay.Clear(); //Clear everyone out
  1357. m_scene.ForEachClient(SendParcelOverlay);
  1358. land.SendLandUpdateToClient(true, remote_client);
  1359. UpdateLandObject(land);
  1360. }
  1361. }
  1362. }
  1363. public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client)
  1364. {
  1365. ILandObject land = GetLandObject(local_id);
  1366. if (land != null)
  1367. {
  1368. if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land))
  1369. {
  1370. land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  1371. land.LandData.AuctionID = 0; //This must be reset!
  1372. land.LandData.GroupID = UUID.Zero;
  1373. land.LandData.IsGroupOwned = false;
  1374. land.LandData.SalePrice = 0;
  1375. land.LandData.AuthBuyerID = UUID.Zero;
  1376. land.LandData.Flags &=
  1377. ~(uint)
  1378. (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects |
  1379. ParcelFlags.ShowDirectory | ParcelFlags.AllowDeedToGroup | ParcelFlags.ContributeWithDeed);
  1380. m_hasSentParcelOverLay.Clear(); //Clear everyone out
  1381. m_scene.ForEachClient(SendParcelOverlay);
  1382. land.SendLandUpdateToClient(true, remote_client);
  1383. UpdateLandObject(land);
  1384. }
  1385. }
  1386. }
  1387. public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client)
  1388. {
  1389. ILandObject land = GetLandObject(local_id);
  1390. if (land != null)
  1391. {
  1392. if (m_scene.Permissions.CanReclaimParcel(remote_client.AgentId, land))
  1393. {
  1394. land.LandData.AuctionID = 0; //This must be reset!
  1395. land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  1396. land.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
  1397. land.LandData.GroupID = UUID.Zero;
  1398. land.LandData.IsGroupOwned = false;
  1399. land.LandData.SalePrice = 0;
  1400. land.LandData.AuthBuyerID = UUID.Zero;
  1401. land.LandData.Flags &=
  1402. ~(uint)
  1403. (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects |
  1404. ParcelFlags.ShowDirectory | ParcelFlags.AllowDeedToGroup | ParcelFlags.ContributeWithDeed);
  1405. land.SendLandUpdateToClient(true, remote_client);
  1406. m_hasSentParcelOverLay.Clear(); //Clear everyone out
  1407. m_scene.ForEachClient(SendParcelOverlay);
  1408. UpdateLandObject(land);
  1409. }
  1410. }
  1411. }
  1412. #endregion
  1413. #region Parcel Buy/Deed
  1414. public void ProcessParcelBuy(UUID agentId, UUID groupId, bool final, bool groupOwned,
  1415. bool removeContribution, int parcelLocalID, int parcelArea, int parcelPrice,
  1416. bool authenticated)
  1417. {
  1418. ILandObject land = GetLandObject(parcelLocalID);
  1419. if (land != null)
  1420. {
  1421. EventManager.LandBuyArgs args = new EventManager.LandBuyArgs(agentId, groupId, final, groupOwned,
  1422. removeContribution, parcelLocalID,
  1423. parcelArea,
  1424. parcelPrice, authenticated,
  1425. land.LandData.OwnerID);
  1426. // Make sure that we do all checking that we can sell this land
  1427. if (m_scene.EventManager.TriggerValidateBuyLand(args))
  1428. {
  1429. land.UpdateLandSold(args.agentId, args.groupId, args.groupOwned, (uint) args.transactionID,
  1430. args.parcelPrice, args.parcelArea);
  1431. }
  1432. }
  1433. }
  1434. // After receiving a land buy packet, first the data needs to
  1435. // be validated. This method validates the right to buy the
  1436. // parcel
  1437. public bool EventManagerOnValidateLandBuy(EventManager.LandBuyArgs e)
  1438. {
  1439. if (e.landValidated == false)
  1440. {
  1441. ILandObject lob = GetLandObject(e.parcelLocalID);
  1442. if (lob != null)
  1443. {
  1444. UUID AuthorizedID = lob.LandData.AuthBuyerID;
  1445. int saleprice = lob.LandData.SalePrice;
  1446. UUID pOwnerID = lob.LandData.OwnerID;
  1447. bool landforsale = ((lob.LandData.Flags &
  1448. (uint)
  1449. (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects |
  1450. ParcelFlags.SellParcelObjects)) != 0);
  1451. if ((AuthorizedID == UUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice &&
  1452. landforsale)
  1453. {
  1454. e.parcelOwnerID = pOwnerID;
  1455. e.landValidated = true;
  1456. }
  1457. else
  1458. return false;
  1459. }
  1460. else
  1461. return false;
  1462. }
  1463. return true;
  1464. }
  1465. public void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client)
  1466. {
  1467. ILandObject land = GetLandObject(parcelLocalID);
  1468. if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land))
  1469. return;
  1470. if (land != null)
  1471. {
  1472. land.DeedToGroup(groupID);
  1473. land.SendLandUpdateToClient(true, remote_client);
  1474. m_hasSentParcelOverLay.Clear(); //Clear everyone out
  1475. m_scene.ForEachClient(SendParcelOverlay);
  1476. UpdateLandObject(land);
  1477. }
  1478. }
  1479. #endregion
  1480. #region Land Object From Storage Functions
  1481. public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data, Vector2 parcelOffset)
  1482. {
  1483. bool result = true;
  1484. foreach (LandData t in data.Where(t => !PreprocessIncomingLandObjectFromStorage(t, parcelOffset)))
  1485. result = false;
  1486. if (!result || data.Count == 0) //Force a new base first, then force a merge later
  1487. ResetSimLandObjects();
  1488. foreach (LandData t in data)
  1489. {
  1490. ILandObject new_land = new LandObject(t.OwnerID, t.IsGroupOwned, m_scene);
  1491. new_land.LandData = t;
  1492. if (SetLandBitmapFromByteArray(new_land, !result, parcelOffset))
  1493. //Merge it into the large parcel if possible
  1494. {
  1495. new_land.ForceUpdateLandInfo();
  1496. new_land.SetInfoID();
  1497. AddLandObject(new_land, true);
  1498. }
  1499. }
  1500. if (AllParcels().Count == 0) //Serious fallback
  1501. ResetSimLandObjects();
  1502. }
  1503. private bool SetLandBitmapFromByteArray(ILandObject parcel, bool forceSet, Vector2 offsetOfParcel)
  1504. {
  1505. int avg = (m_scene.RegionInfo.RegionSizeX*m_scene.RegionInfo.RegionSizeY/128);
  1506. int oldParcelRegionAvg = (int) Math.Sqrt(parcel.LandData.Bitmap.Length*128);
  1507. if (parcel.LandData.Bitmap.Length != avg && !(forceSet && parcel.LandData.Bitmap.Length < avg))
  1508. //Are the sizes the same
  1509. {
  1510. //The sim size changed, deal with it
  1511. return false;
  1512. }
  1513. byte tempByte = 0;
  1514. int x = (int) offsetOfParcel.X/4, y = (int) offsetOfParcel.Y/4, i = 0, bitNum = 0;
  1515. if (parcel.LandData.Bitmap.Length < avg)
  1516. {
  1517. byte[] newArray = new byte[avg];
  1518. Array.Copy(parcel.LandData.Bitmap, newArray, parcel.LandData.Bitmap.Length);
  1519. parcel.LandData.Bitmap = newArray;
  1520. }
  1521. for (i = 0; i < avg; i++)
  1522. {
  1523. if (i < parcel.LandData.Bitmap.Length)
  1524. tempByte = parcel.LandData.Bitmap[i];
  1525. else
  1526. break; //All the rest are false then
  1527. for (bitNum = 0; bitNum < 8; bitNum++)
  1528. {
  1529. bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & 1);
  1530. if (bit)
  1531. m_landIDList[x, y] = parcel.LandData.LocalID;
  1532. x++;
  1533. //Remove the offset so that we get a calc from the beginning of the array, not the offset array
  1534. if (x - (int) (offsetOfParcel.X/4) >
  1535. (((forceSet ? oldParcelRegionAvg : m_scene.RegionInfo.RegionSizeX)/4) - 1))
  1536. {
  1537. x = (int) offsetOfParcel.X/4; //Back to the beginning
  1538. y++;
  1539. }
  1540. }
  1541. }
  1542. return true;
  1543. }
  1544. public bool PreprocessIncomingLandObjectFromStorage(LandData data, Vector2 parcelOffset)
  1545. {
  1546. ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
  1547. new_land.LandData = data;
  1548. return SetLandBitmapFromByteArray(new_land, false, parcelOffset);
  1549. }
  1550. public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs,
  1551. IClientAPI remoteClient)
  1552. {
  1553. if (localID != -1)
  1554. {
  1555. ILandObject selectedParcel = GetLandObject(localID);
  1556. if (selectedParcel == null) return;
  1557. selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
  1558. }
  1559. else //Region
  1560. {
  1561. foreach (ILandObject selectedParcel in AllParcels())
  1562. {
  1563. selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
  1564. }
  1565. }
  1566. }
  1567. public void DisableObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs,
  1568. IClientAPI remoteClient)
  1569. {
  1570. if (localID != -1)
  1571. {
  1572. ILandObject selectedParcel = GetLandObject(localID);
  1573. if (selectedParcel == null) return;
  1574. selectedParcel.DisableLandObjects(returnType, agentIDs, taskIDs, remoteClient);
  1575. }
  1576. else
  1577. {
  1578. foreach (ILandObject selectedParcel in AllParcels())
  1579. {
  1580. selectedParcel.DisableLandObjects(returnType, agentIDs, taskIDs, remoteClient);
  1581. }
  1582. }
  1583. }
  1584. #endregion
  1585. #region CAPS handler
  1586. private OSDMap EventManagerOnRegisterCaps(UUID agentID, IHttpServer server)
  1587. {
  1588. OSDMap retVal = new OSDMap();
  1589. retVal["RemoteParcelRequest"] = CapsUtil.CreateCAPS("RemoteParcelRequest", remoteParcelRequestPath);
  1590. server.AddStreamHandler(new GenericStreamHandler("POST", retVal["RemoteParcelRequest"],
  1591. delegate(string path, Stream request,
  1592. OSHttpRequest httpRequest,
  1593. OSHttpResponse httpResponse)
  1594. { return RemoteParcelRequest(request, agentID); }));
  1595. retVal["ParcelPropertiesUpdate"] = CapsUtil.CreateCAPS("ParcelPropertiesUpdate", "");
  1596. server.AddStreamHandler(new GenericStreamHandler("POST", retVal["ParcelPropertiesUpdate"],
  1597. delegate(string path, Stream request,
  1598. OSHttpRequest httpRequest,
  1599. OSHttpResponse httpResponse)
  1600. { return ProcessPropertiesUpdate(request, agentID); }));
  1601. retVal["ParcelMediaURLFilterList"] = CapsUtil.CreateCAPS("ParcelMediaURLFilterList", "");
  1602. server.AddStreamHandler(new GenericStreamHandler("POST", retVal["ParcelMediaURLFilterList"],
  1603. delegate(string path, Stream request,
  1604. OSHttpRequest httpRequest,
  1605. OSHttpResponse httpResponse)
  1606. {
  1607. return ProcessParcelMediaURLFilterList(request,
  1608. agentID);
  1609. }));
  1610. return retVal;
  1611. }
  1612. private byte[] ProcessParcelMediaURLFilterList(Stream request, UUID agentID)
  1613. {
  1614. IClientAPI client;
  1615. if (!m_scene.ClientManager.TryGetValue(agentID, out client))
  1616. {
  1617. MainConsole.Instance.WarnFormat("[LAND] unable to retrieve IClientAPI for {0}", agentID.ToString());
  1618. return OSDParser.SerializeLLSDXmlBytes(new OSDMap());
  1619. }
  1620. OSDMap args = (OSDMap) OSDParser.DeserializeLLSDXml(request);
  1621. ILandObject o = GetLandObject(args["local-id"].AsInteger());
  1622. OSDArray respList = new OSDArray();
  1623. OSDMap resp = new OSDMap();
  1624. resp["local-id"] = o.LandData.LocalID;
  1625. resp["list"] = respList;
  1626. return OSDParser.SerializeLLSDXmlBytes(resp);
  1627. }
  1628. private byte[] ProcessPropertiesUpdate(Stream request, UUID agentID)
  1629. {
  1630. IClientAPI client;
  1631. if (!m_scene.ClientManager.TryGetValue(agentID, out client))
  1632. {
  1633. MainConsole.Instance.WarnFormat("[LAND] unable to retrieve IClientAPI for {0}", agentID.ToString());
  1634. return new byte[0];
  1635. }
  1636. ParcelPropertiesUpdateMessage properties = new ParcelPropertiesUpdateMessage();
  1637. OSDMap args = (OSDMap) OSDParser.DeserializeLLSDXml(request);
  1638. properties.Deserialize(args);
  1639. LandUpdateArgs land_update = new LandUpdateArgs();
  1640. int parcelID = properties.LocalID;
  1641. land_update.AuthBuyerID = properties.AuthBuyerID;
  1642. land_update.Category = properties.Category;
  1643. land_update.Desc = properties.Desc;
  1644. land_update.GroupID = properties.GroupID;
  1645. land_update.LandingType = (byte) properties.Landing;
  1646. land_update.MediaAutoScale = (byte) Convert.ToInt32(properties.MediaAutoScale);
  1647. land_update.MediaID = properties.MediaID;
  1648. land_update.MediaURL = properties.MediaURL;
  1649. land_update.MusicURL = properties.MusicURL;
  1650. land_update.Name = properties.Name;
  1651. land_update.ParcelFlags = (uint) properties.ParcelFlags;
  1652. land_update.PassHours = (int) properties.PassHours;
  1653. land_update.PassPrice = (int) properties.PassPrice;
  1654. land_update.Privacy = properties.Privacy;
  1655. land_update.SalePrice = (int) properties.SalePrice;
  1656. land_update.SnapshotID = properties.SnapshotID;
  1657. land_update.UserLocation = properties.UserLocation;
  1658. land_update.UserLookAt = properties.UserLookAt;
  1659. land_update.MediaDescription = properties.MediaDesc;
  1660. land_update.MediaType = properties.MediaType;
  1661. land_update.MediaWidth = properties.MediaWidth;
  1662. land_update.MediaHeight = properties.MediaHeight;
  1663. land_update.MediaLoop = properties.MediaLoop;
  1664. land_update.ObscureMusic = properties.ObscureMusic;
  1665. land_update.ObscureMedia = properties.ObscureMedia;
  1666. ILandObject land = GetLandObject(parcelID);
  1667. if (land != null)
  1668. land.UpdateLandProperties(land_update, client);
  1669. else
  1670. MainConsole.Instance.WarnFormat("[LAND] unable to find parcelID {0}", parcelID);
  1671. return OSDParser.SerializeLLSDXmlBytes(new OSDMap());
  1672. }
  1673. // We create the InfoUUID by using the regionHandle (64 bit), and the local (integer) x
  1674. // and y coordinate (each 8 bit), encoded in a UUID (128 bit).
  1675. //
  1676. // Request format:
  1677. // <llsd>
  1678. // <map>
  1679. // <key>location</key>
  1680. // <array>
  1681. // <real>1.23</real>
  1682. // <real>45..6</real>
  1683. // <real>78.9</real>
  1684. // </array>
  1685. // <key>region_id</key>
  1686. // <uuid>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</uuid>
  1687. // </map>
  1688. // </llsd>
  1689. private byte[] RemoteParcelRequest(Stream request, UUID agentID)
  1690. {
  1691. UUID parcelID = UUID.Zero;
  1692. try
  1693. {
  1694. OSDMap map = (OSDMap) OSDParser.DeserializeLLSDXml(request);
  1695. if ((map.ContainsKey("region_id") || map.ContainsKey("region_handle")) && map.ContainsKey("location"))
  1696. {
  1697. UUID regionID = map["region_id"].AsUUID();
  1698. OSDArray list = (OSDArray) map["location"];
  1699. uint x = list[0].AsUInteger();
  1700. uint y = list[1].AsUInteger();
  1701. if (map.ContainsKey("region_handle"))
  1702. {
  1703. // if you do a "About Landmark" on a landmark a second time, the viewer sends the
  1704. // region_handle it got earlier via RegionHandleRequest
  1705. ulong regionHandle = map["region_handle"].AsULong();
  1706. parcelID = Util.BuildFakeParcelID(regionHandle, x, y);
  1707. }
  1708. else if (regionID == m_scene.RegionInfo.RegionID)
  1709. {
  1710. // a parcel request for a local parcel => no need to query the grid
  1711. parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y);
  1712. }
  1713. else
  1714. {
  1715. // a parcel request for a parcel in another region. Ask the grid about the region
  1716. GridRegion info = m_scene.GridService.GetRegionByUUID(null, regionID);
  1717. if (info != null)
  1718. parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
  1719. }
  1720. }
  1721. }
  1722. catch (Exception e)
  1723. {
  1724. MainConsole.Instance.ErrorFormat("[LAND] Fetch error: {0}", e.Message);
  1725. MainConsole.Instance.ErrorFormat("[LAND] ... in request {0}", request);
  1726. }
  1727. if (parcelID == UUID.Zero)
  1728. MainConsole.Instance.Warn("[RemoteParcelRequest]: Failed to find parcel, " + request);
  1729. OSDMap res = new OSDMap();
  1730. res["parcel_id"] = parcelID;
  1731. if (parcelID != UUID.Zero)
  1732. MainConsole.Instance.DebugFormat("[RemoteParcelRequest]: Found parcelID {0}", parcelID);
  1733. return OSDParser.SerializeLLSDXmlBytes(res);
  1734. }
  1735. #endregion
  1736. #region IParcelManagementModule Members
  1737. public Vector3 GetNearestAllowedPosition(IScenePresence avatar)
  1738. {
  1739. ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X,
  1740. avatar.AbsolutePosition.Y);
  1741. if (nearestParcel != null)
  1742. {
  1743. Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1));
  1744. //Try to get a location that feels like where they came from
  1745. Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir,
  1746. nearestParcel);
  1747. if (nearestPoint != null)
  1748. {
  1749. //MainConsole.Instance.Info("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
  1750. //Fix Z pos
  1751. nearestPoint = new Vector3(nearestPoint.Value.X, nearestPoint.Value.Y, avatar.AbsolutePosition.Z);
  1752. return nearestPoint.Value;
  1753. }
  1754. //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel
  1755. Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel),
  1756. avatar.AbsolutePosition);
  1757. dir = Vector3.Normalize(directionToParcelCenter);
  1758. nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir,
  1759. nearestParcel);
  1760. if (nearestPoint != null)
  1761. {
  1762. //MainConsole.Instance.Info("They had a zero velocity, sending them to: " + nearestPoint.ToString());
  1763. return nearestPoint.Value;
  1764. }
  1765. //Ultimate backup if we have no idea where they are
  1766. //MainConsole.Instance.Info("Have no idea where they are, sending them to the center of the parcel");
  1767. return GetParcelCenterAtGround(nearestParcel);
  1768. }
  1769. //Go to the edge, this happens in teleporting to a region with no available parcels
  1770. Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
  1771. //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
  1772. return nearestRegionEdgePoint;
  1773. }
  1774. public Vector3 GetParcelCenterAtGround(ILandObject parcel)
  1775. {
  1776. Vector2 center = GetParcelCenter(parcel);
  1777. return GetPositionAtGround(center.X, center.Y);
  1778. }
  1779. public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
  1780. {
  1781. List<ILandObject> all = AllParcels();
  1782. float minParcelDistance = float.MaxValue;
  1783. ILandObject nearestParcel = null;
  1784. foreach (var parcel in all)
  1785. {
  1786. if (!parcel.IsEitherBannedOrRestricted(avatarId))
  1787. {
  1788. float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
  1789. if (parcelDistance < minParcelDistance)
  1790. {
  1791. minParcelDistance = parcelDistance;
  1792. nearestParcel = parcel;
  1793. }
  1794. }
  1795. }
  1796. return nearestParcel;
  1797. }
  1798. public Vector3 GetNearestRegionEdgePosition(IScenePresence avatar)
  1799. {
  1800. float xdistance = avatar.AbsolutePosition.X < m_scene.RegionInfo.RegionSizeX/2
  1801. ? avatar.AbsolutePosition.X
  1802. : m_scene.RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
  1803. float ydistance = avatar.AbsolutePosition.Y < m_scene.RegionInfo.RegionSizeY/2
  1804. ? avatar.AbsolutePosition.Y
  1805. : m_scene.RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
  1806. //find out what vertical edge to go to
  1807. if (xdistance < ydistance)
  1808. {
  1809. if (avatar.AbsolutePosition.X < m_scene.RegionInfo.RegionSizeX/2)
  1810. {
  1811. return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
  1812. }
  1813. else
  1814. {
  1815. return GetPositionAtAvatarHeightOrGroundHeight(avatar, m_scene.RegionInfo.RegionSizeX,
  1816. avatar.AbsolutePosition.Y);
  1817. }
  1818. }
  1819. //find out what horizontal edge to go to
  1820. else
  1821. {
  1822. if (avatar.AbsolutePosition.Y < m_scene.RegionInfo.RegionSizeY/2)
  1823. {
  1824. return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
  1825. }
  1826. else
  1827. {
  1828. return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X,
  1829. m_scene.RegionInfo.RegionSizeY);
  1830. }
  1831. }
  1832. }
  1833. #endregion
  1834. #region Finding parcel point information
  1835. private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction,
  1836. ILandObject parcel)
  1837. {
  1838. Vector3 unitDirection = Vector3.Normalize(direction);
  1839. //Making distance to search go through some sane limit of distance
  1840. int size = m_scene.RegionInfo.RegionSizeX > m_scene.RegionInfo.RegionSizeY
  1841. ? m_scene.RegionInfo.RegionSizeX
  1842. : m_scene.RegionInfo.RegionSizeY;
  1843. for (float distance = 0; distance < size*2; distance += .5f)
  1844. {
  1845. Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
  1846. if (parcel.ContainsPoint((int) testPos.X, (int) testPos.Y))
  1847. {
  1848. return GetPositionAtGround(testPos.X, testPos.Y);
  1849. }
  1850. }
  1851. return null;
  1852. }
  1853. private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y)
  1854. {
  1855. return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel));
  1856. }
  1857. //calculate the average center point of a parcel
  1858. private Vector2 GetParcelCenter(ILandObject parcel)
  1859. {
  1860. int count = 0;
  1861. float avgx = 0;
  1862. float avgy = 0;
  1863. for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x++)
  1864. {
  1865. for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y++)
  1866. {
  1867. //Just keep a running average as we check if all the points are inside or not
  1868. if (parcel.ContainsPoint(x, y))
  1869. {
  1870. if (count == 0)
  1871. {
  1872. //Set this to 1 so that when we multiply down below, it doesn't lock to 0
  1873. if (x == 0)
  1874. x = 1;
  1875. if (y == 0)
  1876. y = 1;
  1877. avgx = x;
  1878. avgy = y;
  1879. }
  1880. else
  1881. {
  1882. avgx = (avgx*count + x)/(count + 1);
  1883. avgy = (avgy*count + y)/(count + 1);
  1884. }
  1885. count += 1;
  1886. }
  1887. }
  1888. }
  1889. return new Vector2(avgx, avgy);
  1890. }
  1891. private Vector3 GetPositionAtAvatarHeightOrGroundHeight(IScenePresence avatar, float x, float y)
  1892. {
  1893. Vector3 ground = GetPositionAtGround(x, y);
  1894. if (avatar.AbsolutePosition.Z > ground.Z)
  1895. {
  1896. ground.Z = avatar.AbsolutePosition.Z;
  1897. }
  1898. return ground;
  1899. }
  1900. private Vector3 GetPositionAtGround(float x, float y)
  1901. {
  1902. ITerrainChannel heightmap = m_scene.RequestModuleInterface<ITerrainChannel>();
  1903. if (heightmap == null)
  1904. return new Vector3(x, y, float.MinValue);
  1905. return new Vector3(x, y, heightmap.GetNormalizedGroundHeight((int) x, (int) y));
  1906. }
  1907. #endregion
  1908. #region Search Updates
  1909. private void EventManager_OnStartupComplete(IScene scene, List<string> data)
  1910. {
  1911. UpdateDirectoryTimerElapsed(null, null);
  1912. }
  1913. private void UpdateDirectoryTimerElapsed(object sender, ElapsedEventArgs e)
  1914. {
  1915. if (m_TaintedLandData)
  1916. {
  1917. DoSearchUpdate();
  1918. m_TaintedLandData = false;
  1919. }
  1920. }
  1921. private void DoSearchUpdate()
  1922. {
  1923. IDirectoryServiceConnector DSC = Framework.Utilities.DataManager.RequestPlugin<IDirectoryServiceConnector>();
  1924. if (DSC != null)
  1925. DSC.AddRegion(AllParcels().ConvertAll(delegate(ILandObject o)
  1926. {
  1927. LandData d = o.LandData.Copy();
  1928. if (d.UserLocation == Vector3.Zero)
  1929. d.UserLocation = GetParcelCenterAtGround(o);
  1930. d.RegionID = o.RegionUUID;
  1931. return d;
  1932. }));
  1933. }
  1934. #endregion
  1935. #region Client Packets
  1936. private void EventManagerOnNewClient(IClientAPI client)
  1937. {
  1938. //Register some client events
  1939. client.OnParcelPropertiesRequest += ClientOnParcelPropertiesRequest;
  1940. client.OnParcelDivideRequest += ClientOnParcelDivideRequest;
  1941. client.OnParcelJoinRequest += ClientOnParcelJoinRequest;
  1942. client.OnParcelPropertiesUpdateRequest += ClientOnParcelPropertiesUpdateRequest;
  1943. client.OnParcelSelectObjects += ClientOnParcelSelectObjects;
  1944. client.OnParcelObjectOwnerRequest += ClientOnParcelObjectOwnerRequest;
  1945. client.OnParcelAccessListRequest += ClientOnParcelAccessListRequest;
  1946. client.OnParcelAccessListUpdateRequest += ClientOnParcelAccessUpdateListRequest;
  1947. client.OnParcelAbandonRequest += ClientOnParcelAbandonRequest;
  1948. client.OnParcelGodForceOwner += ClientOnParcelGodForceOwner;
  1949. client.OnParcelReclaim += ClientOnParcelReclaim;
  1950. client.OnGodlikeMessage += client_OnGodlikeMessage;
  1951. client.OnParcelGodMark += client_OnParcelGodMark;
  1952. client.OnParcelInfoRequest += ClientOnParcelInfoRequest;
  1953. client.OnParcelDwellRequest += ClientOnParcelDwellRequest;
  1954. client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
  1955. client.OnParcelBuyPass += ParcelBuyPass;
  1956. client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
  1957. client.OnParcelEjectUser += ClientOnParcelEjectUser;
  1958. client.OnParcelReturnObjectsRequest += ReturnObjectsInParcel;
  1959. client.OnParcelDisableObjectsRequest += DisableObjectsInParcel;
  1960. client.OnParcelSetOtherCleanTime += SetParcelOtherCleanTime;
  1961. client.OnParcelBuy += ProcessParcelBuy;
  1962. EstateSettings ES = m_scene.RegionInfo.EstateSettings;
  1963. if (UseDwell)
  1964. UseDwell = !ES.BlockDwell;
  1965. m_hasSentParcelOverLay.Remove(client.AgentId);
  1966. IScenePresence presenceEntity;
  1967. if (m_scene.TryGetScenePresence(client.AgentId, out presenceEntity) && !presenceEntity.IsChildAgent)
  1968. {
  1969. /*if (presenceEntity.PhysicsActor != null)
  1970. {
  1971. presenceEntity.PhysicsActor.OnPositionAndVelocityUpdate += delegate ()
  1972. {
  1973. if (m_lastResults.ContainsKey (presenceEntity.UUID) && m_lastResults[presenceEntity.UUID] != 0)
  1974. {
  1975. m_lastLandObject[presenceEntity.UUID].SendLandProperties (m_lastResults[presenceEntity.UUID], false, (int)m_lastDataResults[presenceEntity.UUID], presenceEntity.ControllingClient);
  1976. }
  1977. };
  1978. }*/
  1979. SendParcelOverlay(client);
  1980. }
  1981. }
  1982. private void client_OnGodlikeMessage(IClientAPI client, UUID requester, string Method, List<string> Parameter)
  1983. {
  1984. if (Method == "claimpublicland")
  1985. {
  1986. if (m_scene.Permissions.IsGod(client.AgentId))
  1987. {
  1988. foreach (ILandObject landObject in AllParcels())
  1989. {
  1990. landObject.LandData.OwnerID = client.AgentId;
  1991. landObject.SendLandUpdateToAvatarsOverMe();
  1992. landObject.SendLandUpdateToClient(client);
  1993. }
  1994. }
  1995. }
  1996. }
  1997. private void client_OnParcelGodMark(IClientAPI client, UUID agentID, int ParcelLocalID)
  1998. {
  1999. if (m_scene.Permissions.IsGod(client.AgentId))
  2000. {
  2001. ILandObject parcel = GetLandObject(ParcelLocalID);
  2002. if (parcel != null)
  2003. {
  2004. parcel.LandData.OwnerID = GodParcelOwner;
  2005. parcel.LandData.FirstParty = !parcel.LandData.FirstParty;
  2006. parcel.LandData.Status = ParcelStatus.Abandoned;
  2007. parcel.SendLandUpdateToAvatarsOverMe();
  2008. }
  2009. }
  2010. }
  2011. private void OnClosingClient(IClientAPI client)
  2012. {
  2013. client.OnParcelPropertiesRequest -= ClientOnParcelPropertiesRequest;
  2014. client.OnParcelDivideRequest -= ClientOnParcelDivideRequest;
  2015. client.OnParcelJoinRequest -= ClientOnParcelJoinRequest;
  2016. client.OnParcelPropertiesUpdateRequest -= ClientOnParcelPropertiesUpdateRequest;
  2017. client.OnParcelSelectObjects -= ClientOnParcelSelectObjects;
  2018. client.OnParcelObjectOwnerRequest -= ClientOnParcelObjectOwnerRequest;
  2019. client.OnParcelAccessListRequest -= ClientOnParcelAccessListRequest;
  2020. client.OnParcelAccessListUpdateRequest -= ClientOnParcelAccessUpdateListRequest;
  2021. client.OnParcelAbandonRequest -= ClientOnParcelAbandonRequest;
  2022. client.OnParcelGodForceOwner -= ClientOnParcelGodForceOwner;
  2023. client.OnParcelReclaim -= ClientOnParcelReclaim;
  2024. client.OnParcelInfoRequest -= ClientOnParcelInfoRequest;
  2025. client.OnParcelDwellRequest -= ClientOnParcelDwellRequest;
  2026. client.OnParcelDeedToGroup -= ClientOnParcelDeedToGroup;
  2027. client.OnParcelBuyPass -= ParcelBuyPass;
  2028. client.OnParcelFreezeUser -= ClientOnParcelFreezeUser;
  2029. client.OnParcelEjectUser -= ClientOnParcelEjectUser;
  2030. client.OnParcelReturnObjectsRequest -= ReturnObjectsInParcel;
  2031. client.OnParcelDisableObjectsRequest -= DisableObjectsInParcel;
  2032. client.OnParcelSetOtherCleanTime -= SetParcelOtherCleanTime;
  2033. client.OnParcelBuy -= ProcessParcelBuy;
  2034. m_hasSentParcelOverLay.Remove(client.AgentId);
  2035. }
  2036. private void ClientOnParcelDwellRequest(int localID, IClientAPI remoteClient)
  2037. {
  2038. ILandObject selectedParcel = GetLandObject(localID);
  2039. if (selectedParcel == null)
  2040. return;
  2041. remoteClient.SendParcelDwellReply(localID, selectedParcel.LandData.GlobalID, selectedParcel.LandData.Dwell);
  2042. }
  2043. private void ClientOnParcelInfoRequest(IClientAPI remoteClient, UUID parcelID)
  2044. {
  2045. if (parcelID == UUID.Zero)
  2046. return;
  2047. ulong RegionHandle = 0;
  2048. uint X, Y, Z;
  2049. Util.ParseFakeParcelID(parcelID, out RegionHandle,
  2050. out X, out Y, out Z);
  2051. MainConsole.Instance.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
  2052. RegionHandle, X, Y);
  2053. IDirectoryServiceConnector DSC = Framework.Utilities.DataManager.RequestPlugin<IDirectoryServiceConnector>();
  2054. if (DSC != null)
  2055. {
  2056. LandData data = DSC.GetParcelInfo(parcelID);
  2057. if (data != null) // if we found some data, send it
  2058. {
  2059. GridRegion info;
  2060. int RegionX, RegionY;
  2061. Util.UlongToInts(RegionHandle, out RegionX, out RegionY);
  2062. RegionX = (int) ((float) RegionX/Constants.RegionSize)*Constants.RegionSize;
  2063. RegionY = (RegionY/Constants.RegionSize)*Constants.RegionSize;
  2064. if (RegionX == m_scene.RegionInfo.RegionLocX &&
  2065. RegionY == m_scene.RegionInfo.RegionLocY)
  2066. {
  2067. info = new GridRegion(m_scene.RegionInfo);
  2068. }
  2069. else
  2070. {
  2071. // most likely still cached from building the extLandData entry
  2072. info = m_scene.GridService.GetRegionByPosition(null, RegionX, RegionY);
  2073. }
  2074. if (info == null)
  2075. {
  2076. MainConsole.Instance.WarnFormat("[LAND]: Failed to find region having parcel {0} @ {1} {2}",
  2077. parcelID, X, Y);
  2078. return;
  2079. }
  2080. // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
  2081. MainConsole.Instance.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...",
  2082. data.Name, RegionHandle);
  2083. remoteClient.SendParcelInfo(data, parcelID, (uint) (info.RegionLocX + data.UserLocation.X),
  2084. (uint) (info.RegionLocY + data.UserLocation.Y), info.RegionName);
  2085. }
  2086. else
  2087. MainConsole.Instance.WarnFormat("[LAND]: Failed to find parcel {0}", parcelID);
  2088. }
  2089. else
  2090. MainConsole.Instance.Debug("[LAND] got no directory service; not sending");
  2091. }
  2092. public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
  2093. {
  2094. ILandObject land = GetLandObject(localID);
  2095. if (land == null) return;
  2096. if (!m_scene.Permissions.CanEditParcel(remoteClient.AgentId, land))
  2097. return;
  2098. if (land.LandData.OtherCleanTime != otherCleanTime)
  2099. ResetRezzedObjectTime(land);
  2100. land.LandData.OtherCleanTime = otherCleanTime;
  2101. UpdateLandObject(land);
  2102. }
  2103. private void ResetRezzedObjectTime(ILandObject land)
  2104. {
  2105. IPrimCountModule primCount = m_scene.RequestModuleInterface<IPrimCountModule>();
  2106. foreach (ISceneEntity sog in primCount.GetPrimCounts(land.LandData.GlobalID).Objects)
  2107. {
  2108. sog.RootChild.Rezzed = DateTime.UtcNow;
  2109. }
  2110. }
  2111. public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
  2112. {
  2113. IScenePresence targetAvatar = m_scene.GetScenePresence(target);
  2114. IScenePresence parcelOwner = m_scene.GetScenePresence(parcelowner);
  2115. ILandObject land = GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
  2116. if (
  2117. !m_scene.Permissions.GenericParcelPermission(client.AgentId, land,
  2118. (ulong) GroupPowers.LandEjectAndFreeze))
  2119. return;
  2120. if (flags == 0)
  2121. {
  2122. targetAvatar.Frozen = true;
  2123. targetAvatar.ControllingClient.SendAlertMessage(parcelOwner.Name +
  2124. " has frozen you for 30 seconds. You cannot move or interact with the world.");
  2125. parcelOwner.ControllingClient.SendAlertMessage("Avatar Frozen.");
  2126. }
  2127. else
  2128. {
  2129. targetAvatar.Frozen = false;
  2130. targetAvatar.ControllingClient.SendAlertMessage(parcelOwner.Name + " has unfrozen you.");
  2131. parcelOwner.ControllingClient.SendAlertMessage("Avatar Unfrozen.");
  2132. }
  2133. }
  2134. public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
  2135. {
  2136. IScenePresence targetAvatar = m_scene.GetScenePresence(target);
  2137. IScenePresence parcelOwner = m_scene.GetScenePresence(parcelowner);
  2138. ILandObject land = GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
  2139. if (
  2140. !m_scene.Permissions.GenericParcelPermission(client.AgentId, land,
  2141. (ulong) GroupPowers.LandEjectAndFreeze))
  2142. return;
  2143. land.LandData.ParcelAccessList.Add(new ParcelManager.ParcelAccessEntry
  2144. {
  2145. AgentID = targetAvatar.UUID,
  2146. Flags = AccessList.Ban,
  2147. Time = DateTime.MaxValue
  2148. });
  2149. land.LandData.Flags |= (uint) ParcelFlags.UseBanList;
  2150. Vector3 Pos = GetNearestAllowedPosition(targetAvatar);
  2151. if (flags == 0)
  2152. {
  2153. //Remove if ban wasn't selected
  2154. land.LandData.ParcelAccessList.Remove(new ParcelManager.ParcelAccessEntry
  2155. {
  2156. AgentID = targetAvatar.UUID,
  2157. Flags = AccessList.Ban,
  2158. Time = DateTime.MaxValue
  2159. });
  2160. }
  2161. targetAvatar.Teleport(Pos);
  2162. targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelOwner.Name);
  2163. parcelOwner.ControllingClient.SendAlertMessage("Avatar Ejected.");
  2164. }
  2165. #endregion
  2166. }
  2167. }