LandManagementModule.cs 114 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816
  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.Net;
  31. using System.Reflection;
  32. using System.Text;
  33. using log4net;
  34. using Nini.Config;
  35. using OpenMetaverse;
  36. using OpenMetaverse.StructuredData;
  37. using OpenMetaverse.Messages.Linden;
  38. using Mono.Addins;
  39. using OpenSim.Framework;
  40. using OpenSim.Framework.Capabilities;
  41. using OpenSim.Framework.Console;
  42. using OpenSim.Framework.Servers;
  43. using OpenSim.Framework.Monitoring;
  44. using OpenSim.Framework.Servers.HttpServer;
  45. using OpenSim.Region.Framework.Interfaces;
  46. using OpenSim.Region.Framework.Scenes;
  47. using OpenSim.Region.PhysicsModules.SharedBase;
  48. using OpenSim.Services.Interfaces;
  49. using Caps = OpenSim.Framework.Capabilities.Caps;
  50. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  51. using OSDMap = OpenMetaverse.StructuredData.OSDMap;
  52. using OSDArray = OpenMetaverse.StructuredData.OSDArray;
  53. namespace OpenSim.Region.CoreModules.World.Land
  54. {
  55. // used for caching
  56. internal class ExtendedLandData
  57. {
  58. public LandData LandData;
  59. public ulong RegionHandle;
  60. public uint X, Y;
  61. public byte RegionAccess;
  62. }
  63. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LandManagementModule")]
  64. public class LandManagementModule : INonSharedRegionModule , ILandChannel
  65. {
  66. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  67. private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
  68. /// <summary>
  69. /// Minimum land unit size in region co-ordinates.
  70. /// </summary>
  71. public const int LandUnit = 4;
  72. private Scene m_scene;
  73. //private LandChannel m_landChannel;
  74. private ulong m_regionHandler;
  75. private int m_regionSizeX;
  76. private int m_regionSizeY;
  77. protected IGroupsModule m_groupManager;
  78. protected IUserManagement m_userManager;
  79. protected IPrimCountModule m_primCountModule;
  80. protected IDialogModule m_Dialog;
  81. /// <value>
  82. /// Local land ids at specified region co-ordinates (region size / 4)
  83. /// </value>
  84. private int[,] m_landIDList;
  85. /// <value>
  86. /// Land objects keyed by local id
  87. /// </value>
  88. private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
  89. private readonly Dictionary<UUID, int> m_landGlobalIDs = new Dictionary<UUID, int>();
  90. private readonly Dictionary<UUID, int> m_landFakeIDs = new Dictionary<UUID, int>();
  91. private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
  92. private bool m_allowedForcefulBans = true;
  93. private bool m_showBansLines = true;
  94. private UUID DefaultGodParcelGroup;
  95. private string DefaultGodParcelName;
  96. private UUID DefaultGodParcelOwner;
  97. // caches ExtendedLandData
  98. static private readonly ExpiringCacheOS<UUID,ExtendedLandData> m_parcelInfoCache = new ExpiringCacheOS<UUID, ExtendedLandData>(10000);
  99. /// <summary>
  100. /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
  101. /// </summary>
  102. private HashSet<UUID> forcedPosition = new HashSet<UUID>();
  103. // Enables limiting parcel layer info transmission when doing simple updates
  104. private bool shouldLimitParcelLayerInfoToViewDistance { get; set; }
  105. // "View distance" for sending parcel layer info if asked for from a view point in the region
  106. private int parcelLayerViewDistance { get; set; }
  107. private float m_BanLineSafeHeight = 100.0f;
  108. public float BanLineSafeHeight
  109. {
  110. get { return m_BanLineSafeHeight; }
  111. private set
  112. {
  113. if (value > 20f && value <= 5000f)
  114. m_BanLineSafeHeight = value;
  115. else
  116. m_BanLineSafeHeight = 100.0f;
  117. }
  118. }
  119. #region INonSharedRegionModule Members
  120. public Type ReplaceableInterface
  121. {
  122. get { return null; }
  123. }
  124. public void Initialise(IConfigSource source)
  125. {
  126. shouldLimitParcelLayerInfoToViewDistance = true;
  127. parcelLayerViewDistance = 128;
  128. IConfig landManagementConfig = source.Configs["LandManagement"];
  129. if (landManagementConfig != null)
  130. {
  131. shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance);
  132. parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance);
  133. DefaultGodParcelGroup = new UUID(landManagementConfig.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
  134. DefaultGodParcelName = landManagementConfig.GetString("DefaultAdministratorParcelName", "Admin Parcel");
  135. DefaultGodParcelOwner = new UUID(landManagementConfig.GetString("DefaultAdministratorOwnerUUID", UUID.Zero.ToString()));
  136. bool disablebans = landManagementConfig.GetBoolean("DisableParcelBans", !m_allowedForcefulBans);
  137. m_allowedForcefulBans = !disablebans;
  138. m_showBansLines = landManagementConfig.GetBoolean("ShowParcelBansLines", m_showBansLines);
  139. m_BanLineSafeHeight = landManagementConfig.GetFloat("BanLineSafeHeight", m_BanLineSafeHeight);
  140. }
  141. }
  142. public void AddRegion(Scene scene)
  143. {
  144. m_scene = scene;
  145. m_regionHandler = m_scene.RegionInfo.RegionHandle;
  146. m_regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
  147. m_regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
  148. m_landIDList = new int[m_regionSizeX / LandUnit, m_regionSizeY / LandUnit];
  149. m_scene.LandChannel = this;
  150. m_scene.EventManager.OnObjectAddedToScene += EventManagerOnParcelPrimCountAdd;
  151. m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd;
  152. m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
  153. m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate;
  154. m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate;
  155. m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel;
  156. m_scene.EventManager.OnClientMovement += EventManagerOnClientMovement;
  157. m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy;
  158. m_scene.EventManager.OnLandBuy += EventManagerOnLandBuy;
  159. m_scene.EventManager.OnNewClient += EventManagerOnNewClient;
  160. m_scene.EventManager.OnMakeChildAgent += EventMakeChildAgent;
  161. m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement;
  162. m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage;
  163. m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
  164. m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
  165. m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
  166. RegisterCommands();
  167. }
  168. public void RegionLoaded(Scene scene)
  169. {
  170. m_userManager = m_scene.RequestModuleInterface<IUserManagement>();
  171. m_groupManager = m_scene.RequestModuleInterface<IGroupsModule>();
  172. m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>();
  173. m_Dialog = m_scene.RequestModuleInterface<IDialogModule>();
  174. }
  175. public void RemoveRegion(Scene scene)
  176. {
  177. // TODO: Release event manager listeners here
  178. }
  179. // private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
  180. // {
  181. // ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
  182. // reason = "You are not allowed to enter this sim.";
  183. // return nearestParcel != null;
  184. // }
  185. void EventManagerOnNewClient(IClientAPI client)
  186. {
  187. //Register some client events
  188. client.OnParcelPropertiesRequest += ClientOnParcelPropertiesRequest;
  189. client.OnParcelDivideRequest += ClientOnParcelDivideRequest;
  190. client.OnParcelJoinRequest += ClientOnParcelJoinRequest;
  191. client.OnParcelPropertiesUpdateRequest += ClientOnParcelPropertiesUpdateRequest;
  192. client.OnParcelSelectObjects += ClientOnParcelSelectObjects;
  193. client.OnParcelObjectOwnerRequest += ClientOnParcelObjectOwnerRequest;
  194. client.OnParcelAccessListRequest += ClientOnParcelAccessListRequest;
  195. client.OnParcelAccessListUpdateRequest += ClientOnParcelAccessListUpdateRequest;
  196. client.OnParcelAbandonRequest += ClientOnParcelAbandonRequest;
  197. client.OnParcelGodForceOwner += ClientOnParcelGodForceOwner;
  198. client.OnParcelReclaim += ClientOnParcelReclaim;
  199. client.OnParcelInfoRequest += ClientOnParcelInfoRequest;
  200. client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
  201. client.OnParcelEjectUser += ClientOnParcelEjectUser;
  202. client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
  203. client.OnSetStartLocationRequest += ClientOnSetHome;
  204. client.OnParcelBuyPass += ClientParcelBuyPass;
  205. client.OnParcelGodMark += ClientOnParcelGodMark;
  206. }
  207. public void EventMakeChildAgent(ScenePresence avatar)
  208. {
  209. avatar.currentParcelUUID = UUID.Zero;
  210. }
  211. public void Close()
  212. {
  213. }
  214. public string Name
  215. {
  216. get { return "LandManagementModule"; }
  217. }
  218. #endregion
  219. #region Parcel Add/Remove/Get/Create
  220. public void EventManagerOnSetAllowedForcefulBan(bool forceful)
  221. {
  222. AllowedForcefulBans = forceful;
  223. }
  224. public void UpdateLandObject(int local_id, LandData data)
  225. {
  226. LandData newData = data.Copy();
  227. newData.LocalID = local_id;
  228. ILandObject land;
  229. lock (m_landList)
  230. {
  231. if (m_landList.TryGetValue(local_id, out land))
  232. {
  233. m_landGlobalIDs.Remove(land.LandData.GlobalID);
  234. if (land.LandData.FakeID != UUID.Zero)
  235. m_landFakeIDs.Remove(land.LandData.FakeID);
  236. land.LandData = newData;
  237. m_landGlobalIDs[newData.GlobalID] = local_id;
  238. if (newData.FakeID != UUID.Zero)
  239. m_landFakeIDs[newData.FakeID] = local_id;
  240. }
  241. }
  242. if (land != null)
  243. m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land);
  244. }
  245. public bool IsForcefulBansAllowed()
  246. {
  247. return AllowedForcefulBans;
  248. }
  249. public bool AllowedForcefulBans
  250. {
  251. get { return m_allowedForcefulBans; }
  252. set { m_allowedForcefulBans = value; }
  253. }
  254. /// <summary>
  255. /// Resets the sim to the default land object (full sim piece of land owned by the default user)
  256. /// </summary>
  257. public void ResetSimLandObjects()
  258. {
  259. //Remove all the land objects in the sim and add a blank, full sim land object set to public
  260. lock (m_landList)
  261. {
  262. foreach(ILandObject parcel in m_landList.Values)
  263. parcel.Clear();
  264. m_landList.Clear();
  265. m_landGlobalIDs.Clear();
  266. m_landFakeIDs.Clear();
  267. m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
  268. m_landIDList = new int[m_regionSizeX / LandUnit, m_regionSizeY / LandUnit];
  269. }
  270. }
  271. /// <summary>
  272. /// Create a default parcel that spans the entire region and is owned by the estate owner.
  273. /// </summary>
  274. /// <returns>The parcel created.</returns>
  275. protected ILandObject CreateDefaultParcel()
  276. {
  277. m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName);
  278. ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
  279. fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, m_regionSizeX, m_regionSizeY));
  280. LandData ldata = fullSimParcel.LandData;
  281. ldata.SimwideArea = ldata.Area;
  282. ldata.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  283. ldata.ClaimDate = Util.UnixTimeSinceEpoch();
  284. return AddLandObject(fullSimParcel);
  285. }
  286. public List<ILandObject> AllParcels()
  287. {
  288. lock (m_landList)
  289. {
  290. return new List<ILandObject>(m_landList.Values);
  291. }
  292. }
  293. public List<ILandObject> ParcelsNearPoint(Vector3 position)
  294. {
  295. List<ILandObject> parcelsNear = new List<ILandObject>();
  296. for (int x = -8; x <= 8; x += 4)
  297. {
  298. for (int y = -8; y <= 8; y += 4)
  299. {
  300. ILandObject check = GetLandObject(position.X + x, position.Y + y);
  301. if (check != null)
  302. {
  303. if (!parcelsNear.Contains(check))
  304. {
  305. parcelsNear.Add(check);
  306. }
  307. }
  308. }
  309. }
  310. return parcelsNear;
  311. }
  312. // checks and enforces bans or restrictions
  313. // returns true if enforced
  314. public bool EnforceBans(ILandObject land, ScenePresence avatar)
  315. {
  316. Vector3 agentpos = avatar.AbsolutePosition;
  317. float h = m_scene.GetGroundHeight(agentpos.X, agentpos.Y) + m_scene.LandChannel.BanLineSafeHeight;
  318. float zdif = avatar.AbsolutePosition.Z - h;
  319. if (zdif > 0 )
  320. {
  321. forcedPosition.Remove(avatar.UUID);
  322. avatar.lastKnownAllowedPosition = agentpos;
  323. return false;
  324. }
  325. bool ban = false;
  326. string reason = "";
  327. if (land.IsRestrictedFromLand(avatar.UUID))
  328. {
  329. reason = "You do not have access to the parcel";
  330. ban = true;
  331. }
  332. if (land.IsBannedFromLand(avatar.UUID))
  333. {
  334. if ( m_allowedForcefulBans)
  335. {
  336. reason ="You are banned from parcel";
  337. ban = true;
  338. }
  339. else if(!ban)
  340. {
  341. if (forcedPosition.Contains(avatar.UUID))
  342. avatar.ControllingClient.SendAlertMessage("You are banned from parcel, please leave by your own will");
  343. forcedPosition.Remove(avatar.UUID);
  344. avatar.lastKnownAllowedPosition = agentpos;
  345. return false;
  346. }
  347. }
  348. if(ban)
  349. {
  350. if (!forcedPosition.Contains(avatar.UUID))
  351. avatar.ControllingClient.SendAlertMessage(reason);
  352. if(zdif > -4f)
  353. {
  354. agentpos.Z = h + 4.0f;
  355. ForceAvatarToPosition(avatar, agentpos);
  356. return true;
  357. }
  358. if (land.ContainsPoint((int)avatar.lastKnownAllowedPosition.X,
  359. (int) avatar.lastKnownAllowedPosition.Y))
  360. {
  361. Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
  362. if (pos == null)
  363. {
  364. forcedPosition.Remove(avatar.UUID);
  365. m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
  366. }
  367. else
  368. ForceAvatarToPosition(avatar, (Vector3)pos);
  369. }
  370. else
  371. {
  372. ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
  373. }
  374. return true;
  375. }
  376. else
  377. {
  378. forcedPosition.Remove(avatar.UUID);
  379. avatar.lastKnownAllowedPosition = agentpos;
  380. return false;
  381. }
  382. }
  383. private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
  384. {
  385. if (m_scene.Permissions.IsGod(avatar.UUID)) return;
  386. if (!position.HasValue)
  387. return;
  388. if(avatar.MovingToTarget)
  389. avatar.ResetMoveToTarget();
  390. avatar.AbsolutePosition = position.Value;
  391. avatar.lastKnownAllowedPosition = position.Value;
  392. avatar.Velocity = Vector3.Zero;
  393. if(avatar.IsSitting)
  394. avatar.StandUp();
  395. forcedPosition.Add(avatar.UUID);
  396. }
  397. public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID)
  398. {
  399. if (m_scene.RegionInfo.RegionID == regionID)
  400. {
  401. ILandObject parcelAvatarIsEntering;
  402. lock (m_landList)
  403. {
  404. parcelAvatarIsEntering = m_landList[localLandID];
  405. }
  406. if (parcelAvatarIsEntering != null &&
  407. avatar.currentParcelUUID != parcelAvatarIsEntering.LandData.GlobalID)
  408. {
  409. SendLandUpdate(avatar, parcelAvatarIsEntering);
  410. avatar.currentParcelUUID = parcelAvatarIsEntering.LandData.GlobalID;
  411. EnforceBans(parcelAvatarIsEntering, avatar);
  412. }
  413. }
  414. }
  415. public void SendOutNearestBanLine(IClientAPI client)
  416. {
  417. ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
  418. if (sp == null || sp.IsDeleted)
  419. return;
  420. List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition);
  421. foreach (ILandObject checkBan in checkLandParcels)
  422. {
  423. if (checkBan.IsBannedFromLand(client.AgentId))
  424. {
  425. checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, client);
  426. return; //Only send one
  427. }
  428. if (checkBan.IsRestrictedFromLand(client.AgentId))
  429. {
  430. checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, client);
  431. return; //Only send one
  432. }
  433. }
  434. return;
  435. }
  436. public void sendClientInitialLandInfo(IClientAPI remoteClient, bool overlay)
  437. {
  438. ScenePresence avatar;
  439. if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out avatar))
  440. return;
  441. if (!avatar.IsChildAgent)
  442. {
  443. ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
  444. if (over == null)
  445. return;
  446. avatar.currentParcelUUID = over.LandData.GlobalID;
  447. over.SendLandUpdateToClient(avatar.ControllingClient);
  448. }
  449. if(overlay)
  450. SendParcelOverlay(remoteClient);
  451. }
  452. public void SendLandUpdate(ScenePresence avatar, ILandObject over)
  453. {
  454. if (avatar.IsChildAgent)
  455. return;
  456. if (over != null)
  457. {
  458. over.SendLandUpdateToClient(avatar.ControllingClient);
  459. // sl doesnt seem to send this now, as it used 2
  460. // SendParcelOverlay(avatar.ControllingClient);
  461. }
  462. }
  463. public void EventManagerOnSignificantClientMovement(ScenePresence avatar)
  464. {
  465. if (avatar.IsChildAgent)
  466. return;
  467. if ( m_allowedForcefulBans && m_showBansLines && !m_scene.RegionInfo.EstateSettings.TaxFree)
  468. SendOutNearestBanLine(avatar.ControllingClient);
  469. }
  470. /// <summary>
  471. /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance.
  472. /// </summary>
  473. /// <param name="avatar"></param>
  474. public void EventManagerOnClientMovement(ScenePresence avatar)
  475. {
  476. if (avatar.IsChildAgent)
  477. return;
  478. Vector3 pos = avatar.AbsolutePosition;
  479. ILandObject over = GetLandObject(pos.X, pos.Y);
  480. if (over != null)
  481. {
  482. EnforceBans(over, avatar);
  483. pos = avatar.AbsolutePosition;
  484. ILandObject newover = GetLandObject(pos.X, pos.Y);
  485. if(over != newover || avatar.currentParcelUUID != newover.LandData.GlobalID)
  486. {
  487. m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar,
  488. newover.LandData.LocalID, m_scene.RegionInfo.RegionID);
  489. }
  490. }
  491. }
  492. public void ClientParcelBuyPass(IClientAPI remote_client, UUID targetID, int landLocalID)
  493. {
  494. ILandObject land;
  495. lock (m_landList)
  496. {
  497. m_landList.TryGetValue(landLocalID, out land);
  498. }
  499. // trivial checks
  500. if(land == null)
  501. return;
  502. LandData ldata = land.LandData;
  503. if(ldata == null)
  504. return;
  505. if(ldata.OwnerID == targetID)
  506. return;
  507. if(ldata.PassHours == 0)
  508. return;
  509. if (m_scene.RegionInfo.EstateSettings.TaxFree)
  510. return;
  511. // don't allow passes on group owned until we can give money to groups
  512. if (ldata.IsGroupOwned)
  513. {
  514. remote_client.SendAgentAlertMessage("pass to group owned parcel not suported", false);
  515. return;
  516. }
  517. if((ldata.Flags & (uint)ParcelFlags.UsePassList) == 0)
  518. return;
  519. int cost = ldata.PassPrice;
  520. int idx = land.LandData.ParcelAccessList.FindIndex(
  521. delegate(LandAccessEntry e)
  522. {
  523. if (e.AgentID == targetID && e.Flags == AccessList.Access)
  524. return true;
  525. return false;
  526. });
  527. int now = Util.UnixTimeSinceEpoch();
  528. int expires = (int)(3600.0 * ldata.PassHours + 0.5f);
  529. int currenttime = -1;
  530. if (idx != -1)
  531. {
  532. if(ldata.ParcelAccessList[idx].Expires == 0)
  533. {
  534. remote_client.SendAgentAlertMessage("You already have access to parcel", false);
  535. return;
  536. }
  537. currenttime = ldata.ParcelAccessList[idx].Expires - now;
  538. if(currenttime > (int)(0.25f * expires + 0.5f))
  539. {
  540. if(currenttime > 3600)
  541. remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.###} hours",
  542. currenttime/3600f), false);
  543. else if(currenttime > 60)
  544. remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.##} minutes",
  545. currenttime/60f), false);
  546. else
  547. remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.#} seconds",
  548. currenttime), false);
  549. return;
  550. }
  551. }
  552. LandAccessEntry entry = new LandAccessEntry();
  553. entry.AgentID = targetID;
  554. entry.Flags = AccessList.Access;
  555. entry.Expires = now + expires;
  556. if(currenttime > 0)
  557. entry.Expires += currenttime;
  558. IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
  559. if(cost != 0 && mm != null)
  560. {
  561. WorkManager.RunInThreadPool(
  562. delegate
  563. {
  564. string regionName = m_scene.RegionInfo.RegionName;
  565. if (!mm.AmountCovered(remote_client.AgentId, cost))
  566. {
  567. remote_client.SendAgentAlertMessage(String.Format("Insufficient funds in region '{0}' money system", regionName), true);
  568. return;
  569. }
  570. string payDescription = String.Format("Parcel '{0}' at region '{1} {2:0.###} hours access pass", ldata.Name, regionName, ldata.PassHours);
  571. if(!mm.MoveMoney(remote_client.AgentId, ldata.OwnerID, cost,MoneyTransactionType.LandPassSale, payDescription))
  572. {
  573. remote_client.SendAgentAlertMessage("Sorry pass payment processing failed, please try again later", true);
  574. return;
  575. }
  576. if (idx != -1)
  577. ldata.ParcelAccessList.RemoveAt(idx);
  578. ldata.ParcelAccessList.Add(entry);
  579. m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
  580. return;
  581. }, null, "ParcelBuyPass");
  582. }
  583. else
  584. {
  585. if (idx != -1)
  586. ldata.ParcelAccessList.RemoveAt(idx);
  587. ldata.ParcelAccessList.Add(entry);
  588. m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
  589. }
  590. }
  591. public void ClientOnParcelAccessListRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID,
  592. int landLocalID, IClientAPI remote_client)
  593. {
  594. ILandObject land;
  595. lock (m_landList)
  596. {
  597. m_landList.TryGetValue(landLocalID, out land);
  598. }
  599. if (land != null)
  600. {
  601. land.SendAccessList(agentID, sessionID, flags, sequenceID, remote_client);
  602. }
  603. }
  604. public void ClientOnParcelAccessListUpdateRequest(UUID agentID,
  605. uint flags, UUID transactionID, int landLocalID, List<LandAccessEntry> entries,
  606. IClientAPI remote_client)
  607. {
  608. if ((flags & 0x03) == 0)
  609. return; // we only have access and ban
  610. if(m_scene.RegionInfo.EstateSettings.TaxFree)
  611. return;
  612. ILandObject land;
  613. lock (m_landList)
  614. {
  615. m_landList.TryGetValue(landLocalID, out land);
  616. }
  617. if (land != null)
  618. {
  619. GroupPowers requiredPowers = GroupPowers.None;
  620. if ((flags & (uint)AccessList.Access) != 0)
  621. requiredPowers |= GroupPowers.LandManageAllowed;
  622. if ((flags & (uint)AccessList.Ban) != 0)
  623. requiredPowers |= GroupPowers.LandManageBanned;
  624. if(requiredPowers == GroupPowers.None)
  625. return;
  626. if (m_scene.Permissions.CanEditParcelProperties(agentID,
  627. land, requiredPowers, false))
  628. {
  629. land.UpdateAccessList(flags, transactionID, entries);
  630. }
  631. }
  632. else
  633. {
  634. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid local land ID {0}", landLocalID);
  635. }
  636. }
  637. /// <summary>
  638. /// Adds a land object to the stored list and adds them to the landIDList to what they own
  639. /// </summary>
  640. /// <param name="new_land">
  641. /// The land object being added.
  642. /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted.
  643. /// </param>
  644. public ILandObject AddLandObject(ILandObject new_land)
  645. {
  646. // Only now can we add the prim counts to the land object - we rely on the global ID which is generated
  647. // as a random UUID inside LandData initialization
  648. if (m_primCountModule != null)
  649. new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID);
  650. lock (m_landList)
  651. {
  652. int newLandLocalID = m_lastLandLocalID + 1;
  653. new_land.LandData.LocalID = newLandLocalID;
  654. bool[,] landBitmap = new_land.GetLandBitmap();
  655. if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
  656. {
  657. // Going to variable sized regions can cause mismatches
  658. m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
  659. LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1));
  660. }
  661. else
  662. {
  663. // If other land objects still believe that they occupy any parts of the same space,
  664. // then do not allow the add to proceed.
  665. for (int x = 0; x < landBitmap.GetLength(0); x++)
  666. {
  667. for (int y = 0; y < landBitmap.GetLength(1); y++)
  668. {
  669. if (landBitmap[x, y])
  670. {
  671. int lastRecordedLandId = m_landIDList[x, y];
  672. if (lastRecordedLandId > 0)
  673. {
  674. ILandObject lastRecordedLo = m_landList[lastRecordedLandId];
  675. if (lastRecordedLo.LandBitmap[x, y])
  676. {
  677. m_log.ErrorFormat(
  678. "{0}: Cannot add parcel \"{1}\", local ID {2} at tile {3},{4} because this is still occupied by parcel \"{5}\", local ID {6} in {7}",
  679. LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y,
  680. lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name);
  681. return null;
  682. }
  683. }
  684. }
  685. }
  686. }
  687. for (int x = 0; x < landBitmap.GetLength(0); x++)
  688. {
  689. for (int y = 0; y < landBitmap.GetLength(1); y++)
  690. {
  691. if (landBitmap[x, y])
  692. {
  693. // m_log.DebugFormat(
  694. // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
  695. // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
  696. m_landIDList[x, y] = newLandLocalID;
  697. }
  698. }
  699. }
  700. }
  701. m_landList.Add(newLandLocalID, new_land);
  702. m_landGlobalIDs[new_land.LandData.GlobalID] = newLandLocalID;
  703. m_landFakeIDs[new_land.LandData.FakeID] = newLandLocalID;
  704. m_lastLandLocalID++;
  705. }
  706. new_land.ForceUpdateLandInfo();
  707. m_scene.EventManager.TriggerLandObjectAdded(new_land);
  708. return new_land;
  709. }
  710. /// <summary>
  711. /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList
  712. /// </summary>
  713. /// <param name="local_id">Land.localID of the peice of land to remove.</param>
  714. public void removeLandObject(int local_id)
  715. {
  716. ILandObject land;
  717. UUID landGlobalID = UUID.Zero;
  718. lock (m_landList)
  719. {
  720. for (int x = 0; x < m_landIDList.GetLength(0); x++)
  721. {
  722. for (int y = 0; y < m_landIDList.GetLength(1); y++)
  723. {
  724. if (m_landIDList[x, y] == local_id)
  725. {
  726. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Not removing land object {0}; still being used at {1}, {2}",
  727. local_id, x, y);
  728. return;
  729. //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
  730. }
  731. }
  732. }
  733. land = m_landList[local_id];
  734. m_landList.Remove(local_id);
  735. if(land != null && land.LandData != null)
  736. {
  737. landGlobalID = land.LandData.GlobalID;
  738. m_landGlobalIDs.Remove(landGlobalID);
  739. m_landFakeIDs.Remove(land.LandData.FakeID);
  740. }
  741. }
  742. if(landGlobalID != UUID.Zero)
  743. {
  744. m_scene.EventManager.TriggerLandObjectRemoved(landGlobalID);
  745. land.Clear();
  746. }
  747. }
  748. /// <summary>
  749. /// Clear the scene of all parcels
  750. /// </summary>
  751. public void Clear(bool setupDefaultParcel)
  752. {
  753. List<UUID> landworkList = new List<UUID>(m_landList.Count);
  754. // move to work pointer since we are deleting it all
  755. lock (m_landList)
  756. {
  757. foreach (ILandObject lo in m_landList.Values)
  758. landworkList.Add(lo.LandData.GlobalID);
  759. }
  760. // this 2 methods have locks (now)
  761. ResetSimLandObjects();
  762. if (setupDefaultParcel)
  763. CreateDefaultParcel();
  764. // fire outside events unlocked
  765. foreach (UUID id in landworkList)
  766. {
  767. //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID);
  768. m_scene.EventManager.TriggerLandObjectRemoved(id);
  769. }
  770. landworkList.Clear();
  771. }
  772. private void performFinalLandJoin(ILandObject master, ILandObject slave)
  773. {
  774. bool[,] landBitmapSlave = slave.GetLandBitmap();
  775. lock (m_landList)
  776. {
  777. for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
  778. {
  779. for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
  780. {
  781. if (landBitmapSlave[x, y])
  782. {
  783. m_landIDList[x, y] = master.LandData.LocalID;
  784. }
  785. }
  786. }
  787. }
  788. master.LandData.Dwell += slave.LandData.Dwell;
  789. removeLandObject(slave.LandData.LocalID);
  790. UpdateLandObject(master.LandData.LocalID, master.LandData);
  791. }
  792. public ILandObject GetLandObject(UUID globalID)
  793. {
  794. lock (m_landList)
  795. {
  796. int lid = -1;
  797. if (m_landGlobalIDs.TryGetValue(globalID, out lid) && lid >= 0)
  798. {
  799. if (m_landList.ContainsKey(lid))
  800. {
  801. return m_landList[lid];
  802. }
  803. else
  804. m_landGlobalIDs.Remove(globalID); // auto heal
  805. }
  806. }
  807. return null;
  808. }
  809. public ILandObject GetLandObjectByfakeID(UUID fakeID)
  810. {
  811. lock (m_landList)
  812. {
  813. int lid = -1;
  814. if (m_landFakeIDs.TryGetValue(fakeID, out lid) && lid >= 0)
  815. {
  816. if (m_landList.ContainsKey(lid))
  817. {
  818. return m_landList[lid];
  819. }
  820. else
  821. m_landFakeIDs.Remove(fakeID); // auto heal
  822. }
  823. }
  824. if(Util.ParseFakeParcelID(fakeID, out ulong rhandle, out uint x, out uint y) && rhandle == m_regionHandler)
  825. {
  826. return GetLandObjectClippedXY(x, y);
  827. }
  828. return null;
  829. }
  830. public ILandObject GetLandObject(int parcelLocalID)
  831. {
  832. lock (m_landList)
  833. {
  834. if (m_landList.ContainsKey(parcelLocalID))
  835. {
  836. return m_landList[parcelLocalID];
  837. }
  838. }
  839. return null;
  840. }
  841. /// <summary>
  842. /// Get the land object at the specified point
  843. /// </summary>
  844. /// <param name="x_float">Value between 0 - 256 on the x axis of the point</param>
  845. /// <param name="y_float">Value between 0 - 256 on the y axis of the point</param>
  846. /// <returns>Land object at the point supplied</returns>
  847. public ILandObject GetLandObject(float x_float, float y_float)
  848. {
  849. return GetLandObject((int)x_float, (int)y_float, true);
  850. }
  851. public ILandObject GetLandObject(Vector3 position)
  852. {
  853. return GetLandObject(position.X, position.Y);
  854. }
  855. // if x,y is off region this will return the parcel at cliped x,y
  856. // as did code it replaces
  857. public ILandObject GetLandObjectClippedXY(float x, float y)
  858. {
  859. //do clip inline
  860. int avx = (int)(Math.Round(x));
  861. if (avx < 0)
  862. avx = 0;
  863. else if (avx >= m_regionSizeX)
  864. avx = m_regionSizeX - 1;
  865. int avy = (int)(Math.Round(y));
  866. if (avy < 0)
  867. avy = 0;
  868. else if (avy >= m_regionSizeY)
  869. avy = m_regionSizeY - 1;
  870. lock (m_landIDList)
  871. {
  872. try
  873. {
  874. return m_landList[m_landIDList[avx / LandUnit, avy / LandUnit]];
  875. }
  876. catch (IndexOutOfRangeException)
  877. {
  878. return null;
  879. }
  880. }
  881. }
  882. // Public entry.
  883. // Throws exception if land object is not found
  884. public ILandObject GetLandObject(int x, int y)
  885. {
  886. return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
  887. }
  888. public ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds)
  889. {
  890. if (x >= m_regionSizeX || y >= m_regionSizeY || x < 0 || y < 0)
  891. {
  892. // These exceptions here will cause a lot of complaints from the users specifically because
  893. // they happen every time at border crossings
  894. if (returnNullIfLandObjectOutsideBounds)
  895. return null;
  896. else
  897. throw new Exception("Error: Parcel not found at point " + x + ", " + y);
  898. }
  899. if(m_landList.Count == 0 || m_landIDList == null)
  900. return null;
  901. lock (m_landIDList)
  902. {
  903. try
  904. {
  905. return m_landList[m_landIDList[x / LandUnit, y / LandUnit]];
  906. }
  907. catch (IndexOutOfRangeException)
  908. {
  909. return null;
  910. }
  911. }
  912. }
  913. public ILandObject GetLandObjectinLandUnits(int x, int y)
  914. {
  915. if (m_landList.Count == 0 || m_landIDList == null)
  916. return null;
  917. lock (m_landIDList)
  918. {
  919. try
  920. {
  921. return m_landList[m_landIDList[x, y]];
  922. }
  923. catch (IndexOutOfRangeException)
  924. {
  925. return null;
  926. }
  927. }
  928. }
  929. public ILandObject GetLandObjectinLandUnitsInt(int x, int y)
  930. {
  931. lock (m_landIDList)
  932. {
  933. try
  934. {
  935. return m_landList[m_landIDList[x, y]];
  936. }
  937. catch (IndexOutOfRangeException)
  938. {
  939. return null;
  940. }
  941. }
  942. }
  943. public int GetLandObjectIDinLandUnits(int x, int y)
  944. {
  945. lock (m_landIDList)
  946. {
  947. try
  948. {
  949. return m_landIDList[x, y];
  950. }
  951. catch (IndexOutOfRangeException)
  952. {
  953. return -1;
  954. }
  955. }
  956. }
  957. // Create a 'parcel is here' bitmap for the parcel identified by the passed landID
  958. private bool[,] CreateBitmapForID(int landID)
  959. {
  960. bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)];
  961. for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
  962. for (int yy = 0; yy < m_landIDList.GetLength(1); yy++)
  963. if (m_landIDList[xx, yy] == landID)
  964. ret[xx, yy] = true;
  965. return ret;
  966. }
  967. #endregion
  968. #region Parcel Modification
  969. public void ResetOverMeRecords()
  970. {
  971. lock (m_landList)
  972. {
  973. foreach (LandObject p in m_landList.Values)
  974. {
  975. p.ResetOverMeRecord();
  976. }
  977. }
  978. }
  979. public void EventManagerOnParcelPrimCountAdd(SceneObjectGroup obj)
  980. {
  981. Vector3 position = obj.AbsolutePosition;
  982. ILandObject landUnderPrim = GetLandObject(position.X, position.Y);
  983. if (landUnderPrim != null)
  984. {
  985. ((LandObject)landUnderPrim).AddPrimOverMe(obj);
  986. }
  987. }
  988. public void EventManagerOnObjectBeingRemovedFromScene(SceneObjectGroup obj)
  989. {
  990. lock (m_landList)
  991. {
  992. foreach (LandObject p in m_landList.Values)
  993. {
  994. p.RemovePrimFromOverMe(obj);
  995. }
  996. }
  997. }
  998. private void FinalizeLandPrimCountUpdate()
  999. {
  1000. //Get Simwide prim count for owner
  1001. Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>();
  1002. lock (m_landList)
  1003. {
  1004. foreach (LandObject p in m_landList.Values)
  1005. {
  1006. if (!landOwnersAndParcels.ContainsKey(p.LandData.OwnerID))
  1007. {
  1008. List<LandObject> tempList = new List<LandObject>();
  1009. tempList.Add(p);
  1010. landOwnersAndParcels.Add(p.LandData.OwnerID, tempList);
  1011. }
  1012. else
  1013. {
  1014. landOwnersAndParcels[p.LandData.OwnerID].Add(p);
  1015. }
  1016. }
  1017. }
  1018. foreach (UUID owner in landOwnersAndParcels.Keys)
  1019. {
  1020. int simArea = 0;
  1021. int simPrims = 0;
  1022. foreach (LandObject p in landOwnersAndParcels[owner])
  1023. {
  1024. simArea += p.LandData.Area;
  1025. simPrims += p.PrimCounts.Total;
  1026. }
  1027. foreach (LandObject p in landOwnersAndParcels[owner])
  1028. {
  1029. p.LandData.SimwideArea = simArea;
  1030. p.LandData.SimwidePrims = simPrims;
  1031. }
  1032. }
  1033. }
  1034. public void EventManagerOnParcelPrimCountUpdate()
  1035. {
  1036. //m_log.DebugFormat(
  1037. // "[land management module]: triggered eventmanageronparcelprimcountupdate() for {0}",
  1038. // m_scene.RegionInfo.RegionName);
  1039. ResetOverMeRecords();
  1040. EntityBase[] entities = m_scene.Entities.GetEntities();
  1041. foreach (EntityBase obj in entities)
  1042. {
  1043. if (obj != null)
  1044. {
  1045. if ((obj is SceneObjectGroup) && !obj.IsDeleted && !((SceneObjectGroup) obj).IsAttachment)
  1046. {
  1047. m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup) obj);
  1048. }
  1049. }
  1050. }
  1051. FinalizeLandPrimCountUpdate();
  1052. }
  1053. public void EventManagerOnRequestParcelPrimCountUpdate()
  1054. {
  1055. ResetOverMeRecords();
  1056. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  1057. FinalizeLandPrimCountUpdate();
  1058. }
  1059. /// <summary>
  1060. /// Subdivides a piece of land
  1061. /// </summary>
  1062. /// <param name="start_x">West Point</param>
  1063. /// <param name="start_y">South Point</param>
  1064. /// <param name="end_x">East Point</param>
  1065. /// <param name="end_y">North Point</param>
  1066. /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param>
  1067. /// <returns>Returns true if successful</returns>
  1068. public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  1069. {
  1070. //First, lets loop through the points and make sure they are all in the same peice of land
  1071. //Get the land object at start
  1072. ILandObject startLandObject = GetLandObject(start_x, start_y);
  1073. if (startLandObject == null)
  1074. return;
  1075. if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin, true))
  1076. {
  1077. return;
  1078. }
  1079. //Loop through the points
  1080. try
  1081. {
  1082. for (int y = start_y; y < end_y; y++)
  1083. {
  1084. for (int x = start_x; x < end_x; x++)
  1085. {
  1086. ILandObject tempLandObject = GetLandObject(x, y);
  1087. if (tempLandObject == null)
  1088. return;
  1089. if (tempLandObject != startLandObject)
  1090. return;
  1091. }
  1092. }
  1093. }
  1094. catch (Exception)
  1095. {
  1096. return;
  1097. }
  1098. //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
  1099. ILandObject newLand = startLandObject.Copy();
  1100. newLand.LandData.Name = newLand.LandData.Name;
  1101. newLand.LandData.GlobalID = UUID.Random();
  1102. newLand.LandData.Dwell = 0;
  1103. // Clear "Show in search" on the cut out parcel to prevent double-charging
  1104. newLand.LandData.Flags &= ~(uint)ParcelFlags.ShowDirectory;
  1105. // invalidate landing point
  1106. newLand.LandData.LandingType = (byte)LandingType.Direct;
  1107. newLand.LandData.UserLocation = Vector3.Zero;
  1108. newLand.LandData.UserLookAt = Vector3.Zero;
  1109. newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
  1110. //lets set the subdivision area of the original to false
  1111. int startLandObjectIndex = startLandObject.LandData.LocalID;
  1112. lock (m_landList)
  1113. {
  1114. m_landList[startLandObjectIndex].SetLandBitmap(
  1115. newLand.ModifyLandBitmapSquare(startLandObject.GetLandBitmap(), start_x, start_y, end_x, end_y, false));
  1116. m_landList[startLandObjectIndex].ForceUpdateLandInfo();
  1117. }
  1118. //add the new land object
  1119. ILandObject result = AddLandObject(newLand);
  1120. UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData);
  1121. if(startLandObject.LandData.LandingType == (byte)LandingType.LandingPoint)
  1122. {
  1123. int x = (int)startLandObject.LandData.UserLocation.X;
  1124. int y = (int)startLandObject.LandData.UserLocation.Y;
  1125. if(!startLandObject.ContainsPoint(x, y))
  1126. {
  1127. startLandObject.LandData.LandingType = (byte)LandingType.Direct;
  1128. startLandObject.LandData.UserLocation = Vector3.Zero;
  1129. startLandObject.LandData.UserLookAt = Vector3.Zero;
  1130. }
  1131. }
  1132. m_scene.EventManager.TriggerParcelPrimCountTainted();
  1133. result.SendLandUpdateToAvatarsOverMe();
  1134. startLandObject.SendLandUpdateToAvatarsOverMe();
  1135. m_scene.ForEachClient(SendParcelOverlay);
  1136. }
  1137. /// <summary>
  1138. /// Join 2 land objects together
  1139. /// </summary>
  1140. /// <param name="start_x">start x of selection area</param>
  1141. /// <param name="start_y">start y of selection area</param>
  1142. /// <param name="end_x">end x of selection area</param>
  1143. /// <param name="end_y">end y of selection area</param>
  1144. /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param>
  1145. /// <returns>Returns true if successful</returns>
  1146. public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
  1147. {
  1148. int index = 0;
  1149. int maxindex = -1;
  1150. int maxArea = 0;
  1151. List<ILandObject> selectedLandObjects = new List<ILandObject>();
  1152. for (int x = start_x; x < end_x; x += 4)
  1153. {
  1154. for (int y = start_y; y < end_y; y += 4)
  1155. {
  1156. ILandObject p = GetLandObject(x, y);
  1157. if (p != null)
  1158. {
  1159. if (!selectedLandObjects.Contains(p))
  1160. {
  1161. selectedLandObjects.Add(p);
  1162. if(p.LandData.Area > maxArea)
  1163. {
  1164. maxArea = p.LandData.Area;
  1165. maxindex = index;
  1166. }
  1167. index++;
  1168. }
  1169. }
  1170. }
  1171. }
  1172. if(maxindex < 0 || selectedLandObjects.Count < 2)
  1173. return;
  1174. ILandObject masterLandObject = selectedLandObjects[maxindex];
  1175. selectedLandObjects.RemoveAt(maxindex);
  1176. if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin, true))
  1177. {
  1178. return;
  1179. }
  1180. UUID masterOwner = masterLandObject.LandData.OwnerID;
  1181. foreach (ILandObject p in selectedLandObjects)
  1182. {
  1183. if (p.LandData.OwnerID != masterOwner)
  1184. return;
  1185. }
  1186. lock (m_landList)
  1187. {
  1188. foreach (ILandObject slaveLandObject in selectedLandObjects)
  1189. {
  1190. m_landList[masterLandObject.LandData.LocalID].SetLandBitmap(
  1191. slaveLandObject.MergeLandBitmaps(masterLandObject.GetLandBitmap(), slaveLandObject.GetLandBitmap()));
  1192. performFinalLandJoin(masterLandObject, slaveLandObject);
  1193. }
  1194. }
  1195. m_scene.EventManager.TriggerParcelPrimCountTainted();
  1196. masterLandObject.SendLandUpdateToAvatarsOverMe();
  1197. m_scene.ForEachClient(SendParcelOverlay);
  1198. }
  1199. #endregion
  1200. #region Parcel Updating
  1201. //legacy name
  1202. public void SendParcelsOverlay(IClientAPI client)
  1203. {
  1204. SendParcelsOverlay(client);
  1205. }
  1206. /// <summary>
  1207. /// Send the parcel overlay blocks to the client.
  1208. /// </summary>
  1209. /// <param name="remote_client">The object representing the client</param>
  1210. public void SendParcelOverlay(IClientAPI remote_client)
  1211. {
  1212. if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
  1213. return;
  1214. const int LAND_BLOCKS_PER_PACKET = 1024;
  1215. int curID;
  1216. int southID;
  1217. byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  1218. int byteArrayCount = 0;
  1219. int sequenceID = 0;
  1220. int sx = m_regionSizeX / LandUnit;
  1221. byte curByte;
  1222. byte tmpByte;
  1223. // Layer data is in LandUnit (4m) chunks
  1224. for (int y = 0; y < m_regionSizeY / LandUnit; ++y)
  1225. {
  1226. for (int x = 0; x < sx;)
  1227. {
  1228. curID = GetLandObjectIDinLandUnits(x,y);
  1229. if(curID < 0)
  1230. continue;
  1231. ILandObject currentParcel = GetLandObject(curID);
  1232. if (currentParcel == null)
  1233. continue;
  1234. // types
  1235. if (currentParcel.LandData.OwnerID == remote_client.AgentId)
  1236. {
  1237. //Owner Flag
  1238. curByte = LandChannel.LAND_TYPE_OWNED_BY_REQUESTER;
  1239. }
  1240. else if (currentParcel.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcel.LandData.GroupID))
  1241. {
  1242. curByte = LandChannel.LAND_TYPE_OWNED_BY_GROUP;
  1243. }
  1244. else if (currentParcel.LandData.SalePrice > 0 &&
  1245. (currentParcel.LandData.AuthBuyerID == UUID.Zero ||
  1246. currentParcel.LandData.AuthBuyerID == remote_client.AgentId))
  1247. {
  1248. //Sale type
  1249. curByte = LandChannel.LAND_TYPE_IS_FOR_SALE;
  1250. }
  1251. else if (currentParcel.LandData.OwnerID == UUID.Zero)
  1252. {
  1253. //Public type
  1254. curByte = LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero
  1255. }
  1256. // LAND_TYPE_IS_BEING_AUCTIONED still unsuported
  1257. else
  1258. {
  1259. //Other
  1260. curByte = LandChannel.LAND_TYPE_OWNED_BY_OTHER;
  1261. }
  1262. // now flags
  1263. // local sound
  1264. if ((currentParcel.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0)
  1265. curByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND;
  1266. // hide avatars
  1267. if (!currentParcel.LandData.SeeAVs)
  1268. curByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS;
  1269. // border flags for current
  1270. if (y == 0)
  1271. {
  1272. curByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
  1273. tmpByte = curByte;
  1274. }
  1275. else
  1276. {
  1277. tmpByte = curByte;
  1278. southID = GetLandObjectIDinLandUnits(x, (y - 1));
  1279. if (southID >= 0 && southID != curID)
  1280. tmpByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
  1281. }
  1282. tmpByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
  1283. byteArray[byteArrayCount] = tmpByte;
  1284. byteArrayCount++;
  1285. if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
  1286. {
  1287. remote_client.SendLandParcelOverlay(byteArray, sequenceID);
  1288. byteArrayCount = 0;
  1289. sequenceID++;
  1290. byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  1291. }
  1292. // keep adding while on same parcel, checking south border
  1293. if (y == 0)
  1294. {
  1295. // all have south border and that is already on curByte
  1296. while (++x < sx && GetLandObjectIDinLandUnits(x, y) == curID)
  1297. {
  1298. byteArray[byteArrayCount] = curByte;
  1299. byteArrayCount++;
  1300. if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
  1301. {
  1302. remote_client.SendLandParcelOverlay(byteArray, sequenceID);
  1303. byteArrayCount = 0;
  1304. sequenceID++;
  1305. byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  1306. }
  1307. }
  1308. }
  1309. else
  1310. {
  1311. while (++x < sx && GetLandObjectIDinLandUnits(x, y) == curID)
  1312. {
  1313. // need to check south one by one
  1314. southID = GetLandObjectIDinLandUnits(x, (y - 1));
  1315. if (southID >= 0 && southID != curID)
  1316. {
  1317. tmpByte = curByte;
  1318. tmpByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
  1319. byteArray[byteArrayCount] = tmpByte;
  1320. }
  1321. else
  1322. byteArray[byteArrayCount] = curByte;
  1323. byteArrayCount++;
  1324. if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
  1325. {
  1326. remote_client.SendLandParcelOverlay(byteArray, sequenceID);
  1327. byteArrayCount = 0;
  1328. sequenceID++;
  1329. byteArray = new byte[LAND_BLOCKS_PER_PACKET];
  1330. }
  1331. }
  1332. }
  1333. }
  1334. }
  1335. if (byteArrayCount > 0)
  1336. {
  1337. remote_client.SendLandParcelOverlay(byteArray, sequenceID);
  1338. }
  1339. }
  1340. public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
  1341. bool snap_selection, IClientAPI remote_client)
  1342. {
  1343. if (m_landList.Count == 0 || m_landIDList == null)
  1344. return;
  1345. if (start_x < 0 || start_y < 0 || end_x < 0 || end_y < 0)
  1346. return;
  1347. if (start_x >= m_regionSizeX || start_y >= m_regionSizeX || end_x >= m_regionSizeY || end_y >= m_regionSizeY)
  1348. return;
  1349. if (end_x - start_x <= LandUnit &&
  1350. end_y - start_y <= LandUnit)
  1351. {
  1352. ILandObject parcel = GetLandObject(start_x, start_y);
  1353. if(parcel != null)
  1354. parcel.SendLandProperties(sequence_id, snap_selection, LandChannel.LAND_RESULT_SINGLE, remote_client);
  1355. return;
  1356. }
  1357. start_x /= LandUnit;
  1358. start_y /= LandUnit;
  1359. end_x /= LandUnit;
  1360. end_y /= LandUnit;
  1361. //Get the land objects within the bounds
  1362. Dictionary<int, ILandObject> temp = new Dictionary<int, ILandObject>();
  1363. for (int x = start_x; x < end_x; ++x)
  1364. {
  1365. for (int y = start_y; y < end_y; ++y)
  1366. {
  1367. ILandObject currentParcel = GetLandObjectinLandUnits(x, y);
  1368. if (currentParcel != null)
  1369. {
  1370. if (!temp.ContainsKey(currentParcel.LandData.LocalID))
  1371. {
  1372. if (!currentParcel.IsBannedFromLand(remote_client.AgentId))
  1373. {
  1374. temp[currentParcel.LandData.LocalID] = currentParcel;
  1375. }
  1376. }
  1377. }
  1378. }
  1379. }
  1380. int requestResult = (temp.Count > 1) ? LandChannel.LAND_RESULT_MULTIPLE : LandChannel.LAND_RESULT_SINGLE;
  1381. foreach(ILandObject lo in temp.Values)
  1382. {
  1383. lo.SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
  1384. }
  1385. // SendParcelOverlay(remote_client);
  1386. }
  1387. public void UpdateLandProperties(ILandObject land, LandUpdateArgs args, IClientAPI remote_client)
  1388. {
  1389. bool snap_selection = false;
  1390. bool needOverlay = false;
  1391. if (land.UpdateLandProperties(args, remote_client, out snap_selection, out needOverlay))
  1392. {
  1393. UUID parcelID = land.LandData.GlobalID;
  1394. m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
  1395. {
  1396. if (avatar.IsDeleted || avatar.IsNPC)
  1397. return;
  1398. IClientAPI client = avatar.ControllingClient;
  1399. if (needOverlay)
  1400. SendParcelOverlay(client);
  1401. if (avatar.IsChildAgent)
  1402. {
  1403. land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client);
  1404. return;
  1405. }
  1406. ILandObject aland = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
  1407. if (aland != null)
  1408. {
  1409. if(land != aland)
  1410. land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client);
  1411. else if (land == aland)
  1412. aland.SendLandProperties(0, true, LandChannel.LAND_RESULT_SINGLE, client);
  1413. }
  1414. if (avatar.currentParcelUUID == parcelID)
  1415. avatar.currentParcelUUID = parcelID; // force parcel flags review
  1416. });
  1417. }
  1418. }
  1419. public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
  1420. {
  1421. ILandObject land;
  1422. lock (m_landList)
  1423. {
  1424. m_landList.TryGetValue(localID, out land);
  1425. }
  1426. if (land != null)
  1427. {
  1428. UpdateLandProperties(land, args, remote_client);
  1429. m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client);
  1430. }
  1431. }
  1432. public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
  1433. {
  1434. Subdivide(west, south, east, north, remote_client.AgentId);
  1435. }
  1436. public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
  1437. {
  1438. Join(west, south, east, north, remote_client.AgentId);
  1439. }
  1440. public void ClientOnParcelSelectObjects(int local_id, int request_type,
  1441. List<UUID> returnIDs, IClientAPI remote_client)
  1442. {
  1443. m_landList[local_id].SendForceObjectSelect(local_id, request_type, returnIDs, remote_client);
  1444. }
  1445. public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client)
  1446. {
  1447. ILandObject land = null;
  1448. lock (m_landList)
  1449. {
  1450. m_landList.TryGetValue(local_id, out land);
  1451. }
  1452. if (land != null)
  1453. {
  1454. m_scene.EventManager.TriggerParcelPrimCountUpdate();
  1455. land.SendLandObjectOwners(remote_client);
  1456. }
  1457. else
  1458. {
  1459. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid land object {0} passed for parcel object owner request", local_id);
  1460. }
  1461. }
  1462. public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client)
  1463. {
  1464. ILandObject land = null;
  1465. lock (m_landList)
  1466. {
  1467. m_landList.TryGetValue(local_id, out land);
  1468. }
  1469. if (land != null)
  1470. {
  1471. if (m_scene.Permissions.IsGod(remote_client.AgentId))
  1472. {
  1473. land.LandData.OwnerID = ownerID;
  1474. land.LandData.GroupID = UUID.Zero;
  1475. land.LandData.IsGroupOwned = false;
  1476. land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  1477. UpdateLandObject(land.LandData.LocalID, land.LandData);
  1478. m_scene.ForEachClient(SendParcelOverlay);
  1479. land.SendLandUpdateToClient(true, remote_client);
  1480. }
  1481. }
  1482. }
  1483. public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client)
  1484. {
  1485. ILandObject land = null;
  1486. lock (m_landList)
  1487. {
  1488. m_landList.TryGetValue(local_id, out land);
  1489. }
  1490. if (land != null)
  1491. {
  1492. if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land))
  1493. {
  1494. land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  1495. land.LandData.GroupID = UUID.Zero;
  1496. land.LandData.IsGroupOwned = false;
  1497. land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  1498. UpdateLandObject(land.LandData.LocalID, land.LandData);
  1499. m_scene.ForEachClient(SendParcelOverlay);
  1500. land.SendLandUpdateToAvatars();
  1501. }
  1502. }
  1503. }
  1504. public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client)
  1505. {
  1506. ILandObject land = null;
  1507. lock (m_landList)
  1508. {
  1509. m_landList.TryGetValue(local_id, out land);
  1510. }
  1511. if (land != null)
  1512. {
  1513. if (m_scene.Permissions.CanReclaimParcel(remote_client.AgentId, land))
  1514. {
  1515. land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  1516. land.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
  1517. land.LandData.GroupID = UUID.Zero;
  1518. land.LandData.IsGroupOwned = false;
  1519. land.LandData.SalePrice = 0;
  1520. land.LandData.AuthBuyerID = UUID.Zero;
  1521. land.LandData.SeeAVs = true;
  1522. land.LandData.AnyAVSounds = true;
  1523. land.LandData.GroupAVSounds = true;
  1524. land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
  1525. UpdateLandObject(land.LandData.LocalID, land.LandData);
  1526. m_scene.ForEachClient(SendParcelOverlay);
  1527. land.SendLandUpdateToAvatars();
  1528. }
  1529. }
  1530. }
  1531. #endregion
  1532. // If the economy has been validated by the economy module,
  1533. // and land has been validated as well, this method transfers
  1534. // the land ownership
  1535. public void EventManagerOnLandBuy(Object o, EventManager.LandBuyArgs e)
  1536. {
  1537. if (e.economyValidated && e.landValidated)
  1538. {
  1539. ILandObject land;
  1540. lock (m_landList)
  1541. {
  1542. m_landList.TryGetValue(e.parcelLocalID, out land);
  1543. }
  1544. if (land != null)
  1545. {
  1546. land.UpdateLandSold(e.agentId, e.groupId, e.groupOwned, (uint)e.transactionID, e.parcelPrice, e.parcelArea);
  1547. m_scene.ForEachClient(SendParcelOverlay);
  1548. land.SendLandUpdateToAvatars();
  1549. }
  1550. }
  1551. }
  1552. // After receiving a land buy packet, first the data needs to
  1553. // be validated. This method validates the right to buy the
  1554. // parcel
  1555. public void EventManagerOnValidateLandBuy(Object o, EventManager.LandBuyArgs e)
  1556. {
  1557. if (e.landValidated == false)
  1558. {
  1559. ILandObject lob = null;
  1560. lock (m_landList)
  1561. {
  1562. m_landList.TryGetValue(e.parcelLocalID, out lob);
  1563. }
  1564. if (lob != null)
  1565. {
  1566. UUID AuthorizedID = lob.LandData.AuthBuyerID;
  1567. int saleprice = lob.LandData.SalePrice;
  1568. UUID pOwnerID = lob.LandData.OwnerID;
  1569. bool landforsale = ((lob.LandData.Flags &
  1570. (uint)(ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects)) != 0);
  1571. if ((AuthorizedID == UUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale)
  1572. {
  1573. // TODO I don't think we have to lock it here, no?
  1574. //lock (e)
  1575. //{
  1576. e.parcelOwnerID = pOwnerID;
  1577. e.landValidated = true;
  1578. //}
  1579. }
  1580. }
  1581. }
  1582. }
  1583. void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client)
  1584. {
  1585. ILandObject land = null;
  1586. lock (m_landList)
  1587. {
  1588. m_landList.TryGetValue(parcelLocalID, out land);
  1589. }
  1590. if (land != null)
  1591. {
  1592. if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land))
  1593. return;
  1594. land.DeedToGroup(groupID);
  1595. m_scene.ForEachClient(SendParcelOverlay);
  1596. land.SendLandUpdateToAvatars();
  1597. }
  1598. }
  1599. #region Land Object From Storage Functions
  1600. private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
  1601. {
  1602. lock (m_landList)
  1603. {
  1604. for (int i = 0; i < data.Count; i++)
  1605. IncomingLandObjectFromStorage(data[i]);
  1606. // Layer data is in LandUnit (4m) chunks
  1607. for (int y = 0; y < m_regionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
  1608. {
  1609. for (int x = 0; x < m_regionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
  1610. {
  1611. if (m_landIDList[x, y] == 0)
  1612. {
  1613. if (m_landList.Count == 1)
  1614. {
  1615. m_log.DebugFormat(
  1616. "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}",
  1617. LogHeader, x, y, m_scene.Name);
  1618. int onlyParcelID = 0;
  1619. ILandObject onlyLandObject = null;
  1620. foreach (KeyValuePair<int, ILandObject> kvp in m_landList)
  1621. {
  1622. onlyParcelID = kvp.Key;
  1623. onlyLandObject = kvp.Value;
  1624. break;
  1625. }
  1626. // There is only one parcel. Grow it to fill all the unallocated spaces.
  1627. for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
  1628. for (int yy = 0; yy < m_landIDList.GetLength(1); yy++)
  1629. if (m_landIDList[xx, yy] == 0)
  1630. m_landIDList[xx, yy] = onlyParcelID;
  1631. onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID);
  1632. }
  1633. else if (m_landList.Count > 1)
  1634. {
  1635. m_log.DebugFormat(
  1636. "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}",
  1637. LogHeader, x, y, m_scene.Name);
  1638. // There are several other parcels so we must create a new one for the unassigned space
  1639. ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
  1640. // Claim all the unclaimed "0" ids
  1641. newLand.SetLandBitmap(CreateBitmapForID(0));
  1642. newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  1643. newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
  1644. newLand = AddLandObject(newLand);
  1645. }
  1646. else
  1647. {
  1648. // We should never reach this point as the separate code path when no land data exists should have fired instead.
  1649. m_log.WarnFormat(
  1650. "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present",
  1651. LogHeader, m_scene.Name);
  1652. }
  1653. }
  1654. }
  1655. }
  1656. FinalizeLandPrimCountUpdate(); // update simarea information
  1657. lock (m_landList)
  1658. {
  1659. foreach(LandObject lo in m_landList.Values)
  1660. lo.SendLandUpdateToAvatarsOverMe();
  1661. }
  1662. }
  1663. }
  1664. private void IncomingLandObjectFromStorage(LandData data)
  1665. {
  1666. ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene, data);
  1667. new_land.SetLandBitmapFromByteArray();
  1668. AddLandObject(new_land);
  1669. }
  1670. public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
  1671. {
  1672. if (localID != -1)
  1673. {
  1674. ILandObject selectedParcel = null;
  1675. lock (m_landList)
  1676. {
  1677. m_landList.TryGetValue(localID, out selectedParcel);
  1678. }
  1679. if (selectedParcel == null)
  1680. return;
  1681. selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
  1682. }
  1683. else
  1684. {
  1685. if (returnType != 1)
  1686. {
  1687. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown return type {0}", returnType);
  1688. return;
  1689. }
  1690. // We get here when the user returns objects from the list of Top Colliders or Top Scripts.
  1691. // In that case we receive specific object UUID's, but no parcel ID.
  1692. Dictionary<UUID, HashSet<SceneObjectGroup>> returns = new Dictionary<UUID, HashSet<SceneObjectGroup>>();
  1693. foreach (UUID groupID in taskIDs)
  1694. {
  1695. SceneObjectGroup obj = m_scene.GetSceneObjectGroup(groupID);
  1696. if (obj != null)
  1697. {
  1698. if (!returns.ContainsKey(obj.OwnerID))
  1699. returns[obj.OwnerID] = new HashSet<SceneObjectGroup>();
  1700. returns[obj.OwnerID].Add(obj);
  1701. }
  1702. else
  1703. {
  1704. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown object {0}", groupID);
  1705. }
  1706. }
  1707. int num = 0;
  1708. foreach (HashSet<SceneObjectGroup> objs in returns.Values)
  1709. num += objs.Count;
  1710. m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Returning {0} specific object(s)", num);
  1711. foreach (HashSet<SceneObjectGroup> objs in returns.Values)
  1712. {
  1713. List<SceneObjectGroup> objs2 = new List<SceneObjectGroup>(objs);
  1714. if (m_scene.Permissions.CanReturnObjects(null, remoteClient, objs2))
  1715. {
  1716. m_scene.returnObjects(objs2.ToArray(), remoteClient);
  1717. }
  1718. else
  1719. {
  1720. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: not permitted to return {0} object(s) belonging to user {1}",
  1721. objs2.Count, objs2[0].OwnerID);
  1722. }
  1723. }
  1724. }
  1725. }
  1726. public void EventManagerOnNoLandDataFromStorage()
  1727. {
  1728. ResetSimLandObjects();
  1729. CreateDefaultParcel();
  1730. }
  1731. #endregion
  1732. public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel)
  1733. {
  1734. lock (m_landList)
  1735. {
  1736. foreach (LandObject obj in m_landList.Values)
  1737. {
  1738. obj.SetParcelObjectMaxOverride(overrideDel);
  1739. }
  1740. }
  1741. }
  1742. public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
  1743. {
  1744. }
  1745. #region CAPS handler
  1746. private void EventManagerOnRegisterCaps(UUID agentID, Caps caps)
  1747. {
  1748. caps.RegisterSimpleHandler("RemoteParcelRequest", new SimpleOSDMapHandler("POST","/" + UUID.Random(), RemoteParcelRequest));
  1749. caps.RegisterSimpleHandler("ParcelPropertiesUpdate", new SimpleStreamHandler("/" + UUID.Random(),
  1750. delegate (IOSHttpRequest request, IOSHttpResponse response)
  1751. {
  1752. ProcessPropertiesUpdate(request, response, agentID);
  1753. }));
  1754. }
  1755. private void ProcessPropertiesUpdate(IOSHttpRequest request, IOSHttpResponse response, UUID agentID)
  1756. {
  1757. if (request.HttpMethod != "POST")
  1758. {
  1759. response.StatusCode = (int)HttpStatusCode.NotFound;
  1760. return;
  1761. }
  1762. IClientAPI client;
  1763. if (!m_scene.TryGetClient(agentID, out client))
  1764. {
  1765. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID);
  1766. response.StatusCode = (int)HttpStatusCode.Gone;
  1767. return;
  1768. }
  1769. OSDMap args;
  1770. ParcelPropertiesUpdateMessage properties;
  1771. try
  1772. {
  1773. args = (OSDMap)OSDParser.DeserializeLLSDXml(request.InputStream);
  1774. properties = new ParcelPropertiesUpdateMessage();
  1775. properties.Deserialize(args);
  1776. }
  1777. catch
  1778. {
  1779. response.StatusCode = (int)HttpStatusCode.BadRequest;
  1780. return;
  1781. }
  1782. int parcelID = properties.LocalID;
  1783. ILandObject land = null;
  1784. lock (m_landList)
  1785. {
  1786. m_landList.TryGetValue(parcelID, out land);
  1787. }
  1788. if (land == null)
  1789. {
  1790. m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID);
  1791. response.StatusCode = (int)HttpStatusCode.NotFound;
  1792. return;
  1793. }
  1794. try
  1795. {
  1796. LandUpdateArgs land_update = new LandUpdateArgs();
  1797. land_update.AuthBuyerID = properties.AuthBuyerID;
  1798. land_update.Category = properties.Category;
  1799. land_update.Desc = properties.Desc;
  1800. land_update.GroupID = properties.GroupID;
  1801. land_update.LandingType = (byte) properties.Landing;
  1802. land_update.MediaAutoScale = (byte) Convert.ToInt32(properties.MediaAutoScale);
  1803. land_update.MediaID = properties.MediaID;
  1804. land_update.MediaURL = properties.MediaURL;
  1805. land_update.MusicURL = properties.MusicURL;
  1806. land_update.Name = properties.Name;
  1807. land_update.ParcelFlags = (uint) properties.ParcelFlags;
  1808. land_update.PassHours = properties.PassHours;
  1809. land_update.PassPrice = (int) properties.PassPrice;
  1810. land_update.SalePrice = (int) properties.SalePrice;
  1811. land_update.SnapshotID = properties.SnapshotID;
  1812. land_update.UserLocation = properties.UserLocation;
  1813. land_update.UserLookAt = properties.UserLookAt;
  1814. land_update.MediaDescription = properties.MediaDesc;
  1815. land_update.MediaType = properties.MediaType;
  1816. land_update.MediaWidth = properties.MediaWidth;
  1817. land_update.MediaHeight = properties.MediaHeight;
  1818. land_update.MediaLoop = properties.MediaLoop;
  1819. land_update.ObscureMusic = properties.ObscureMusic;
  1820. land_update.ObscureMedia = properties.ObscureMedia;
  1821. if (args.ContainsKey("see_avs"))
  1822. {
  1823. land_update.SeeAVs = args["see_avs"].AsBoolean();
  1824. land_update.AnyAVSounds = args["any_av_sounds"].AsBoolean();
  1825. land_update.GroupAVSounds = args["group_av_sounds"].AsBoolean();
  1826. }
  1827. else
  1828. {
  1829. land_update.SeeAVs = true;
  1830. land_update.AnyAVSounds = true;
  1831. land_update.GroupAVSounds = true;
  1832. }
  1833. UpdateLandProperties(land,land_update, client);
  1834. m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client);
  1835. }
  1836. catch
  1837. {
  1838. response.StatusCode = (int)HttpStatusCode.InternalServerError;
  1839. return;
  1840. }
  1841. response.StatusCode = (int)HttpStatusCode.OK;
  1842. }
  1843. // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
  1844. // "real" parcelID, because we wouldn't be able to map that to the region the parcel belongs to.
  1845. // So, we create a "fake" parcelID by using the regionHandle (64 bit), and the local (integer) x
  1846. // and y coordinate (each 8 bit), encoded in a UUID (128 bit).
  1847. //
  1848. // Request format:
  1849. // <llsd>
  1850. // <map>
  1851. // <key>location</key>
  1852. // <array>
  1853. // <real>1.23</real>
  1854. // <real>45..6</real>
  1855. // <real>78.9</real>
  1856. // </array>
  1857. // <key>region_id</key>
  1858. // <uuid>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</uuid>
  1859. // </map>
  1860. // </llsd>
  1861. private void RemoteParcelRequest(IOSHttpRequest request, IOSHttpResponse response, OSDMap args)
  1862. {
  1863. UUID parcelID = UUID.Zero;
  1864. OSD tmp;
  1865. try
  1866. {
  1867. if (args.TryGetValue("location", out tmp) && tmp is OSDArray)
  1868. {
  1869. UUID scope = m_scene.RegionInfo.ScopeID;
  1870. OSDArray list = (OSDArray)tmp;
  1871. uint x = (uint)(double)list[0];
  1872. uint y = (uint)(double)list[1];
  1873. ulong myHandle = m_scene.RegionInfo.RegionHandle;
  1874. if (args.TryGetValue("region_handle", out tmp) && tmp is OSDBinary)
  1875. {
  1876. // if you do a "About Landmark" on a landmark a second time, the viewer sends the
  1877. // region_handle it got earlier via RegionHandleRequest
  1878. ulong regionHandle = Util.BytesToUInt64Big((byte[])tmp);
  1879. if(regionHandle == myHandle)
  1880. {
  1881. ILandObject l = GetLandObjectClippedXY(x, y);
  1882. if (l != null)
  1883. parcelID = l.LandData.FakeID;
  1884. else
  1885. parcelID = Util.BuildFakeParcelID(myHandle, x, y);
  1886. }
  1887. else
  1888. {
  1889. uint wx;
  1890. uint wy;
  1891. Util.RegionHandleToWorldLoc(regionHandle, out wx, out wy);
  1892. GridRegion info = m_scene.GridService.GetRegionByPosition(scope, (int)wx, (int)wy);
  1893. if (info != null)
  1894. {
  1895. wx -= (uint)info.RegionLocX;
  1896. wy -= (uint)info.RegionLocY;
  1897. wx += x;
  1898. wy += y;
  1899. if (wx >= info.RegionSizeX || wy >= info.RegionSizeY)
  1900. {
  1901. wx = x;
  1902. wy = y;
  1903. }
  1904. if (info.RegionHandle == myHandle)
  1905. {
  1906. ILandObject l = GetLandObjectClippedXY(wx, wy);
  1907. if (l != null)
  1908. parcelID = l.LandData.FakeID;
  1909. else
  1910. parcelID = Util.BuildFakeParcelID(myHandle, wx, wy);
  1911. }
  1912. else
  1913. {
  1914. parcelID = Util.BuildFakeParcelID(info.RegionHandle, wx, wy);
  1915. }
  1916. }
  1917. }
  1918. }
  1919. else if (args.TryGetValue("region_id", out tmp) && tmp is OSDUUID)
  1920. {
  1921. UUID regionID = tmp.AsUUID();
  1922. if (regionID == m_scene.RegionInfo.RegionID)
  1923. {
  1924. ILandObject l = GetLandObjectClippedXY(x, y);
  1925. if (l != null)
  1926. parcelID = l.LandData.FakeID;
  1927. else
  1928. parcelID = Util.BuildFakeParcelID(myHandle, x, y);
  1929. }
  1930. else
  1931. {
  1932. // a parcel request for a parcel in another region. Ask the grid about the region
  1933. GridRegion info = m_scene.GridService.GetRegionByUUID(scope, regionID);
  1934. if (info != null)
  1935. parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
  1936. }
  1937. }
  1938. }
  1939. }
  1940. catch
  1941. {
  1942. m_log.Error("[LAND MANAGEMENT MODULE]: RemoteParcelRequest failed");
  1943. response.StatusCode = (int)HttpStatusCode.BadRequest;
  1944. return;
  1945. }
  1946. //m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0} {1}", parcelID, parcelID == UUID.Zero ? args.ToString() :"");
  1947. osUTF8 sb = LLSDxmlEncode2.Start();
  1948. LLSDxmlEncode2.AddMap(sb);
  1949. LLSDxmlEncode2.AddElem("parcel_id", parcelID,sb);
  1950. LLSDxmlEncode2.AddEndMap(sb);
  1951. response.RawBuffer = LLSDxmlEncode2.EndToBytes(sb);
  1952. response.StatusCode = (int)HttpStatusCode.OK;
  1953. }
  1954. #endregion
  1955. private void ClientOnParcelInfoRequest(IClientAPI remoteClient, UUID parcelID)
  1956. {
  1957. if (parcelID == UUID.Zero)
  1958. return;
  1959. if(!m_parcelInfoCache.TryGetValue(parcelID, 30000, out ExtendedLandData data))
  1960. {
  1961. data = null;
  1962. ExtendedLandData extLandData = new ExtendedLandData();
  1963. while(true)
  1964. {
  1965. if(!Util.ParseFakeParcelID(parcelID, out extLandData.RegionHandle,
  1966. out extLandData.X, out extLandData.Y))
  1967. break;
  1968. //m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
  1969. // extLandData.RegionHandle, extLandData.X, extLandData.Y);
  1970. // for this region or for somewhere else?
  1971. if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle)
  1972. {
  1973. ILandObject extLandObject = GetLandObjectByfakeID(parcelID);
  1974. if (extLandObject == null)
  1975. break;
  1976. extLandData.LandData = extLandObject.LandData;
  1977. extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel;
  1978. if (extLandData.LandData != null)
  1979. data = extLandData;
  1980. break;
  1981. }
  1982. else
  1983. {
  1984. ILandService landService = m_scene.RequestModuleInterface<ILandService>();
  1985. extLandData.LandData = landService.GetLandData(m_scene.RegionInfo.ScopeID,
  1986. extLandData.RegionHandle, extLandData.X, extLandData.Y,
  1987. out extLandData.RegionAccess);
  1988. if (extLandData.LandData != null)
  1989. data = extLandData;
  1990. break;
  1991. }
  1992. }
  1993. m_parcelInfoCache.Add(parcelID, data, 30000);
  1994. }
  1995. if (data != null) // if we found some data, send it
  1996. {
  1997. GridRegion info;
  1998. if (data.RegionHandle == m_scene.RegionInfo.RegionHandle)
  1999. {
  2000. info = new GridRegion(m_scene.RegionInfo);
  2001. IDwellModule dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
  2002. if (dwellModule != null)
  2003. data.LandData.Dwell = dwellModule.GetDwell(data.LandData);
  2004. }
  2005. else
  2006. {
  2007. // most likely still cached from building the extLandData entry
  2008. info = m_scene.GridService.GetRegionByHandle(m_scene.RegionInfo.ScopeID, data.RegionHandle);
  2009. }
  2010. // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
  2011. //m_log.DebugFormat("[LAND MANAGEMENT MODULE]: got parcelinfo for parcel {0} in region {1}; sending...",
  2012. // data.LandData.Name, data.RegionHandle);
  2013. // HACK for now
  2014. RegionInfo r = new RegionInfo();
  2015. r.RegionName = info.RegionName;
  2016. r.RegionLocX = (uint)info.RegionLocX;
  2017. r.RegionLocY = (uint)info.RegionLocY;
  2018. r.RegionSettings.Maturity = (int)Util.ConvertAccessLevelToMaturity(data.RegionAccess);
  2019. remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y);
  2020. }
  2021. else
  2022. m_log.Debug("[LAND MANAGEMENT MODULE]: got no parcelinfo; not sending");
  2023. }
  2024. public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
  2025. {
  2026. ILandObject land = null;
  2027. lock (m_landList)
  2028. {
  2029. m_landList.TryGetValue(localID, out land);
  2030. }
  2031. if (land == null) return;
  2032. if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions, false))
  2033. return;
  2034. land.LandData.OtherCleanTime = otherCleanTime;
  2035. UpdateLandObject(localID, land.LandData);
  2036. }
  2037. public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
  2038. {
  2039. ScenePresence sp = null;
  2040. ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out sp);
  2041. if (sp == null)
  2042. return;
  2043. if (sp.IsChildAgent || sp.IsDeleted || sp.IsInTransit || sp.IsNPC)
  2044. return;
  2045. if (!sp.IsGod)
  2046. {
  2047. client.SendAlertMessage("Request denied. You're not priviliged.");
  2048. return;
  2049. }
  2050. ILandObject land = null;
  2051. List<ILandObject> Lands = ((Scene)client.Scene).LandChannel.AllParcels();
  2052. foreach (ILandObject landObject in Lands)
  2053. {
  2054. if (landObject.LandData.LocalID == landID)
  2055. {
  2056. land = landObject;
  2057. break;
  2058. }
  2059. }
  2060. if (land == null)
  2061. return;
  2062. bool validParcelOwner = false;
  2063. if (DefaultGodParcelOwner != UUID.Zero && m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, DefaultGodParcelOwner) != null)
  2064. validParcelOwner = true;
  2065. bool validParcelGroup = false;
  2066. if (m_groupManager != null)
  2067. {
  2068. if (DefaultGodParcelGroup != UUID.Zero && m_groupManager.GetGroupRecord(DefaultGodParcelGroup) != null)
  2069. validParcelGroup = true;
  2070. }
  2071. if (!validParcelOwner && !validParcelGroup)
  2072. {
  2073. client.SendAlertMessage("Please check ini files.\n[LandManagement] config section.");
  2074. return;
  2075. }
  2076. land.LandData.AnyAVSounds = true;
  2077. land.LandData.SeeAVs = true;
  2078. land.LandData.GroupAVSounds = true;
  2079. land.LandData.AuthBuyerID = UUID.Zero;
  2080. land.LandData.Category = ParcelCategory.None;
  2081. land.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
  2082. land.LandData.Description = String.Empty;
  2083. land.LandData.Dwell = 0;
  2084. land.LandData.Flags = (uint)ParcelFlags.AllowFly | (uint)ParcelFlags.AllowLandmark |
  2085. (uint)ParcelFlags.AllowAPrimitiveEntry |
  2086. (uint)ParcelFlags.AllowDeedToGroup |
  2087. (uint)ParcelFlags.CreateObjects | (uint)ParcelFlags.AllowOtherScripts |
  2088. (uint)ParcelFlags.AllowVoiceChat;
  2089. land.LandData.LandingType = (byte)LandingType.Direct;
  2090. land.LandData.LastDwellTimeMS = Util.GetTimeStampMS();
  2091. land.LandData.MediaAutoScale = 0;
  2092. land.LandData.MediaDescription = "";
  2093. land.LandData.MediaHeight = 0;
  2094. land.LandData.MediaID = UUID.Zero;
  2095. land.LandData.MediaLoop = false;
  2096. land.LandData.MediaType = "none/none";
  2097. land.LandData.MediaURL = String.Empty;
  2098. land.LandData.MediaWidth = 0;
  2099. land.LandData.MusicURL = String.Empty;
  2100. land.LandData.ObscureMedia = false;
  2101. land.LandData.ObscureMusic = false;
  2102. land.LandData.OtherCleanTime = 0;
  2103. land.LandData.ParcelAccessList = new List<LandAccessEntry>();
  2104. land.LandData.PassHours = 0;
  2105. land.LandData.PassPrice = 0;
  2106. land.LandData.SalePrice = 0;
  2107. land.LandData.SnapshotID = UUID.Zero;
  2108. land.LandData.Status = ParcelStatus.Leased;
  2109. if (validParcelOwner)
  2110. {
  2111. land.LandData.OwnerID = DefaultGodParcelOwner;
  2112. land.LandData.IsGroupOwned = false;
  2113. }
  2114. else
  2115. {
  2116. land.LandData.OwnerID = DefaultGodParcelGroup;
  2117. land.LandData.IsGroupOwned = true;
  2118. }
  2119. if (validParcelGroup)
  2120. land.LandData.GroupID = DefaultGodParcelGroup;
  2121. else
  2122. land.LandData.GroupID = UUID.Zero;
  2123. land.LandData.Name = DefaultGodParcelName;
  2124. UpdateLandObject(land.LandData.LocalID, land.LandData);
  2125. //m_scene.EventManager.TriggerParcelPrimCountUpdate();
  2126. m_scene.ForEachClient(SendParcelOverlay);
  2127. land.SendLandUpdateToClient(true, client);
  2128. }
  2129. private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
  2130. {
  2131. ScenePresence SP;
  2132. ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
  2133. List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
  2134. if (SP.GodController.UserLevel != 0)
  2135. {
  2136. if (flags == 0) //All parcels, scripted or not
  2137. {
  2138. ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
  2139. {
  2140. if (e.OwnerID == targetID)
  2141. {
  2142. returns.Add(e);
  2143. }
  2144. }
  2145. );
  2146. }
  2147. if (flags == 4) //All parcels, scripted object
  2148. {
  2149. ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
  2150. {
  2151. if (e.OwnerID == targetID)
  2152. {
  2153. if (e.ContainsScripts())
  2154. {
  2155. returns.Add(e);
  2156. }
  2157. }
  2158. });
  2159. }
  2160. if (flags == 4) //not target parcel, scripted object
  2161. {
  2162. ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
  2163. {
  2164. if (e.OwnerID == targetID)
  2165. {
  2166. ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
  2167. if (landobject.LandData.OwnerID != e.OwnerID)
  2168. {
  2169. if (e.ContainsScripts())
  2170. {
  2171. returns.Add(e);
  2172. }
  2173. }
  2174. }
  2175. });
  2176. }
  2177. foreach (SceneObjectGroup ol in returns)
  2178. {
  2179. ReturnObject(ol, client);
  2180. }
  2181. }
  2182. }
  2183. public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
  2184. {
  2185. SceneObjectGroup[] objs = new SceneObjectGroup[1];
  2186. objs[0] = obj;
  2187. ((Scene)client.Scene).returnObjects(objs, client);
  2188. }
  2189. Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
  2190. public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
  2191. {
  2192. ScenePresence targetAvatar = null;
  2193. ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar);
  2194. ScenePresence parcelManager = null;
  2195. ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
  2196. System.Threading.Timer Timer;
  2197. if (targetAvatar.GodController.UserLevel < 200)
  2198. {
  2199. ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
  2200. if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true))
  2201. return;
  2202. if ((flags & 1) == 0) // only lowest bit has meaning for now
  2203. {
  2204. targetAvatar.AllowMovement = false;
  2205. targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world.");
  2206. parcelManager.ControllingClient.SendAlertMessage("Avatar Frozen.");
  2207. System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
  2208. Timer = new System.Threading.Timer(timeCB, targetAvatar, 30000, 0);
  2209. Timers.Add(targetAvatar.UUID, Timer);
  2210. }
  2211. else
  2212. {
  2213. targetAvatar.AllowMovement = true;
  2214. targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has unfrozen you.");
  2215. parcelManager.ControllingClient.SendAlertMessage("Avatar Unfrozen.");
  2216. Timers.TryGetValue(targetAvatar.UUID, out Timer);
  2217. Timers.Remove(targetAvatar.UUID);
  2218. Timer.Dispose();
  2219. }
  2220. }
  2221. }
  2222. private void OnEndParcelFrozen(object avatar)
  2223. {
  2224. ScenePresence targetAvatar = (ScenePresence)avatar;
  2225. targetAvatar.AllowMovement = true;
  2226. System.Threading.Timer Timer;
  2227. Timers.TryGetValue(targetAvatar.UUID, out Timer);
  2228. Timers.Remove(targetAvatar.UUID);
  2229. targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
  2230. }
  2231. public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
  2232. {
  2233. ScenePresence targetAvatar = null;
  2234. ScenePresence parcelManager = null;
  2235. // Must have presences
  2236. if (!m_scene.TryGetScenePresence(target, out targetAvatar) ||
  2237. !m_scene.TryGetScenePresence(client.AgentId, out parcelManager))
  2238. return;
  2239. // Cannot eject estate managers or gods
  2240. if (m_scene.Permissions.IsAdministrator(target))
  2241. return;
  2242. // Check if you even have permission to do this
  2243. ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
  2244. if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true) &&
  2245. !m_scene.Permissions.IsAdministrator(client.AgentId))
  2246. return;
  2247. Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
  2248. targetAvatar.TeleportOnEject(pos);
  2249. targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
  2250. parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
  2251. if ((flags & 1) != 0) // Ban TODO: Remove magic number
  2252. {
  2253. LandAccessEntry entry = new LandAccessEntry();
  2254. entry.AgentID = targetAvatar.UUID;
  2255. entry.Flags = AccessList.Ban;
  2256. entry.Expires = 0; // Perm
  2257. land.LandData.ParcelAccessList.Add(entry);
  2258. }
  2259. }
  2260. public void ClearAllEnvironments()
  2261. {
  2262. List<ILandObject> parcels = AllParcels();
  2263. for (int i = 0; i < parcels.Count; ++i)
  2264. parcels[i].StoreEnvironment(null);
  2265. }
  2266. /// <summary>
  2267. /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
  2268. /// </summary>
  2269. /// <param name="remoteClient"></param>
  2270. /// <param name="regionHandle"></param>
  2271. /// <param name="position"></param>
  2272. /// <param name="lookAt"></param>
  2273. /// <param name="flags"></param>
  2274. public virtual void ClientOnSetHome(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
  2275. {
  2276. // Let's find the parcel in question
  2277. ILandObject land = GetLandObject(position);
  2278. if (land == null || m_scene.GridUserService == null)
  2279. {
  2280. m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
  2281. return;
  2282. }
  2283. // Gather some data
  2284. ulong gpowers = remoteClient.GetGroupPowers(land.LandData.GroupID);
  2285. SceneObjectGroup telehub = null;
  2286. if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
  2287. // Does the telehub exist in the scene?
  2288. telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
  2289. // Can the user set home here?
  2290. if (// Required: local user; foreign users cannot set home
  2291. m_scene.UserManagementModule.IsLocalGridUser(remoteClient.AgentId) &&
  2292. (// (a) gods and land managers can set home
  2293. m_scene.Permissions.IsAdministrator(remoteClient.AgentId) ||
  2294. m_scene.Permissions.IsGod(remoteClient.AgentId) ||
  2295. // (b) land owners can set home
  2296. remoteClient.AgentId == land.LandData.OwnerID ||
  2297. // (c) members of the land-associated group in roles that can set home
  2298. ((gpowers & (ulong)GroupPowers.AllowSetHome) == (ulong)GroupPowers.AllowSetHome) ||
  2299. // (d) parcels with telehubs can be the home of anyone
  2300. (telehub != null && land.ContainsPoint((int)telehub.AbsolutePosition.X, (int)telehub.AbsolutePosition.Y))))
  2301. {
  2302. string userId;
  2303. UUID test;
  2304. if (!m_scene.UserManagementModule.GetUserUUI(remoteClient.AgentId, out userId))
  2305. {
  2306. /* Do not set a home position in this grid for a HG visitor */
  2307. m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed. (User Lookup)");
  2308. }
  2309. else if (!UUID.TryParse(userId, out test))
  2310. {
  2311. m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed. (HG visitor)");
  2312. }
  2313. else if (m_scene.GridUserService.SetHome(userId, land.RegionUUID, position, lookAt))
  2314. {
  2315. // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
  2316. m_Dialog.SendAlertToUser(remoteClient, "Home position set.");
  2317. }
  2318. else
  2319. {
  2320. m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
  2321. }
  2322. }
  2323. else
  2324. m_Dialog.SendAlertToUser(remoteClient, "You are not allowed to set your home location in this parcel.");
  2325. }
  2326. protected void RegisterCommands()
  2327. {
  2328. ICommands commands = MainConsole.Instance.Commands;
  2329. commands.AddCommand(
  2330. "Land", false, "land clear",
  2331. "land clear",
  2332. "Clear all the parcels from the region.",
  2333. "Command will ask for confirmation before proceeding.",
  2334. HandleClearCommand);
  2335. commands.AddCommand(
  2336. "Land", false, "land show",
  2337. "land show [<local-land-id>]",
  2338. "Show information about the parcels on the region.",
  2339. "If no local land ID is given, then summary information about all the parcels is shown.\n"
  2340. + "If a local land ID is given then full information about that parcel is shown.",
  2341. HandleShowCommand);
  2342. }
  2343. protected void HandleClearCommand(string module, string[] args)
  2344. {
  2345. if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
  2346. return;
  2347. string response = MainConsole.Instance.Prompt(
  2348. string.Format(
  2349. "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name),
  2350. "n");
  2351. if (response.ToLower() == "y")
  2352. {
  2353. Clear(true);
  2354. MainConsole.Instance.Output("Cleared all parcels from {0}", m_scene.Name);
  2355. }
  2356. else
  2357. {
  2358. MainConsole.Instance.Output("Aborting clear of all parcels from {0}", m_scene.Name);
  2359. }
  2360. }
  2361. protected void HandleShowCommand(string module, string[] args)
  2362. {
  2363. if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
  2364. return;
  2365. StringBuilder report = new StringBuilder();
  2366. if (args.Length <= 2)
  2367. {
  2368. AppendParcelsSummaryReport(report);
  2369. }
  2370. else
  2371. {
  2372. int landLocalId;
  2373. if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId))
  2374. return;
  2375. ILandObject lo = null;
  2376. lock (m_landList)
  2377. {
  2378. if (!m_landList.TryGetValue(landLocalId, out lo))
  2379. {
  2380. MainConsole.Instance.Output("No parcel found with local ID {0}", landLocalId);
  2381. return;
  2382. }
  2383. }
  2384. AppendParcelReport(report, lo);
  2385. }
  2386. MainConsole.Instance.Output(report.ToString());
  2387. }
  2388. private void AppendParcelsSummaryReport(StringBuilder report)
  2389. {
  2390. report.AppendFormat("Land information for {0}\n", m_scene.Name);
  2391. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  2392. cdt.AddColumn("Parcel Name", ConsoleDisplayUtil.ParcelNameSize);
  2393. cdt.AddColumn("ID", 3);
  2394. cdt.AddColumn("Area", 6);
  2395. cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize);
  2396. cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize);
  2397. cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize);
  2398. cdt.AddColumn("fakeID", 38);
  2399. lock (m_landList)
  2400. {
  2401. foreach (ILandObject lo in m_landList.Values)
  2402. {
  2403. LandData ld = lo.LandData;
  2404. string ownerName;
  2405. if (ld.IsGroupOwned)
  2406. {
  2407. GroupRecord rec = m_groupManager.GetGroupRecord(ld.GroupID);
  2408. ownerName = (rec != null) ? rec.GroupName : "Unknown Group";
  2409. }
  2410. else
  2411. {
  2412. ownerName = m_userManager.GetUserName(ld.OwnerID);
  2413. }
  2414. cdt.AddRow(
  2415. ld.Name, ld.LocalID, ld.Area, lo.StartPoint, lo.EndPoint, ownerName, lo.FakeID);
  2416. }
  2417. }
  2418. report.Append(cdt.ToString());
  2419. }
  2420. private void AppendParcelReport(StringBuilder report, ILandObject lo)
  2421. {
  2422. LandData ld = lo.LandData;
  2423. ConsoleDisplayList cdl = new ConsoleDisplayList();
  2424. cdl.AddRow("Parcel name", ld.Name);
  2425. cdl.AddRow("Local ID", ld.LocalID);
  2426. cdl.AddRow("Fake ID", ld.FakeID);
  2427. cdl.AddRow("Description", ld.Description);
  2428. cdl.AddRow("Snapshot ID", ld.SnapshotID);
  2429. cdl.AddRow("Area", ld.Area);
  2430. cdl.AddRow("AABB Min", ld.AABBMin);
  2431. cdl.AddRow("AABB Max", ld.AABBMax);
  2432. string ownerName;
  2433. if (ld.IsGroupOwned)
  2434. {
  2435. GroupRecord rec = m_groupManager.GetGroupRecord(ld.GroupID);
  2436. ownerName = (rec != null) ? rec.GroupName : "Unknown Group";
  2437. }
  2438. else
  2439. {
  2440. ownerName = m_userManager.GetUserName(ld.OwnerID);
  2441. }
  2442. cdl.AddRow("Owner", ownerName);
  2443. cdl.AddRow("Is group owned?", ld.IsGroupOwned);
  2444. cdl.AddRow("GroupID", ld.GroupID);
  2445. cdl.AddRow("Status", ld.Status);
  2446. cdl.AddRow("Flags", (ParcelFlags)ld.Flags);
  2447. cdl.AddRow("Landing Type", (LandingType)ld.LandingType);
  2448. cdl.AddRow("User Location", ld.UserLocation);
  2449. cdl.AddRow("User look at", ld.UserLookAt);
  2450. cdl.AddRow("Other clean time", ld.OtherCleanTime);
  2451. cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount());
  2452. cdl.AddRow("Simwide Max Prims (owner)", lo.GetSimulatorMaxPrimCount());
  2453. IPrimCounts pc = lo.PrimCounts;
  2454. cdl.AddRow("Owner Prims", pc.Owner);
  2455. cdl.AddRow("Group Prims", pc.Group);
  2456. cdl.AddRow("Other Prims", pc.Others);
  2457. cdl.AddRow("Selected Prims", pc.Selected);
  2458. cdl.AddRow("Total Prims", pc.Total);
  2459. cdl.AddRow("SimWide Prims (owner)", pc.Simulator);
  2460. cdl.AddRow("Music URL", ld.MusicURL);
  2461. cdl.AddRow("Obscure Music", ld.ObscureMusic);
  2462. cdl.AddRow("Media ID", ld.MediaID);
  2463. cdl.AddRow("Media Autoscale", Convert.ToBoolean(ld.MediaAutoScale));
  2464. cdl.AddRow("Media URL", ld.MediaURL);
  2465. cdl.AddRow("Media Type", ld.MediaType);
  2466. cdl.AddRow("Media Description", ld.MediaDescription);
  2467. cdl.AddRow("Media Width", ld.MediaWidth);
  2468. cdl.AddRow("Media Height", ld.MediaHeight);
  2469. cdl.AddRow("Media Loop", ld.MediaLoop);
  2470. cdl.AddRow("Obscure Media", ld.ObscureMedia);
  2471. cdl.AddRow("Parcel Category", ld.Category);
  2472. cdl.AddRow("Claim Date", ld.ClaimDate);
  2473. cdl.AddRow("Claim Price", ld.ClaimPrice);
  2474. cdl.AddRow("Pass Hours", ld.PassHours);
  2475. cdl.AddRow("Pass Price", ld.PassPrice);
  2476. cdl.AddRow("Auction ID", ld.AuctionID);
  2477. cdl.AddRow("Authorized Buyer ID", ld.AuthBuyerID);
  2478. cdl.AddRow("Sale Price", ld.SalePrice);
  2479. cdl.AddToStringBuilder(report);
  2480. }
  2481. }
  2482. }