LandManagementModule.cs 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Diagnostics;
  31. using System.Reflection;
  32. using log4net;
  33. using Nini.Config;
  34. using OpenMetaverse;
  35. using OpenMetaverse.StructuredData;
  36. using OpenMetaverse.Messages.Linden;
  37. using OpenSim.Framework;
  38. using OpenSim.Framework.Capabilities;
  39. using OpenSim.Framework.Servers;
  40. using OpenSim.Framework.Servers.HttpServer;
  41. using OpenSim.Services.Interfaces;
  42. using OpenSim.Region.Framework.Interfaces;
  43. using OpenSim.Region.Framework.Scenes;
  44. using OpenSim.Region.Physics.Manager;
  45. using Caps=OpenSim.Framework.Capabilities.Caps;
  46. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  47. namespace OpenSim.Region.CoreModules.World.Land
  48. {
  49. // used for caching
  50. internal class ExtendedLandData {
  51. public LandData LandData;
  52. public ulong RegionHandle;
  53. public uint X, Y;
  54. public byte RegionAccess;
  55. }
  56. public class LandManagementModule : INonSharedRegionModule
  57. {
  58. private static readonly ILog m_log =
  59. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  60. private static readonly string remoteParcelRequestPath = "0009/";
  61. private LandChannel landChannel;
  62. private Scene m_scene;
  63. // Minimum for parcels to work is 64m even if we don't actually use them.
  64. #pragma warning disable 0429
  65. private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
  66. #pragma warning restore 0429
  67. /// <value>
  68. /// Local land ids at specified region co-ordinates (region size / 4)
  69. /// </value>
  70. private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax];
  71. /// <value>
  72. /// Land objects keyed by local id
  73. /// </value>
  74. private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
  75. private bool m_landPrimCountTainted;
  76. private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
  77. private bool m_allowedForcefulBans = true;
  78. // caches ExtendedLandData
  79. private Cache parcelInfoCache;
  80. private Vector3? forcedPosition = null;
  81. #region INonSharedRegionModule Members
  82. public Type ReplaceableInterface
  83. {
  84. get { return null; }
  85. }
  86. public void Initialise(IConfigSource source)
  87. {
  88. }
  89. public void AddRegion(Scene scene)
  90. {
  91. m_scene = scene;
  92. m_landIDList.Initialize();
  93. landChannel = new LandChannel(scene, this);
  94. parcelInfoCache = new Cache();
  95. parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache
  96. parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0);
  97. m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd;
  98. m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate;
  99. m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel;
  100. m_scene.EventManager.OnClientMovement += EventManagerOnClientMovement;
  101. m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy;
  102. m_scene.EventManager.OnLandBuy += EventManagerOnLandBuy;
  103. m_scene.EventManager.OnNewClient += EventManagerOnNewClient;
  104. m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement;
  105. m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
  106. m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage;
  107. m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
  108. m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
  109. m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate;
  110. m_scene.EventManager.OnParcelPrimCountTainted += EventManagerOnParcelPrimCountTainted;
  111. m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
  112. lock (m_scene)
  113. {
  114. m_scene.LandChannel = (ILandChannel)landChannel;
  115. }
  116. }
  117. public void RegionLoaded(Scene scene)
  118. {
  119. }
  120. public void RemoveRegion(Scene scene)
  121. {
  122. }
  123. // private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
  124. // {
  125. // ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
  126. // reason = "You are not allowed to enter this sim.";
  127. // return nearestParcel != null;
  128. // }
  129. void EventManagerOnNewClient(IClientAPI client)
  130. {
  131. //Register some client events
  132. client.OnParcelPropertiesRequest += ClientOnParcelPropertiesRequest;
  133. client.OnParcelDivideRequest += ClientOnParcelDivideRequest;
  134. client.OnParcelJoinRequest += ClientOnParcelJoinRequest;
  135. client.OnParcelPropertiesUpdateRequest += ClientOnParcelPropertiesUpdateRequest;
  136. client.OnParcelSelectObjects += ClientOnParcelSelectObjects;
  137. client.OnParcelObjectOwnerRequest += ClientOnParcelObjectOwnerRequest;
  138. client.OnParcelAccessListRequest += ClientOnParcelAccessListRequest;
  139. client.OnParcelAccessListUpdateRequest += ClientOnParcelAccessUpdateListRequest;
  140. client.OnParcelAbandonRequest += ClientOnParcelAbandonRequest;
  141. client.OnParcelGodForceOwner += ClientOnParcelGodForceOwner;
  142. client.OnParcelReclaim += ClientOnParcelReclaim;
  143. client.OnParcelInfoRequest += ClientOnParcelInfoRequest;
  144. client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
  145. client.OnPreAgentUpdate += ClientOnPreAgentUpdate;
  146. EntityBase presenceEntity;
  147. if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
  148. {
  149. SendLandUpdate((ScenePresence)presenceEntity, true);
  150. SendParcelOverlay(client);
  151. }
  152. }
  153. void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
  154. {
  155. //If we are forcing a position for them to go
  156. if (forcedPosition != null)
  157. {
  158. ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);
  159. //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
  160. //When the avatar walks into a ban line on the ground, it prevents getting stuck
  161. agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
  162. //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
  163. if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition.Value) < .2)
  164. {
  165. Debug.WriteLine(string.Format("Stopping force position because {0} is close enough to position {1}", forcedPosition.Value, clientAvatar.AbsolutePosition));
  166. forcedPosition = null;
  167. }
  168. //if we are far away, teleport
  169. else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition.Value) > 3)
  170. {
  171. Debug.WriteLine(string.Format("Teleporting out because {0} is too far from avatar position {1}", forcedPosition.Value, clientAvatar.AbsolutePosition));
  172. clientAvatar.Teleport(forcedPosition.Value);
  173. forcedPosition = null;
  174. }
  175. else
  176. {
  177. //Forces them toward the forced position we want if they aren't there yet
  178. agentData.UseClientAgentPosition = true;
  179. agentData.ClientAgentPosition = forcedPosition.Value;
  180. }
  181. }
  182. }
  183. public void PostInitialise()
  184. {
  185. }
  186. public void Close()
  187. {
  188. }
  189. public string Name
  190. {
  191. get { return "LandManagementModule"; }
  192. }
  193. public bool IsSharedModule
  194. {
  195. get { return false; }
  196. }
  197. #endregion
  198. #region Parcel Add/Remove/Get/Create
  199. public void EventManagerOnSetAllowedForcefulBan(bool forceful)
  200. {
  201. AllowedForcefulBans = forceful;
  202. }
  203. public void UpdateLandObject(int local_id, LandData data)
  204. {
  205. LandData newData = data.Copy();
  206. newData.LocalID = local_id;
  207. lock (m_landList)
  208. {
  209. if (m_landList.ContainsKey(local_id))
  210. {
  211. m_landList[local_id].LandData = newData;
  212. m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]);
  213. }
  214. }
  215. }
  216. public bool AllowedForcefulBans
  217. {
  218. get { return m_allowedForcefulBans; }
  219. set { m_allowedForcefulBans = value; }
  220. }
  221. /// <summary>
  222. /// Resets the sim to the default land object (full sim piece of land owned by the default user)
  223. /// </summary>
  224. public void ResetSimLandObjects()
  225. {
  226. //Remove all the land objects in the sim and add a blank, full sim land object set to public
  227. lock (m_landList)
  228. {
  229. m_landList.Clear();
  230. m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
  231. m_landIDList.Initialize();
  232. }
  233. ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
  234. fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
  235. fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  236. fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
  237. AddLandObject(fullSimParcel);
  238. }
  239. public List<ILandObject> AllParcels()
  240. {
  241. lock (m_landList)
  242. {
  243. return new List<ILandObject>(m_landList.Values);
  244. }
  245. }
  246. public List<ILandObject> ParcelsNearPoint(Vector3 position)
  247. {
  248. List<ILandObject> parcelsNear = new List<ILandObject>();
  249. for (int x = -4; x <= 4; x += 4)
  250. {
  251. for (int y = -4; y <= 4; y += 4)
  252. {
  253. ILandObject check = GetLandObject(position.X + x, position.Y + y);
  254. if (check != null)
  255. {
  256. if (!parcelsNear.Contains(check))
  257. {
  258. parcelsNear.Add(check);
  259. }
  260. }
  261. }
  262. }
  263. return parcelsNear;
  264. }
  265. public void SendYouAreBannedNotice(ScenePresence avatar)
  266. {
  267. if (AllowedForcefulBans)
  268. {
  269. avatar.ControllingClient.SendAlertMessage(
  270. "You are not allowed on this parcel because you are banned. Please go away.");
  271. }
  272. else
  273. {
  274. avatar.ControllingClient.SendAlertMessage(
  275. "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!");
  276. }
  277. }
  278. private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
  279. {
  280. if (m_scene.Permissions.IsGod(avatar.UUID)) return;
  281. if (position.HasValue)
  282. {
  283. forcedPosition = position;
  284. }
  285. }
  286. public void SendYouAreRestrictedNotice(ScenePresence avatar)
  287. {
  288. avatar.ControllingClient.SendAlertMessage(
  289. "You are not allowed on this parcel because the land owner has restricted access.");
  290. }
  291. public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID)
  292. {
  293. if (m_scene.RegionInfo.RegionID == regionID)
  294. {
  295. ILandObject parcelAvatarIsEntering;
  296. lock (m_landList)
  297. {
  298. parcelAvatarIsEntering = m_landList[localLandID];
  299. }
  300. if (parcelAvatarIsEntering != null)
  301. {
  302. if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
  303. {
  304. if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
  305. {
  306. SendYouAreBannedNotice(avatar);
  307. ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
  308. }
  309. else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
  310. {
  311. SendYouAreRestrictedNotice(avatar);
  312. ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
  313. }
  314. else
  315. {
  316. avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
  317. }
  318. }
  319. else
  320. {
  321. avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
  322. }
  323. }
  324. }
  325. }
  326. public void SendOutNearestBanLine(IClientAPI client)
  327. {
  328. ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
  329. if (sp == null || sp.IsChildAgent)
  330. return;
  331. List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition);
  332. foreach (ILandObject checkBan in checkLandParcels)
  333. {
  334. if (checkBan.IsBannedFromLand(client.AgentId))
  335. {
  336. checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, client);
  337. return; //Only send one
  338. }
  339. if (checkBan.IsRestrictedFromLand(client.AgentId))
  340. {
  341. checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, client);
  342. return; //Only send one
  343. }
  344. }
  345. return;
  346. }
  347. public void SendLandUpdate(ScenePresence avatar, bool force)
  348. {
  349. ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
  350. (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
  351. if (over != null)
  352. {
  353. if (force)
  354. {
  355. if (!avatar.IsChildAgent)
  356. {
  357. over.SendLandUpdateToClient(avatar.ControllingClient);
  358. m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
  359. m_scene.RegionInfo.RegionID);
  360. }
  361. }
  362. if (avatar.currentParcelUUID != over.LandData.GlobalID)
  363. {
  364. if (!avatar.IsChildAgent)
  365. {
  366. over.SendLandUpdateToClient(avatar.ControllingClient);
  367. avatar.currentParcelUUID = over.LandData.GlobalID;
  368. m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
  369. m_scene.RegionInfo.RegionID);
  370. }
  371. }
  372. }
  373. }
  374. public void SendLandUpdate(ScenePresence avatar)
  375. {
  376. SendLandUpdate(avatar, false);
  377. }
  378. public void EventManagerOnSignificantClientMovement(IClientAPI remote_client)
  379. {
  380. ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId);
  381. if (clientAvatar != null)
  382. {
  383. SendLandUpdate(clientAvatar);
  384. SendOutNearestBanLine(remote_client);
  385. ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y);
  386. if (parcel != null)
  387. {
  388. if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
  389. clientAvatar.sentMessageAboutRestrictedParcelFlyingDown)
  390. {
  391. EventManagerOnAvatarEnteringNewParcel(clientAvatar, parcel.LandData.LocalID,
  392. m_scene.RegionInfo.RegionID);
  393. //They are going under the safety line!
  394. if (!parcel.IsBannedFromLand(clientAvatar.UUID))
  395. {
  396. clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false;
  397. }
  398. }
  399. else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
  400. parcel.IsBannedFromLand(clientAvatar.UUID))
  401. {
  402. //once we've sent the message once, keep going toward the target until we are done
  403. if (forcedPosition == null)
  404. {
  405. SendYouAreBannedNotice(clientAvatar);
  406. ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar));
  407. }
  408. }
  409. else if (parcel.IsRestrictedFromLand(clientAvatar.UUID))
  410. {
  411. //once we've sent the message once, keep going toward the target until we are done
  412. if (forcedPosition == null)
  413. {
  414. SendYouAreRestrictedNotice(clientAvatar);
  415. ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar));
  416. }
  417. }
  418. else
  419. {
  420. //when we are finally in a safe place, lets release the forced position lock
  421. forcedPosition = null;
  422. }
  423. }
  424. }
  425. }
  426. public void EventManagerOnClientMovement(ScenePresence avatar)
  427. //Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance.
  428. {
  429. ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
  430. if (over != null)
  431. {
  432. if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT))
  433. {
  434. avatar.lastKnownAllowedPosition =
  435. new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
  436. }
  437. }
  438. }
  439. public void ClientOnParcelAccessListRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID,
  440. int landLocalID, IClientAPI remote_client)
  441. {
  442. ILandObject land;
  443. lock (m_landList)
  444. {
  445. m_landList.TryGetValue(landLocalID, out land);
  446. }
  447. if (land != null)
  448. {
  449. m_landList[landLocalID].SendAccessList(agentID, sessionID, flags, sequenceID, remote_client);
  450. }
  451. }
  452. public void ClientOnParcelAccessUpdateListRequest(UUID agentID, UUID sessionID, uint flags, int landLocalID,
  453. List<ParcelManager.ParcelAccessEntry> entries,
  454. IClientAPI remote_client)
  455. {
  456. ILandObject land;
  457. lock (m_landList)
  458. {
  459. m_landList.TryGetValue(landLocalID, out land);
  460. }
  461. if (land != null)
  462. {
  463. if (agentID == land.LandData.OwnerID)
  464. {
  465. land.UpdateAccessList(flags, entries, remote_client);
  466. }
  467. }
  468. else
  469. {
  470. m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID);
  471. }
  472. }
  473. /// <summary>
  474. /// Creates a basic Parcel object without an owner (a zeroed key)
  475. /// </summary>
  476. /// <returns></returns>
  477. public ILandObject CreateBaseLand()
  478. {
  479. return new LandObject(UUID.Zero, false, m_scene);
  480. }
  481. /// <summary>
  482. /// Adds a land object to the stored list and adds them to the landIDList to what they own
  483. /// </summary>
  484. /// <param name="new_land">The land object being added</param>
  485. public ILandObject AddLandObject(ILandObject land)
  486. {
  487. ILandObject new_land = land.Copy();
  488. lock (m_landList)
  489. {
  490. int newLandLocalID = ++m_lastLandLocalID;
  491. new_land.LandData.LocalID = newLandLocalID;
  492. bool[,] landBitmap = new_land.GetLandBitmap();
  493. for (int x = 0; x < landArrayMax; x++)
  494. {
  495. for (int y = 0; y < landArrayMax; y++)
  496. {
  497. if (landBitmap[x, y])
  498. {
  499. m_landIDList[x, y] = newLandLocalID;
  500. }
  501. }
  502. }
  503. m_landList.Add(newLandLocalID, new_land);
  504. }
  505. new_land.ForceUpdateLandInfo();
  506. m_scene.EventManager.TriggerLandObjectAdded(new_land);
  507. return new_land;
  508. }
  509. /// <summary>
  510. /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
  511. /// </summary>
  512. /// <param name="local_id">Land.localID of the peice of land to remove.</param>
  513. public void removeLandObject(int local_id)
  514. {
  515. lock (m_landList)
  516. {
  517. for (int x = 0; x < 64; x++)
  518. {
  519. for (int y = 0; y < 64; y++)
  520. {
  521. if (m_landIDList[x, y] == local_id)
  522. {
  523. m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}",
  524. local_id, x, y);
  525. return;
  526. //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
  527. }
  528. }
  529. }
  530. m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID);
  531. m_landList.Remove(local_id);
  532. }
  533. }
  534. private void performFinalLandJoin(ILandObject master, ILandObject slave)
  535. {
  536. bool[,] landBitmapSlave = slave.GetLandBitmap();
  537. lock (m_landList)
  538. {
  539. for (int x = 0; x < 64; x++)
  540. {
  541. for (int y = 0; y < 64; y++)
  542. {
  543. if (landBitmapSlave[x, y])
  544. {
  545. m_landIDList[x, y] = master.LandData.LocalID;
  546. }
  547. }
  548. }
  549. }
  550. removeLandObject(slave.LandData.LocalID);
  551. UpdateLandObject(master.LandData.LocalID, master.LandData);
  552. }
  553. public ILandObject GetLandObject(int parcelLocalID)
  554. {
  555. lock (m_landList)
  556. {
  557. if (m_landList.ContainsKey(parcelLocalID))
  558. {
  559. return m_landList[parcelLocalID];
  560. }
  561. }
  562. return null;
  563. }
  564. /// <summary>
  565. /// Get the land object at the specified point
  566. /// </summary>
  567. /// <param name="x_float">Value between 0 - 256 on the x axis of the point</param>
  568. /// <param name="y_float">Value between 0 - 256 on the y axis of the point</param>
  569. /// <returns>Land object at the point supplied</returns>
  570. public ILandObject GetLandObject(float x_float, float y_float)
  571. {
  572. int x;
  573. int y;
  574. if (x_float > Constants.RegionSize || x_float <= 0 || y_float > Constants.RegionSize || y_float <= 0)
  575. return null;
  576. try
  577. {
  578. x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0));
  579. y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0));
  580. }
  581. catch (OverflowException)
  582. {
  583. return null;
  584. }
  585. if (x >= 64 || y >= 64 || x < 0 || y < 0)
  586. {
  587. return null;
  588. }
  589. lock (m_landList)
  590. {
  591. // Corner case. If an autoreturn happens during sim startup
  592. // we will come here with the list uninitialized
  593. //
  594. if (m_landList.ContainsKey(m_landIDList[x, y]))
  595. return m_landList[m_landIDList[x, y]];
  596. return null;
  597. }
  598. }
  599. public ILandObject GetLandObject(int x, int y)
  600. {
  601. if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
  602. {
  603. // These exceptions here will cause a lot of complaints from the users specifically because
  604. // they happen every time at border crossings
  605. throw new Exception("Error: Parcel not found at point " + x + ", " + y);
  606. }
  607. lock (m_landIDList)
  608. {
  609. try
  610. {
  611. if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4]))
  612. return m_landList[m_landIDList[x / 4, y / 4]];
  613. else
  614. return null;
  615. }
  616. catch (IndexOutOfRangeException)
  617. {
  618. return null;
  619. }
  620. }
  621. }
  622. #endregion
  623. #region Parcel Modification
  624. public void ResetAllLandPrimCounts()
  625. {
  626. lock (m_landList)
  627. {
  628. foreach (LandObject p in m_landList.Values)
  629. {
  630. p.ResetLandPrimCounts();
  631. }
  632. }
  633. }
  634. public void EventManagerOnParcelPrimCountTainted()
  635. {
  636. m_landPrimCountTainted = true;
  637. }
  638. public bool IsLandPrimCountTainted()
  639. {
  640. return m_landPrimCountTainted;
  641. }
  642. public void EventManagerOnParcelPrimCountAdd(SceneObjectGroup obj)
  643. {
  644. Vector3 position = obj.AbsolutePosition;
  645. ILandObject landUnderPrim = GetLandObject(position.X, position.Y);
  646. if (landUnderPrim != null)
  647. {
  648. landUnderPrim.AddPrimToCount(obj);
  649. }
  650. }
  651. public void EventManagerOnObjectBeingRemovedFromScene(SceneObjectGroup obj)
  652. {
  653. lock (m_landList)
  654. {
  655. foreach (LandObject p in m_landList.Values)
  656. {
  657. p.RemovePrimFromCount(obj);
  658. }
  659. }
  660. }
  661. public void FinalizeLandPrimCountUpdate()
  662. {
  663. //Get Simwide prim count for owner
  664. Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>();
  665. lock (m_landList)
  666. {
  667. foreach (LandObject p in m_landList.Values)
  668. {
  669. if (!landOwnersAndParcels.ContainsKey(p.LandData.OwnerID))
  670. {
  671. List<LandObject> tempList = new List<LandObject>();
  672. tempList.Add(p);
  673. landOwnersAndParcels.Add(p.LandData.OwnerID, tempList);
  674. }
  675. else
  676. {
  677. landOwnersAndParcels[p.LandData.OwnerID].Add(p);
  678. }
  679. }
  680. }
  681. foreach (UUID owner in landOwnersAndParcels.Keys)
  682. {
  683. int simArea = 0;
  684. int simPrims = 0;
  685. foreach (LandObject p in landOwnersAndParcels[owner])
  686. {
  687. simArea += p.LandData.Area;
  688. simPrims += p.LandData.OwnerPrims + p.LandData.OtherPrims + p.LandData.GroupPrims +
  689. p.LandData.SelectedPrims;
  690. }
  691. foreach (LandObject p in landOwnersAndParcels[owner])
  692. {
  693. p.LandData.SimwideArea = simArea;
  694. p.LandData.SimwidePrims = simPrims;
  695. }
  696. }
  697. }
  698. public void EventManagerOnParcelPrimCountUpdate()
  699. {
  700. ResetAllLandPrimCounts();
  701. EntityBase[] entities = m_scene.Entities.GetEntities();
  702. foreach (EntityBase obj in entities)
  703. {
  704. if (obj != null)
  705. {
  706. if ((obj is SceneObjectGroup) && !obj.IsDeleted && !((SceneObjectGroup) obj).IsAttachment)
  707. {
  708. m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup) obj);
  709. }
  710. }
  711. }
  712. FinalizeLandPrimCountUpdate();
  713. m_landPrimCountTainted = false;
  714. }
  715. public void EventManagerOnRequestParcelPrimCountUpdate()
  716. {
  717. ResetAllLandPrimCounts();
  718. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  719. FinalizeLandPrimCountUpdate();
  720. m_landPrimCountTainted = false;
  721. }
  722. /// <summary>
  723. /// Subdivides a piece of land
  724. /// </summary>
  725. /// <param name="start_x">West Point</param>
  726. /// <param name="start_y">South Point</param>
  727. /// <param name="end_x">East Point</param>
  728. /// <param name="end_y">North Point</param>
  729. /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param>
  730. /// <returns>Returns true if successful</returns>
  731. private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  732. {
  733. //First, lets loop through the points and make sure they are all in the same peice of land
  734. //Get the land object at start
  735. ILandObject startLandObject = GetLandObject(start_x, start_y);
  736. if (startLandObject == null) return;
  737. //Loop through the points
  738. try
  739. {
  740. int totalX = end_x - start_x;
  741. int totalY = end_y - start_y;
  742. for (int y = 0; y < totalY; y++)
  743. {
  744. for (int x = 0; x < totalX; x++)
  745. {
  746. ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y);
  747. if (tempLandObject == null) return;
  748. if (tempLandObject != startLandObject) return;
  749. }
  750. }
  751. }
  752. catch (Exception)
  753. {
  754. return;
  755. }
  756. //If we are still here, then they are subdividing within one piece of land
  757. //Check owner
  758. if (!m_scene.Permissions.CanEditParcel(attempting_user_id, startLandObject))
  759. {
  760. return;
  761. }
  762. //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
  763. ILandObject newLand = startLandObject.Copy();
  764. newLand.LandData.Name = newLand.LandData.Name;
  765. newLand.LandData.GlobalID = UUID.Random();
  766. newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
  767. //Now, lets set the subdivision area of the original to false
  768. int startLandObjectIndex = startLandObject.LandData.LocalID;
  769. lock (m_landList)
  770. {
  771. m_landList[startLandObjectIndex].SetLandBitmap(
  772. newLand.ModifyLandBitmapSquare(startLandObject.GetLandBitmap(), start_x, start_y, end_x, end_y, false));
  773. m_landList[startLandObjectIndex].ForceUpdateLandInfo();
  774. }
  775. EventManagerOnParcelPrimCountTainted();
  776. //Now add the new land object
  777. ILandObject result = AddLandObject(newLand);
  778. UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData);
  779. result.SendLandUpdateToAvatarsOverMe();
  780. }
  781. /// <summary>
  782. /// Join 2 land objects together
  783. /// </summary>
  784. /// <param name="start_x">x value in first piece of land</param>
  785. /// <param name="start_y">y value in first piece of land</param>
  786. /// <param name="end_x">x value in second peice of land</param>
  787. /// <param name="end_y">y value in second peice of land</param>
  788. /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param>
  789. /// <returns>Returns true if successful</returns>
  790. private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  791. {
  792. end_x -= 4;
  793. end_y -= 4;
  794. List<ILandObject> selectedLandObjects = new List<ILandObject>();
  795. int stepYSelected;
  796. for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
  797. {
  798. int stepXSelected;
  799. for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
  800. {
  801. ILandObject p = GetLandObject(stepXSelected, stepYSelected);
  802. if (p != null)
  803. {
  804. if (!selectedLandObjects.Contains(p))
  805. {
  806. selectedLandObjects.Add(p);
  807. }
  808. }
  809. }
  810. }
  811. ILandObject masterLandObject = selectedLandObjects[0];
  812. selectedLandObjects.RemoveAt(0);
  813. if (selectedLandObjects.Count < 1)
  814. {
  815. return;
  816. }
  817. if (!m_scene.Permissions.CanEditParcel(attempting_user_id, masterLandObject))
  818. {
  819. return;
  820. }
  821. foreach (ILandObject p in selectedLandObjects)
  822. {
  823. if (p.LandData.OwnerID != masterLandObject.LandData.OwnerID)
  824. {
  825. return;
  826. }
  827. }
  828. lock (m_landList)
  829. {
  830. foreach (ILandObject slaveLandObject in selectedLandObjects)
  831. {
  832. m_landList[masterLandObject.LandData.LocalID].SetLandBitmap(
  833. slaveLandObject.MergeLandBitmaps(masterLandObject.GetLandBitmap(), slaveLandObject.GetLandBitmap()));
  834. performFinalLandJoin(masterLandObject, slaveLandObject);
  835. }
  836. }
  837. EventManagerOnParcelPrimCountTainted();
  838. masterLandObject.SendLandUpdateToAvatarsOverMe();
  839. }
  840. public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  841. {
  842. join(start_x, start_y, end_x, end_y, attempting_user_id);
  843. }
  844. public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  845. {
  846. subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
  847. }
  848. #endregion
  849. #region Parcel Updating
  850. /// <summary>
  851. /// Where we send the ParcelOverlay packet to the client
  852. /// </summary>
  853. /// <param name="remote_client">The object representing the client</param>
  854. public void SendParcelOverlay(IClientAPI remote_client)
  855. {
  856. const int LAND_BLOCKS_PER_PACKET = 1024;
  857. byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  858. int byteArrayCount = 0;
  859. int sequenceID = 0;
  860. int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize;
  861. for (int y = 0; y < blockmeters; y++)
  862. {
  863. for (int x = 0; x < blockmeters; x++)
  864. {
  865. byte tempByte = 0; //This represents the byte for the current 4x4
  866. ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4);
  867. if (currentParcelBlock != null)
  868. {
  869. if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
  870. {
  871. //Owner Flag
  872. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
  873. }
  874. else if (currentParcelBlock.LandData.SalePrice > 0 &&
  875. (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
  876. currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
  877. {
  878. //Sale Flag
  879. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
  880. }
  881. else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
  882. {
  883. //Public Flag
  884. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
  885. }
  886. else
  887. {
  888. //Other Flag
  889. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
  890. }
  891. //Now for border control
  892. ILandObject westParcel = null;
  893. ILandObject southParcel = null;
  894. if (x > 0)
  895. {
  896. westParcel = GetLandObject((x - 1) * 4, y * 4);
  897. }
  898. if (y > 0)
  899. {
  900. southParcel = GetLandObject(x * 4, (y - 1) * 4);
  901. }
  902. if (x == 0)
  903. {
  904. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
  905. }
  906. else if (westParcel != null && westParcel != currentParcelBlock)
  907. {
  908. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
  909. }
  910. if (y == 0)
  911. {
  912. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
  913. }
  914. else if (southParcel != null && southParcel != currentParcelBlock)
  915. {
  916. tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
  917. }
  918. byteArray[byteArrayCount] = tempByte;
  919. byteArrayCount++;
  920. if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
  921. {
  922. remote_client.SendLandParcelOverlay(byteArray, sequenceID);
  923. byteArrayCount = 0;
  924. sequenceID++;
  925. byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  926. }
  927. }
  928. }
  929. }
  930. }
  931. public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
  932. bool snap_selection, IClientAPI remote_client)
  933. {
  934. //Get the land objects within the bounds
  935. List<ILandObject> temp = new List<ILandObject>();
  936. int inc_x = end_x - start_x;
  937. int inc_y = end_y - start_y;
  938. for (int x = 0; x < inc_x; x++)
  939. {
  940. for (int y = 0; y < inc_y; y++)
  941. {
  942. ILandObject currentParcel = GetLandObject(start_x + x, start_y + y);
  943. if (currentParcel != null)
  944. {
  945. if (!temp.Contains(currentParcel))
  946. {
  947. currentParcel.ForceUpdateLandInfo();
  948. temp.Add(currentParcel);
  949. }
  950. }
  951. }
  952. }
  953. int requestResult = LandChannel.LAND_RESULT_SINGLE;
  954. if (temp.Count > 1)
  955. {
  956. requestResult = LandChannel.LAND_RESULT_MULTIPLE;
  957. }
  958. for (int i = 0; i < temp.Count; i++)
  959. {
  960. temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
  961. }
  962. SendParcelOverlay(remote_client);
  963. }
  964. public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
  965. {
  966. ILandObject land;
  967. lock (m_landList)
  968. {
  969. m_landList.TryGetValue(localID, out land);
  970. }
  971. if (land != null)
  972. {
  973. land.UpdateLandProperties(args, remote_client);
  974. m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client);
  975. }
  976. }
  977. public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
  978. {
  979. subdivide(west, south, east, north, remote_client.AgentId);
  980. }
  981. public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
  982. {
  983. join(west, south, east, north, remote_client.AgentId);
  984. }
  985. public void ClientOnParcelSelectObjects(int local_id, int request_type,
  986. List<UUID> returnIDs, IClientAPI remote_client)
  987. {
  988. m_landList[local_id].SendForceObjectSelect(local_id, request_type, returnIDs, remote_client);
  989. }
  990. public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client)
  991. {
  992. ILandObject land;
  993. lock (m_landList)
  994. {
  995. m_landList.TryGetValue(local_id, out land);
  996. }
  997. if (land != null)
  998. {
  999. m_landList[local_id].SendLandObjectOwners(remote_client);
  1000. }
  1001. else
  1002. {
  1003. m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id);
  1004. }
  1005. }
  1006. public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client)
  1007. {
  1008. ILandObject land;
  1009. lock (m_landList)
  1010. {
  1011. m_landList.TryGetValue(local_id, out land);
  1012. }
  1013. if (land != null)
  1014. {
  1015. if (m_scene.Permissions.IsGod(remote_client.AgentId))
  1016. {
  1017. land.LandData.OwnerID = ownerID;
  1018. land.LandData.GroupID = UUID.Zero;
  1019. land.LandData.IsGroupOwned = false;
  1020. land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  1021. m_scene.ForEachClient(SendParcelOverlay);
  1022. land.SendLandUpdateToClient(true, remote_client);
  1023. }
  1024. }
  1025. }
  1026. public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client)
  1027. {
  1028. ILandObject land;
  1029. lock (m_landList)
  1030. {
  1031. m_landList.TryGetValue(local_id, out land);
  1032. }
  1033. if (land != null)
  1034. {
  1035. if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land))
  1036. {
  1037. land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  1038. land.LandData.GroupID = UUID.Zero;
  1039. land.LandData.IsGroupOwned = false;
  1040. land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  1041. m_scene.ForEachClient(SendParcelOverlay);
  1042. land.SendLandUpdateToClient(true, remote_client);
  1043. }
  1044. }
  1045. }
  1046. public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client)
  1047. {
  1048. ILandObject land;
  1049. lock (m_landList)
  1050. {
  1051. m_landList.TryGetValue(local_id, out land);
  1052. }
  1053. if (land != null)
  1054. {
  1055. if (m_scene.Permissions.CanReclaimParcel(remote_client.AgentId, land))
  1056. {
  1057. land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  1058. land.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
  1059. land.LandData.GroupID = UUID.Zero;
  1060. land.LandData.IsGroupOwned = false;
  1061. land.LandData.SalePrice = 0;
  1062. land.LandData.AuthBuyerID = UUID.Zero;
  1063. land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  1064. m_scene.ForEachClient(SendParcelOverlay);
  1065. land.SendLandUpdateToClient(true, remote_client);
  1066. }
  1067. }
  1068. }
  1069. #endregion
  1070. // If the economy has been validated by the economy module,
  1071. // and land has been validated as well, this method transfers
  1072. // the land ownership
  1073. public void EventManagerOnLandBuy(Object o, EventManager.LandBuyArgs e)
  1074. {
  1075. if (e.economyValidated && e.landValidated)
  1076. {
  1077. ILandObject land;
  1078. lock (m_landList)
  1079. {
  1080. m_landList.TryGetValue(e.parcelLocalID, out land);
  1081. }
  1082. if (land != null)
  1083. {
  1084. land.UpdateLandSold(e.agentId, e.groupId, e.groupOwned, (uint)e.transactionID, e.parcelPrice, e.parcelArea);
  1085. }
  1086. }
  1087. }
  1088. // After receiving a land buy packet, first the data needs to
  1089. // be validated. This method validates the right to buy the
  1090. // parcel
  1091. public void EventManagerOnValidateLandBuy(Object o, EventManager.LandBuyArgs e)
  1092. {
  1093. if (e.landValidated == false)
  1094. {
  1095. ILandObject lob = null;
  1096. lock (m_landList)
  1097. {
  1098. m_landList.TryGetValue(e.parcelLocalID, out lob);
  1099. }
  1100. if (lob != null)
  1101. {
  1102. UUID AuthorizedID = lob.LandData.AuthBuyerID;
  1103. int saleprice = lob.LandData.SalePrice;
  1104. UUID pOwnerID = lob.LandData.OwnerID;
  1105. bool landforsale = ((lob.LandData.Flags &
  1106. (uint)(ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects)) != 0);
  1107. if ((AuthorizedID == UUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale)
  1108. {
  1109. // TODO I don't think we have to lock it here, no?
  1110. //lock (e)
  1111. //{
  1112. e.parcelOwnerID = pOwnerID;
  1113. e.landValidated = true;
  1114. //}
  1115. }
  1116. }
  1117. }
  1118. }
  1119. void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client)
  1120. {
  1121. ILandObject land;
  1122. lock (m_landList)
  1123. {
  1124. m_landList.TryGetValue(parcelLocalID, out land);
  1125. }
  1126. if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land))
  1127. return;
  1128. if (land != null)
  1129. {
  1130. land.DeedToGroup(groupID);
  1131. }
  1132. }
  1133. #region Land Object From Storage Functions
  1134. public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
  1135. {
  1136. for (int i = 0; i < data.Count; i++)
  1137. {
  1138. IncomingLandObjectFromStorage(data[i]);
  1139. }
  1140. }
  1141. public void IncomingLandObjectFromStorage(LandData data)
  1142. {
  1143. ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
  1144. new_land.LandData = data.Copy();
  1145. new_land.SetLandBitmapFromByteArray();
  1146. AddLandObject(new_land);
  1147. }
  1148. public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
  1149. {
  1150. ILandObject selectedParcel = null;
  1151. lock (m_landList)
  1152. {
  1153. m_landList.TryGetValue(localID, out selectedParcel);
  1154. }
  1155. if (selectedParcel == null) return;
  1156. selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
  1157. }
  1158. public void EventManagerOnNoLandDataFromStorage()
  1159. {
  1160. ResetSimLandObjects();
  1161. }
  1162. #endregion
  1163. public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
  1164. {
  1165. lock (m_landList)
  1166. {
  1167. foreach (LandObject obj in m_landList.Values)
  1168. {
  1169. obj.SetParcelObjectMaxOverride(overrideDel);
  1170. }
  1171. }
  1172. }
  1173. public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
  1174. {
  1175. }
  1176. #region CAPS handler
  1177. private void EventManagerOnRegisterCaps(UUID agentID, Caps caps)
  1178. {
  1179. string capsBase = "/CAPS/" + caps.CapsObjectPath;
  1180. caps.RegisterHandler("RemoteParcelRequest",
  1181. new RestStreamHandler("POST", capsBase + remoteParcelRequestPath,
  1182. delegate(string request, string path, string param,
  1183. OSHttpRequest httpRequest, OSHttpResponse httpResponse)
  1184. {
  1185. return RemoteParcelRequest(request, path, param, agentID, caps);
  1186. }));
  1187. UUID parcelCapID = UUID.Random();
  1188. caps.RegisterHandler("ParcelPropertiesUpdate",
  1189. new RestStreamHandler("POST", "/CAPS/" + parcelCapID,
  1190. delegate(string request, string path, string param,
  1191. OSHttpRequest httpRequest, OSHttpResponse httpResponse)
  1192. {
  1193. return ProcessPropertiesUpdate(request, path, param, agentID, caps);
  1194. }));
  1195. }
  1196. private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps)
  1197. {
  1198. IClientAPI client;
  1199. if ( ! m_scene.TryGetClient(agentID, out client) ) {
  1200. m_log.WarnFormat("[LAND] unable to retrieve IClientAPI for {0}", agentID.ToString() );
  1201. return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
  1202. }
  1203. ParcelPropertiesUpdateMessage properties = new ParcelPropertiesUpdateMessage();
  1204. OpenMetaverse.StructuredData.OSDMap args = (OpenMetaverse.StructuredData.OSDMap) OSDParser.DeserializeLLSDXml(request);
  1205. properties.Deserialize(args);
  1206. LandUpdateArgs land_update = new LandUpdateArgs();
  1207. int parcelID = properties.LocalID;
  1208. land_update.AuthBuyerID = properties.AuthBuyerID;
  1209. land_update.Category = properties.Category;
  1210. land_update.Desc = properties.Desc;
  1211. land_update.GroupID = properties.GroupID;
  1212. land_update.LandingType = (byte) properties.Landing;
  1213. land_update.MediaAutoScale = (byte) Convert.ToInt32(properties.MediaAutoScale);
  1214. land_update.MediaID = properties.MediaID;
  1215. land_update.MediaURL = properties.MediaURL;
  1216. land_update.MusicURL = properties.MusicURL;
  1217. land_update.Name = properties.Name;
  1218. land_update.ParcelFlags = (uint) properties.ParcelFlags;
  1219. land_update.PassHours = (int) properties.PassHours;
  1220. land_update.PassPrice = (int) properties.PassPrice;
  1221. land_update.SalePrice = (int) properties.SalePrice;
  1222. land_update.SnapshotID = properties.SnapshotID;
  1223. land_update.UserLocation = properties.UserLocation;
  1224. land_update.UserLookAt = properties.UserLookAt;
  1225. land_update.MediaDescription = properties.MediaDesc;
  1226. land_update.MediaType = properties.MediaType;
  1227. land_update.MediaWidth = properties.MediaWidth;
  1228. land_update.MediaHeight = properties.MediaHeight;
  1229. land_update.MediaLoop = properties.MediaLoop;
  1230. land_update.ObscureMusic = properties.ObscureMusic;
  1231. land_update.ObscureMedia = properties.ObscureMedia;
  1232. ILandObject land;
  1233. lock (m_landList)
  1234. {
  1235. m_landList.TryGetValue(parcelID, out land);
  1236. }
  1237. if (land != null)
  1238. {
  1239. land.UpdateLandProperties(land_update, client);
  1240. m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client);
  1241. }
  1242. else
  1243. {
  1244. m_log.WarnFormat("[LAND] unable to find parcelID {0}", parcelID);
  1245. }
  1246. return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
  1247. }
  1248. // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
  1249. // "real" parcelID, because we wouldn't be able to map that to the region the parcel belongs to.
  1250. // So, we create a "fake" parcelID by using the regionHandle (64 bit), and the local (integer) x
  1251. // and y coordinate (each 8 bit), encoded in a UUID (128 bit).
  1252. //
  1253. // Request format:
  1254. // <llsd>
  1255. // <map>
  1256. // <key>location</key>
  1257. // <array>
  1258. // <real>1.23</real>
  1259. // <real>45..6</real>
  1260. // <real>78.9</real>
  1261. // </array>
  1262. // <key>region_id</key>
  1263. // <uuid>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</uuid>
  1264. // </map>
  1265. // </llsd>
  1266. private string RemoteParcelRequest(string request, string path, string param, UUID agentID, Caps caps)
  1267. {
  1268. UUID parcelID = UUID.Zero;
  1269. try
  1270. {
  1271. Hashtable hash = new Hashtable();
  1272. hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  1273. if (hash.ContainsKey("region_id") && hash.ContainsKey("location"))
  1274. {
  1275. UUID regionID = (UUID)hash["region_id"];
  1276. ArrayList list = (ArrayList)hash["location"];
  1277. uint x = (uint)(double)list[0];
  1278. uint y = (uint)(double)list[1];
  1279. if (hash.ContainsKey("region_handle"))
  1280. {
  1281. // if you do a "About Landmark" on a landmark a second time, the viewer sends the
  1282. // region_handle it got earlier via RegionHandleRequest
  1283. ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]);
  1284. parcelID = Util.BuildFakeParcelID(regionHandle, x, y);
  1285. }
  1286. else if (regionID == m_scene.RegionInfo.RegionID)
  1287. {
  1288. // a parcel request for a local parcel => no need to query the grid
  1289. parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y);
  1290. }
  1291. else
  1292. {
  1293. // a parcel request for a parcel in another region. Ask the grid about the region
  1294. GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, regionID);
  1295. if (info != null)
  1296. parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
  1297. }
  1298. }
  1299. }
  1300. catch (LLSD.LLSDParseException e)
  1301. {
  1302. m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message);
  1303. m_log.ErrorFormat("[LAND] ... in request {0}", request);
  1304. }
  1305. catch(InvalidCastException)
  1306. {
  1307. m_log.ErrorFormat("[LAND] Wrong type in request {0}", request);
  1308. }
  1309. LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse();
  1310. response.parcel_id = parcelID;
  1311. m_log.DebugFormat("[LAND] got parcelID {0}", parcelID);
  1312. return LLSDHelpers.SerialiseLLSDReply(response);
  1313. }
  1314. #endregion
  1315. private void ClientOnParcelInfoRequest(IClientAPI remoteClient, UUID parcelID)
  1316. {
  1317. if (parcelID == UUID.Zero)
  1318. return;
  1319. ExtendedLandData data =
  1320. (ExtendedLandData)parcelInfoCache.Get(parcelID.ToString(),
  1321. delegate(string id)
  1322. {
  1323. UUID parcel = UUID.Zero;
  1324. UUID.TryParse(id, out parcel);
  1325. // assume we've got the parcelID we just computed in RemoteParcelRequest
  1326. ExtendedLandData extLandData = new ExtendedLandData();
  1327. Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle,
  1328. out extLandData.X, out extLandData.Y);
  1329. m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
  1330. extLandData.RegionHandle, extLandData.X, extLandData.Y);
  1331. // for this region or for somewhere else?
  1332. if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle)
  1333. {
  1334. extLandData.LandData = this.GetLandObject(extLandData.X, extLandData.Y).LandData;
  1335. extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel;
  1336. }
  1337. else
  1338. {
  1339. ILandService landService = m_scene.RequestModuleInterface<ILandService>();
  1340. extLandData.LandData = landService.GetLandData(extLandData.RegionHandle,
  1341. extLandData.X,
  1342. extLandData.Y,
  1343. out extLandData.RegionAccess);
  1344. if (extLandData.LandData == null)
  1345. {
  1346. // we didn't find the region/land => don't cache
  1347. return null;
  1348. }
  1349. }
  1350. return extLandData;
  1351. });
  1352. if (data != null) // if we found some data, send it
  1353. {
  1354. GridRegion info;
  1355. if (data.RegionHandle == m_scene.RegionInfo.RegionHandle)
  1356. {
  1357. info = new GridRegion(m_scene.RegionInfo);
  1358. }
  1359. else
  1360. {
  1361. // most likely still cached from building the extLandData entry
  1362. uint x = 0, y = 0;
  1363. Utils.LongToUInts(data.RegionHandle, out x, out y);
  1364. info = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
  1365. }
  1366. // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
  1367. m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...",
  1368. data.LandData.Name, data.RegionHandle);
  1369. // HACK for now
  1370. RegionInfo r = new RegionInfo();
  1371. r.RegionName = info.RegionName;
  1372. r.RegionLocX = (uint)info.RegionLocX;
  1373. r.RegionLocY = (uint)info.RegionLocY;
  1374. r.RegionSettings.Maturity = (int)Util.ConvertAccessLevelToMaturity(data.RegionAccess);
  1375. remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y);
  1376. }
  1377. else
  1378. m_log.Debug("[LAND] got no parcelinfo; not sending");
  1379. }
  1380. public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
  1381. {
  1382. ILandObject land;
  1383. lock (m_landList)
  1384. {
  1385. m_landList.TryGetValue(localID, out land);
  1386. }
  1387. if (land == null) return;
  1388. if (!m_scene.Permissions.CanEditParcel(remoteClient.AgentId, land))
  1389. return;
  1390. land.LandData.OtherCleanTime = otherCleanTime;
  1391. UpdateLandObject(localID, land.LandData);
  1392. }
  1393. }
  1394. }