LandObject.cs 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055
  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.Generic;
  29. using System.Reflection;
  30. using log4net;
  31. using OpenMetaverse;
  32. using OpenSim.Framework;
  33. using OpenSim.Region.Framework.Interfaces;
  34. using OpenSim.Region.Framework.Scenes;
  35. using RegionFlags = OpenMetaverse.RegionFlags;
  36. namespace OpenSim.Region.CoreModules.World.Land
  37. {
  38. /// <summary>
  39. /// Keeps track of a specific piece of land's information
  40. /// </summary>
  41. public class LandObject : ILandObject
  42. {
  43. #region Member Variables
  44. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  45. private static readonly string LogHeader = "[LAND OBJECT]";
  46. protected const int GROUPMEMBERCACHETIMEOUT = 30000; // cache invalidation after 30s
  47. private readonly int landUnit = 4;
  48. private int m_lastSeqId = 0;
  49. private int m_expiryCounter = 0;
  50. protected Scene m_scene;
  51. protected readonly List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
  52. private readonly Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
  53. private readonly object m_listTransactionsLock = new object();
  54. protected readonly ExpiringCacheOS<UUID, bool> m_groupMemberCache = new ExpiringCacheOS<UUID, bool>();
  55. IDwellModule m_dwellModule;
  56. private bool[,] m_landBitmap;
  57. public bool[,] LandBitmap
  58. {
  59. get { return m_landBitmap; }
  60. set { m_landBitmap = value; }
  61. }
  62. #endregion
  63. public int GetPrimsFree()
  64. {
  65. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  66. int free = GetSimulatorMaxPrimCount() - LandData.SimwidePrims;
  67. return free;
  68. }
  69. protected LandData m_landData;
  70. public LandData LandData
  71. {
  72. get { return m_landData; }
  73. set { m_landData = value; }
  74. }
  75. public UUID GlobalID
  76. {
  77. get
  78. {
  79. return m_landData == null ? UUID.Zero : m_landData.GlobalID;
  80. }
  81. }
  82. public UUID FakeID
  83. {
  84. get
  85. {
  86. return m_landData == null ? UUID.Zero : m_landData.FakeID;
  87. }
  88. }
  89. public UUID OwnerID
  90. {
  91. get
  92. {
  93. return m_landData == null ? UUID.Zero : m_landData.OwnerID;
  94. }
  95. }
  96. public UUID GroupID
  97. {
  98. get
  99. {
  100. return m_landData == null ? UUID.Zero : m_landData.GroupID;
  101. }
  102. }
  103. public int LocalID
  104. {
  105. get
  106. {
  107. return m_landData == null ? -1 : m_landData.LocalID;
  108. }
  109. }
  110. public IPrimCounts PrimCounts { get; set; }
  111. public UUID RegionUUID
  112. {
  113. get { return m_scene.RegionInfo.RegionID; }
  114. }
  115. private Vector2 m_startPoint = Vector2.Zero;
  116. private Vector2 m_endPoint = Vector2.Zero;
  117. private Vector2 m_centerPoint = Vector2.Zero;
  118. private Vector2 m_AABBmin = Vector2.Zero;
  119. private Vector2 m_AABBmax = Vector2.Zero;
  120. public Vector2 StartPoint
  121. {
  122. get
  123. {
  124. return m_startPoint;
  125. }
  126. }
  127. public Vector2 EndPoint
  128. {
  129. get
  130. {
  131. return m_endPoint;
  132. }
  133. }
  134. //estimate a center point of a parcel
  135. public Vector2 CenterPoint
  136. {
  137. get
  138. {
  139. return m_centerPoint;
  140. }
  141. }
  142. public ISceneObject[] GetSceneObjectGroups()
  143. {
  144. return primsOverMe.ToArray();
  145. }
  146. public Vector2? GetNearestPoint(Vector3 pos)
  147. {
  148. Vector3 direction = new Vector3(m_centerPoint.X - pos.X, m_centerPoint.Y - pos.Y, 0f );
  149. return GetNearestPointAlongDirection(pos, direction);
  150. }
  151. public Vector2? GetNearestPointAlongDirection(Vector3 pos, Vector3 pdirection)
  152. {
  153. Vector2 testpos;
  154. Vector2 direction;
  155. testpos.X = pos.X / landUnit;
  156. testpos.Y = pos.Y / landUnit;
  157. if(LandBitmap[(int)testpos.X, (int)testpos.Y])
  158. return new Vector2(pos.X, pos.Y); // we are already here
  159. direction.X = pdirection.X;
  160. direction.Y = pdirection.Y;
  161. if(direction.X == 0f && direction.Y == 0f)
  162. return null; // we can't look anywhere
  163. direction.Normalize();
  164. int minx = (int)(m_AABBmin.X / landUnit);
  165. int maxx = (int)(m_AABBmax.X / landUnit);
  166. // check against AABB
  167. if(direction.X > 0f)
  168. {
  169. if(testpos.X >= maxx)
  170. return null; // will never get there
  171. if(testpos.X < minx)
  172. testpos.X = minx;
  173. }
  174. else if(direction.X < 0f)
  175. {
  176. if(testpos.X < minx)
  177. return null; // will never get there
  178. if(testpos.X >= maxx)
  179. testpos.X = maxx - 1;
  180. }
  181. else
  182. {
  183. if(testpos.X < minx)
  184. return null; // will never get there
  185. else if(testpos.X >= maxx)
  186. return null; // will never get there
  187. }
  188. int miny = (int)(m_AABBmin.Y / landUnit);
  189. int maxy = (int)(m_AABBmax.Y / landUnit);
  190. if(direction.Y > 0f)
  191. {
  192. if(testpos.Y >= maxy)
  193. return null; // will never get there
  194. if(testpos.Y < miny)
  195. testpos.Y = miny;
  196. }
  197. else if(direction.Y < 0f)
  198. {
  199. if(testpos.Y < miny)
  200. return null; // will never get there
  201. if(testpos.Y >= maxy)
  202. testpos.Y = maxy - 1;
  203. }
  204. else
  205. {
  206. if(testpos.Y < miny)
  207. return null; // will never get there
  208. else if(testpos.Y >= maxy)
  209. return null; // will never get there
  210. }
  211. while(!LandBitmap[(int)testpos.X, (int)testpos.Y])
  212. {
  213. testpos += direction;
  214. if(testpos.X < minx)
  215. return null;
  216. if (testpos.X >= maxx)
  217. return null;
  218. if(testpos.Y < miny)
  219. return null;
  220. if (testpos.Y >= maxy)
  221. return null;
  222. }
  223. testpos *= landUnit;
  224. float ftmp;
  225. if(Math.Abs(direction.X) > Math.Abs(direction.Y))
  226. {
  227. if(direction.X < 0)
  228. testpos.X += landUnit - 0.5f;
  229. else
  230. testpos.X += 0.5f;
  231. ftmp = testpos.X - pos.X;
  232. ftmp /= direction.X;
  233. ftmp = Math.Abs(ftmp);
  234. ftmp *= direction.Y;
  235. ftmp += pos.Y;
  236. if(ftmp < testpos.Y + .5f)
  237. ftmp = testpos.Y + .5f;
  238. else
  239. {
  240. testpos.Y += landUnit - 0.5f;
  241. if(ftmp > testpos.Y)
  242. ftmp = testpos.Y;
  243. }
  244. testpos.Y = ftmp;
  245. }
  246. else
  247. {
  248. if(direction.Y < 0)
  249. testpos.Y += landUnit - 0.5f;
  250. else
  251. testpos.Y += 0.5f;
  252. ftmp = testpos.Y - pos.Y;
  253. ftmp /= direction.Y;
  254. ftmp = Math.Abs(ftmp);
  255. ftmp *= direction.X;
  256. ftmp += pos.X;
  257. if(ftmp < testpos.X + .5f)
  258. ftmp = testpos.X + .5f;
  259. else
  260. {
  261. testpos.X += landUnit - 0.5f;
  262. if(ftmp > testpos.X)
  263. ftmp = testpos.X;
  264. }
  265. testpos.X = ftmp;
  266. }
  267. return testpos;
  268. }
  269. #region Constructors
  270. public LandObject(LandData landData, Scene scene)
  271. {
  272. LandData = landData.Copy();
  273. m_scene = scene;
  274. m_scene.EventManager.OnFrame += OnFrame;
  275. m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
  276. }
  277. public LandObject(UUID owner_id, bool is_group_owned, Scene scene, LandData data = null)
  278. {
  279. m_scene = scene;
  280. if (m_scene == null)
  281. LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
  282. else
  283. {
  284. LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
  285. m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
  286. }
  287. if(data == null)
  288. LandData = new LandData();
  289. else
  290. LandData = data;
  291. LandData.OwnerID = owner_id;
  292. if (is_group_owned)
  293. LandData.GroupID = owner_id;
  294. LandData.IsGroupOwned = is_group_owned;
  295. if(m_dwellModule == null)
  296. LandData.Dwell = 0;
  297. m_scene.EventManager.OnFrame += OnFrame;
  298. }
  299. public void Clear()
  300. {
  301. if(m_scene != null)
  302. m_scene.EventManager.OnFrame -= OnFrame;
  303. LandData = null;
  304. }
  305. #endregion
  306. #region Member Functions
  307. #region General Functions
  308. /// <summary>
  309. /// Checks to see if this land object contains a point
  310. /// </summary>
  311. /// <param name="x"></param>
  312. /// <param name="y"></param>
  313. /// <returns>Returns true if the piece of land contains the specified point</returns>
  314. public bool ContainsPoint(int x, int y)
  315. {
  316. if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
  317. {
  318. return LandBitmap[x / landUnit, y / landUnit];
  319. }
  320. else
  321. {
  322. return false;
  323. }
  324. }
  325. public ILandObject Copy()
  326. {
  327. ILandObject newLand = new LandObject(LandData, m_scene);
  328. newLand.LandBitmap = (bool[,]) (LandBitmap.Clone());
  329. return newLand;
  330. }
  331. static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount;
  332. static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount;
  333. public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
  334. {
  335. overrideParcelMaxPrimCount = overrideDel;
  336. }
  337. public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
  338. {
  339. overrideSimulatorMaxPrimCount = overrideDel;
  340. }
  341. public int GetParcelMaxPrimCount()
  342. {
  343. if (overrideParcelMaxPrimCount != null)
  344. {
  345. return overrideParcelMaxPrimCount(this);
  346. }
  347. else
  348. {
  349. // Normal Calculations
  350. int parcelMax = (int)(
  351. (double)LandData.Area
  352. * (double)m_scene.RegionInfo.ObjectCapacity
  353. * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
  354. / (double)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
  355. + 0.5 );
  356. if(parcelMax > m_scene.RegionInfo.ObjectCapacity)
  357. parcelMax = m_scene.RegionInfo.ObjectCapacity;
  358. //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
  359. return parcelMax;
  360. }
  361. }
  362. // the total prims a parcel owner can have on a region
  363. public int GetSimulatorMaxPrimCount()
  364. {
  365. if (overrideSimulatorMaxPrimCount != null)
  366. {
  367. return overrideSimulatorMaxPrimCount(this);
  368. }
  369. else
  370. {
  371. //Normal Calculations
  372. int simMax = (int)( (double)LandData.SimwideArea
  373. * (double)m_scene.RegionInfo.ObjectCapacity
  374. * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
  375. / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
  376. +0.5 );
  377. // sanity check
  378. if(simMax > m_scene.RegionInfo.ObjectCapacity)
  379. simMax = m_scene.RegionInfo.ObjectCapacity;
  380. //m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}, SimWidePrims {3}",
  381. // LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax, LandData.SimwidePrims);
  382. return simMax;
  383. }
  384. }
  385. #endregion
  386. #region Packet Request Handling
  387. public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
  388. {
  389. if(m_scene.RegionInfo.RegionSettings.AllowDamage)
  390. remote_client.SceneAgent.Invulnerable = false;
  391. else
  392. remote_client.SceneAgent.Invulnerable = (m_landData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
  393. if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
  394. return;
  395. IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
  396. // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
  397. uint regionFlags = (uint)(RegionFlags.PublicAllowed
  398. | RegionFlags.AllowDirectTeleport
  399. | RegionFlags.AllowParcelChanges
  400. | RegionFlags.AllowVoice );
  401. if (estateModule != null)
  402. regionFlags = estateModule.GetRegionFlags();
  403. int seq_id;
  404. if (snap_selection && (sequence_id == 0))
  405. {
  406. seq_id = m_lastSeqId;
  407. }
  408. else
  409. {
  410. seq_id = sequence_id;
  411. m_lastSeqId = seq_id;
  412. }
  413. remote_client.SendLandProperties(seq_id,
  414. snap_selection, request_result, this,
  415. (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
  416. GetParcelMaxPrimCount(),
  417. GetSimulatorMaxPrimCount(), regionFlags);
  418. }
  419. public bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
  420. {
  421. //Needs later group support
  422. snap_selection = false;
  423. needOverlay = false;
  424. LandData newData = LandData.Copy();
  425. uint allowedDelta = 0;
  426. // These two are always blocked as no client can set them anyway
  427. // ParcelFlags.ForSaleObjects
  428. // ParcelFlags.LindenHome
  429. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, false))
  430. {
  431. allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
  432. ParcelFlags.AllowTerraform |
  433. ParcelFlags.AllowDamage |
  434. ParcelFlags.CreateObjects |
  435. ParcelFlags.RestrictPushObject |
  436. ParcelFlags.AllowOtherScripts |
  437. ParcelFlags.AllowGroupScripts |
  438. ParcelFlags.CreateGroupObjects |
  439. ParcelFlags.AllowAPrimitiveEntry |
  440. ParcelFlags.AllowGroupObjectEntry |
  441. ParcelFlags.AllowFly);
  442. newData.SeeAVs = args.SeeAVs;
  443. newData.AnyAVSounds = args.AnyAVSounds;
  444. newData.GroupAVSounds = args.GroupAVSounds;
  445. }
  446. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true))
  447. {
  448. if (args.AuthBuyerID != newData.AuthBuyerID ||
  449. args.SalePrice != newData.SalePrice)
  450. {
  451. snap_selection = true;
  452. }
  453. newData.AuthBuyerID = args.AuthBuyerID;
  454. newData.SalePrice = args.SalePrice;
  455. if (!LandData.IsGroupOwned)
  456. {
  457. newData.GroupID = args.GroupID;
  458. if(newData.GroupID != LandData.GroupID)
  459. m_groupMemberCache.Clear();
  460. allowedDelta |= (uint)(ParcelFlags.AllowDeedToGroup |
  461. ParcelFlags.ContributeWithDeed |
  462. ParcelFlags.SellParcelObjects);
  463. }
  464. allowedDelta |= (uint)ParcelFlags.ForSale;
  465. }
  466. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces, false))
  467. {
  468. newData.Category = args.Category;
  469. allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
  470. ParcelFlags.AllowPublish |
  471. ParcelFlags.MaturePublish) | (uint)(1 << 23);
  472. }
  473. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity, false))
  474. {
  475. newData.Description = args.Desc;
  476. newData.Name = args.Name;
  477. newData.SnapshotID = args.SnapshotID;
  478. }
  479. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint, false))
  480. {
  481. newData.LandingType = args.LandingType;
  482. newData.UserLocation = args.UserLocation;
  483. newData.UserLookAt = args.UserLookAt;
  484. }
  485. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia, false))
  486. {
  487. newData.MediaAutoScale = args.MediaAutoScale;
  488. newData.MediaID = args.MediaID;
  489. newData.MediaURL = args.MediaURL;
  490. newData.MusicURL = args.MusicURL;
  491. newData.MediaType = args.MediaType;
  492. newData.MediaDescription = args.MediaDescription;
  493. newData.MediaWidth = args.MediaWidth;
  494. newData.MediaHeight = args.MediaHeight;
  495. newData.MediaLoop = args.MediaLoop;
  496. newData.ObscureMusic = args.ObscureMusic;
  497. newData.ObscureMedia = args.ObscureMedia;
  498. allowedDelta |= (uint)(ParcelFlags.SoundLocal |
  499. ParcelFlags.UrlWebPage |
  500. ParcelFlags.UrlRawHtml |
  501. ParcelFlags.AllowVoiceChat |
  502. ParcelFlags.UseEstateVoiceChan);
  503. }
  504. if(!m_scene.RegionInfo.EstateSettings.TaxFree)
  505. {
  506. // don't allow passes on group owned until we can give money to groups
  507. if (!newData.IsGroupOwned && m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
  508. {
  509. newData.PassHours = args.PassHours;
  510. newData.PassPrice = args.PassPrice;
  511. allowedDelta |= (uint)ParcelFlags.UsePassList;
  512. }
  513. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed, false))
  514. {
  515. allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
  516. ParcelFlags.UseAccessList);
  517. }
  518. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned, false))
  519. {
  520. allowedDelta |= (uint)(ParcelFlags.UseBanList |
  521. ParcelFlags.DenyAnonymous |
  522. ParcelFlags.DenyAgeUnverified);
  523. }
  524. }
  525. // enforce estate age and payinfo limitations
  526. if (m_scene.RegionInfo.EstateSettings.DenyMinors)
  527. {
  528. args.ParcelFlags |= (uint)ParcelFlags.DenyAgeUnverified;
  529. allowedDelta |= (uint)ParcelFlags.DenyAgeUnverified;
  530. }
  531. if (m_scene.RegionInfo.EstateSettings.DenyAnonymous)
  532. {
  533. args.ParcelFlags |= (uint)ParcelFlags.DenyAnonymous;
  534. allowedDelta |= (uint)ParcelFlags.DenyAnonymous;
  535. }
  536. if (allowedDelta != (uint)ParcelFlags.None)
  537. {
  538. uint preserve = LandData.Flags & ~allowedDelta;
  539. newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
  540. uint curdelta = LandData.Flags ^ newData.Flags;
  541. curdelta &= (uint)(ParcelFlags.SoundLocal);
  542. if(curdelta != 0 || newData.SeeAVs != LandData.SeeAVs)
  543. needOverlay = true;
  544. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  545. return true;
  546. }
  547. return false;
  548. }
  549. public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
  550. {
  551. LandData newData = LandData.Copy();
  552. newData.OwnerID = avatarID;
  553. newData.GroupID = groupID;
  554. newData.IsGroupOwned = groupOwned;
  555. //newData.auctionID = AuctionID;
  556. newData.ClaimDate = Util.UnixTimeSinceEpoch();
  557. newData.ClaimPrice = claimprice;
  558. newData.SalePrice = 0;
  559. newData.AuthBuyerID = UUID.Zero;
  560. newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  561. bool sellObjects = (LandData.Flags & (uint)(ParcelFlags.SellParcelObjects)) != 0
  562. && !LandData.IsGroupOwned && !groupOwned;
  563. UUID previousOwner = LandData.OwnerID;
  564. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  565. if (sellObjects)
  566. SellLandObjects(previousOwner);
  567. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  568. }
  569. public void DeedToGroup(UUID groupID)
  570. {
  571. LandData newData = LandData.Copy();
  572. newData.OwnerID = groupID;
  573. newData.GroupID = groupID;
  574. newData.IsGroupOwned = true;
  575. // Reset show in directory flag on deed
  576. newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  577. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
  578. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  579. }
  580. public bool IsEitherBannedOrRestricted(UUID avatar)
  581. {
  582. if (m_scene.RegionInfo.EstateSettings.TaxFree) // region access control only
  583. return false;
  584. if (IsBannedFromLand(avatar))
  585. {
  586. return true;
  587. }
  588. else if (IsRestrictedFromLand(avatar))
  589. {
  590. return true;
  591. }
  592. return false;
  593. }
  594. public bool CanBeOnThisLand(UUID avatar, float posHeight)
  595. {
  596. if (m_scene.RegionInfo.EstateSettings.TaxFree) // region access control only
  597. return true;
  598. if (posHeight < m_scene.LandChannel.BanLineSafeHeight && IsBannedFromLand(avatar))
  599. {
  600. return false;
  601. }
  602. else if (IsRestrictedFromLand(avatar))
  603. {
  604. return false;
  605. }
  606. return true;
  607. }
  608. public bool HasGroupAccess(UUID avatar)
  609. {
  610. if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup)
  611. {
  612. if (m_groupMemberCache.TryGetValue(avatar, out bool isMember))
  613. {
  614. m_groupMemberCache.Add(avatar, isMember, GROUPMEMBERCACHETIMEOUT);
  615. return isMember;
  616. }
  617. if (!m_scene.TryGetScenePresence(avatar, out ScenePresence sp))
  618. {
  619. IGroupsModule groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
  620. if (groupsModule == null)
  621. return false;
  622. GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar);
  623. if (membership == null || membership.Length == 0)
  624. {
  625. m_groupMemberCache.Add(avatar, false, GROUPMEMBERCACHETIMEOUT);
  626. return false;
  627. }
  628. foreach (GroupMembershipData d in membership)
  629. {
  630. if (d.GroupID == LandData.GroupID)
  631. {
  632. m_groupMemberCache.Add(avatar, true, GROUPMEMBERCACHETIMEOUT);
  633. return true;
  634. }
  635. }
  636. m_groupMemberCache.Add(avatar, false, GROUPMEMBERCACHETIMEOUT);
  637. return false;
  638. }
  639. else
  640. {
  641. isMember = sp.ControllingClient.IsGroupMember(LandData.GroupID);
  642. m_groupMemberCache.Add(avatar, isMember, GROUPMEMBERCACHETIMEOUT);
  643. return isMember;
  644. }
  645. }
  646. return false;
  647. }
  648. public bool IsBannedFromLand(UUID avatar)
  649. {
  650. ExpireAccessList();
  651. if (m_scene.RegionInfo.EstateSettings.TaxFree) // region access control only
  652. return false;
  653. if (m_scene.Permissions.IsAdministrator(avatar))
  654. return false;
  655. if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
  656. return false;
  657. if (avatar == LandData.OwnerID)
  658. return false;
  659. if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
  660. {
  661. if (LandData.ParcelAccessList.FindIndex(
  662. delegate(LandAccessEntry e)
  663. {
  664. if (e.AgentID == avatar && e.Flags == AccessList.Ban)
  665. return true;
  666. return false;
  667. }) != -1)
  668. {
  669. return true;
  670. }
  671. }
  672. return false;
  673. }
  674. public bool IsRestrictedFromLand(UUID avatar)
  675. {
  676. if (m_scene.RegionInfo.EstateSettings.TaxFree) // estate access only
  677. return false;
  678. if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0)
  679. {
  680. bool adults = m_scene.RegionInfo.EstateSettings.DoDenyMinors &&
  681. (m_scene.RegionInfo.EstateSettings.DenyMinors || ((LandData.Flags & (uint)ParcelFlags.DenyAgeUnverified) != 0));
  682. bool anonymous = m_scene.RegionInfo.EstateSettings.DoDenyAnonymous &&
  683. (m_scene.RegionInfo.EstateSettings.DenyAnonymous || ((LandData.Flags & (uint)ParcelFlags.DenyAnonymous) != 0));
  684. if(adults || anonymous)
  685. {
  686. int userflags;
  687. if(m_scene.TryGetScenePresence(avatar, out ScenePresence snp))
  688. {
  689. if(snp.IsNPC)
  690. return false;
  691. userflags = snp.UserFlags;
  692. }
  693. else
  694. userflags = m_scene.GetUserFlags(avatar);
  695. if(adults && ((userflags & 32) == 0))
  696. return true;
  697. if(anonymous && ((userflags & 4) == 0))
  698. return true;
  699. }
  700. return false;
  701. }
  702. if (m_scene.Permissions.IsAdministrator(avatar))
  703. return false;
  704. if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar))
  705. return false;
  706. if (avatar == LandData.OwnerID)
  707. return false;
  708. if (HasGroupAccess(avatar))
  709. return false;
  710. if(IsInLandAccessList(avatar))
  711. return false;
  712. // check for a NPC
  713. ScenePresence sp;
  714. if (!m_scene.TryGetScenePresence(avatar, out sp))
  715. return true;
  716. if(sp==null || !sp.IsNPC)
  717. return true;
  718. INPC npccli = (INPC)sp.ControllingClient;
  719. if(npccli== null)
  720. return true;
  721. UUID owner = npccli.Owner;
  722. if(owner == UUID.Zero)
  723. return true;
  724. if (owner == LandData.OwnerID)
  725. return false;
  726. return !IsInLandAccessList(owner);
  727. }
  728. public bool IsInLandAccessList(UUID avatar)
  729. {
  730. ExpireAccessList();
  731. if (LandData.ParcelAccessList.FindIndex(
  732. delegate(LandAccessEntry e)
  733. {
  734. if (e.AgentID == avatar && e.Flags == AccessList.Access)
  735. return true;
  736. return false;
  737. }) == -1)
  738. {
  739. return false;
  740. }
  741. return true;
  742. }
  743. public void SendLandUpdateToClient(IClientAPI remote_client)
  744. {
  745. SendLandProperties(0, false, 0, remote_client);
  746. }
  747. public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client)
  748. {
  749. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  750. SendLandProperties(0, snap_selection, 0, remote_client);
  751. }
  752. public void SendLandUpdateToAvatarsOverMe()
  753. {
  754. SendLandUpdateToAvatarsOverMe(false);
  755. }
  756. public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
  757. {
  758. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  759. m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
  760. {
  761. if (avatar.IsNPC)
  762. return;
  763. ILandObject over = null;
  764. try
  765. {
  766. over =
  767. m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
  768. Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
  769. }
  770. catch (Exception)
  771. {
  772. m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " +
  773. Math.Round(avatar.AbsolutePosition.Y));
  774. }
  775. if (over != null)
  776. {
  777. if (over.LandData.LocalID == LandData.LocalID)
  778. {
  779. if(m_scene.RegionInfo.RegionSettings.AllowDamage)
  780. avatar.Invulnerable = false;
  781. else
  782. avatar.Invulnerable = (over.LandData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
  783. SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
  784. avatar.currentParcelUUID = LandData.GlobalID;
  785. }
  786. }
  787. });
  788. }
  789. public void SendLandUpdateToAvatars()
  790. {
  791. m_scene.ForEachScenePresence(delegate (ScenePresence avatar)
  792. {
  793. if (avatar.IsNPC)
  794. return;
  795. if(avatar.IsChildAgent)
  796. {
  797. SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, avatar.ControllingClient);
  798. return;
  799. }
  800. ILandObject over = null;
  801. try
  802. {
  803. over =
  804. m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
  805. Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
  806. }
  807. catch (Exception)
  808. {
  809. m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " +
  810. Math.Round(avatar.AbsolutePosition.Y));
  811. }
  812. if (over != null)
  813. {
  814. if (over.LandData.LocalID == LandData.LocalID)
  815. {
  816. if (m_scene.RegionInfo.RegionSettings.AllowDamage)
  817. avatar.Invulnerable = false;
  818. else
  819. avatar.Invulnerable = (over.LandData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
  820. avatar.currentParcelUUID = LandData.GlobalID;
  821. SendLandProperties(0, true, LandChannel.LAND_RESULT_SINGLE, avatar.ControllingClient);
  822. return;
  823. }
  824. }
  825. SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, avatar.ControllingClient);
  826. });
  827. }
  828. #endregion
  829. #region AccessList Functions
  830. public List<LandAccessEntry> CreateAccessListArrayByFlag(AccessList flag)
  831. {
  832. ExpireAccessList();
  833. List<LandAccessEntry> list = new List<LandAccessEntry>();
  834. foreach (LandAccessEntry entry in LandData.ParcelAccessList)
  835. {
  836. if (entry.Flags == flag)
  837. list.Add(entry);
  838. }
  839. if (list.Count == 0)
  840. {
  841. LandAccessEntry e = new LandAccessEntry();
  842. e.AgentID = UUID.Zero;
  843. e.Flags = 0;
  844. e.Expires = 0;
  845. list.Add(e);
  846. }
  847. return list;
  848. }
  849. public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID,
  850. IClientAPI remote_client)
  851. {
  852. if ((flags & (uint) AccessList.Access) != 0)
  853. {
  854. List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access);
  855. remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID);
  856. }
  857. if ((flags & (uint) AccessList.Ban) != 0)
  858. {
  859. List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban);
  860. remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID);
  861. }
  862. }
  863. public void UpdateAccessList(uint flags, UUID transactionID, List<LandAccessEntry> entries)
  864. {
  865. if((flags & 0x03) == 0)
  866. return; // we only have access and ban
  867. flags &=0x03 ;
  868. // get a work copy of lists
  869. List<LandAccessEntry> parcelAccessList = new List<LandAccessEntry>(LandData.ParcelAccessList);
  870. // first packet on a transaction clears before adding
  871. // we need to this way because viewer protocol does not seem reliable
  872. lock (m_listTransactionsLock)
  873. {
  874. if ((!m_listTransactions.ContainsKey(flags)) ||
  875. m_listTransactions[flags] != transactionID)
  876. {
  877. m_listTransactions[flags] = transactionID;
  878. List<LandAccessEntry> toRemove = new List<LandAccessEntry>();
  879. foreach (LandAccessEntry entry in parcelAccessList)
  880. {
  881. if (((uint)entry.Flags & flags) != 0)
  882. toRemove.Add(entry);
  883. }
  884. foreach (LandAccessEntry entry in toRemove)
  885. parcelAccessList.Remove(entry);
  886. // a delete all command ?
  887. if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
  888. {
  889. LandData.ParcelAccessList = parcelAccessList;
  890. if ((flags & (uint)AccessList.Access) != 0)
  891. LandData.Flags &= ~(uint)ParcelFlags.UseAccessList;
  892. if ((flags & (uint)AccessList.Ban) != 0)
  893. LandData.Flags &= ~(uint)ParcelFlags.UseBanList;
  894. m_listTransactions.Remove(flags);
  895. return;
  896. }
  897. }
  898. }
  899. foreach (LandAccessEntry entry in entries)
  900. {
  901. LandAccessEntry temp = new LandAccessEntry();
  902. temp.AgentID = entry.AgentID;
  903. temp.Expires = entry.Expires;
  904. temp.Flags = (AccessList)flags;
  905. parcelAccessList.Add(temp);
  906. }
  907. LandData.ParcelAccessList = parcelAccessList;
  908. if ((flags & (uint)AccessList.Access) != 0)
  909. LandData.Flags |= (uint)ParcelFlags.UseAccessList;
  910. if ((flags & (uint)AccessList.Ban) != 0)
  911. LandData.Flags |= (uint)ParcelFlags.UseBanList;
  912. }
  913. #endregion
  914. #region Update Functions
  915. public void UpdateLandBitmapByteArray()
  916. {
  917. LandData.Bitmap = ConvertLandBitmapToBytes();
  918. }
  919. /// <summary>
  920. /// Update all settings in land such as area, bitmap byte array, etc
  921. /// </summary>
  922. public void ForceUpdateLandInfo()
  923. {
  924. UpdateGeometryValues();
  925. UpdateLandBitmapByteArray();
  926. }
  927. public void SetLandBitmapFromByteArray()
  928. {
  929. LandBitmap = ConvertBytesToLandBitmap();
  930. }
  931. /// <summary>
  932. /// Updates geomtric values after area/shape modification of the land object
  933. /// </summary>
  934. private void UpdateGeometryValues()
  935. {
  936. int min_x = Int32.MaxValue;
  937. int min_y = Int32.MaxValue;
  938. int max_x = Int32.MinValue;
  939. int max_y = Int32.MinValue;
  940. int tempArea = 0;
  941. int x, y;
  942. int lastX = 0;
  943. int lastY = 0;
  944. float avgx = 0f;
  945. float avgy = 0f;
  946. bool needFirst = true;
  947. for (x = 0; x < LandBitmap.GetLength(0); x++)
  948. {
  949. for (y = 0; y < LandBitmap.GetLength(1); y++)
  950. {
  951. if (LandBitmap[x, y])
  952. {
  953. if (min_x > x)
  954. min_x = x;
  955. if (min_y > y)
  956. min_y = y;
  957. if (max_x < x)
  958. max_x = x;
  959. if (max_y < y)
  960. max_y = y;
  961. if(needFirst)
  962. {
  963. avgx = x;
  964. avgy = y;
  965. m_startPoint.X = x * landUnit;
  966. m_startPoint.Y = y * landUnit;
  967. needFirst = false;
  968. }
  969. else
  970. {
  971. // keeping previous odd average
  972. avgx = (avgx * tempArea + x) / (tempArea + 1);
  973. avgy = (avgy * tempArea + y) / (tempArea + 1);
  974. }
  975. tempArea++;
  976. lastX = x;
  977. lastY = y;
  978. }
  979. }
  980. }
  981. int halfunit = landUnit/2;
  982. m_centerPoint.X = avgx * landUnit + halfunit;
  983. m_centerPoint.Y = avgy * landUnit + halfunit;
  984. m_endPoint.X = lastX * landUnit + landUnit;
  985. m_endPoint.Y = lastY * landUnit + landUnit;
  986. // next tests should not be needed
  987. // if they fail, something is wrong
  988. int regionSizeX = (int)Constants.RegionSize;
  989. int regionSizeY = (int)Constants.RegionSize;
  990. ulong regionHandle;
  991. if(m_scene != null)
  992. {
  993. RegionInfo ri = m_scene.RegionInfo;
  994. regionSizeX = (int)ri.RegionSizeX;
  995. regionSizeY = (int)ri.RegionSizeY;
  996. regionHandle = ri.RegionHandle;
  997. //create a fake ID
  998. LandData.FakeID = Util.BuildFakeParcelID(regionHandle, (uint)(lastX * landUnit), (uint)(lastY * landUnit));
  999. }
  1000. int tx = min_x * landUnit;
  1001. if (tx >= regionSizeX)
  1002. tx = regionSizeX - 1;
  1003. int ty = min_y * landUnit;
  1004. if (ty >= regionSizeY)
  1005. ty = regionSizeY - 1;
  1006. m_AABBmin.X = tx;
  1007. m_AABBmin.Y = ty;
  1008. if(m_scene == null || m_scene.Heightmap == null)
  1009. LandData.AABBMin = new Vector3(tx, ty, 0f);
  1010. else
  1011. LandData.AABBMin = new Vector3(tx, ty, (float)m_scene.Heightmap[tx, ty]);
  1012. max_x++;
  1013. tx = max_x * landUnit;
  1014. if (tx > regionSizeX)
  1015. tx = regionSizeX;
  1016. max_y++;
  1017. ty = max_y * landUnit;
  1018. if (ty > regionSizeY)
  1019. ty = regionSizeY;
  1020. m_AABBmax.X = tx;
  1021. m_AABBmax.Y = ty;
  1022. if(m_scene == null || m_scene.Heightmap == null)
  1023. LandData.AABBMax = new Vector3(tx, ty, 0f);
  1024. else
  1025. LandData.AABBMax = new Vector3(tx, ty, (float)m_scene.Heightmap[tx - 1, ty - 1]);
  1026. tempArea *= landUnit * landUnit;
  1027. LandData.Area = tempArea;
  1028. }
  1029. #endregion
  1030. #region Land Bitmap Functions
  1031. /// <summary>
  1032. /// Sets the land's bitmap manually
  1033. /// </summary>
  1034. /// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
  1035. public void SetLandBitmap(bool[,] bitmap)
  1036. {
  1037. LandBitmap = bitmap;
  1038. ForceUpdateLandInfo();
  1039. }
  1040. /// <summary>
  1041. /// Gets the land's bitmap manually
  1042. /// </summary>
  1043. /// <returns></returns>
  1044. public bool[,] GetLandBitmap()
  1045. {
  1046. return LandBitmap;
  1047. }
  1048. public bool[,] BasicFullRegionLandBitmap()
  1049. {
  1050. return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY, true);
  1051. }
  1052. public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y, bool set_value = true)
  1053. {
  1054. bool[,] tempBitmap = ModifyLandBitmapSquare(null, start_x, start_y, end_x, end_y, set_value);
  1055. return tempBitmap;
  1056. }
  1057. /// <summary>
  1058. /// Change a land bitmap at within a square and set those points to a specific value
  1059. /// </summary>
  1060. /// <param name="land_bitmap"></param>
  1061. /// <param name="start_x"></param>
  1062. /// <param name="start_y"></param>
  1063. /// <param name="end_x"></param>
  1064. /// <param name="end_y"></param>
  1065. /// <param name="set_value"></param>
  1066. /// <returns></returns>
  1067. public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
  1068. bool set_value)
  1069. {
  1070. if(land_bitmap == null)
  1071. {
  1072. land_bitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
  1073. if(!set_value)
  1074. return land_bitmap;
  1075. }
  1076. start_x /= landUnit;
  1077. end_x /= landUnit;
  1078. start_y /= landUnit;
  1079. end_y /= landUnit;
  1080. for (int x = start_x; x < end_x; ++x)
  1081. {
  1082. for (int y = start_y; y < end_y; ++y)
  1083. {
  1084. land_bitmap[x, y] = set_value;
  1085. }
  1086. }
  1087. // m_log.DebugFormat("{0} ModifyLandBitmapSquare. startXY=<{1},{2}>, endXY=<{3},{4}>, val={5}, landBitmapSize=<{6},{7}>",
  1088. // LogHeader, start_x, start_y, end_x, end_y, set_value, land_bitmap.GetLength(0), land_bitmap.GetLength(1));
  1089. return land_bitmap;
  1090. }
  1091. /// <summary>
  1092. /// Join the true values of 2 bitmaps together
  1093. /// </summary>
  1094. /// <param name="bitmap_base"></param>
  1095. /// <param name="bitmap_add"></param>
  1096. /// <returns></returns>
  1097. public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
  1098. {
  1099. if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
  1100. || bitmap_base.GetLength(1) != bitmap_add.GetLength(1))
  1101. {
  1102. throw new Exception(
  1103. String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
  1104. LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
  1105. );
  1106. }
  1107. for (int x = 0; x < bitmap_add.GetLength(0); x++)
  1108. {
  1109. for (int y = 0; y < bitmap_base.GetLength(1); y++)
  1110. {
  1111. bitmap_base[x, y] |= bitmap_add[x, y];
  1112. }
  1113. }
  1114. return bitmap_base;
  1115. }
  1116. /// <summary>
  1117. /// Remap a land bitmap. Takes the supplied land bitmap and rotates it, crops it and finally offsets it into
  1118. /// a final land bitmap of the target region size.
  1119. /// </summary>
  1120. /// <param name="bitmap_base">The original parcel bitmap</param>
  1121. /// <param name="rotationDegrees"></param>
  1122. /// <param name="displacement">&lt;x,y,?&gt;</param>
  1123. /// <param name="boundingOrigin">&lt;x,y,?&gt;</param>
  1124. /// <param name="boundingSize">&lt;x,y,?&gt;</param>
  1125. /// <param name="regionSize">&lt;x,y,?&gt;</param>
  1126. /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
  1127. /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
  1128. /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
  1129. /// <returns>New parcel bitmap</returns>
  1130. public bool[,] RemapLandBitmap(bool[,] bitmap_base, Vector2 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Vector2 regionSize, out bool isEmptyNow)
  1131. {
  1132. // get the size of the incoming bitmap
  1133. int baseX = bitmap_base.GetLength(0);
  1134. int baseY = bitmap_base.GetLength(1);
  1135. // create an intermediate bitmap that is 25% bigger on each side that we can work with to handle rotations
  1136. int offsetX = baseX / 4; // the original origin will now be at these coordinates so now we can have imaginary negative coordinates ;)
  1137. int offsetY = baseY / 4;
  1138. int tmpX = baseX + baseX / 2;
  1139. int tmpY = baseY + baseY / 2;
  1140. int centreX = tmpX / 2;
  1141. int centreY = tmpY / 2;
  1142. bool[,] bitmap_tmp = new bool[tmpX, tmpY];
  1143. double radianRotation = Math.PI * rotationDegrees / 180f;
  1144. double cosR = Math.Cos(radianRotation);
  1145. double sinR = Math.Sin(radianRotation);
  1146. if (rotationDegrees < 0f) rotationDegrees += 360f; //-90=270 -180=180 -270=90
  1147. // So first we apply the rotation to the incoming bitmap, storing the result in bitmap_tmp
  1148. // We special case orthogonal rotations for accuracy because even using double precision math, Math.Cos(90 degrees) is never fully 0
  1149. // and we can never rotate around a centre pixel because the bitmap size is always even
  1150. int x, y, sx, sy;
  1151. for (y = 0; y <= tmpY; y++)
  1152. {
  1153. for (x = 0; x <= tmpX; x++)
  1154. {
  1155. if (rotationDegrees == 0f)
  1156. {
  1157. sx = x - offsetX;
  1158. sy = y - offsetY;
  1159. }
  1160. else if (rotationDegrees == 90f)
  1161. {
  1162. sx = y - offsetX;
  1163. sy = tmpY - 1 - x - offsetY;
  1164. }
  1165. else if (rotationDegrees == 180f)
  1166. {
  1167. sx = tmpX - 1 - x - offsetX;
  1168. sy = tmpY - 1 - y - offsetY;
  1169. }
  1170. else if (rotationDegrees == 270f)
  1171. {
  1172. sx = tmpX - 1 - y - offsetX;
  1173. sy = x - offsetY;
  1174. }
  1175. else
  1176. {
  1177. // arbitary rotation: hmmm should I be using (centreX - 0.5) and (centreY - 0.5) and round cosR and sinR to say only 5 decimal places?
  1178. sx = centreX + (int)Math.Round((((double)x - centreX) * cosR) + (((double)y - centreY) * sinR)) - offsetX;
  1179. sy = centreY + (int)Math.Round((((double)y - centreY) * cosR) - (((double)x - centreX) * sinR)) - offsetY;
  1180. }
  1181. if (sx >= 0 && sx < baseX && sy >= 0 && sy < baseY)
  1182. {
  1183. try
  1184. {
  1185. if (bitmap_base[sx, sy]) bitmap_tmp[x, y] = true;
  1186. }
  1187. catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
  1188. {
  1189. m_log.DebugFormat("{0} RemapLandBitmap Rotate: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, sx, sy, x, y);
  1190. }
  1191. }
  1192. }
  1193. }
  1194. // We could also incorporate the next steps, bounding-rectangle and displacement in the loop above, but it's simpler to visualise if done separately
  1195. // and will also make it much easier when later I want the option for maybe a circular or oval bounding shape too ;).
  1196. // So... our output land bitmap must be the size of the current region but rememeber, parcel landbitmaps are landUnit metres (4x4 metres) per point,
  1197. // and region sizes, boundaries and displacements are in metres so we need to scale down
  1198. int newX = (int)(regionSize.X / landUnit);
  1199. int newY = (int)(regionSize.Y / landUnit);
  1200. bool[,] bitmap_new = new bool[newX, newY];
  1201. // displacement is relative to <0,0> in the destination region and defines where the origin of the data selected by the bounding-rectangle is placed
  1202. int dispX = (int)Math.Floor(displacement.X / landUnit);
  1203. int dispY = (int)Math.Floor(displacement.Y / landUnit);
  1204. // startX/Y and endX/Y are coordinates in bitmap_tmp
  1205. int startX = (int)Math.Floor(boundingOrigin.X / landUnit) + offsetX;
  1206. if (startX > tmpX) startX = tmpX;
  1207. if (startX < 0) startX = 0;
  1208. int startY = (int)Math.Floor(boundingOrigin.Y / landUnit) + offsetY;
  1209. if (startY > tmpY) startY = tmpY;
  1210. if (startY < 0) startY = 0;
  1211. int endX = (int)Math.Floor((boundingOrigin.X + boundingSize.X) / landUnit) + offsetX;
  1212. if (endX > tmpX) endX = tmpX;
  1213. if (endX < 0) endX = 0;
  1214. int endY = (int)Math.Floor((boundingOrigin.Y + boundingSize.Y) / landUnit) + offsetY;
  1215. if (endY > tmpY) endY = tmpY;
  1216. if (endY < 0) endY = 0;
  1217. //m_log.DebugFormat("{0} RemapLandBitmap: inSize=<{1},{2}>, disp=<{3},{4}> rot={5}, offset=<{6},{7}>, boundingStart=<{8},{9}>, boundingEnd=<{10},{11}>, cosR={12}, sinR={13}, outSize=<{14},{15}>", LogHeader,
  1218. // baseX, baseY, dispX, dispY, radianRotation, offsetX, offsetY, startX, startY, endX, endY, cosR, sinR, newX, newY);
  1219. isEmptyNow = true;
  1220. int dx, dy;
  1221. for (y = startY; y < endY; y++)
  1222. {
  1223. for (x = startX; x < endX; x++)
  1224. {
  1225. dx = x - startX + dispX;
  1226. dy = y - startY + dispY;
  1227. if (dx >= 0 && dx < newX && dy >= 0 && dy < newY)
  1228. {
  1229. try
  1230. {
  1231. if (bitmap_tmp[x, y])
  1232. {
  1233. bitmap_new[dx, dy] = true;
  1234. isEmptyNow = false;
  1235. }
  1236. }
  1237. catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
  1238. {
  1239. m_log.DebugFormat("{0} RemapLandBitmap - Bound & Displace: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, x, y, dx, dy);
  1240. }
  1241. }
  1242. }
  1243. }
  1244. return bitmap_new;
  1245. }
  1246. /// <summary>
  1247. /// Clears any parcel data in bitmap_base where there exists parcel data in bitmap_new. In other words the parcel data
  1248. /// in bitmap_new takes over the space of the parcel data in bitmap_base.
  1249. /// </summary>
  1250. /// <param name="bitmap_base"></param>
  1251. /// <param name="bitmap_new"></param>
  1252. /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
  1253. /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
  1254. /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
  1255. /// <returns>New parcel bitmap</returns>
  1256. public bool[,] RemoveFromLandBitmap(bool[,] bitmap_base, bool[,] bitmap_new, out bool isEmptyNow)
  1257. {
  1258. // get the size of the incoming bitmaps
  1259. int baseX = bitmap_base.GetLength(0);
  1260. int baseY = bitmap_base.GetLength(1);
  1261. int newX = bitmap_new.GetLength(0);
  1262. int newY = bitmap_new.GetLength(1);
  1263. if (baseX != newX || baseY != newY)
  1264. {
  1265. throw new Exception(
  1266. String.Format("{0} RemoveFromLandBitmap: Land bitmaps are not the same size! baseX={1} baseY={2} newX={3} newY={4}", LogHeader, baseX, baseY, newX, newY));
  1267. }
  1268. isEmptyNow = true;
  1269. for (int x = 0; x < baseX; x++)
  1270. {
  1271. for (int y = 0; y < baseY; y++)
  1272. {
  1273. if (bitmap_new[x, y]) bitmap_base[x, y] = false;
  1274. if (bitmap_base[x, y])
  1275. {
  1276. isEmptyNow = false;
  1277. }
  1278. }
  1279. }
  1280. return bitmap_base;
  1281. }
  1282. /// <summary>
  1283. /// Converts the land bitmap to a packet friendly byte array
  1284. /// </summary>
  1285. /// <returns></returns>
  1286. public byte[] ConvertLandBitmapToBytes()
  1287. {
  1288. byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
  1289. int tempByte = 0;
  1290. int byteNum = 0;
  1291. int mask = 1;
  1292. for (int y = 0; y < LandBitmap.GetLength(1); y++)
  1293. {
  1294. for (int x = 0; x < LandBitmap.GetLength(0); x++)
  1295. {
  1296. if (LandBitmap[x, y])
  1297. tempByte |= mask;
  1298. mask = mask << 1;
  1299. if (mask == 0x100)
  1300. {
  1301. mask = 1;
  1302. tempConvertArr[byteNum++] = (byte)tempByte;
  1303. tempByte = 0;
  1304. }
  1305. }
  1306. }
  1307. if(tempByte != 0 && byteNum < 512)
  1308. tempConvertArr[byteNum] = (byte)tempByte;
  1309. return tempConvertArr;
  1310. }
  1311. public bool[,] ConvertBytesToLandBitmap(bool overrideRegionSize = false)
  1312. {
  1313. int bitmapLen;
  1314. int xLen;
  1315. bool[,] tempConvertMap;
  1316. if (overrideRegionSize)
  1317. {
  1318. // Importing land parcel data from an OAR where the source region is a different size to the dest region requires us
  1319. // to make a LandBitmap that's not derived from the current region's size. We use the LandData.Bitmap size in bytes
  1320. // to figure out what the OAR's region dimensions are. (Is there a better way to get the src region x and y from the OAR?)
  1321. // This method assumes we always will have square regions
  1322. bitmapLen = LandData.Bitmap.Length;
  1323. xLen = (int)Math.Abs(Math.Sqrt(bitmapLen * 8));
  1324. tempConvertMap = new bool[xLen, xLen];
  1325. tempConvertMap.Initialize();
  1326. }
  1327. else
  1328. {
  1329. tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
  1330. tempConvertMap.Initialize();
  1331. // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
  1332. bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
  1333. xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
  1334. if (bitmapLen == 512)
  1335. {
  1336. // Legacy bitmap being passed in. Use the legacy region size
  1337. // and only set the lower area of the larger region.
  1338. xLen = (int)(Constants.RegionSize / landUnit);
  1339. }
  1340. }
  1341. // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
  1342. byte tempByte;
  1343. int x = 0, y = 0;
  1344. for (int i = 0; i < bitmapLen; i++)
  1345. {
  1346. tempByte = LandData.Bitmap[i];
  1347. for (int bitmask = 0x01; bitmask < 0x100; bitmask = bitmask << 1)
  1348. {
  1349. bool bit = (tempByte & bitmask) == bitmask;
  1350. try
  1351. {
  1352. tempConvertMap[x, y] = bit;
  1353. }
  1354. catch (Exception)
  1355. {
  1356. m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
  1357. }
  1358. x++;
  1359. if (x >= xLen)
  1360. {
  1361. x = 0;
  1362. y++;
  1363. }
  1364. }
  1365. }
  1366. return tempConvertMap;
  1367. }
  1368. public bool IsLandBitmapEmpty(bool[,] landBitmap)
  1369. {
  1370. for (int y = 0; y < landBitmap.GetLength(1); y++)
  1371. {
  1372. for (int x = 0; x < landBitmap.GetLength(0); x++)
  1373. {
  1374. if (landBitmap[x, y]) return false;
  1375. }
  1376. }
  1377. return true;
  1378. }
  1379. public void DebugLandBitmap(bool[,] landBitmap)
  1380. {
  1381. m_log.InfoFormat("{0}: Map Key: #=claimed land .=unclaimed land.", LogHeader);
  1382. for (int y = landBitmap.GetLength(1) - 1; y >= 0; y--)
  1383. {
  1384. string row = "";
  1385. for (int x = 0; x < landBitmap.GetLength(0); x++)
  1386. {
  1387. row += landBitmap[x, y] ? "#" : ".";
  1388. }
  1389. m_log.InfoFormat("{0}: {1}", LogHeader, row);
  1390. }
  1391. }
  1392. #endregion
  1393. #region Object Select and Object Owner Listing
  1394. public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
  1395. {
  1396. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
  1397. {
  1398. List<uint> resultLocalIDs = new List<uint>();
  1399. try
  1400. {
  1401. lock (primsOverMe)
  1402. {
  1403. foreach (SceneObjectGroup obj in primsOverMe)
  1404. {
  1405. if (obj.LocalId > 0)
  1406. {
  1407. if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID)
  1408. {
  1409. resultLocalIDs.Add(obj.LocalId);
  1410. }
  1411. else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero)
  1412. {
  1413. resultLocalIDs.Add(obj.LocalId);
  1414. }
  1415. else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER &&
  1416. obj.OwnerID != remote_client.AgentId)
  1417. {
  1418. resultLocalIDs.Add(obj.LocalId);
  1419. }
  1420. else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID))
  1421. {
  1422. resultLocalIDs.Add(obj.LocalId);
  1423. }
  1424. }
  1425. }
  1426. }
  1427. } catch (InvalidOperationException)
  1428. {
  1429. m_log.Error("[LAND]: Unable to force select the parcel objects. Arr.");
  1430. }
  1431. remote_client.SendForceClientSelectObjects(resultLocalIDs);
  1432. }
  1433. }
  1434. /// <summary>
  1435. /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
  1436. /// aggreagete details such as the number of prims.
  1437. ///
  1438. /// </summary>
  1439. /// <param name="remote_client">
  1440. /// A <see cref="IClientAPI"/>
  1441. /// </param>
  1442. public void SendLandObjectOwners(IClientAPI remote_client)
  1443. {
  1444. if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
  1445. {
  1446. Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
  1447. List<UUID> groups = new List<UUID>();
  1448. lock (primsOverMe)
  1449. {
  1450. // m_log.DebugFormat(
  1451. // "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region",
  1452. // remote_client.Name, primsOverMe.Count);
  1453. try
  1454. {
  1455. foreach (SceneObjectGroup obj in primsOverMe)
  1456. {
  1457. try
  1458. {
  1459. if (!primCount.ContainsKey(obj.OwnerID))
  1460. {
  1461. primCount.Add(obj.OwnerID, 0);
  1462. }
  1463. }
  1464. catch (NullReferenceException)
  1465. {
  1466. m_log.Error("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel");
  1467. }
  1468. try
  1469. {
  1470. primCount[obj.OwnerID] += obj.PrimCount;
  1471. }
  1472. catch (KeyNotFoundException)
  1473. {
  1474. m_log.Error("[LAND]: Unable to match a prim with it's owner.");
  1475. }
  1476. if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID)))
  1477. groups.Add(obj.OwnerID);
  1478. }
  1479. }
  1480. catch (InvalidOperationException)
  1481. {
  1482. m_log.Error("[LAND]: Unable to Enumerate Land object arr.");
  1483. }
  1484. }
  1485. remote_client.SendLandObjectOwners(LandData, groups, primCount);
  1486. }
  1487. }
  1488. public Dictionary<UUID, int> GetLandObjectOwners()
  1489. {
  1490. Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
  1491. lock (primsOverMe)
  1492. {
  1493. try
  1494. {
  1495. foreach (SceneObjectGroup obj in primsOverMe)
  1496. {
  1497. if (!ownersAndCount.ContainsKey(obj.OwnerID))
  1498. {
  1499. ownersAndCount.Add(obj.OwnerID, 0);
  1500. }
  1501. ownersAndCount[obj.OwnerID] += obj.PrimCount;
  1502. }
  1503. }
  1504. catch (InvalidOperationException)
  1505. {
  1506. m_log.Error("[LAND]: Unable to enumerate land owners. arr.");
  1507. }
  1508. }
  1509. return ownersAndCount;
  1510. }
  1511. #endregion
  1512. #region Object Sales
  1513. public void SellLandObjects(UUID previousOwner)
  1514. {
  1515. // m_log.DebugFormat(
  1516. // "[LAND OBJECT]: Request to sell objects in {0} from {1}", LandData.Name, previousOwner);
  1517. if (LandData.IsGroupOwned)
  1518. return;
  1519. IBuySellModule m_BuySellModule = m_scene.RequestModuleInterface<IBuySellModule>();
  1520. if (m_BuySellModule == null)
  1521. {
  1522. m_log.Error("[LAND OBJECT]: BuySellModule not found");
  1523. return;
  1524. }
  1525. ScenePresence sp;
  1526. if (!m_scene.TryGetScenePresence(LandData.OwnerID, out sp))
  1527. {
  1528. m_log.Error("[LAND OBJECT]: New owner is not present in scene");
  1529. return;
  1530. }
  1531. lock (primsOverMe)
  1532. {
  1533. foreach (SceneObjectGroup obj in primsOverMe)
  1534. {
  1535. if(m_scene.Permissions.CanSellObject(previousOwner,obj, (byte)SaleType.Original))
  1536. m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, (byte)SaleType.Original, 0);
  1537. }
  1538. }
  1539. }
  1540. #endregion
  1541. #region Object Returning
  1542. public void ReturnObject(SceneObjectGroup obj)
  1543. {
  1544. SceneObjectGroup[] objs = new SceneObjectGroup[1];
  1545. objs[0] = obj;
  1546. m_scene.returnObjects(objs, null);
  1547. }
  1548. public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
  1549. {
  1550. // m_log.DebugFormat(
  1551. // "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name);
  1552. Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>();
  1553. lock (primsOverMe)
  1554. {
  1555. if (type == (uint)ObjectReturnType.Owner)
  1556. {
  1557. foreach (SceneObjectGroup obj in primsOverMe)
  1558. {
  1559. if (obj.OwnerID == LandData.OwnerID)
  1560. {
  1561. if (!returns.ContainsKey(obj.OwnerID))
  1562. returns[obj.OwnerID] =
  1563. new List<SceneObjectGroup>();
  1564. returns[obj.OwnerID].Add(obj);
  1565. }
  1566. }
  1567. }
  1568. else if (type == (uint)ObjectReturnType.Group && LandData.GroupID != UUID.Zero)
  1569. {
  1570. foreach (SceneObjectGroup obj in primsOverMe)
  1571. {
  1572. if (obj.GroupID == LandData.GroupID)
  1573. {
  1574. if (obj.OwnerID == LandData.OwnerID)
  1575. continue;
  1576. if (!returns.ContainsKey(obj.OwnerID))
  1577. returns[obj.OwnerID] =
  1578. new List<SceneObjectGroup>();
  1579. returns[obj.OwnerID].Add(obj);
  1580. }
  1581. }
  1582. }
  1583. else if (type == (uint)ObjectReturnType.Other)
  1584. {
  1585. foreach (SceneObjectGroup obj in primsOverMe)
  1586. {
  1587. if (obj.OwnerID != LandData.OwnerID &&
  1588. (obj.GroupID != LandData.GroupID ||
  1589. LandData.GroupID == UUID.Zero))
  1590. {
  1591. if (!returns.ContainsKey(obj.OwnerID))
  1592. returns[obj.OwnerID] =
  1593. new List<SceneObjectGroup>();
  1594. returns[obj.OwnerID].Add(obj);
  1595. }
  1596. }
  1597. }
  1598. else if (type == (uint)ObjectReturnType.List)
  1599. {
  1600. List<UUID> ownerlist = new List<UUID>(owners);
  1601. foreach (SceneObjectGroup obj in primsOverMe)
  1602. {
  1603. if (ownerlist.Contains(obj.OwnerID))
  1604. {
  1605. if (!returns.ContainsKey(obj.OwnerID))
  1606. returns[obj.OwnerID] =
  1607. new List<SceneObjectGroup>();
  1608. returns[obj.OwnerID].Add(obj);
  1609. }
  1610. }
  1611. }
  1612. }
  1613. foreach (List<SceneObjectGroup> ol in returns.Values)
  1614. {
  1615. if (m_scene.Permissions.CanReturnObjects(this, remote_client, ol))
  1616. m_scene.returnObjects(ol.ToArray(), remote_client);
  1617. }
  1618. }
  1619. #endregion
  1620. #region Object Adding/Removing from Parcel
  1621. public void ResetOverMeRecord()
  1622. {
  1623. lock (primsOverMe)
  1624. primsOverMe.Clear();
  1625. }
  1626. public void AddPrimOverMe(SceneObjectGroup obj)
  1627. {
  1628. // m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name);
  1629. lock (primsOverMe)
  1630. primsOverMe.Add(obj);
  1631. }
  1632. public void RemovePrimFromOverMe(SceneObjectGroup obj)
  1633. {
  1634. // m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name);
  1635. lock (primsOverMe)
  1636. primsOverMe.Remove(obj);
  1637. }
  1638. #endregion
  1639. /// <summary>
  1640. /// Set the media url for this land parcel
  1641. /// </summary>
  1642. /// <param name="url"></param>
  1643. public void SetMediaUrl(string url)
  1644. {
  1645. if (String.IsNullOrWhiteSpace(url))
  1646. LandData.MediaURL = String.Empty;
  1647. else
  1648. {
  1649. try
  1650. {
  1651. Uri dummmy = new Uri(url, UriKind.Absolute);
  1652. LandData.MediaURL = url;
  1653. }
  1654. catch (Exception e)
  1655. {
  1656. m_log.ErrorFormat("[LAND OBJECT]: SetMediaUrl error: {0}", e.Message);
  1657. return;
  1658. }
  1659. }
  1660. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
  1661. SendLandUpdateToAvatarsOverMe();
  1662. }
  1663. /// <summary>
  1664. /// Set the music url for this land parcel
  1665. /// </summary>
  1666. /// <param name="url"></param>
  1667. public void SetMusicUrl(string url)
  1668. {
  1669. if (String.IsNullOrWhiteSpace(url))
  1670. LandData.MusicURL = String.Empty;
  1671. else
  1672. {
  1673. try
  1674. {
  1675. Uri dummmy = new Uri(url, UriKind.Absolute);
  1676. LandData.MusicURL = url;
  1677. }
  1678. catch (Exception e)
  1679. {
  1680. m_log.ErrorFormat("[LAND OBJECT]: SetMusicUrl error: {0}", e.Message);
  1681. return;
  1682. }
  1683. }
  1684. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
  1685. SendLandUpdateToAvatarsOverMe();
  1686. }
  1687. /// <summary>
  1688. /// Get the music url for this land parcel
  1689. /// </summary>
  1690. /// <returns>The music url.</returns>
  1691. public string GetMusicUrl()
  1692. {
  1693. return LandData.MusicURL;
  1694. }
  1695. #endregion
  1696. private void OnFrame()
  1697. {
  1698. m_expiryCounter++;
  1699. if (m_expiryCounter >= 50)
  1700. {
  1701. ExpireAccessList();
  1702. m_expiryCounter = 0;
  1703. }
  1704. // need to update dwell here bc landdata has no parent info
  1705. if(LandData != null && m_dwellModule != null)
  1706. {
  1707. double now = Util.GetTimeStampMS();
  1708. double elapsed = now - LandData.LastDwellTimeMS;
  1709. if(elapsed > 150000) //2.5 minutes resolution / throttle
  1710. {
  1711. float dwell = LandData.Dwell;
  1712. double cur = dwell * 60000.0;
  1713. double decay = 1.5e-8 * cur * elapsed;
  1714. cur -= decay;
  1715. if(cur < 0)
  1716. cur = 0;
  1717. UUID lgid = LandData.GlobalID;
  1718. m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
  1719. {
  1720. if(sp.IsNPC || sp.IsDeleted || sp.currentParcelUUID != lgid)
  1721. return;
  1722. cur += (now - sp.ParcelDwellTickMS);
  1723. sp.ParcelDwellTickMS = now;
  1724. });
  1725. float newdwell = (float)(cur * 1.666666666667e-5);
  1726. LandData.Dwell = newdwell;
  1727. if(Math.Abs(newdwell - dwell) >= 0.9)
  1728. m_scene.EventManager.TriggerLandObjectAdded(this);
  1729. }
  1730. }
  1731. }
  1732. private void ExpireAccessList()
  1733. {
  1734. List<LandAccessEntry> delete = new List<LandAccessEntry>();
  1735. foreach (LandAccessEntry entry in LandData.ParcelAccessList)
  1736. {
  1737. if (entry.Expires != 0 && entry.Expires < Util.UnixTimeSinceEpoch())
  1738. delete.Add(entry);
  1739. }
  1740. foreach (LandAccessEntry entry in delete)
  1741. {
  1742. LandData.ParcelAccessList.Remove(entry);
  1743. ScenePresence presence;
  1744. if (m_scene.TryGetScenePresence(entry.AgentID, out presence) && (!presence.IsChildAgent))
  1745. {
  1746. ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
  1747. if (land.LandData.LocalID == LandData.LocalID)
  1748. {
  1749. Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
  1750. presence.TeleportOnEject(pos);
  1751. presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
  1752. }
  1753. }
  1754. m_log.DebugFormat("[LAND]: Removing entry {0} because it has expired", entry.AgentID);
  1755. }
  1756. if (delete.Count > 0)
  1757. m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this);
  1758. }
  1759. public void StoreEnvironment(ViewerEnvironment VEnv)
  1760. {
  1761. int lastVersion = LandData.EnvironmentVersion;
  1762. LandData.Environment = VEnv;
  1763. if (VEnv == null)
  1764. LandData.EnvironmentVersion = -1;
  1765. else
  1766. {
  1767. ++LandData.EnvironmentVersion;
  1768. VEnv.version = LandData.EnvironmentVersion;
  1769. }
  1770. if(lastVersion != LandData.EnvironmentVersion)
  1771. {
  1772. m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
  1773. SendLandUpdateToAvatarsOverMe();
  1774. }
  1775. }
  1776. }
  1777. }