/*
* Copyright (c) 2006-2007, Second Life Reverse Engineering Team
* 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 Second Life Reverse Engineering Team 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.Timers;
using System.Collections.Generic;
using libsecondlife.Packets;
namespace libsecondlife
{
#region Structs
///
/// Some information about a parcel of land
///
public struct ParcelInfo
{
///
public LLUUID ID;
///
public LLUUID OwnerID;
///
public string Name;
///
public string Description;
///
public int ActualArea;
///
public int BillableArea;
///
public bool Mature;
///
public float GlobalX;
///
public float GlobalY;
///
public float GlobalZ;
///
public string SimName;
///
public LLUUID SnapshotID;
///
public float Dwell;
///
public int SalePrice;
///
public int AuctionID;
}
#endregion Structs
#region Parcel Class
///
/// Parcel of land, a portion of virtual real estate in a simulator
///
public class Parcel
{
#region Enums
///
/// Various parcel properties
///
[Flags]
public enum ParcelFlags : uint
{
/// No flags set
None = 0,
/// Allow avatars to fly (a client-side only restriction)
AllowFly = 1 << 0,
/// Allow foreign scripts to run
AllowOtherScripts = 1 << 1,
/// This parcel is for sale
ForSale = 1 << 2,
/// Allow avatars to create a landmark on this parcel
AllowLandmark = 1 << 3,
/// Allows all avatars to edit the terrain on this parcel
AllowTerraform = 1 << 4,
/// Avatars have health and can take damage on this parcel.
/// If set, avatars can be killed and sent home here
AllowDamage = 1 << 5,
/// Foreign avatars can create objects here
CreateObjects = 1 << 6,
/// All objects on this parcel can be purchased
ForSaleObjects = 1 << 7,
/// Access is restricted to a group
UseAccessGroup = 1 << 8,
/// Access is restricted to a whitelist
UseAccessList = 1 << 9,
/// Ban blacklist is enabled
UseBanList = 1 << 10,
/// Unknown
UsePassList = 1 << 11,
/// List this parcel in the search directory
ShowDirectory = 1 << 12,
/// Unknown
AllowDeedToGroup = 1 << 13,
/// Unknown
ContributeWithDeed = 1 << 14,
/// Restrict sounds originating on this parcel to the
/// parcel boundaries
SoundLocal = 1 << 15,
/// Objects on this parcel are sold when the land is
/// purchsaed
SellParcelObjects = 1 << 16,
/// Allow this parcel to be published on the web
AllowPublish = 1 << 17,
/// The information for this parcel is mature content
MaturePublish = 1 << 18,
/// The media URL is an HTML page
UrlWebPage = 1 << 19,
/// The media URL is a raw HTML string
UrlRawHtml = 1 << 20,
/// Restrict foreign object pushes
RestrictPushObject = 1 << 21,
/// Ban all non identified/transacted avatars
DenyAnonymous = 1 << 22,
/// Ban all identified avatars
DenyIdentified = 1 << 23,
/// Ban all transacted avatars
DenyTransacted = 1 << 24,
/// Allow group-owned scripts to run
AllowGroupScripts = 1 << 25,
/// Allow object creation by group members or group
/// objects
CreateGroupObjects = 1 << 26,
/// Allow all objects to enter this parcel
AllowAllObjectEntry = 1 << 27,
/// Only allow group and owner objects to enter this parcel
AllowGroupObjectEntry = 1 << 28,
}
///
/// Parcel ownership status
///
public enum ParcelStatus : sbyte
{
///
None = -1,
///
Leased = 0,
///
LeasePending = 1,
///
Abandoned = 2
}
///
///
///
public enum ParcelCategory : sbyte
{
/// No assigned category
None = 0,
///
Linden,
///
Adult,
///
Arts,
///
Business,
///
Educational,
///
Gaming,
///
Hangout,
///
Newcomer,
///
Park,
///
Residential,
///
Shopping,
///
Stage,
///
Other,
/// Not an actual category, only used for queries
Any = -1
}
#endregion Enums
///
public int RequestResult;
///
public int SequenceID;
///
public bool SnapSelection;
///
public int SelfCount;
///
public int OtherCount;
///
public int PublicCount;
/// Simulator-local ID of this parcel
public int LocalID { get { return localid; } }
/// UUID of the owner of this parcel
public LLUUID OwnerID;
/// Whether the land is deeded to a group or not
public bool IsGroupOwned;
///
public uint AuctionID;
/// Date land was claimed
public DateTime ClaimDate;
/// Appears to always be zero
public int ClaimPrice;
///
public int RentPrice;
/// Minimum corner of the axis-aligned bounding box for this
/// parcel
public LLVector3 AABBMin;
/// Maximum corner of the axis-aligned bounding box for this
/// parcel
public LLVector3 AABBMax;
/// Bitmap describing land layout in 4x4m squares across the
/// entire region
public byte[] Bitmap;
/// Total parcel land area
public int Area;
///
public ParcelStatus Status;
/// Maximum primitives across the entire simulator
public int SimWideMaxPrims;
/// Total primitives across the entire simulator
public int SimWideTotalPrims;
/// Maximum number of primitives this parcel supports
public int MaxPrims;
/// Total number of primitives on this parcel
public int TotalPrims;
/// Total number of primitives owned by the parcel owner on
/// this parcel
public int OwnerPrims;
/// Total number of primitives owned by the parcel group on
/// this parcel
public int GroupPrims;
/// Total number of other primitives on this parcel
public int OtherPrims;
/// Total number of primitives you are currently selecting and
/// sitting on
public int SelectedPrims;
///
public float ParcelPrimBonus;
/// Autoreturn value in minutes for others' objects
public int OtherCleanTime;
///
public ParcelFlags Flags;
/// Sale price of the parcel, only useful if ForSale is set
/// 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
public int SalePrice;
/// Parcel Name
public string Name;
/// Parcel Description
public string Desc;
/// URL For Music Stream
public string MusicURL;
/// URL For other Media
public string MediaURL;
/// Key to Picture for Media Placeholder
public LLUUID MediaID;
///
public byte MediaAutoScale;
///
public LLUUID GroupID;
/// Price for a temporary pass
public int PassPrice;
/// How long is pass valid for
public float PassHours;
///
public ParcelCategory Category;
/// Key of authorized buyer
public LLUUID AuthBuyerID;
/// Key of parcel snapshot
public LLUUID SnapshotID;
///
public LLVector3 UserLocation;
///
public LLVector3 UserLookAt;
///
public byte LandingType;
///
public float Dwell;
///
public bool RegionDenyAnonymous;
///
public bool RegionDenyIdentified;
///
public bool RegionDenyTransacted;
///
public bool RegionPushOverride;
///
public Simulator Simulator;
/// Access list of who is whitelisted or blacklisted on this
/// parcel
public List AccessList;
private int localid;
///
/// Defalt constructor
///
/// Simulator this parcel resides in
/// Local ID of this parcel
public Parcel(Simulator simulator, int localID)
{
Simulator = simulator;
localid = localID;
}
///
/// Update the simulator with any local changes to this Parcel object
///
/// Whether we want the simulator to confirm
/// the update with a reply packet or not
public void Update(bool wantReply)
{
ParcelPropertiesUpdatePacket request = new ParcelPropertiesUpdatePacket();
request.AgentData.AgentID = Simulator.Client.Network.AgentID;
request.AgentData.SessionID = Simulator.Client.Network.SessionID;
request.ParcelData.LocalID = this.LocalID;
request.ParcelData.AuthBuyerID = this.AuthBuyerID;
request.ParcelData.Category = (byte)this.Category;
request.ParcelData.Desc = Helpers.StringToField(this.Desc);
request.ParcelData.GroupID = this.GroupID;
request.ParcelData.LandingType = this.LandingType;
request.ParcelData.MediaAutoScale = this.MediaAutoScale;
request.ParcelData.MediaID = this.MediaID;
request.ParcelData.MediaURL = Helpers.StringToField(this.MediaURL);
request.ParcelData.MusicURL = Helpers.StringToField(this.MusicURL);
request.ParcelData.Name = Helpers.StringToField(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.Client.Network.SendPacket(request, Simulator);
UpdateOtherCleanTime();
}
public void UpdateOtherCleanTime()
{
ParcelSetOtherCleanTimePacket request = new ParcelSetOtherCleanTimePacket();
request.AgentData.AgentID = Simulator.Client.Network.AgentID;
request.AgentData.SessionID = Simulator.Client.Network.SessionID;
request.ParcelData.LocalID = this.LocalID;
request.ParcelData.OtherCleanTime = this.OtherCleanTime;
Simulator.Client.Network.SendPacket(request, Simulator);
}
}
#endregion Parcel Class
///
/// Parcel (subdivided simulator lots) subsystem
///
public class ParcelManager
{
#region Enums
///
/// Type of return to use when returning objects from a parcel
///
public enum ObjectReturnType : uint
{
///
None = 0,
///
Owner = 1 << 1,
///
Group = 1 << 2,
///
Other = 1 << 3,
///
List = 1 << 4,
///
Sell = 1 << 5
}
///
///
///
public enum ParcelAccessFlags : uint
{
///
NoAccess = 0,
///
Access = 1
}
///
/// The result of a request for parcel properties
///
public enum ParcelResult : int
{
/// No matches were found for the request
NoData = -1,
/// Request matched a single parcel
Single = 0,
/// Request matched multiple parcels
Multiple = 1
}
///
/// Flags used in the ParcelAccessListRequest packet to specify whether
/// we want the access list (whitelist), ban list (blacklist), or both
///
[Flags]
public enum AccessList : uint
{
/// Request the access list
Access = 1 << 0,
/// Request the ban list
Ban = 1 << 1,
/// Request both the access list and ban list
Both = Access | Ban
}
#endregion Enums
#region Structs
///
///
///
public struct ParcelAccessEntry
{
///
public LLUUID AgentID;
///
public DateTime Time;
///
public AccessList Flags;
}
#endregion Structs
#region Delegates
///
///
///
/// UUID of the requested parcel
/// Simulator-local ID of the requested parcel
/// Dwell value of the requested parcel
public delegate void ParcelDwellCallback(LLUUID parcelID, int localID, float dwell);
///
///
///
///
public delegate void ParcelInfoCallback(ParcelInfo parcel);
///
///
///
/// Full properties for a single parcel. If result
/// is NoData this will be incomplete or incorrect data
/// Success of the query
/// User-assigned identifier for the query
/// User-assigned boolean for the query
public delegate void ParcelPropertiesCallback(Parcel parcel, ParcelResult result, int sequenceID, bool snapSelection);
///
///
///
///
///
///
///
public delegate void ParcelAccessListReplyCallback(Simulator simulator, int sequenceID, int localID, uint flags, List accessEntries);
#endregion Delegates
#region Events
///
public event ParcelDwellCallback OnParcelDwell;
///
public event ParcelInfoCallback OnParcelInfo;
///
public event ParcelPropertiesCallback OnParcelProperties;
///
public event ParcelAccessListReplyCallback OnAccessListReply;
#endregion Events
private SecondLife Client;
#region Public Methods
///
/// Default constructor
///
/// A reference to the SecondLife client
public ParcelManager(SecondLife client)
{
Client = client;
// Setup the callbacks
Client.Network.RegisterCallback(PacketType.ParcelInfoReply, new NetworkManager.PacketCallback(ParcelInfoReplyHandler));
Client.Network.RegisterCallback(PacketType.ParcelProperties, new NetworkManager.PacketCallback(ParcelPropertiesHandler));
Client.Network.RegisterCallback(PacketType.ParcelDwellReply, new NetworkManager.PacketCallback(ParcelDwellReplyHandler));
Client.Network.RegisterCallback(PacketType.ParcelAccessListReply, new NetworkManager.PacketCallback(ParcelAccessListReplyHandler));
}
///
/// Request basic information for a single parcel
///
/// Simulator-local ID of the parcel
public void InfoRequest(LLUUID parcelID)
{
ParcelInfoRequestPacket request = new ParcelInfoRequestPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.Data.ParcelID = parcelID;
Client.Network.SendPacket(request);
}
///
/// Request properties of a single parcel
///
/// Simulator containing the parcel
/// Simulator-local ID of the parcel
/// An arbitrary integer that will be returned
/// with the ParcelProperties reply, useful for distinguishing between
/// multiple simultaneous requests
public void PropertiesRequest(Simulator simulator, int localID, int sequenceID)
{
ParcelPropertiesRequestByIDPacket request = new ParcelPropertiesRequestByIDPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.ParcelData.LocalID = localID;
request.ParcelData.SequenceID = sequenceID;
Client.Network.SendPacket(request, simulator);
}
///
/// Request the access list for a single parcel
///
/// Simulator containing the parcel
/// Simulator-local ID of the parcel
/// An arbitrary integer that will be returned
/// with the ParcelAccessList reply, useful for distinguishing between
/// multiple simultaneous requests
public void AccessListRequest(Simulator simulator, int localID, AccessList flags, int sequenceID)
{
ParcelAccessListRequestPacket request = new ParcelAccessListRequestPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.Data.LocalID = localID;
request.Data.Flags = (uint)flags;
request.Data.SequenceID = sequenceID;
Client.Network.SendPacket(request, simulator);
}
///
/// Request properties of parcels using a bounding box selection
///
/// Simulator containing the parcel
/// Northern boundary of the parcel selection
/// Eastern boundary of the parcel selection
/// Southern boundary of the parcel selection
/// Western boundary of the parcel selection
/// An arbitrary integer that will be returned
/// with the ParcelProperties reply, useful for distinguishing between
/// different types of parcel property requests
/// A boolean that is returned with the
/// ParcelProperties reply, useful for snapping focus to a single
/// parcel
public void PropertiesRequest(Simulator simulator, float north, float east, float south, float west,
int sequenceID, bool snapSelection)
{
ParcelPropertiesRequestPacket request = new ParcelPropertiesRequestPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.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);
}
///
/// Request the dwell value for a parcel
///
/// Simulator containing the parcel
/// Simulator-local ID of the parcel
public void DwellRequest(Simulator simulator, int localID)
{
ParcelDwellRequestPacket request = new ParcelDwellRequestPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.Data.LocalID = localID;
request.Data.ParcelID = LLUUID.Zero; // Not used by clients
Client.Network.SendPacket(request, simulator);
}
///
///
///
///
///
///
///
///
///
public void Buy(Simulator simulator, int localID, bool forGroup, LLUUID groupID, bool removeContribution)
{
ParcelBuyPacket request = new ParcelBuyPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.Data.Final = true;
request.Data.GroupID = groupID;
request.Data.LocalID = localID;
request.Data.IsGroupOwned = forGroup;
request.Data.RemoveContribution = removeContribution;
Client.Network.SendPacket(request, simulator);
}
///
///
///
///
///
public void Reclaim(Simulator simulator, int localID)
{
ParcelReclaimPacket request = new ParcelReclaimPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.Data.LocalID = localID;
Client.Network.SendPacket(request, simulator);
}
///
///
///
///
///
///
public void DeedToGroup(Simulator simulator, int localID, LLUUID groupID)
{
ParcelDeedToGroupPacket request = new ParcelDeedToGroupPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.Data.LocalID = localID;
request.Data.GroupID = groupID;
Client.Network.SendPacket(request, simulator);
}
///
///
///
///
///
///
///
public void ReturnObjects(Simulator simulator, int localID, ObjectReturnType type, List ownerIDs)
{
ParcelReturnObjectsPacket request = new ParcelReturnObjectsPacket();
request.AgentData.AgentID = Client.Network.AgentID;
request.AgentData.SessionID = Client.Network.SessionID;
request.ParcelData.LocalID = localID;
request.ParcelData.ReturnType = (uint)type;
// A single null TaskID is (not) used for parcel object returns
request.TaskIDs = new ParcelReturnObjectsPacket.TaskIDsBlock[1];
request.TaskIDs[0] = new ParcelReturnObjectsPacket.TaskIDsBlock();
request.TaskIDs[0].TaskID = LLUUID.Zero;
// Convert the list of owner UUIDs to packet blocks if a list is given
if (ownerIDs != null)
{
request.OwnerIDs = new ParcelReturnObjectsPacket.OwnerIDsBlock[ownerIDs.Count];
for (int i = 0; i < ownerIDs.Count; i++)
{
request.OwnerIDs[i] = new ParcelReturnObjectsPacket.OwnerIDsBlock();
request.OwnerIDs[i].OwnerID = ownerIDs[i];
}
}
else
{
request.OwnerIDs = new ParcelReturnObjectsPacket.OwnerIDsBlock[0];
}
Client.Network.SendPacket(request, simulator);
}
///
///
///
///
///
///
///
///
public void ParcelSubdivide(Simulator simulator, float west, float south, float east, float north)
{
ParcelDividePacket divide = new ParcelDividePacket();
divide.AgentData.AgentID = Client.Network.AgentID;
divide.AgentData.SessionID = Client.Network.SessionID;
divide.ParcelData.East = east;
divide.ParcelData.North = north;
divide.ParcelData.South = south;
divide.ParcelData.West = west;
Client.Network.SendPacket(divide, simulator);
}
///
///
///
///
///
///
///
///
public void ParcelJoin(Simulator simulator, float west, float south, float east, float north)
{
ParcelJoinPacket join = new ParcelJoinPacket();
join.AgentData.AgentID = Client.Network.AgentID;
join.AgentData.SessionID = Client.Network.SessionID;
join.ParcelData.East = east;
join.ParcelData.North = north;
join.ParcelData.South = south;
join.ParcelData.West = west;
Client.Network.SendPacket(join, simulator);
}
#endregion Public Methods
#region Packet Handlers
private void ParcelDwellReplyHandler(Packet packet, Simulator simulator)
{
if (OnParcelDwell != null)
{
ParcelDwellReplyPacket dwell = (ParcelDwellReplyPacket)packet;
try { OnParcelDwell(dwell.Data.ParcelID, dwell.Data.LocalID, dwell.Data.Dwell); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void ParcelInfoReplyHandler(Packet packet, Simulator simulator)
{
if (OnParcelInfo != null)
{
ParcelInfoReplyPacket info = (ParcelInfoReplyPacket)packet;
ParcelInfo parcelInfo = new ParcelInfo();
parcelInfo.ActualArea = info.Data.ActualArea;
parcelInfo.AuctionID = info.Data.AuctionID;
parcelInfo.BillableArea = info.Data.BillableArea;
parcelInfo.Description = Helpers.FieldToUTF8String(info.Data.Desc);
parcelInfo.Dwell = info.Data.Dwell;
parcelInfo.GlobalX = info.Data.GlobalX;
parcelInfo.GlobalY = info.Data.GlobalY;
parcelInfo.GlobalZ = info.Data.GlobalZ;
parcelInfo.ID = info.Data.ParcelID;
parcelInfo.Mature = ((info.Data.Flags & 1) != 0) ? true : false;
parcelInfo.Name = Helpers.FieldToUTF8String(info.Data.Name);
parcelInfo.OwnerID = info.Data.OwnerID;
parcelInfo.SalePrice = info.Data.SalePrice;
parcelInfo.SimName = Helpers.FieldToUTF8String(info.Data.SimName);
parcelInfo.SnapshotID = info.Data.SnapshotID;
try { OnParcelInfo(parcelInfo); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
private void ParcelPropertiesHandler(Packet packet, Simulator simulator)
{
if (OnParcelProperties != null)
{
ParcelPropertiesPacket properties = (ParcelPropertiesPacket)packet;
Parcel parcel = new Parcel(simulator, properties.ParcelData.LocalID);
parcel.AABBMax = properties.ParcelData.AABBMax;
parcel.AABBMin = properties.ParcelData.AABBMin;
parcel.Area = properties.ParcelData.Area;
parcel.AuctionID = properties.ParcelData.AuctionID;
parcel.AuthBuyerID = properties.ParcelData.AuthBuyerID;
parcel.Bitmap = properties.ParcelData.Bitmap;
parcel.Category = (Parcel.ParcelCategory)(sbyte)properties.ParcelData.Category;
parcel.ClaimDate = Helpers.UnixTimeToDateTime((uint)properties.ParcelData.ClaimDate);
// ClaimPrice seems to always be zero?
parcel.ClaimPrice = properties.ParcelData.ClaimPrice;
parcel.Desc = Helpers.FieldToUTF8String(properties.ParcelData.Desc);
parcel.GroupID = properties.ParcelData.GroupID;
parcel.GroupPrims = properties.ParcelData.GroupPrims;
parcel.IsGroupOwned = properties.ParcelData.IsGroupOwned;
parcel.LandingType = properties.ParcelData.LandingType;
parcel.MaxPrims = properties.ParcelData.MaxPrims;
parcel.MediaAutoScale = properties.ParcelData.MediaAutoScale;
parcel.MediaID = properties.ParcelData.MediaID;
parcel.MediaURL = Helpers.FieldToUTF8String(properties.ParcelData.MediaURL);
parcel.MusicURL = Helpers.FieldToUTF8String(properties.ParcelData.MusicURL);
parcel.Name = Helpers.FieldToUTF8String(properties.ParcelData.Name);
parcel.OtherCleanTime = properties.ParcelData.OtherCleanTime;
parcel.OtherCount = properties.ParcelData.OtherCount;
parcel.OtherPrims = properties.ParcelData.OtherPrims;
parcel.OwnerID = properties.ParcelData.OwnerID;
parcel.OwnerPrims = properties.ParcelData.OwnerPrims;
parcel.Flags = (Parcel.ParcelFlags)properties.ParcelData.ParcelFlags;
parcel.ParcelPrimBonus = properties.ParcelData.ParcelPrimBonus;
parcel.PassHours = properties.ParcelData.PassHours;
parcel.PassPrice = properties.ParcelData.PassPrice;
parcel.PublicCount = properties.ParcelData.PublicCount;
parcel.RegionDenyAnonymous = properties.ParcelData.RegionDenyAnonymous;
parcel.RegionDenyIdentified = properties.ParcelData.RegionDenyIdentified;
parcel.RegionDenyTransacted = properties.ParcelData.RegionDenyTransacted;
parcel.RegionPushOverride = properties.ParcelData.RegionPushOverride;
parcel.RentPrice = properties.ParcelData.RentPrice;
parcel.SalePrice = properties.ParcelData.SalePrice;
parcel.SelectedPrims = properties.ParcelData.SelectedPrims;
parcel.SelfCount = properties.ParcelData.SelfCount;
parcel.SimWideMaxPrims = properties.ParcelData.SimWideMaxPrims;
parcel.SimWideTotalPrims = properties.ParcelData.SimWideTotalPrims;
parcel.SnapshotID = properties.ParcelData.SnapshotID;
parcel.Status = (Parcel.ParcelStatus)(sbyte)properties.ParcelData.Status;
parcel.TotalPrims = properties.ParcelData.TotalPrims;
parcel.UserLocation = properties.ParcelData.UserLocation;
parcel.UserLookAt = properties.ParcelData.UserLookAt;
// Fire the callback
try
{
OnParcelProperties(parcel, (ParcelResult)properties.ParcelData.RequestResult,
properties.ParcelData.SequenceID, properties.ParcelData.SnapSelection);
}
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
protected void ParcelAccessListReplyHandler(Packet packet, Simulator simulator)
{
if (OnAccessListReply != null)
{
ParcelAccessListReplyPacket reply = (ParcelAccessListReplyPacket)packet;
List accessList = new List(reply.List.Length);
for (int i = 0; i < reply.List.Length; i++)
{
ParcelAccessEntry pae = new ParcelAccessEntry();
pae.AgentID = reply.List[i].ID;
pae.Flags = (AccessList)reply.List[i].Flags;
pae.Time = Helpers.UnixTimeToDateTime((uint)reply.List[i].Time);
accessList.Add(pae);
}
try { OnAccessListReply(simulator, reply.Data.SequenceID, reply.Data.LocalID, reply.Data.Flags,
accessList); }
catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
}
}
#endregion Packet Handlers
}
}