/OpenMetaverse/Modules/ObjectManager.cs
C# | 3701 lines | 2227 code | 476 blank | 998 comment | 228 complexity | 61a42fa1eb6dc4a06150942dc8c58f3a MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) 2006-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.Collections.Generic;
- using System.Threading;
- using OpenMetaverse.Packets;
- using OpenMetaverse.Http;
- using OpenMetaverse.StructuredData;
- using OpenMetaverse.Interfaces;
- using OpenMetaverse.Messages.Linden;
- namespace OpenMetaverse
- {
- #region Enums
- /// <summary>
- ///
- /// </summary>
- public enum ReportType : uint
- {
- /// <summary>No report</summary>
- None = 0,
- /// <summary>Unknown report type</summary>
- Unknown = 1,
- /// <summary>Bug report</summary>
- Bug = 2,
- /// <summary>Complaint report</summary>
- Complaint = 3,
- /// <summary>Customer service report</summary>
- CustomerServiceRequest = 4
- }
- /// <summary>
- /// Bitflag field for ObjectUpdateCompressed data blocks, describing
- /// which options are present for each object
- /// </summary>
- [Flags]
- public enum CompressedFlags : uint
- {
- None = 0x00,
- /// <summary>Unknown</summary>
- ScratchPad = 0x01,
- /// <summary>Whether the object has a TreeSpecies</summary>
- Tree = 0x02,
- /// <summary>Whether the object has floating text ala llSetText</summary>
- HasText = 0x04,
- /// <summary>Whether the object has an active particle system</summary>
- HasParticles = 0x08,
- /// <summary>Whether the object has sound attached to it</summary>
- HasSound = 0x10,
- /// <summary>Whether the object is attached to a root object or not</summary>
- HasParent = 0x20,
- /// <summary>Whether the object has texture animation settings</summary>
- TextureAnimation = 0x40,
- /// <summary>Whether the object has an angular velocity</summary>
- HasAngularVelocity = 0x80,
- /// <summary>Whether the object has a name value pairs string</summary>
- HasNameValues = 0x100,
- /// <summary>Whether the object has a Media URL set</summary>
- MediaURL = 0x200
- }
- /// <summary>
- /// Specific Flags for MultipleObjectUpdate requests
- /// </summary>
- [Flags]
- public enum UpdateType : uint
- {
- /// <summary>None</summary>
- None = 0x00,
- /// <summary>Change position of prims</summary>
- Position = 0x01,
- /// <summary>Change rotation of prims</summary>
- Rotation = 0x02,
- /// <summary>Change size of prims</summary>
- Scale = 0x04,
- /// <summary>Perform operation on link set</summary>
- Linked = 0x08,
- /// <summary>Scale prims uniformly, same as selecing ctrl+shift in the
- /// viewer. Used in conjunction with Scale</summary>
- Uniform = 0x10
- }
- /// <summary>
- /// Special values in PayPriceReply. If the price is not one of these
- /// literal value of the price should be use
- /// </summary>
- public enum PayPriceType : int
- {
- /// <summary>
- /// Indicates that this pay option should be hidden
- /// </summary>
- Hide = -1,
- /// <summary>
- /// Indicates that this pay option should have the default value
- /// </summary>
- Default = -2
- }
- #endregion Enums
- #region Structs
- /// <summary>
- /// Contains the variables sent in an object update packet for objects.
- /// Used to track position and movement of prims and avatars
- /// </summary>
- public struct ObjectMovementUpdate
- {
- /// <summary></summary>
- public bool Avatar;
- /// <summary></summary>
- public Vector4 CollisionPlane;
- /// <summary></summary>
- public byte State;
- /// <summary></summary>
- public uint LocalID;
- /// <summary></summary>
- public Vector3 Position;
- /// <summary></summary>
- public Vector3 Velocity;
- /// <summary></summary>
- public Vector3 Acceleration;
- /// <summary></summary>
- public Quaternion Rotation;
- /// <summary></summary>
- public Vector3 AngularVelocity;
- /// <summary></summary>
- public Primitive.TextureEntry Textures;
- }
- #endregion Structs
- /// <summary>
- /// Handles all network traffic related to prims and avatar positions and
- /// movement.
- /// </summary>
- public class ObjectManager
- {
- public const float HAVOK_TIMESTEP = 1.0f / 45.0f;
- #region Delegates
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<PrimEventArgs> m_ObjectUpdate;
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ObjectUpdateLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// A <see cref="Primitive"/>, Foliage or Attachment</summary>
- /// <seealso cref="RequestObject"/>
- /// <seealso cref="RequestObjects"/>
- public event EventHandler<PrimEventArgs> ObjectUpdate
- {
- add { lock (m_ObjectUpdateLock) { m_ObjectUpdate += value; } }
- remove { lock (m_ObjectUpdateLock) { m_ObjectUpdate -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<ObjectPropertiesEventArgs> m_ObjectProperties;
- ///<summary>Raises the ObjectProperties Event</summary>
- /// <param name="e">A ObjectPropertiesEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnObjectProperties(ObjectPropertiesEventArgs e)
- {
- EventHandler<ObjectPropertiesEventArgs> handler = m_ObjectProperties;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ObjectPropertiesLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// additional <seea cref="Primitive"/> information</summary>
- /// <seealso cref="SelectObject"/>
- /// <seealso cref="SelectObjects"/>
- public event EventHandler<ObjectPropertiesEventArgs> ObjectProperties
- {
- add { lock (m_ObjectPropertiesLock) { m_ObjectProperties += value; } }
- remove { lock (m_ObjectPropertiesLock) { m_ObjectProperties -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<ObjectPropertiesUpdatedEventArgs> m_ObjectPropertiesUpdated;
- ///<summary>Raises the ObjectPropertiesUpdated Event</summary>
- /// <param name="e">A ObjectPropertiesUpdatedEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnObjectPropertiesUpdated(ObjectPropertiesUpdatedEventArgs e)
- {
- EventHandler<ObjectPropertiesUpdatedEventArgs> handler = m_ObjectPropertiesUpdated;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ObjectPropertiesUpdatedLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// Primitive.ObjectProperties for an object we are currently tracking</summary>
- public event EventHandler<ObjectPropertiesUpdatedEventArgs> ObjectPropertiesUpdated
- {
- add { lock (m_ObjectPropertiesUpdatedLock) { m_ObjectPropertiesUpdated += value; } }
- remove { lock (m_ObjectPropertiesUpdatedLock) { m_ObjectPropertiesUpdated -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<ObjectPropertiesFamilyEventArgs> m_ObjectPropertiesFamily;
- ///<summary>Raises the ObjectPropertiesFamily Event</summary>
- /// <param name="e">A ObjectPropertiesFamilyEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnObjectPropertiesFamily(ObjectPropertiesFamilyEventArgs e)
- {
- EventHandler<ObjectPropertiesFamilyEventArgs> handler = m_ObjectPropertiesFamily;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ObjectPropertiesFamilyLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// additional <seea cref="Primitive"/> and <see cref="Avatar"/> details</summary>
- /// <seealso cref="RequestObjectPropertiesFamily"/>
- public event EventHandler<ObjectPropertiesFamilyEventArgs> ObjectPropertiesFamily
- {
- add { lock (m_ObjectPropertiesFamilyLock) { m_ObjectPropertiesFamily += value; } }
- remove { lock (m_ObjectPropertiesFamilyLock) { m_ObjectPropertiesFamily -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<AvatarUpdateEventArgs> m_AvatarUpdate;
- ///<summary>Raises the AvatarUpdate Event</summary>
- /// <param name="e">A AvatarUpdateEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnAvatarUpdate(AvatarUpdateEventArgs e)
- {
- EventHandler<AvatarUpdateEventArgs> handler = m_AvatarUpdate;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_AvatarUpdateLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// updated information for an <see cref="Avatar"/></summary>
- public event EventHandler<AvatarUpdateEventArgs> AvatarUpdate
- {
- add { lock (m_AvatarUpdateLock) { m_AvatarUpdate += value; } }
- remove { lock (m_AvatarUpdateLock) { m_AvatarUpdate -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<TerseObjectUpdateEventArgs> m_TerseObjectUpdate;
- /// <summary>Thread sync lock object</summary>
- private readonly object m_TerseObjectUpdateLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// <see cref="Primitive"/> and <see cref="Avatar"/> movement changes</summary>
- public event EventHandler<TerseObjectUpdateEventArgs> TerseObjectUpdate
- {
- add { lock (m_TerseObjectUpdateLock) { m_TerseObjectUpdate += value; } }
- remove { lock (m_TerseObjectUpdateLock) { m_TerseObjectUpdate -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<ObjectDataBlockUpdateEventArgs> m_ObjectDataBlockUpdate;
- ///<summary>Raises the ObjectDataBlockUpdate Event</summary>
- /// <param name="e">A ObjectDataBlockUpdateEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnObjectDataBlockUpdate(ObjectDataBlockUpdateEventArgs e)
- {
- EventHandler<ObjectDataBlockUpdateEventArgs> handler = m_ObjectDataBlockUpdate;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_ObjectDataBlockUpdateLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// updates to an Objects DataBlock</summary>
- public event EventHandler<ObjectDataBlockUpdateEventArgs> ObjectDataBlockUpdate
- {
- add { lock (m_ObjectDataBlockUpdateLock) { m_ObjectDataBlockUpdate += value; } }
- remove { lock (m_ObjectDataBlockUpdateLock) { m_ObjectDataBlockUpdate -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<KillObjectEventArgs> m_KillObject;
- ///<summary>Raises the KillObject Event</summary>
- /// <param name="e">A KillObjectEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnKillObject(KillObjectEventArgs e)
- {
- EventHandler<KillObjectEventArgs> handler = m_KillObject;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_KillObjectLock = new object();
- /// <summary>Raised when the simulator informs us an <see cref="Primitive"/>
- /// or <see cref="Avatar"/> is no longer within view</summary>
- public event EventHandler<KillObjectEventArgs> KillObject
- {
- add { lock (m_KillObjectLock) { m_KillObject += value; } }
- remove { lock (m_KillObjectLock) { m_KillObject -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<AvatarSitChangedEventArgs> m_AvatarSitChanged;
- ///<summary>Raises the AvatarSitChanged Event</summary>
- /// <param name="e">A AvatarSitChangedEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnAvatarSitChanged(AvatarSitChangedEventArgs e)
- {
- EventHandler<AvatarSitChangedEventArgs> handler = m_AvatarSitChanged;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_AvatarSitChangedLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// updated sit information for our <see cref="Avatar"/></summary>
- public event EventHandler<AvatarSitChangedEventArgs> AvatarSitChanged
- {
- add { lock (m_AvatarSitChangedLock) { m_AvatarSitChanged += value; } }
- remove { lock (m_AvatarSitChangedLock) { m_AvatarSitChanged -= value; } }
- }
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<PayPriceReplyEventArgs> m_PayPriceReply;
- ///<summary>Raises the PayPriceReply Event</summary>
- /// <param name="e">A PayPriceReplyEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnPayPriceReply(PayPriceReplyEventArgs e)
- {
- EventHandler<PayPriceReplyEventArgs> handler = m_PayPriceReply;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_PayPriceReplyLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// purchase price information for a <see cref="Primitive"/></summary>
- public event EventHandler<PayPriceReplyEventArgs> PayPriceReply
- {
- add { lock (m_PayPriceReplyLock) { m_PayPriceReply += value; } }
- remove { lock (m_PayPriceReplyLock) { m_PayPriceReply -= value; } }
- }
- /// <summary>
- /// Callback for getting object media data via CAP
- /// </summary>
- /// <param name="success">Indicates if the operation was succesfull</param>
- /// <param name="version">Object media version string</param>
- /// <param name="faceMedia">Array indexed on prim face of media entry data</param>
- public delegate void ObjectMediaCallback(bool success, string version, MediaEntry[] faceMedia);
- /// <summary>The event subscribers, null of no subscribers</summary>
- private EventHandler<PhysicsPropertiesEventArgs> m_PhysicsProperties;
- ///<summary>Raises the PhysicsProperties Event</summary>
- /// <param name="e">A PhysicsPropertiesEventArgs object containing
- /// the data sent from the simulator</param>
- protected virtual void OnPhysicsProperties(PhysicsPropertiesEventArgs e)
- {
- EventHandler<PhysicsPropertiesEventArgs> handler = m_PhysicsProperties;
- if (handler != null)
- handler(this, e);
- }
- /// <summary>Thread sync lock object</summary>
- private readonly object m_PhysicsPropertiesLock = new object();
- /// <summary>Raised when the simulator sends us data containing
- /// additional <seea cref="Primitive"/> information</summary>
- /// <seealso cref="SelectObject"/>
- /// <seealso cref="SelectObjects"/>
- public event EventHandler<PhysicsPropertiesEventArgs> PhysicsProperties
- {
- add { lock (m_PhysicsPropertiesLock) { m_PhysicsProperties += value; } }
- remove { lock (m_PhysicsPropertiesLock) { m_PhysicsProperties -= value; } }
- }
- #endregion Delegates
- /// <summary>Reference to the GridClient object</summary>
- protected GridClient Client;
- /// <summary>Does periodic dead reckoning calculation to convert
- /// velocity and acceleration to new positions for objects</summary>
- private Timer InterpolationTimer;
- /// <summary>
- /// Construct a new instance of the ObjectManager class
- /// </summary>
- /// <param name="client">A reference to the <see cref="GridClient"/> instance</param>
- public ObjectManager(GridClient client)
- {
- Client = client;
- Client.Network.RegisterCallback(PacketType.ObjectUpdate, ObjectUpdateHandler, false);
- Client.Network.RegisterCallback(PacketType.ImprovedTerseObjectUpdate, ImprovedTerseObjectUpdateHandler, false);
- Client.Network.RegisterCallback(PacketType.ObjectUpdateCompressed, ObjectUpdateCompressedHandler);
- Client.Network.RegisterCallback(PacketType.ObjectUpdateCached, ObjectUpdateCachedHandler);
- Client.Network.RegisterCallback(PacketType.KillObject, KillObjectHandler);
- Client.Network.RegisterCallback(PacketType.ObjectPropertiesFamily, ObjectPropertiesFamilyHandler);
- Client.Network.RegisterCallback(PacketType.ObjectProperties, ObjectPropertiesHandler);
- Client.Network.RegisterCallback(PacketType.PayPriceReply, PayPriceReplyHandler);
- Client.Network.RegisterEventCallback("ObjectPhysicsProperties", ObjectPhysicsPropertiesHandler);
- }
- #region Internal event handlers
- private void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
- {
- if (InterpolationTimer != null)
- {
- InterpolationTimer.Dispose();
- InterpolationTimer = null;
- }
- }
- private void Network_OnConnected(object sender)
- {
- if (Client.Settings.USE_INTERPOLATION_TIMER)
- {
- InterpolationTimer = new Timer(InterpolationTimer_Elapsed, null, Settings.INTERPOLATION_INTERVAL, Timeout.Infinite);
- }
- }
- #endregion Internal event handlers
- #region Public Methods
- /// <summary>
- /// Request information for a single object from a <see cref="Simulator"/>
- /// you are currently connected to
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- public void RequestObject(Simulator simulator, uint localID)
- {
- RequestMultipleObjectsPacket request = new RequestMultipleObjectsPacket();
- request.AgentData.AgentID = Client.Self.AgentID;
- request.AgentData.SessionID = Client.Self.SessionID;
- request.ObjectData = new RequestMultipleObjectsPacket.ObjectDataBlock[1];
- request.ObjectData[0] = new RequestMultipleObjectsPacket.ObjectDataBlock();
- request.ObjectData[0].ID = localID;
- request.ObjectData[0].CacheMissType = 0;
- Client.Network.SendPacket(request, simulator);
- }
- /// <summary>
- /// Request information for multiple objects contained in
- /// the same simulator
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
- /// <param name="localIDs">An array containing the Local IDs of the objects</param>
- public void RequestObjects(Simulator simulator, List<uint> localIDs)
- {
- RequestMultipleObjectsPacket request = new RequestMultipleObjectsPacket();
- request.AgentData.AgentID = Client.Self.AgentID;
- request.AgentData.SessionID = Client.Self.SessionID;
- request.ObjectData = new RequestMultipleObjectsPacket.ObjectDataBlock[localIDs.Count];
- for (int i = 0; i < localIDs.Count; i++)
- {
- request.ObjectData[i] = new RequestMultipleObjectsPacket.ObjectDataBlock();
- request.ObjectData[i].ID = localIDs[i];
- request.ObjectData[i].CacheMissType = 0;
- }
- Client.Network.SendPacket(request, simulator);
- }
- /// <summary>
- /// Attempt to purchase an original object, a copy, or the contents of
- /// an object
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- /// <param name="saleType">Whether the original, a copy, or the object
- /// contents are on sale. This is used for verification, if the this
- /// sale type is not valid for the object the purchase will fail</param>
- /// <param name="price">Price of the object. This is used for
- /// verification, if it does not match the actual price the purchase
- /// will fail</param>
- /// <param name="groupID">Group ID that will be associated with the new
- /// purchase</param>
- /// <param name="categoryID">Inventory folder UUID where the object or objects
- /// purchased should be placed</param>
- /// <example>
- /// <code>
- /// BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy,
- /// 100, UUID.Zero, Client.Self.InventoryRootFolderUUID);
- /// </code>
- ///</example>
- public void BuyObject(Simulator simulator, uint localID, SaleType saleType, int price, UUID groupID,
- UUID categoryID)
- {
- ObjectBuyPacket buy = new ObjectBuyPacket();
- buy.AgentData.AgentID = Client.Self.AgentID;
- buy.AgentData.SessionID = Client.Self.SessionID;
- buy.AgentData.GroupID = groupID;
- buy.AgentData.CategoryID = categoryID;
- buy.ObjectData = new ObjectBuyPacket.ObjectDataBlock[1];
- buy.ObjectData[0] = new ObjectBuyPacket.ObjectDataBlock();
- buy.ObjectData[0].ObjectLocalID = localID;
- buy.ObjectData[0].SaleType = (byte)saleType;
- buy.ObjectData[0].SalePrice = price;
- Client.Network.SendPacket(buy, simulator);
- }
- /// <summary>
- /// Request prices that should be displayed in pay dialog. This will triggger the simulator
- /// to send us back a PayPriceReply which can be handled by OnPayPriceReply event
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="objectID">The ID of the object</param>
- /// <remarks>The result is raised in the <see cref="PayPriceReply"/> event</remarks>
- public void RequestPayPrice(Simulator simulator, UUID objectID)
- {
- RequestPayPricePacket payPriceRequest = new RequestPayPricePacket();
- payPriceRequest.ObjectData = new RequestPayPricePacket.ObjectDataBlock();
- payPriceRequest.ObjectData.ObjectID = objectID;
- Client.Network.SendPacket(payPriceRequest, simulator);
- }
- /// <summary>
- /// Select a single object. This will cause the <see cref="Simulator"/> to send us
- /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
- public void SelectObject(Simulator simulator, uint localID)
- {
- SelectObject(simulator, localID, true);
- }
- /// <summary>
- /// Select a single object. This will cause the <see cref="Simulator"/> to send us
- /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- /// <param name="automaticDeselect">if true, a call to <see cref="DeselectObject"/> is
- /// made immediately following the request</param>
- /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
- public void SelectObject(Simulator simulator, uint localID, bool automaticDeselect)
- {
- ObjectSelectPacket select = new ObjectSelectPacket();
- select.AgentData.AgentID = Client.Self.AgentID;
- select.AgentData.SessionID = Client.Self.SessionID;
- select.ObjectData = new ObjectSelectPacket.ObjectDataBlock[1];
- select.ObjectData[0] = new ObjectSelectPacket.ObjectDataBlock();
- select.ObjectData[0].ObjectLocalID = localID;
- Client.Network.SendPacket(select, simulator);
- if (automaticDeselect)
- {
- DeselectObject(simulator, localID);
- }
- }
- /// <summary>
- /// Select multiple objects. This will cause the <see cref="Simulator"/> to send us
- /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
- /// <param name="localIDs">An array containing the Local IDs of the objects</param>
- /// <param name="automaticDeselect">Should objects be deselected immediately after selection</param>
- /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
- public void SelectObjects(Simulator simulator, uint[] localIDs, bool automaticDeselect)
- {
- ObjectSelectPacket select = new ObjectSelectPacket();
- select.AgentData.AgentID = Client.Self.AgentID;
- select.AgentData.SessionID = Client.Self.SessionID;
- select.ObjectData = new ObjectSelectPacket.ObjectDataBlock[localIDs.Length];
- for (int i = 0; i < localIDs.Length; i++)
- {
- select.ObjectData[i] = new ObjectSelectPacket.ObjectDataBlock();
- select.ObjectData[i].ObjectLocalID = localIDs[i];
- }
- Client.Network.SendPacket(select, simulator);
- if (automaticDeselect)
- {
- DeselectObjects(simulator, localIDs);
- }
- }
- /// <summary>
- /// Select multiple objects. This will cause the <see cref="Simulator"/> to send us
- /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
- /// <param name="localIDs">An array containing the Local IDs of the objects</param>
- /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
- public void SelectObjects(Simulator simulator, uint[] localIDs)
- {
- SelectObjects(simulator, localIDs, true);
- }
- /// <summary>
- /// Update the properties of an object
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- /// <param name="physical">true to turn the objects physical property on</param>
- /// <param name="temporary">true to turn the objects temporary property on</param>
- /// <param name="phantom">true to turn the objects phantom property on</param>
- /// <param name="castsShadow">true to turn the objects cast shadows property on</param>
- public void SetFlags(Simulator simulator, uint localID, bool physical, bool temporary, bool phantom, bool castsShadow)
- {
- SetFlags(simulator, localID, physical, temporary, phantom, castsShadow, PhysicsShapeType.Prim, 1000f, 0.6f, 0.5f, 1f);
- }
- /// <summary>
- /// Update the properties of an object
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- /// <param name="physical">true to turn the objects physical property on</param>
- /// <param name="temporary">true to turn the objects temporary property on</param>
- /// <param name="phantom">true to turn the objects phantom property on</param>
- /// <param name="castsShadow">true to turn the objects cast shadows property on</param>
- /// <param name="physicsType">Type of the represetnation prim will have in the physics engine</param>
- /// <param name="density">Density - normal value 1000</param>
- /// <param name="friction">Friction - normal value 0.6</param>
- /// <param name="restitution">Restitution - standard value 0.5</param>
- /// <param name="gravityMultiplier">Gravity multiplier - standar value 1.0</param>
- public void SetFlags(Simulator simulator, uint localID, bool physical, bool temporary, bool phantom, bool castsShadow,
- PhysicsShapeType physicsType, float density, float friction, float restitution, float gravityMultiplier)
- {
- ObjectFlagUpdatePacket flags = new ObjectFlagUpdatePacket();
- flags.AgentData.AgentID = Client.Self.AgentID;
- flags.AgentData.SessionID = Client.Self.SessionID;
- flags.AgentData.ObjectLocalID = localID;
- flags.AgentData.UsePhysics = physical;
- flags.AgentData.IsTemporary = temporary;
- flags.AgentData.IsPhantom = phantom;
- flags.AgentData.CastsShadows = castsShadow;
- flags.ExtraPhysics = new ObjectFlagUpdatePacket.ExtraPhysicsBlock[1];
- flags.ExtraPhysics[0] = new ObjectFlagUpdatePacket.ExtraPhysicsBlock();
- flags.ExtraPhysics[0].PhysicsShapeType = (byte)physicsType;
- flags.ExtraPhysics[0].Density = density;
- flags.ExtraPhysics[0].Friction = friction;
- flags.ExtraPhysics[0].Restitution = restitution;
- flags.ExtraPhysics[0].GravityMultiplier = gravityMultiplier;
- Client.Network.SendPacket(flags, simulator);
- }
- /// <summary>
- /// Sets the sale properties of a single object
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- /// <param name="saleType">One of the options from the <see cref="SaleType"/> enum</param>
- /// <param name="price">The price of the object</param>
- public void SetSaleInfo(Simulator simulator, uint localID, SaleType saleType, int price)
- {
- ObjectSaleInfoPacket sale = new ObjectSaleInfoPacket();
- sale.AgentData.AgentID = Client.Self.AgentID;
- sale.AgentData.SessionID = Client.Self.SessionID;
- sale.ObjectData = new ObjectSaleInfoPacket.ObjectDataBlock[1];
- sale.ObjectData[0] = new ObjectSaleInfoPacket.ObjectDataBlock();
- sale.ObjectData[0].LocalID = localID;
- sale.ObjectData[0].SalePrice = price;
- sale.ObjectData[0].SaleType = (byte)saleType;
- Client.Network.SendPacket(sale, simulator);
- }
- /// <summary>
- /// Sets the sale properties of multiple objects
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
- /// <param name="localIDs">An array containing the Local IDs of the objects</param>
- /// <param name="saleType">One of the options from the <see cref="SaleType"/> enum</param>
- /// <param name="price">The price of the object</param>
- public void SetSaleInfo(Simulator simulator, List<uint> localIDs, SaleType saleType, int price)
- {
- ObjectSaleInfoPacket sale = new ObjectSaleInfoPacket();
- sale.AgentData.AgentID = Client.Self.AgentID;
- sale.AgentData.SessionID = Client.Self.SessionID;
- sale.ObjectData = new ObjectSaleInfoPacket.ObjectDataBlock[localIDs.Count];
- for (int i = 0; i < localIDs.Count; i++)
- {
- sale.ObjectData[i] = new ObjectSaleInfoPacket.ObjectDataBlock();
- sale.ObjectData[i].LocalID = localIDs[i];
- sale.ObjectData[i].SalePrice = price;
- sale.ObjectData[i].SaleType = (byte)saleType;
- }
- Client.Network.SendPacket(sale, simulator);
- }
- /// <summary>
- /// Deselect a single object
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- public void DeselectObject(Simulator simulator, uint localID)
- {
- ObjectDeselectPacket deselect = new ObjectDeselectPacket();
- deselect.AgentData.AgentID = Client.Self.AgentID;
- deselect.AgentData.SessionID = Client.Self.SessionID;
- deselect.ObjectData = new ObjectDeselectPacket.ObjectDataBlock[1];
- deselect.ObjectData[0] = new ObjectDeselectPacket.ObjectDataBlock();
- deselect.ObjectData[0].ObjectLocalID = localID;
- Client.Network.SendPacket(deselect, simulator);
- }
- /// <summary>
- /// Deselect multiple objects.
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
- /// <param name="localIDs">An array containing the Local IDs of the objects</param>
- public void DeselectObjects(Simulator simulator, uint[] localIDs)
- {
- ObjectDeselectPacket deselect = new ObjectDeselectPacket();
- deselect.AgentData.AgentID = Client.Self.AgentID;
- deselect.AgentData.SessionID = Client.Self.SessionID;
- deselect.ObjectData = new ObjectDeselectPacket.ObjectDataBlock[localIDs.Length];
- for (int i = 0; i < localIDs.Length; i++)
- {
- deselect.ObjectData[i] = new ObjectDeselectPacket.ObjectDataBlock();
- deselect.ObjectData[i].ObjectLocalID = localIDs[i];
- }
- Client.Network.SendPacket(deselect, simulator);
- }
- /// <summary>
- /// Perform a click action on an object
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- public void ClickObject(Simulator simulator, uint localID)
- {
- ClickObject(simulator, localID, Vector3.Zero, Vector3.Zero, 0, Vector3.Zero, Vector3.Zero, Vector3.Zero);
- }
- /// <summary>
- /// Perform a click action (Grab) on a single object
- /// </summary>
- /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
- /// <param name="localID">The Local ID of the object</param>
- /// <param name="uvCoord">The texture coordinates to touch</param>
- /// <param name="stCoord">The surface coordinates to touch</param>
- /// <param name="faceIndex">The face of the position to touch</param>
- /// <param name="position">The region coordinates of the position to touch</param>
- /// <param name="normal">The surface normal of the position to touch (A normal is a vector perpindicular to the surface)</param>
- /// <param name="binormal">The surface binormal of the position to touch (A binormal is a vector tangen to the surface
- /// pointing along the U direction of the tangent space</param>
- public void ClickObject(Simulator simulator, uint localID, Vector3 uvCoord, Vector3 stCoord, int faceIndex, Vector3 position,
- Vector3 normal, Vector3 binormal)
- {
- ObjectGrabPacket grab = new ObjectGrabPacket();
- grab.AgentData.AgentID = Client.Self.AgentID;
- grab.AgentData.SessionID = Client.Self.SessionID;
- grab.ObjectData.GrabOffset = Vector3.Zero;
- grab.ObjectData.LocalID = localID;
- grab.SurfaceInfo = new ObjectGrabPacket.SurfaceInfoBlock[1];
- grab.SurfaceInfo[0] = new ObjectGrabPacket.SurfaceInfoBlock();
- grab.SurfaceInfo[0].UVCoord = uvCoord;
- grab.SurfaceInfo[0].STCoord = stCoord;
- grab.SurfaceInfo[0].FaceIndex = faceIndex;
- grab.SurfaceInfo[0].Position = position;
- grab.SurfaceInfo[0].Normal = normal;
- grab.SurfaceInfo[0].Binormal = binormal;
- Client.Network.SendPacket(grab, simulator);
- // TODO: If these hit the server out of order the click will fail
- // and we'll be grabbing the object
- Thread.Sleep(50);
- ObjectDeGrabPacket degrab = new ObjectDeGrabPacket();
- degrab.AgentData.AgentID = Client.Self.AgentID;
- degrab.AgentData.SessionID = Client.Self.SessionID;
- degrab.ObjectData.LocalID = localID;
- degrab.SurfaceInfo = new ObjectDeGrabPacket.SurfaceInfoBlock[1];
- degrab.SurfaceInfo[0] = new ObjectDeGrabPacket.SurfaceInfoBlock();
- degrab.SurfaceInfo[0].UVCoord = uvCoord;
- degrab.SurfaceInfo[0].STCoord = stCoord;
- degrab.SurfaceInfo[0].FaceIndex = faceIndex;
- degrab.SurfaceInfo[0].Position = position;
- degrab.SurfaceInfo[0].Normal = normal;
- degrab.SurfaceInfo[0].Binormal = binormal;
- Client.Network.SendPacket(degrab, simulator);
- }
- /// <summary>
- /// Create (rez) a new prim object in a simulator
- /// </summary>
- /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object to place the object in</param>
- /// <param name="prim">Data describing the prim object to rez</param>
- /// <param name="groupID">Group ID that this prim will be set to, or UUID.Zero if you
- /// do not want the object to be associated with a specific group</param>
- /// <param name="position">An approximation of the position at which to rez the prim</param>
- /// <param name="scale">Scale vector to size this prim</param>
- /// <param name="rotation">Rotation quaternion to rotate this prim</param>
- /// <remarks>Due to the way client prim rezzing is done on the server,
- /// the requested position for an object is only close to where the prim
- /// actually ends up. If you desire exact placement you'll need to
- /// follow up by moving the object after it has been created. This
- /// function will not set textures, light and flexible data, or other
- /// extended primitive properties</remarks>
- public void AddPrim(Simulator simulator, Primitive.ConstructionData prim, UUID groupID, Vector3 position,
- Vector3 scale, Quaternion rotation)
- {
- AddPrim(simulator, prim, groupID, position, scale, rotation, PrimFlags.CreateSelected);
- }
- /// <summary>
- /// Create (rez) a new prim object in a simulator
- /// </summary>
- /// <param name="simulator">A reference to the <seealso cref="Simulator"/> object to place the object in</param>
- /// <param name="prim">Data describing the prim object to rez</param>
- /// <param name="groupID">Group ID that this prim will be set to, or UUID.Zero if you
- /// do not want the object to be associated with a specific group</param>
- /// <param name="position">An approximation of the position at which to rez the prim</param>
- /// <param name="scale">Scale vector to size this prim</param>
- /// <param name="rotation">Rotation quaternion to rotate this prim</param>
- /// <param name="createFlags">Specify the <seealso cref="PrimFlags"/></param>
- /// <remarks>Due to the way client prim rezzing is done on the server,
- /// the requested position for an object is only close to where the prim
- /// actually ends up. If you desire exact placement you'll need to
- /// follow up by moving the object after it has been created. This
- /// function will not set textures, light and flexible data, or other
- /// extended primitive properties</remarks>
- public void AddPrim(Simulator simulator, Primitive.ConstructionData prim, UUID groupID, Vector3 position,
- Vector3 scale, Quaternion rotation, PrimFlags createFlags)
- {
- ObjectAddPacket packet = new ObjectAddPacket();
- packet.AgentData.AgentID = Client.Self.AgentID;
- packet.AgentData.SessionID = Client.Self.SessionID;
- packet.AgentData.GroupID = groupID;
- packet.ObjectData.State = prim.State;
- packet.ObjectData.AddFlags = (uint)createFlags;
- packet.ObjectData.PCode = (byte)PCode.Prim;
- packet.ObjectData.Material = (byte)prim.Material;
- packet.ObjectData.Scale = scale;
- packet.ObjectData.Rotation = rotation;
- packet.ObjectData.PathCurve = (byte)prim.PathCurve;
- packet.ObjectData.PathBegin = Primitive.PackBeginCut(prim.PathBegin);
- packet.ObjectData.PathEnd = Primitive.PackEndCut(prim.PathEnd);
- packet.ObjectData.PathRadiusOffset = Primitive.PackPathTwist(prim.PathRadiusOffset);
- packet.ObjectData.PathRevolutions = Primitive.PackPathRevolutions(prim.PathRevolutions);
- packet.ObjectData.PathScaleX = Primitive.PackPathScale(prim.PathScaleX);
- packet.ObjectData.PathScaleY = Primitive.PackPathScale(prim.PathScaleY);
- packet.ObjectData.PathShearX = (byte)Primitive.PackPathShear(prim.PathShearX);
- packet.ObjectData.PathShearY = (byte)Primitive.PackPathShear(prim.PathShearY);
- packet.ObjectData.PathSkew = Primitive.PackPathTwist(prim.PathSkew);
- packet.ObjectData.PathTaperX = Primitive.PackPathTaper(prim.PathTaperX);
- packet.ObjectData.PathTaperY = Primitive.PackPathTaper(prim.PathTaperY);
- packet.ObjectData.PathTwist = Primitive.PackPathTwist(prim.PathTwist);
- packet.ObjectData.PathTwistBegin = Primitive.PackPathTwist(prim.PathTwistBegin);
- packet.ObjectData.ProfileCurve = prim.profileCurve;
- packet.ObjectData.ProfileBegin = Primitive.PackBeginCut(prim.ProfileBegin);
- packet.ObjectData.ProfileEnd = Primitive.PackEndCut(prim.ProfileEnd);
- packet.ObjectData.ProfileHollow = Primitive.PackProfileHollow(prim.ProfileHollow);
- packet.ObjectData.RayStart = position;
- packet.ObjectData.RayEnd = position;
- packet.ObjectData.RayEndIsIntersection = 0;
- packet.ObjectData.RayTargetID = UUID.Zero;
- packet.ObjectData.BypassRaycast = 1;
- Client.Network.SendPacket(packet, simulator);
- }
- /// <summary>
- /// Rez a Linden tree
- /// </summary>
- /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
- /// <param name="scale">The size of the tree</param>
- /// <param name="rotation">The rotation of the tree</param>
- /// <param name="position">The position of the tree</param>
- /// <param name="treeType">The Type of tree</param>
- /// <param name="groupOwner">The <seealso cref="UUID"/> of the group to set the tree to,
- /// or UUID.Zero if no group is to be set</param>
- /// <param name="newTree">true to use the "new" Linden trees, false to use the old</param>
- public void AddTree(Simulator simulator, Vector3 scale, Quaternion rotation, Vector3 position,
- Tree treeType, UUID groupOwner, bool newTree)
- {
- ObjectAddPacket add = new ObjectAddPacket();
- add.AgentData.AgentID = Client.Self.AgentID;
- add.AgentData.SessionID = Client.Self.SessionID;
- add.AgentData.GroupID = groupOwner;
- add.ObjectData.BypassRaycast = 1;
- add.ObjectData.Material = 3;
- add.ObjectData.PathCurve = 16;
- add.ObjectData.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree;
- add.ObjectData.RayEnd = position;
- add.ObjectData.RayStart = position;
- add.ObjectData.RayTargetID = UUID.Zero;
- add.ObjectData.Rotation = rotation;
- add.ObjectData.Scale = scale;
- add.ObjectData.State = (byte)treeType;
- Client.Network.SendPacket(add, simulator);
- }
- /// <summary>
- /// Rez grass and ground cover
- /// </summary>
- /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
- /// <param name="scale">The size of the grass</param>
- /// <param name="rotation">The rotation of the grass</param>
- /// <param name="position">The position of the grass</param>
- /// <param name="grassType">The type of grass from the <seealso cref="Grass"/> enum</param>
- /// <param name="groupOwner">The <seealso cref="UUID"/> of the group to set the tree to,
- /// or UUID.Zero if no group is to be set</param>
- public void AddGrass(Simulator simulator, Vector3 scale, Quaternion rotation, Vector3 position,
- Grass grassType, UUID groupOwner)
- {
- ObjectAddPacket add = new ObjectAddPacket();
- add.AgentData.AgentID = Client.Self.AgentID;
- add.AgentData.SessionID = Client.Self.SessionID;
- add.AgentData.GroupID = groupOwner;
- add.ObjectData.BypassRaycast = 1;
- add.ObjectData.Material = 3;
- add.ObjectData.PathCurve = 16;
- add.ObjectData.PCode = (byte)PCode.Grass;
- add.ObjectData.RayEnd = position;
- add.ObjectData.RayStart = position;
- add.ObjectData.RayTargetID = UUID.Zero;
- add.ObjectData.Rotation = rotation;
- add.ObjectData.Scale = scale;
- add.ObjectData.State = (byte)grassType;
- Client.Network.SendPacket(add, simulator);
- }
- /// <summary>
- /// Set the textures to apply to the faces of an object
- /// </summary>
- /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
- /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
- /// <param name="textures">The texture data to apply</param>
- public void SetTextures(Simulator simulator, uint localID, Primitive.TextureEntry textures)
- {
- SetTextures(simulator, localID, textures, String.Empty);
- }
- /// <summary>
- /// Set the textures to apply to the faces of an object
- /// </summary>
- /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
- /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
- /// <param name="textures">The texture data to apply</param>
- /// <param name="mediaUrl">A media URL (not used)</param>
- public void SetTextures(Simulator simulator, uint localID, Primitive.TextureEntry textures, string mediaUrl)
- {
- …
Large files files are truncated, but you can click here to view the full file