/OpenMetaverse/Modules/ParcelManager.cs
C# | 2280 lines | 1293 code | 246 blank | 741 comment | 111 complexity | ade307e822a96a4cedda2b1a4e5d7e63 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) 2007-2009, openmetaverse.org
- * All rights reserved.
- *
- * - Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * - Neither the name of the openmetaverse.org nor the names
- * of its contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Threading;
- using System.Reflection;
- using System.Collections.Generic;
- using OpenMetaverse.Http;
- using OpenMetaverse.Packets;
- using OpenMetaverse.Interfaces;
- using OpenMetaverse.StructuredData;
- using OpenMetaverse.Messages.Linden;
- namespace OpenMetaverse
- {
- #region Enums
- /// <summary>
- /// Type of return to use when returning objects from a parcel
- /// </summary>
- public enum ObjectReturnType : uint
- {
- /// <summary></summary>
- None = 0,
- /// <summary>Return objects owned by parcel owner</summary>
- Owner = 1 << 1,
- /// <summary>Return objects set to group</summary>
- Group = 1 << 2,
- /// <summary>Return objects not owned by parcel owner or set to group</summary>
- Other = 1 << 3,
- /// <summary>Return a specific list of objects on parcel</summary>
- List = 1 << 4,
- /// <summary>Return objects that are marked for-sale</summary>
- Sell = 1 << 5
- }
- /// <summary>
- /// Blacklist/Whitelist flags used in parcels Access List
- /// </summary>
- public enum ParcelAccessFlags : uint
- {
- /// <summary>Agent is denied access</summary>
- NoAccess = 0,
- /// <summary>Agent is granted access</summary>
- Access = 1
- }
- /// <summary>
- /// The result of a request for parcel properties
- /// </summary>
- public enum ParcelResult : int
- {
- /// <summary>No matches were found for the request</summary>
- NoData = -1,
- /// <summary>Request matched a single parcel</summary>
- Single = 0,
- /// <summary>Request matched multiple parcels</summary>
- Multiple = 1
- }
- /// <summary>
- /// Flags used in the ParcelAccessListRequest packet to specify whether
- /// we want the access list (whitelist), ban list (blacklist), or both
- /// </summary>
- [Flags]
- public enum AccessList : uint
- {
- /// <summary>Request the access list</summary>
- Access = 1 << 0,
- /// <summary>Request the ban list</summary>
- Ban = 1 << 1,
- /// <summary>Request both White and Black lists</summary>
- Both = Access | Ban
- }
- /// <summary>
- /// Sequence ID in ParcelPropertiesReply packets (sent when avatar
- /// tries to cross a parcel border)
- /// </summary>
- public enum ParcelPropertiesStatus : int
- {
- /// <summary>Parcel is currently selected</summary>
- ParcelSelected = -10000,
- /// <summary>Parcel restricted to a group the avatar is not a
- /// member of</summary>
- CollisionNotInGroup = -20000,
- /// <summary>Avatar is banned from the parcel</summary>
- CollisionBanned = -30000,
- /// <summary>Parcel is restricted to an access list that the
- /// avatar is not on</summary>
- CollisionNotOnAccessList = -40000,
- /// <summary>Response to hovering over a parcel</summary>
- HoveredOverParcel = -50000
- }
- /// <summary>
- /// The tool to use when modifying terrain levels
- /// </summary>
- public enum TerraformAction : byte
- {
- /// <summary>Level the terrain</summary>
- Level = 0,
- /// <summary>Raise the terrain</summary>
- Raise = 1,
- /// <summary>Lower the terrain</summary>
- Lower = 2,
- /// <summary>Smooth the terrain</summary>
- Smooth = 3,
- /// <summary>Add random noise to the terrain</summary>
- Noise = 4,
- /// <summary>Revert terrain to simulator default</summary>
- Revert = 5
- }
- /// <summary>
- /// The tool size to use when changing terrain levels
- /// </summary>
- public enum TerraformBrushSize : byte
- {
- /// <summary>Small</summary>
- Small = 1,
- /// <summary>Medium</summary>
- Medium = 2,
- /// <summary>Large</summary>
- Large = 4
- }
- /// <summary>
- /// Reasons agent is denied access to a parcel on the simulator
- /// </summary>
- public enum AccessDeniedReason : byte
- {
- /// <summary>Agent is not denied, access is granted</summary>
- NotDenied = 0,
- /// <summary>Agent is not a member of the group set for the parcel, or which owns the parcel</summary>
- NotInGroup = 1,
- /// <summary>Agent is not on the parcels specific allow list</summary>
- NotOnAllowList = 2,
- /// <summary>Agent is on the parcels ban list</summary>
- BannedFromParcel = 3,
- /// <summary>Unknown</summary>
- NoAccess = 4,
- /// <summary>Agent is not age verified and parcel settings deny access to non age verified avatars</summary>
- NotAgeVerified = 5
- }
- /// <summary>
- /// Parcel overlay type. This is used primarily for highlighting and
- /// coloring which is why it is a single integer instead of a set of
- /// flags
- /// </summary>
- /// <remarks>These values seem to be poorly thought out. The first three
- /// bits represent a single value, not flags. For example Auction (0x05) is
- /// not a combination of OwnedByOther (0x01) and ForSale(0x04). However,
- /// the BorderWest and BorderSouth values are bit flags that get attached
- /// to the value stored in the first three bits. Bits four, five, and six
- /// are unused</remarks>
- [Flags]
- public enum ParcelOverlayType : byte
- {
- /// <summary>Public land</summary>
- Public = 0,
- /// <summary>Land is owned by another avatar</summary>
- OwnedByOther = 1,
- /// <summary>Land is owned by a group</summary>
- OwnedByGroup = 2,
- /// <summary>Land is owned by the current avatar</summary>
- OwnedBySelf = 3,
- /// <summary>Land is for sale</summary>
- ForSale = 4,
- /// <summary>Land is being auctioned</summary>
- Auction = 5,
- /// <summary>Land is private</summary>
- Private = 32,
- /// <summary>To the west of this area is a parcel border</summary>
- BorderWest = 64,
- /// <summary>To the south of this area is a parcel border</summary>
- BorderSouth = 128
- }
- /// <summary>
- /// Various parcel properties
- /// </summary>
- [Flags]
- public enum ParcelFlags : uint
- {
- /// <summary>No flags set</summary>
- None = 0,
- /// <summary>Allow avatars to fly (a client-side only restriction)</summary>
- AllowFly = 1 << 0,
- /// <summary>Allow foreign scripts to run</summary>
- AllowOtherScripts = 1 << 1,
- /// <summary>This parcel is for sale</summary>
- ForSale = 1 << 2,
- /// <summary>Allow avatars to create a landmark on this parcel</summary>
- AllowLandmark = 1 << 3,
- /// <summary>Allows all avatars to edit the terrain on this parcel</summary>
- AllowTerraform = 1 << 4,
- /// <summary>Avatars have health and can take damage on this parcel.
- /// If set, avatars can be killed and sent home here</summary>
- AllowDamage = 1 << 5,
- /// <summary>Foreign avatars can create objects here</summary>
- CreateObjects = 1 << 6,
- /// <summary>All objects on this parcel can be purchased</summary>
- ForSaleObjects = 1 << 7,
- /// <summary>Access is restricted to a group</summary>
- UseAccessGroup = 1 << 8,
- /// <summary>Access is restricted to a whitelist</summary>
- UseAccessList = 1 << 9,
- /// <summary>Ban blacklist is enabled</summary>
- UseBanList = 1 << 10,
- /// <summary>Unknown</summary>
- UsePassList = 1 << 11,
- /// <summary>List this parcel in the search directory</summary>
- ShowDirectory = 1 << 12,
- /// <summary>Allow personally owned parcels to be deeded to group</summary>
- AllowDeedToGroup = 1 << 13,
- /// <summary>If Deeded, owner contributes required tier to group parcel is deeded to</summary>
- ContributeWithDeed = 1 << 14,
- /// <summary>Restrict sounds originating on this parcel to the
- /// parcel boundaries</summary>
- SoundLocal = 1 << 15,
- /// <summary>Objects on this parcel are sold when the land is
- /// purchsaed</summary>
- SellParcelObjects = 1 << 16,
- /// <summary>Allow this parcel to be published on the web</summary>
- AllowPublish = 1 << 17,
- /// <summary>The information for this parcel is mature content</summary>
- MaturePublish = 1 << 18,
- /// <summary>The media URL is an HTML page</summary>
- UrlWebPage = 1 << 19,
- /// <summary>The media URL is a raw HTML string</summary>
- UrlRawHtml = 1 << 20,
- /// <summary>Restrict foreign object pushes</summary>
- RestrictPushObject = 1 << 21,
- /// <summary>Ban all non identified/transacted avatars</summary>
- DenyAnonymous = 1 << 22,
- // <summary>Ban all identified avatars [OBSOLETE]</summary>
- //[Obsolete]
- // This was obsoleted in 1.19.0 but appears to be recycled and is used on linden homes parcels
- LindenHome = 1 << 23,
- // <summary>Ban all transacted avatars [OBSOLETE]</summary>
- //[Obsolete]
- //DenyTransacted = 1 << 24,
- /// <summary>Allow group-owned scripts to run</summary>
- AllowGroupScripts = 1 << 25,
- /// <summary>Allow object creation by group members or group
- /// objects</summary>
- CreateGroupObjects = 1 << 26,
- /// <summary>Allow all objects to enter this parcel</summary>
- AllowAPrimitiveEntry = 1 << 27,
- /// <summary>Only allow group and owner objects to enter this parcel</summary>
- AllowGroupObjectEntry = 1 << 28,
- /// <summary>Voice Enabled on this parcel</summary>
- AllowVoiceChat = 1 << 29,
- /// <summary>Use Estate Voice channel for Voice on this parcel</summary>
- UseEstateVoiceChan = 1 << 30,
- /// <summary>Deny Age Unverified Users</summary>
- DenyAgeUnverified = 1U << 31
- }
- /// <summary>
- /// Parcel ownership status
- /// </summary>
- public enum ParcelStatus : sbyte
- {
- /// <summary>Placeholder</summary>
- None = -1,
- /// <summary>Parcel is leased (owned) by an avatar or group</summary>
- Leased = 0,
- /// <summary>Parcel is in process of being leased (purchased) by an avatar or group</summary>
- LeasePending = 1,
- /// <summary>Parcel has been abandoned back to Governor Linden</summary>
- Abandoned = 2
- }
- /// <summary>
- /// Category parcel is listed in under search
- /// </summary>
- public enum ParcelCategory : sbyte
- {
- /// <summary>No assigned category</summary>
- None = 0,
- /// <summary>Linden Infohub or public area</summary>
- Linden,
- /// <summary>Adult themed area</summary>
- Adult,
- /// <summary>Arts and Culture</summary>
- Arts,
- /// <summary>Business</summary>
- Business,
- /// <summary>Educational</summary>
- Educational,
- /// <summary>Gaming</summary>
- Gaming,
- /// <summary>Hangout or Club</summary>
- Hangout,
- /// <summary>Newcomer friendly</summary>
- Newcomer,
- /// <summary>Parks and Nature</summary>
- Park,
- /// <summary>Residential</summary>
- Residential,
- /// <summary>Shopping</summary>
- Shopping,
- /// <summary>Not Used?</summary>
- Stage,
- /// <summary>Other</summary>
- Other,
- /// <summary>Not an actual category, only used for queries</summary>
- Any = -1
- }
- /// <summary>
- /// Type of teleport landing for a parcel
- /// </summary>
- public enum LandingType : byte
- {
- /// <summary>Unset, simulator default</summary>
- None = 0,
- /// <summary>Specific landing point set for this parcel</summary>
- LandingPoint = 1,
- /// <summary>No landing point set, direct teleports enabled for
- /// this parcel</summary>
- Direct = 2
- }
- /// <summary>
- /// Parcel Media Command used in ParcelMediaCommandMessage
- /// </summary>
- public enum ParcelMediaCommand : uint
- {
- /// <summary>Stop the media stream and go back to the first frame</summary>
- Stop = 0,
- /// <summary>Pause the media stream (stop playing but stay on current frame)</summary>
- Pause,
- /// <summary>Start the current media stream playing and stop when the end is reached</summary>
- Play,
- /// <summary>Start the current media stream playing,
- /// loop to the beginning when the end is reached and continue to play</summary>
- Loop,
- /// <summary>Specifies the texture to replace with video</summary>
- /// <remarks>If passing the key of a texture, it must be explicitly typecast as a key,
- /// not just passed within double quotes.</remarks>
- Texture,
- /// <summary>Specifies the movie URL (254 characters max)</summary>
- URL,
- /// <summary>Specifies the time index at which to begin playing</summary>
- Time,
- /// <summary>Specifies a single agent to apply the media command to</summary>
- Agent,
- /// <summary>Unloads the stream. While the stop command sets the texture to the first frame of the movie,
- /// unload resets it to the real texture that the movie was replacing.</summary>
- Unload,
- /// <summary>Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties
- /// (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter.</summary>
- AutoAlign,
- /// <summary>Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only).
- /// Use "text/html" for HTML.</summary>
- Type,
- /// <summary>Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only).</summary>
- /// <remarks>This might still not be working</remarks>
- Size,
- /// <summary>Sets a description for the media being displayed (1.19.1 RC0 and later only).</summary>
- Desc
- }
- #endregion Enums
- #region Structs
- /// <summary>
- /// Some information about a parcel of land returned from a DirectoryManager search
- /// </summary>
- public struct ParcelInfo
- {
- /// <summary>Global Key of record</summary>
- public UUID ID;
- /// <summary>Parcel Owners <seealso cref="UUID"/></summary>
- public UUID OwnerID;
- /// <summary>Name field of parcel, limited to 128 characters</summary>
- public string Name;
- /// <summary>Description field of parcel, limited to 256 characters</summary>
- public string Description;
- /// <summary>Total Square meters of parcel</summary>
- public int ActualArea;
- /// <summary>Total area billable as Tier, for group owned land this will be 10% less than ActualArea</summary>
- public int BillableArea;
- /// <summary>True of parcel is in Mature simulator</summary>
- public bool Mature;
- /// <summary>Grid global X position of parcel</summary>
- public float GlobalX;
- /// <summary>Grid global Y position of parcel</summary>
- public float GlobalY;
- /// <summary>Grid global Z position of parcel (not used)</summary>
- public float GlobalZ;
- /// <summary>Name of simulator parcel is located in</summary>
- public string SimName;
- /// <summary>Texture <seealso cref="T:OpenMetaverse.UUID"/> of parcels display picture</summary>
- public UUID SnapshotID;
- /// <summary>Float representing calculated traffic based on time spent on parcel by avatars</summary>
- public float Dwell;
- /// <summary>Sale price of parcel (not used)</summary>
- public int SalePrice;
- /// <summary>Auction ID of parcel</summary>
- public int AuctionID;
- }
- /// <summary>
- /// Parcel Media Information
- /// </summary>
- public struct ParcelMedia
- {
- /// <summary>A byte, if 0x1 viewer should auto scale media to fit object</summary>
- public bool MediaAutoScale;
- /// <summary>A boolean, if true the viewer should loop the media</summary>
- public bool MediaLoop;
- /// <summary>The Asset UUID of the Texture which when applied to a
- /// primitive will display the media</summary>
- public UUID MediaID;
- /// <summary>A URL which points to any Quicktime supported media type</summary>
- public string MediaURL;
- /// <summary>A description of the media</summary>
- public string MediaDesc;
- /// <summary>An Integer which represents the height of the media</summary>
- public int MediaHeight;
- /// <summary>An integer which represents the width of the media</summary>
- public int MediaWidth;
- /// <summary>A string which contains the mime type of the media</summary>
- public string MediaType;
- }
- #endregion Structs
- #region Parcel Class
- /// <summary>
- /// Parcel of land, a portion of virtual real estate in a simulator
- /// </summary>
- public class Parcel
- {
- /// <summary>The total number of contiguous 4x4 meter blocks your agent owns within this parcel</summary>
- public int SelfCount;
- /// <summary>The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own</summary>
- public int OtherCount;
- /// <summary>Deprecated, Value appears to always be 0</summary>
- public int PublicCount;
- /// <summary>Simulator-local ID of this parcel</summary>
- public int LocalID;
- /// <summary>UUID of the owner of this parcel</summary>
- public UUID OwnerID;
- /// <summary>Whether the land is deeded to a group or not</summary>
- public bool IsGroupOwned;
- /// <summary></summary>
- public uint AuctionID;
- /// <summary>Date land was claimed</summary>
- public DateTime ClaimDate;
- /// <summary>Appears to always be zero</summary>
- public int ClaimPrice;
- /// <summary>This field is no longer used</summary>
- public int RentPrice;
- /// <summary>Minimum corner of the axis-aligned bounding box for this
- /// parcel</summary>
- public Vector3 AABBMin;
- /// <summary>Maximum corner of the axis-aligned bounding box for this
- /// parcel</summary>
- public Vector3 AABBMax;
- /// <summary>Bitmap describing land layout in 4x4m squares across the
- /// entire region</summary>
- public byte[] Bitmap;
- /// <summary>Total parcel land area</summary>
- public int Area;
- /// <summary></summary>
- public ParcelStatus Status;
- /// <summary>Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used</summary>
- public int SimWideMaxPrims;
- /// <summary>Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel
- /// owned by the agent or group that owns this parcel</summary>
- public int SimWideTotalPrims;
- /// <summary>Maximum number of primitives this parcel supports</summary>
- public int MaxPrims;
- /// <summary>Total number of primitives on this parcel</summary>
- public int TotalPrims;
- /// <summary>For group-owned parcels this indicates the total number of prims deeded to the group,
- /// for parcels owned by an individual this inicates the number of prims owned by the individual</summary>
- public int OwnerPrims;
- /// <summary>Total number of primitives owned by the parcel group on
- /// this parcel, or for parcels owned by an individual with a group set the
- /// total number of prims set to that group.</summary>
- public int GroupPrims;
- /// <summary>Total number of prims owned by other avatars that are not set to group, or not the parcel owner</summary>
- public int OtherPrims;
- /// <summary>A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect
- /// the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed</summary>
- public float ParcelPrimBonus;
- /// <summary>Autoreturn value in minutes for others' objects</summary>
- public int OtherCleanTime;
- /// <summary></summary>
- public ParcelFlags Flags;
- /// <summary>Sale price of the parcel, only useful if ForSale is set</summary>
- /// <remarks>The SalePrice will remain the same after an ownership
- /// transfer (sale), so it can be used to see the purchase price after
- /// a sale if the new owner has not changed it</remarks>
- public int SalePrice;
- /// <summary>Parcel Name</summary>
- public string Name;
- /// <summary>Parcel Description</summary>
- public string Desc;
- /// <summary>URL For Music Stream</summary>
- public string MusicURL;
- /// <summary></summary>
- public UUID GroupID;
- /// <summary>Price for a temporary pass</summary>
- public int PassPrice;
- /// <summary>How long is pass valid for</summary>
- public float PassHours;
- /// <summary></summary>
- public ParcelCategory Category;
- /// <summary>Key of authorized buyer</summary>
- public UUID AuthBuyerID;
- /// <summary>Key of parcel snapshot</summary>
- public UUID SnapshotID;
- /// <summary>The landing point location</summary>
- public Vector3 UserLocation;
- /// <summary>The landing point LookAt</summary>
- public Vector3 UserLookAt;
- /// <summary>The type of landing enforced from the <see cref="LandingType"/> enum</summary>
- public LandingType Landing;
- /// <summary></summary>
- public float Dwell;
- /// <summary></summary>
- public bool RegionDenyAnonymous;
- /// <summary></summary>
- public bool RegionPushOverride;
- /// <summary>Access list of who is whitelisted on this
- /// parcel</summary>
- public List<ParcelManager.ParcelAccessEntry> AccessWhiteList;
- /// <summary>Access list of who is blacklisted on this
- /// parcel</summary>
- public List<ParcelManager.ParcelAccessEntry> AccessBlackList;
- /// <summary>TRUE of region denies access to age unverified users</summary>
- public bool RegionDenyAgeUnverified;
- /// <summary>true to obscure (hide) media url</summary>
- public bool ObscureMedia;
- /// <summary>true to obscure (hide) music url</summary>
- public bool ObscureMusic;
- /// <summary>A struct containing media details</summary>
- public ParcelMedia Media;
- /// <summary>
- /// Displays a parcel object in string format
- /// </summary>
- /// <returns>string containing key=value pairs of a parcel object</returns>
- public override string ToString()
- {
- string result = "";
- Type parcelType = this.GetType();
- FieldInfo[] fields = parcelType.GetFields();
- foreach (FieldInfo field in fields)
- {
- result += (field.Name + " = " + field.GetValue(this) + " ");
- }
- return result;
- }
- /// <summary>
- /// Defalt constructor
- /// </summary>
- /// <param name="localID">Local ID of this parcel</param>
- public Parcel(int localID)
- {
- LocalID = localID;
- ClaimDate = Utils.Epoch;
- Bitmap = Utils.EmptyBytes;
- Name = String.Empty;
- Desc = String.Empty;
- MusicURL = String.Empty;
- AccessWhiteList = new List<ParcelManager.ParcelAccessEntry>(0);
- AccessBlackList = new List<ParcelManager.ParcelAccessEntry>(0);
- Media = new ParcelMedia();
- }
- /// <summary>
- /// Update the simulator with any local changes to this Parcel object
- /// </summary>
- /// <param name="simulator">Simulator to send updates to</param>
- /// <param name="wantReply">Whether we want the simulator to confirm
- /// the update with a reply packet or not</param>
- public void Update(Simulator simulator, bool wantReply)
- {
- Uri url = simulator.Caps.CapabilityURI("ParcelPropertiesUpdate");
- if (url != null)
- {
- ParcelPropertiesUpdateMessage req = new ParcelPropertiesUpdateMessage();
- req.AuthBuyerID = this.AuthBuyerID;
- req.Category = this.Category;
- req.Desc = this.Desc;
- req.GroupID = this.GroupID;
- req.Landing = this.Landing;
- req.LocalID = this.LocalID;
- req.MediaAutoScale = this.Media.MediaAutoScale;
- req.MediaDesc = this.Media.MediaDesc;
- req.MediaHeight = this.Media.MediaHeight;
- req.MediaID = this.Media.MediaID;
- req.MediaLoop = this.Media.MediaLoop;
- req.MediaType = this.Media.MediaType;
- req.MediaURL = this.Media.MediaURL;
- req.MediaWidth = this.Media.MediaWidth;
- req.MusicURL = this.MusicURL;
- req.Name = this.Name;
- req.ObscureMedia = this.ObscureMedia;
- req.ObscureMusic = this.ObscureMusic;
- req.ParcelFlags = this.Flags;
- req.PassHours = this.PassHours;
- req.PassPrice = (uint)this.PassPrice;
- req.SalePrice = (uint)this.SalePrice;
- req.SnapshotID = this.SnapshotID;
- req.UserLocation = this.UserLocation;
- req.UserLookAt = this.UserLookAt;
-
- OSDMap body = req.Serialize();
- CapsClient capsPost = new CapsClient(url);
- capsPost.BeginGetResponse(body, OSDFormat.Xml, simulator.Client.Settings.CAPS_TIMEOUT);
- }
- else
- {
- ParcelPropertiesUpdatePacket request = new ParcelPropertiesUpdatePacket();
- request.AgentData.AgentID = simulator.Client.Self.AgentID;
- request.AgentData.SessionID = simulator.Client.Self.SessionID;
- request.ParcelData.LocalID = this.LocalID;
- request.ParcelData.AuthBuyerID = this.AuthBuyerID;
- request.ParcelData.Category = (byte)this.Category;
- request.ParcelData.Desc = Utils.StringToBytes(this.Desc);
- request.ParcelData.GroupID = this.GroupID;
- request.ParcelData.LandingType = (byte)this.Landing;
- request.ParcelData.MediaAutoScale = (this.Media.MediaAutoScale) ? (byte)0x1 : (byte)0x0;
- request.ParcelData.MediaID = this.Media.MediaID;
- request.ParcelData.MediaURL = Utils.StringToBytes(this.Media.MediaURL.ToString());
- request.ParcelData.MusicURL = Utils.StringToBytes(this.MusicURL.ToString());
- request.ParcelData.Name = Utils.StringToBytes(this.Name);
- if (wantReply) request.ParcelData.Flags = 1;
- request.ParcelData.ParcelFlags = (uint)this.Flags;
- request.ParcelData.PassHours = this.PassHours;
- request.ParcelData.PassPrice = this.PassPrice;
- request.ParcelData.SalePrice = this.SalePrice;
- request.ParcelData.SnapshotID = this.SnapshotID;
- request.ParcelData.UserLocation = this.UserLocation;
- request.ParcelData.UserLookAt = this.UserLookAt;
- simulator.SendPacket(request);
- }
- UpdateOtherCleanTime(simulator);
-
- }
- /// <summary>
- /// Set Autoreturn time
- /// </summary>
- /// <param name="simulator">Simulator to send the update to</param>
- public void UpdateOtherCleanTime(Simulator simulator)
- {
- ParcelSetOtherCleanTimePacket request = new ParcelSetOtherCleanTimePacket();
- request.AgentData.AgentID = simulator.Client.Self.AgentID;
- request.AgentData.SessionID = simulator.Client.Self.SessionID;
- request.ParcelData.LocalID = this.LocalID;
- request.ParcelData.OtherCleanTime = this.OtherCleanTime;
- simulator.SendPacket(request);
- }
- }
- #endregion Parcel Class
- /// <summary>
- /// Parcel (subdivided simulator lots) subsystem
- /// </summary>
- public class ParcelManager
- {
- #region Structs
- /// <summary>
- /// Parcel Accesslist
- /// </summary>
- public struct ParcelAccessEntry
- {
- /// <summary>Agents <seealso cref="T:OpenMetaverse.UUID"/></summary>
- public UUID AgentID;
- /// <summary></summary>
- public DateTime Time;
- /// <summary>Flags for specific entry in white/black lists</summary>
- public AccessList Flags;
- }
- /// <summary>
- /// Owners of primitives on parcel
- /// </summary>
- public struct ParcelPrimOwners
- {
- /// <summary>Prim Owners <seealso cref="T:OpenMetaverse.UUID"/></summary>
- public UUID OwnerID;
- /// <summary>True of owner is group</summary>
- public bool IsGroupOwned;
- /// <summary>Total count of prims owned by OwnerID</summary>
- public int Count;
- /// <summary>true of OwnerID is currently online and is not a group</summary>
- public bool OnlineStatus;
- /// <summary>The date of the most recent prim left by OwnerID</summary>
- public DateTime NewestPrim;
- }
- #endregion Structs
- #region Delegates
- /// <summary>
- /// Called once parcel resource usage information has been collected
- /// </summary>
- /// <param name="success">Indicates if operation was successfull</param>
- /// <param name="info">Parcel resource usage information</param>
- public delegate void LandResourcesCallback(bool success, LandResourcesInfo info);
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ParcelDwellReplyEventArgs> m_DwellReply;
- /// <summary>Raises the ParcelDwellReply event</summary>
- /// <param name="e">A ParcelDwellReplyEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnParcelDwellReply(ParcelDwellReplyEventArgs e)
- {
- EventHandler<ParcelDwellReplyEventArgs> handler = m_DwellReply;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_DwellReplyLock = new object();
-
- /// <summary>Raised when the simulator responds to a <see cref="RequestDwell"/> request</summary>
- public event EventHandler<ParcelDwellReplyEventArgs> ParcelDwellReply
- {
- add { lock (m_DwellReplyLock) { m_DwellReply += value; } }
- remove { lock (m_DwellReplyLock) { m_DwellReply -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ParcelInfoReplyEventArgs> m_ParcelInfo;
- /// <summary>Raises the ParcelInfoReply event</summary>
- /// <param name="e">A ParcelInfoReplyEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnParcelInfoReply(ParcelInfoReplyEventArgs e)
- {
- EventHandler<ParcelInfoReplyEventArgs> handler = m_ParcelInfo;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ParcelInfoLock = new object();
- /// <summary>Raised when the simulator responds to a <see cref="RequestParcelInfo"/> request</summary>
- public event EventHandler<ParcelInfoReplyEventArgs> ParcelInfoReply
- {
- add { lock (m_ParcelInfoLock) { m_ParcelInfo += value; } }
- remove { lock (m_ParcelInfoLock) { m_ParcelInfo -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ParcelPropertiesEventArgs> m_ParcelProperties;
- /// <summary>Raises the ParcelProperties event</summary>
- /// <param name="e">A ParcelPropertiesEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnParcelProperties(ParcelPropertiesEventArgs e)
- {
- EventHandler<ParcelPropertiesEventArgs> handler = m_ParcelProperties;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ParcelPropertiesLock = new object();
- /// <summary>Raised when the simulator responds to a <see cref="RequestParcelProperties"/> request</summary>
- public event EventHandler<ParcelPropertiesEventArgs> ParcelProperties
- {
- add { lock (m_ParcelPropertiesLock) { m_ParcelProperties += value; } }
- remove { lock (m_ParcelPropertiesLock) { m_ParcelProperties -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ParcelAccessListReplyEventArgs> m_ParcelACL;
- /// <summary>Raises the ParcelAccessListReply event</summary>
- /// <param name="e">A ParcelAccessListReplyEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnParcelAccessListReply(ParcelAccessListReplyEventArgs e)
- {
- EventHandler<ParcelAccessListReplyEventArgs> handler = m_ParcelACL;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ParcelACLLock = new object();
- /// <summary>Raised when the simulator responds to a <see cref="RequestParcelAccessList"/> request</summary>
- public event EventHandler<ParcelAccessListReplyEventArgs> ParcelAccessListReply
- {
- add { lock (m_ParcelACLLock) { m_ParcelACL += value; } }
- remove { lock (m_ParcelACLLock) { m_ParcelACL -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ParcelObjectOwnersReplyEventArgs> m_ParcelObjectOwnersReply;
- /// <summary>Raises the ParcelObjectOwnersReply event</summary>
- /// <param name="e">A ParcelObjectOwnersReplyEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnParcelObjectOwnersReply(ParcelObjectOwnersReplyEventArgs e)
- {
- EventHandler<ParcelObjectOwnersReplyEventArgs> handler = m_ParcelObjectOwnersReply;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ParcelObjectOwnersLock = new object();
- /// <summary>Raised when the simulator responds to a <see cref="RequestObjectOwners"/> request</summary>
- public event EventHandler<ParcelObjectOwnersReplyEventArgs> ParcelObjectOwnersReply
- {
- add { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply += value; } }
- remove { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<SimParcelsDownloadedEventArgs> m_SimParcelsDownloaded;
- /// <summary>Raises the SimParcelsDownloaded event</summary>
- /// <param name="e">A SimParcelsDownloadedEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnSimParcelsDownloaded(SimParcelsDownloadedEventArgs e)
- {
- EventHandler<SimParcelsDownloadedEventArgs> handler = m_SimParcelsDownloaded;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_SimParcelsDownloadedLock = new object();
- /// <summary>Raised when the simulator responds to a <see cref="RequestAllSimParcels"/> request</summary>
- public event EventHandler<SimParcelsDownloadedEventArgs> SimParcelsDownloaded
- {
- add { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded += value; } }
- remove { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ForceSelectObjectsReplyEventArgs> m_ForceSelectObjects;
- /// <summary>Raises the ForceSelectObjectsReply event</summary>
- /// <param name="e">A ForceSelectObjectsReplyEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnForceSelectObjectsReply(ForceSelectObjectsReplyEventArgs e)
- {
- EventHandler<ForceSelectObjectsReplyEventArgs> handler = m_ForceSelectObjects;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ForceSelectObjectsLock = new object();
- /// <summary>Raised when the simulator responds to a <see cref="RequestForceSelectObjects"/> request</summary>
- public event EventHandler<ForceSelectObjectsReplyEventArgs> ForceSelectObjectsReply
- {
- add { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects += value; } }
- remove { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ParcelMediaUpdateReplyEventArgs> m_ParcelMediaUpdateReply;
- /// <summary>Raises the ParcelMediaUpdateReply event</summary>
- /// <param name="e">A ParcelMediaUpdateReplyEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnParcelMediaUpdateReply(ParcelMediaUpdateReplyEventArgs e)
- {
- EventHandler<ParcelMediaUpdateReplyEventArgs> handler = m_ParcelMediaUpdateReply;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ParcelMediaUpdateReplyLock = new object();
- /// <summary>Raised when the simulator responds to a Parcel Update request</summary>
- public event EventHandler<ParcelMediaUpdateReplyEventArgs> ParcelMediaUpdateReply
- {
- add { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply += value; } }
- remove { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply -= value; } }
- }
- /// <summary>The event subscribers. null if no subcribers</summary>
- private EventHandler<ParcelMediaCommandEventArgs> m_ParcelMediaCommand;
- /// <summary>Raises the ParcelMediaCommand event</summary>
- /// <param name="e">A ParcelMediaCommandEventArgs object containing the
- /// data returned from the simulator</param>
- protected virtual void OnParcelMediaCommand(ParcelMediaCommandEventArgs e)
- {
- EventHandler<ParcelMediaCommandEventArgs> handler = m_ParcelMediaCommand;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ParcelMediaCommandLock = new object();
- /// <summary>Raised when the parcel your agent is located sends a ParcelMediaCommand</summary>
- public event EventHandler<ParcelMediaCommandEventArgs> ParcelMediaCommand
- {
- add { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand += value; } }
- remove { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand -= value; } }
- }
- #endregion Delegates
- private GridClient Client;
- private AutoResetEvent WaitForSimParcel;
- #region Public Methods
- /// <summary>
- /// Default constructor
- /// </summary>
- /// <param name="client">A reference to the GridClient object</param>
- public ParcelManager(GridClient client)
- {
- Client = client;
-
- // Setup the callbacks
- Client.Network.RegisterCallback(PacketType.ParcelInfoReply, ParcelInfoReplyHandler);
- Client.Network.RegisterEventCallback("ParcelObjectOwnersReply", new Caps.EventQueueCallback(ParcelObjectOwnersReplyHandler));
- // CAPS packet handler, to allow for Media Data not contained in the message template
- Client.Network.RegisterEventCallback("ParcelProperties", new Caps.EventQueueCallback(ParcelPropertiesReplyHandler));
- Client.Network.RegisterCallback(PacketType.ParcelDwellReply, ParcelDwellReplyHandler);
- Client.Network.RegisterCallback(PacketType.ParcelAccessListReply, ParcelAccessListReplyHandler);
- Client.Network.RegisterCallback(PacketType.ForceObjectSelect, SelectParcelObjectsReplyHandler);
- Client.Network.RegisterCallback(PacketType.ParcelMediaUpdate, ParcelMediaUpdateHandler);
- Client.Network.RegisterCallback(PacketType.ParcelOverlay, ParcelOverlayHandler);
- Client.Network.RegisterCallback(PacketType.ParcelMediaCommandMessage, ParcelMediaCommandMessagePacketHandler);
- }
- /// <summary>
- /// Request basic information for a single parcel
- /// </summary>
- /// <param name="parcelID">Simulator-local ID of the parcel</param>
- public void RequestParcelInfo(UUID parcelID)
- {
- ParcelInfoRequestPacket request = new ParcelInfoRequestPacket();
- request.AgentData.AgentID = Client.Self.AgentID;
- request.AgentData.SessionID = Client.Self.SessionID;
- request.Data.ParcelID = parcelID;
- Client.Network.SendPacket(request);
- }
- /// <summary>
- /// Request properties of a single parcel
- /// </summary>
- /// <param name="simulator">Simulator containing the parcel</param>
- /// <param name="localID">Simulator-local ID of the parcel</param>
- /// <param name="sequenceID">An arbitrary integer that will be returned
- /// with the ParcelProperties reply, useful for distinguishing between
- /// multiple simultaneous requests</param>
- public void RequestParcelProperties(Simulator simulator, int localID, int sequenceID)
- {
- ParcelPropertiesRequestByIDPacket request = new ParcelPropertiesRequestByIDPacket();
- request.AgentData.AgentID = Client.Self.AgentID;
- request.AgentData.SessionID = Client.Self.SessionID;
- request.ParcelData.LocalID = localID;
- request.ParcelData.SequenceID = sequenceID;
- Client.Network.SendPacket(request, simulator);
- }
- /// <summary>
- /// Request the access list for a single parcel
- /// </summary>
- /// <param name="simulator">Simulator containing the parcel</param>
- /// <param name="localID">Simulator-local ID of the parcel</param>
- /// <param name="sequenceID">An arbitrary integer that will be returned
- /// with the ParcelAccessList reply, useful for distinguishing between
- /// multiple simultaneous requests</param>
- /// <param name="flags"></param>
- public void RequestParcelAccessList(Simulator simulator, int localID, AccessList flags, int sequenceID)
- {
- ParcelAccessListRequestPacket request = new ParcelAccessListRequestPacket();
- request.AgentData.AgentID = Client.Self.AgentID;
- request.AgentData.SessionID = Client.Self.SessionID;
- request.Data.LocalID = localID;
- request.Data.Flags = (uint)flags;
- request.Data.SequenceID = sequenceID;
- Client.Network.SendPacket(request, simulator);
- }
- /// <summary>
- /// Request properties of parcels using a bounding box selection
- /// </summary>
- /// <param name="simulator">Simulator containing the parcel</param>
- /// <param name="north">Northern boundary of the parcel selection</param>
- /// <param name="east">Eastern boundary of the parcel selection</param>
- /// <param name="south">Southern boundary of the parcel selection</param>
- /// <param name="west">Western boundary of the parcel selection</param>
- /// <param name="sequenceID">An arbitrary integer that will be returned
- /// with the ParcelProperties reply, useful for distinguishing between
- /// different types of parcel property requests</param>
- /// <param name="snapSelection">A boolean that is returned with the
- /// ParcelProperties reply, useful for snapping focus to a single
- /// parcel</param>
- public void RequestParcelProperties(Simulator simulator, float north, float east, float south, float west,
- int sequenceID, bool snapSelection)
- {
- ParcelPropertiesRequestPacket request = new ParcelPropertiesRequestPacket();
- request.AgentData.AgentID = Client.Self.AgentID;
- request.AgentData.SessionID = Client.Self.SessionID;
- request.ParcelData.North = north;
- request.ParcelData.East = east;
- request.ParcelData.South = south;
- request.ParcelData.West = west;
- request.ParcelData.SequenceID = sequenceID;
- request.ParcelData.SnapSelection = snapSelection;
- Client.Network.SendPacket(request, simulator);
- }
- /// <summary>
- /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
- /// dictionary)
- /// </summary>
- /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
- public void RequestAllSimParcels(Simulator simulator)
- {
- RequestAllSimParcels(simulator, false, 750);
- }
- /// <summary>
- /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
- /// dictionary)
- /// </summary>
- /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
- /// <param name="refresh">If TRUE, will force a full refresh</param>
- /// <param name="msDelay">Number of milliseconds to pause in between each request</param>
- public void RequestAllSimParcels(Simulator simulator, bool refresh, int msDelay)
- {
- if (simulator.DownloadingParcelMap)
- {
- Logger.Log("Already downloading parcels in " + simulator.Name, Helpers.LogLevel.Info, Client);
- return;
- }
- else
- {
- simulator.DownloadingParcelMap = true;
- WaitForSimParcel = new AutoResetEvent(false);
- }
- if (refresh)
- {
- for (int y = 0; y < 64; y++)
- for (int x = 0; x < 64; x++)
- simulator.ParcelMap[y, x] = 0;
- }
- Thread th = new Thread(delegate()
- {
- int count = 0, timeouts = 0, y, x;
- for (y = 0; y < 64; y++)
- {
- for (x = 0; x < 64; x++)
- {
- if (!Client.Network.Connected)
- return;
- if (simulator.ParcelMap[y, x] == 0)
- {
- Client.Parcels.RequestParcelProperties(simulator,
- (y + 1) * 4.0f, (x + 1) * 4.0f,
- y * 4.0f, x * 4.0f, int.MaxValue, false);
- // Wait the given amount of time for a reply beforeā¦
Large files files are truncated, but you can click here to view the full file