PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/OpenMetaverse/Modules/ObjectManager.cs

https://bitbucket.org/VirtualReality/3rdparty-addon-modules
C# | 3701 lines | 2227 code | 476 blank | 998 comment | 228 complexity | 61a42fa1eb6dc4a06150942dc8c58f3a MD5 | raw file
  1. /*
  2. * Copyright (c) 2006-2009, openmetaverse.org
  3. * All rights reserved.
  4. *
  5. * - Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * - Neither the name of the openmetaverse.org nor the names
  11. * of its contributors may be used to endorse or promote products derived from
  12. * this software without specific prior written permission.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  18. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. using System;
  27. using System.Collections.Generic;
  28. using System.Threading;
  29. using OpenMetaverse.Packets;
  30. using OpenMetaverse.Http;
  31. using OpenMetaverse.StructuredData;
  32. using OpenMetaverse.Interfaces;
  33. using OpenMetaverse.Messages.Linden;
  34. namespace OpenMetaverse
  35. {
  36. #region Enums
  37. /// <summary>
  38. ///
  39. /// </summary>
  40. public enum ReportType : uint
  41. {
  42. /// <summary>No report</summary>
  43. None = 0,
  44. /// <summary>Unknown report type</summary>
  45. Unknown = 1,
  46. /// <summary>Bug report</summary>
  47. Bug = 2,
  48. /// <summary>Complaint report</summary>
  49. Complaint = 3,
  50. /// <summary>Customer service report</summary>
  51. CustomerServiceRequest = 4
  52. }
  53. /// <summary>
  54. /// Bitflag field for ObjectUpdateCompressed data blocks, describing
  55. /// which options are present for each object
  56. /// </summary>
  57. [Flags]
  58. public enum CompressedFlags : uint
  59. {
  60. None = 0x00,
  61. /// <summary>Unknown</summary>
  62. ScratchPad = 0x01,
  63. /// <summary>Whether the object has a TreeSpecies</summary>
  64. Tree = 0x02,
  65. /// <summary>Whether the object has floating text ala llSetText</summary>
  66. HasText = 0x04,
  67. /// <summary>Whether the object has an active particle system</summary>
  68. HasParticles = 0x08,
  69. /// <summary>Whether the object has sound attached to it</summary>
  70. HasSound = 0x10,
  71. /// <summary>Whether the object is attached to a root object or not</summary>
  72. HasParent = 0x20,
  73. /// <summary>Whether the object has texture animation settings</summary>
  74. TextureAnimation = 0x40,
  75. /// <summary>Whether the object has an angular velocity</summary>
  76. HasAngularVelocity = 0x80,
  77. /// <summary>Whether the object has a name value pairs string</summary>
  78. HasNameValues = 0x100,
  79. /// <summary>Whether the object has a Media URL set</summary>
  80. MediaURL = 0x200
  81. }
  82. /// <summary>
  83. /// Specific Flags for MultipleObjectUpdate requests
  84. /// </summary>
  85. [Flags]
  86. public enum UpdateType : uint
  87. {
  88. /// <summary>None</summary>
  89. None = 0x00,
  90. /// <summary>Change position of prims</summary>
  91. Position = 0x01,
  92. /// <summary>Change rotation of prims</summary>
  93. Rotation = 0x02,
  94. /// <summary>Change size of prims</summary>
  95. Scale = 0x04,
  96. /// <summary>Perform operation on link set</summary>
  97. Linked = 0x08,
  98. /// <summary>Scale prims uniformly, same as selecing ctrl+shift in the
  99. /// viewer. Used in conjunction with Scale</summary>
  100. Uniform = 0x10
  101. }
  102. /// <summary>
  103. /// Special values in PayPriceReply. If the price is not one of these
  104. /// literal value of the price should be use
  105. /// </summary>
  106. public enum PayPriceType : int
  107. {
  108. /// <summary>
  109. /// Indicates that this pay option should be hidden
  110. /// </summary>
  111. Hide = -1,
  112. /// <summary>
  113. /// Indicates that this pay option should have the default value
  114. /// </summary>
  115. Default = -2
  116. }
  117. #endregion Enums
  118. #region Structs
  119. /// <summary>
  120. /// Contains the variables sent in an object update packet for objects.
  121. /// Used to track position and movement of prims and avatars
  122. /// </summary>
  123. public struct ObjectMovementUpdate
  124. {
  125. /// <summary></summary>
  126. public bool Avatar;
  127. /// <summary></summary>
  128. public Vector4 CollisionPlane;
  129. /// <summary></summary>
  130. public byte State;
  131. /// <summary></summary>
  132. public uint LocalID;
  133. /// <summary></summary>
  134. public Vector3 Position;
  135. /// <summary></summary>
  136. public Vector3 Velocity;
  137. /// <summary></summary>
  138. public Vector3 Acceleration;
  139. /// <summary></summary>
  140. public Quaternion Rotation;
  141. /// <summary></summary>
  142. public Vector3 AngularVelocity;
  143. /// <summary></summary>
  144. public Primitive.TextureEntry Textures;
  145. }
  146. #endregion Structs
  147. /// <summary>
  148. /// Handles all network traffic related to prims and avatar positions and
  149. /// movement.
  150. /// </summary>
  151. public class ObjectManager
  152. {
  153. public const float HAVOK_TIMESTEP = 1.0f / 45.0f;
  154. #region Delegates
  155. /// <summary>The event subscribers, null of no subscribers</summary>
  156. private EventHandler<PrimEventArgs> m_ObjectUpdate;
  157. /// <summary>Thread sync lock object</summary>
  158. private readonly object m_ObjectUpdateLock = new object();
  159. /// <summary>Raised when the simulator sends us data containing
  160. /// A <see cref="Primitive"/>, Foliage or Attachment</summary>
  161. /// <seealso cref="RequestObject"/>
  162. /// <seealso cref="RequestObjects"/>
  163. public event EventHandler<PrimEventArgs> ObjectUpdate
  164. {
  165. add { lock (m_ObjectUpdateLock) { m_ObjectUpdate += value; } }
  166. remove { lock (m_ObjectUpdateLock) { m_ObjectUpdate -= value; } }
  167. }
  168. /// <summary>The event subscribers, null of no subscribers</summary>
  169. private EventHandler<ObjectPropertiesEventArgs> m_ObjectProperties;
  170. ///<summary>Raises the ObjectProperties Event</summary>
  171. /// <param name="e">A ObjectPropertiesEventArgs object containing
  172. /// the data sent from the simulator</param>
  173. protected virtual void OnObjectProperties(ObjectPropertiesEventArgs e)
  174. {
  175. EventHandler<ObjectPropertiesEventArgs> handler = m_ObjectProperties;
  176. if (handler != null)
  177. handler(this, e);
  178. }
  179. /// <summary>Thread sync lock object</summary>
  180. private readonly object m_ObjectPropertiesLock = new object();
  181. /// <summary>Raised when the simulator sends us data containing
  182. /// additional <seea cref="Primitive"/> information</summary>
  183. /// <seealso cref="SelectObject"/>
  184. /// <seealso cref="SelectObjects"/>
  185. public event EventHandler<ObjectPropertiesEventArgs> ObjectProperties
  186. {
  187. add { lock (m_ObjectPropertiesLock) { m_ObjectProperties += value; } }
  188. remove { lock (m_ObjectPropertiesLock) { m_ObjectProperties -= value; } }
  189. }
  190. /// <summary>The event subscribers, null of no subscribers</summary>
  191. private EventHandler<ObjectPropertiesUpdatedEventArgs> m_ObjectPropertiesUpdated;
  192. ///<summary>Raises the ObjectPropertiesUpdated Event</summary>
  193. /// <param name="e">A ObjectPropertiesUpdatedEventArgs object containing
  194. /// the data sent from the simulator</param>
  195. protected virtual void OnObjectPropertiesUpdated(ObjectPropertiesUpdatedEventArgs e)
  196. {
  197. EventHandler<ObjectPropertiesUpdatedEventArgs> handler = m_ObjectPropertiesUpdated;
  198. if (handler != null)
  199. handler(this, e);
  200. }
  201. /// <summary>Thread sync lock object</summary>
  202. private readonly object m_ObjectPropertiesUpdatedLock = new object();
  203. /// <summary>Raised when the simulator sends us data containing
  204. /// Primitive.ObjectProperties for an object we are currently tracking</summary>
  205. public event EventHandler<ObjectPropertiesUpdatedEventArgs> ObjectPropertiesUpdated
  206. {
  207. add { lock (m_ObjectPropertiesUpdatedLock) { m_ObjectPropertiesUpdated += value; } }
  208. remove { lock (m_ObjectPropertiesUpdatedLock) { m_ObjectPropertiesUpdated -= value; } }
  209. }
  210. /// <summary>The event subscribers, null of no subscribers</summary>
  211. private EventHandler<ObjectPropertiesFamilyEventArgs> m_ObjectPropertiesFamily;
  212. ///<summary>Raises the ObjectPropertiesFamily Event</summary>
  213. /// <param name="e">A ObjectPropertiesFamilyEventArgs object containing
  214. /// the data sent from the simulator</param>
  215. protected virtual void OnObjectPropertiesFamily(ObjectPropertiesFamilyEventArgs e)
  216. {
  217. EventHandler<ObjectPropertiesFamilyEventArgs> handler = m_ObjectPropertiesFamily;
  218. if (handler != null)
  219. handler(this, e);
  220. }
  221. /// <summary>Thread sync lock object</summary>
  222. private readonly object m_ObjectPropertiesFamilyLock = new object();
  223. /// <summary>Raised when the simulator sends us data containing
  224. /// additional <seea cref="Primitive"/> and <see cref="Avatar"/> details</summary>
  225. /// <seealso cref="RequestObjectPropertiesFamily"/>
  226. public event EventHandler<ObjectPropertiesFamilyEventArgs> ObjectPropertiesFamily
  227. {
  228. add { lock (m_ObjectPropertiesFamilyLock) { m_ObjectPropertiesFamily += value; } }
  229. remove { lock (m_ObjectPropertiesFamilyLock) { m_ObjectPropertiesFamily -= value; } }
  230. }
  231. /// <summary>The event subscribers, null of no subscribers</summary>
  232. private EventHandler<AvatarUpdateEventArgs> m_AvatarUpdate;
  233. ///<summary>Raises the AvatarUpdate Event</summary>
  234. /// <param name="e">A AvatarUpdateEventArgs object containing
  235. /// the data sent from the simulator</param>
  236. protected virtual void OnAvatarUpdate(AvatarUpdateEventArgs e)
  237. {
  238. EventHandler<AvatarUpdateEventArgs> handler = m_AvatarUpdate;
  239. if (handler != null)
  240. handler(this, e);
  241. }
  242. /// <summary>Thread sync lock object</summary>
  243. private readonly object m_AvatarUpdateLock = new object();
  244. /// <summary>Raised when the simulator sends us data containing
  245. /// updated information for an <see cref="Avatar"/></summary>
  246. public event EventHandler<AvatarUpdateEventArgs> AvatarUpdate
  247. {
  248. add { lock (m_AvatarUpdateLock) { m_AvatarUpdate += value; } }
  249. remove { lock (m_AvatarUpdateLock) { m_AvatarUpdate -= value; } }
  250. }
  251. /// <summary>The event subscribers, null of no subscribers</summary>
  252. private EventHandler<TerseObjectUpdateEventArgs> m_TerseObjectUpdate;
  253. /// <summary>Thread sync lock object</summary>
  254. private readonly object m_TerseObjectUpdateLock = new object();
  255. /// <summary>Raised when the simulator sends us data containing
  256. /// <see cref="Primitive"/> and <see cref="Avatar"/> movement changes</summary>
  257. public event EventHandler<TerseObjectUpdateEventArgs> TerseObjectUpdate
  258. {
  259. add { lock (m_TerseObjectUpdateLock) { m_TerseObjectUpdate += value; } }
  260. remove { lock (m_TerseObjectUpdateLock) { m_TerseObjectUpdate -= value; } }
  261. }
  262. /// <summary>The event subscribers, null of no subscribers</summary>
  263. private EventHandler<ObjectDataBlockUpdateEventArgs> m_ObjectDataBlockUpdate;
  264. ///<summary>Raises the ObjectDataBlockUpdate Event</summary>
  265. /// <param name="e">A ObjectDataBlockUpdateEventArgs object containing
  266. /// the data sent from the simulator</param>
  267. protected virtual void OnObjectDataBlockUpdate(ObjectDataBlockUpdateEventArgs e)
  268. {
  269. EventHandler<ObjectDataBlockUpdateEventArgs> handler = m_ObjectDataBlockUpdate;
  270. if (handler != null)
  271. handler(this, e);
  272. }
  273. /// <summary>Thread sync lock object</summary>
  274. private readonly object m_ObjectDataBlockUpdateLock = new object();
  275. /// <summary>Raised when the simulator sends us data containing
  276. /// updates to an Objects DataBlock</summary>
  277. public event EventHandler<ObjectDataBlockUpdateEventArgs> ObjectDataBlockUpdate
  278. {
  279. add { lock (m_ObjectDataBlockUpdateLock) { m_ObjectDataBlockUpdate += value; } }
  280. remove { lock (m_ObjectDataBlockUpdateLock) { m_ObjectDataBlockUpdate -= value; } }
  281. }
  282. /// <summary>The event subscribers, null of no subscribers</summary>
  283. private EventHandler<KillObjectEventArgs> m_KillObject;
  284. ///<summary>Raises the KillObject Event</summary>
  285. /// <param name="e">A KillObjectEventArgs object containing
  286. /// the data sent from the simulator</param>
  287. protected virtual void OnKillObject(KillObjectEventArgs e)
  288. {
  289. EventHandler<KillObjectEventArgs> handler = m_KillObject;
  290. if (handler != null)
  291. handler(this, e);
  292. }
  293. /// <summary>Thread sync lock object</summary>
  294. private readonly object m_KillObjectLock = new object();
  295. /// <summary>Raised when the simulator informs us an <see cref="Primitive"/>
  296. /// or <see cref="Avatar"/> is no longer within view</summary>
  297. public event EventHandler<KillObjectEventArgs> KillObject
  298. {
  299. add { lock (m_KillObjectLock) { m_KillObject += value; } }
  300. remove { lock (m_KillObjectLock) { m_KillObject -= value; } }
  301. }
  302. /// <summary>The event subscribers, null of no subscribers</summary>
  303. private EventHandler<AvatarSitChangedEventArgs> m_AvatarSitChanged;
  304. ///<summary>Raises the AvatarSitChanged Event</summary>
  305. /// <param name="e">A AvatarSitChangedEventArgs object containing
  306. /// the data sent from the simulator</param>
  307. protected virtual void OnAvatarSitChanged(AvatarSitChangedEventArgs e)
  308. {
  309. EventHandler<AvatarSitChangedEventArgs> handler = m_AvatarSitChanged;
  310. if (handler != null)
  311. handler(this, e);
  312. }
  313. /// <summary>Thread sync lock object</summary>
  314. private readonly object m_AvatarSitChangedLock = new object();
  315. /// <summary>Raised when the simulator sends us data containing
  316. /// updated sit information for our <see cref="Avatar"/></summary>
  317. public event EventHandler<AvatarSitChangedEventArgs> AvatarSitChanged
  318. {
  319. add { lock (m_AvatarSitChangedLock) { m_AvatarSitChanged += value; } }
  320. remove { lock (m_AvatarSitChangedLock) { m_AvatarSitChanged -= value; } }
  321. }
  322. /// <summary>The event subscribers, null of no subscribers</summary>
  323. private EventHandler<PayPriceReplyEventArgs> m_PayPriceReply;
  324. ///<summary>Raises the PayPriceReply Event</summary>
  325. /// <param name="e">A PayPriceReplyEventArgs object containing
  326. /// the data sent from the simulator</param>
  327. protected virtual void OnPayPriceReply(PayPriceReplyEventArgs e)
  328. {
  329. EventHandler<PayPriceReplyEventArgs> handler = m_PayPriceReply;
  330. if (handler != null)
  331. handler(this, e);
  332. }
  333. /// <summary>Thread sync lock object</summary>
  334. private readonly object m_PayPriceReplyLock = new object();
  335. /// <summary>Raised when the simulator sends us data containing
  336. /// purchase price information for a <see cref="Primitive"/></summary>
  337. public event EventHandler<PayPriceReplyEventArgs> PayPriceReply
  338. {
  339. add { lock (m_PayPriceReplyLock) { m_PayPriceReply += value; } }
  340. remove { lock (m_PayPriceReplyLock) { m_PayPriceReply -= value; } }
  341. }
  342. /// <summary>
  343. /// Callback for getting object media data via CAP
  344. /// </summary>
  345. /// <param name="success">Indicates if the operation was succesfull</param>
  346. /// <param name="version">Object media version string</param>
  347. /// <param name="faceMedia">Array indexed on prim face of media entry data</param>
  348. public delegate void ObjectMediaCallback(bool success, string version, MediaEntry[] faceMedia);
  349. /// <summary>The event subscribers, null of no subscribers</summary>
  350. private EventHandler<PhysicsPropertiesEventArgs> m_PhysicsProperties;
  351. ///<summary>Raises the PhysicsProperties Event</summary>
  352. /// <param name="e">A PhysicsPropertiesEventArgs object containing
  353. /// the data sent from the simulator</param>
  354. protected virtual void OnPhysicsProperties(PhysicsPropertiesEventArgs e)
  355. {
  356. EventHandler<PhysicsPropertiesEventArgs> handler = m_PhysicsProperties;
  357. if (handler != null)
  358. handler(this, e);
  359. }
  360. /// <summary>Thread sync lock object</summary>
  361. private readonly object m_PhysicsPropertiesLock = new object();
  362. /// <summary>Raised when the simulator sends us data containing
  363. /// additional <seea cref="Primitive"/> information</summary>
  364. /// <seealso cref="SelectObject"/>
  365. /// <seealso cref="SelectObjects"/>
  366. public event EventHandler<PhysicsPropertiesEventArgs> PhysicsProperties
  367. {
  368. add { lock (m_PhysicsPropertiesLock) { m_PhysicsProperties += value; } }
  369. remove { lock (m_PhysicsPropertiesLock) { m_PhysicsProperties -= value; } }
  370. }
  371. #endregion Delegates
  372. /// <summary>Reference to the GridClient object</summary>
  373. protected GridClient Client;
  374. /// <summary>Does periodic dead reckoning calculation to convert
  375. /// velocity and acceleration to new positions for objects</summary>
  376. private Timer InterpolationTimer;
  377. /// <summary>
  378. /// Construct a new instance of the ObjectManager class
  379. /// </summary>
  380. /// <param name="client">A reference to the <see cref="GridClient"/> instance</param>
  381. public ObjectManager(GridClient client)
  382. {
  383. Client = client;
  384. Client.Network.RegisterCallback(PacketType.ObjectUpdate, ObjectUpdateHandler, false);
  385. Client.Network.RegisterCallback(PacketType.ImprovedTerseObjectUpdate, ImprovedTerseObjectUpdateHandler, false);
  386. Client.Network.RegisterCallback(PacketType.ObjectUpdateCompressed, ObjectUpdateCompressedHandler);
  387. Client.Network.RegisterCallback(PacketType.ObjectUpdateCached, ObjectUpdateCachedHandler);
  388. Client.Network.RegisterCallback(PacketType.KillObject, KillObjectHandler);
  389. Client.Network.RegisterCallback(PacketType.ObjectPropertiesFamily, ObjectPropertiesFamilyHandler);
  390. Client.Network.RegisterCallback(PacketType.ObjectProperties, ObjectPropertiesHandler);
  391. Client.Network.RegisterCallback(PacketType.PayPriceReply, PayPriceReplyHandler);
  392. Client.Network.RegisterEventCallback("ObjectPhysicsProperties", ObjectPhysicsPropertiesHandler);
  393. }
  394. #region Internal event handlers
  395. private void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
  396. {
  397. if (InterpolationTimer != null)
  398. {
  399. InterpolationTimer.Dispose();
  400. InterpolationTimer = null;
  401. }
  402. }
  403. private void Network_OnConnected(object sender)
  404. {
  405. if (Client.Settings.USE_INTERPOLATION_TIMER)
  406. {
  407. InterpolationTimer = new Timer(InterpolationTimer_Elapsed, null, Settings.INTERPOLATION_INTERVAL, Timeout.Infinite);
  408. }
  409. }
  410. #endregion Internal event handlers
  411. #region Public Methods
  412. /// <summary>
  413. /// Request information for a single object from a <see cref="Simulator"/>
  414. /// you are currently connected to
  415. /// </summary>
  416. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  417. /// <param name="localID">The Local ID of the object</param>
  418. public void RequestObject(Simulator simulator, uint localID)
  419. {
  420. RequestMultipleObjectsPacket request = new RequestMultipleObjectsPacket();
  421. request.AgentData.AgentID = Client.Self.AgentID;
  422. request.AgentData.SessionID = Client.Self.SessionID;
  423. request.ObjectData = new RequestMultipleObjectsPacket.ObjectDataBlock[1];
  424. request.ObjectData[0] = new RequestMultipleObjectsPacket.ObjectDataBlock();
  425. request.ObjectData[0].ID = localID;
  426. request.ObjectData[0].CacheMissType = 0;
  427. Client.Network.SendPacket(request, simulator);
  428. }
  429. /// <summary>
  430. /// Request information for multiple objects contained in
  431. /// the same simulator
  432. /// </summary>
  433. /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
  434. /// <param name="localIDs">An array containing the Local IDs of the objects</param>
  435. public void RequestObjects(Simulator simulator, List<uint> localIDs)
  436. {
  437. RequestMultipleObjectsPacket request = new RequestMultipleObjectsPacket();
  438. request.AgentData.AgentID = Client.Self.AgentID;
  439. request.AgentData.SessionID = Client.Self.SessionID;
  440. request.ObjectData = new RequestMultipleObjectsPacket.ObjectDataBlock[localIDs.Count];
  441. for (int i = 0; i < localIDs.Count; i++)
  442. {
  443. request.ObjectData[i] = new RequestMultipleObjectsPacket.ObjectDataBlock();
  444. request.ObjectData[i].ID = localIDs[i];
  445. request.ObjectData[i].CacheMissType = 0;
  446. }
  447. Client.Network.SendPacket(request, simulator);
  448. }
  449. /// <summary>
  450. /// Attempt to purchase an original object, a copy, or the contents of
  451. /// an object
  452. /// </summary>
  453. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  454. /// <param name="localID">The Local ID of the object</param>
  455. /// <param name="saleType">Whether the original, a copy, or the object
  456. /// contents are on sale. This is used for verification, if the this
  457. /// sale type is not valid for the object the purchase will fail</param>
  458. /// <param name="price">Price of the object. This is used for
  459. /// verification, if it does not match the actual price the purchase
  460. /// will fail</param>
  461. /// <param name="groupID">Group ID that will be associated with the new
  462. /// purchase</param>
  463. /// <param name="categoryID">Inventory folder UUID where the object or objects
  464. /// purchased should be placed</param>
  465. /// <example>
  466. /// <code>
  467. /// BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy,
  468. /// 100, UUID.Zero, Client.Self.InventoryRootFolderUUID);
  469. /// </code>
  470. ///</example>
  471. public void BuyObject(Simulator simulator, uint localID, SaleType saleType, int price, UUID groupID,
  472. UUID categoryID)
  473. {
  474. ObjectBuyPacket buy = new ObjectBuyPacket();
  475. buy.AgentData.AgentID = Client.Self.AgentID;
  476. buy.AgentData.SessionID = Client.Self.SessionID;
  477. buy.AgentData.GroupID = groupID;
  478. buy.AgentData.CategoryID = categoryID;
  479. buy.ObjectData = new ObjectBuyPacket.ObjectDataBlock[1];
  480. buy.ObjectData[0] = new ObjectBuyPacket.ObjectDataBlock();
  481. buy.ObjectData[0].ObjectLocalID = localID;
  482. buy.ObjectData[0].SaleType = (byte)saleType;
  483. buy.ObjectData[0].SalePrice = price;
  484. Client.Network.SendPacket(buy, simulator);
  485. }
  486. /// <summary>
  487. /// Request prices that should be displayed in pay dialog. This will triggger the simulator
  488. /// to send us back a PayPriceReply which can be handled by OnPayPriceReply event
  489. /// </summary>
  490. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  491. /// <param name="objectID">The ID of the object</param>
  492. /// <remarks>The result is raised in the <see cref="PayPriceReply"/> event</remarks>
  493. public void RequestPayPrice(Simulator simulator, UUID objectID)
  494. {
  495. RequestPayPricePacket payPriceRequest = new RequestPayPricePacket();
  496. payPriceRequest.ObjectData = new RequestPayPricePacket.ObjectDataBlock();
  497. payPriceRequest.ObjectData.ObjectID = objectID;
  498. Client.Network.SendPacket(payPriceRequest, simulator);
  499. }
  500. /// <summary>
  501. /// Select a single object. This will cause the <see cref="Simulator"/> to send us
  502. /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
  503. /// </summary>
  504. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  505. /// <param name="localID">The Local ID of the object</param>
  506. /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
  507. public void SelectObject(Simulator simulator, uint localID)
  508. {
  509. SelectObject(simulator, localID, true);
  510. }
  511. /// <summary>
  512. /// Select a single object. This will cause the <see cref="Simulator"/> to send us
  513. /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
  514. /// </summary>
  515. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  516. /// <param name="localID">The Local ID of the object</param>
  517. /// <param name="automaticDeselect">if true, a call to <see cref="DeselectObject"/> is
  518. /// made immediately following the request</param>
  519. /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
  520. public void SelectObject(Simulator simulator, uint localID, bool automaticDeselect)
  521. {
  522. ObjectSelectPacket select = new ObjectSelectPacket();
  523. select.AgentData.AgentID = Client.Self.AgentID;
  524. select.AgentData.SessionID = Client.Self.SessionID;
  525. select.ObjectData = new ObjectSelectPacket.ObjectDataBlock[1];
  526. select.ObjectData[0] = new ObjectSelectPacket.ObjectDataBlock();
  527. select.ObjectData[0].ObjectLocalID = localID;
  528. Client.Network.SendPacket(select, simulator);
  529. if (automaticDeselect)
  530. {
  531. DeselectObject(simulator, localID);
  532. }
  533. }
  534. /// <summary>
  535. /// Select multiple objects. This will cause the <see cref="Simulator"/> to send us
  536. /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
  537. /// </summary>
  538. /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
  539. /// <param name="localIDs">An array containing the Local IDs of the objects</param>
  540. /// <param name="automaticDeselect">Should objects be deselected immediately after selection</param>
  541. /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
  542. public void SelectObjects(Simulator simulator, uint[] localIDs, bool automaticDeselect)
  543. {
  544. ObjectSelectPacket select = new ObjectSelectPacket();
  545. select.AgentData.AgentID = Client.Self.AgentID;
  546. select.AgentData.SessionID = Client.Self.SessionID;
  547. select.ObjectData = new ObjectSelectPacket.ObjectDataBlock[localIDs.Length];
  548. for (int i = 0; i < localIDs.Length; i++)
  549. {
  550. select.ObjectData[i] = new ObjectSelectPacket.ObjectDataBlock();
  551. select.ObjectData[i].ObjectLocalID = localIDs[i];
  552. }
  553. Client.Network.SendPacket(select, simulator);
  554. if (automaticDeselect)
  555. {
  556. DeselectObjects(simulator, localIDs);
  557. }
  558. }
  559. /// <summary>
  560. /// Select multiple objects. This will cause the <see cref="Simulator"/> to send us
  561. /// an <see cref="ObjectPropertiesPacket"/> which will raise the <see cref="ObjectProperties"/> event
  562. /// </summary>
  563. /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
  564. /// <param name="localIDs">An array containing the Local IDs of the objects</param>
  565. /// <seealso cref="ObjectPropertiesFamilyEventArgs"/>
  566. public void SelectObjects(Simulator simulator, uint[] localIDs)
  567. {
  568. SelectObjects(simulator, localIDs, true);
  569. }
  570. /// <summary>
  571. /// Update the properties of an object
  572. /// </summary>
  573. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  574. /// <param name="localID">The Local ID of the object</param>
  575. /// <param name="physical">true to turn the objects physical property on</param>
  576. /// <param name="temporary">true to turn the objects temporary property on</param>
  577. /// <param name="phantom">true to turn the objects phantom property on</param>
  578. /// <param name="castsShadow">true to turn the objects cast shadows property on</param>
  579. public void SetFlags(Simulator simulator, uint localID, bool physical, bool temporary, bool phantom, bool castsShadow)
  580. {
  581. SetFlags(simulator, localID, physical, temporary, phantom, castsShadow, PhysicsShapeType.Prim, 1000f, 0.6f, 0.5f, 1f);
  582. }
  583. /// <summary>
  584. /// Update the properties of an object
  585. /// </summary>
  586. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  587. /// <param name="localID">The Local ID of the object</param>
  588. /// <param name="physical">true to turn the objects physical property on</param>
  589. /// <param name="temporary">true to turn the objects temporary property on</param>
  590. /// <param name="phantom">true to turn the objects phantom property on</param>
  591. /// <param name="castsShadow">true to turn the objects cast shadows property on</param>
  592. /// <param name="physicsType">Type of the represetnation prim will have in the physics engine</param>
  593. /// <param name="density">Density - normal value 1000</param>
  594. /// <param name="friction">Friction - normal value 0.6</param>
  595. /// <param name="restitution">Restitution - standard value 0.5</param>
  596. /// <param name="gravityMultiplier">Gravity multiplier - standar value 1.0</param>
  597. public void SetFlags(Simulator simulator, uint localID, bool physical, bool temporary, bool phantom, bool castsShadow,
  598. PhysicsShapeType physicsType, float density, float friction, float restitution, float gravityMultiplier)
  599. {
  600. ObjectFlagUpdatePacket flags = new ObjectFlagUpdatePacket();
  601. flags.AgentData.AgentID = Client.Self.AgentID;
  602. flags.AgentData.SessionID = Client.Self.SessionID;
  603. flags.AgentData.ObjectLocalID = localID;
  604. flags.AgentData.UsePhysics = physical;
  605. flags.AgentData.IsTemporary = temporary;
  606. flags.AgentData.IsPhantom = phantom;
  607. flags.AgentData.CastsShadows = castsShadow;
  608. flags.ExtraPhysics = new ObjectFlagUpdatePacket.ExtraPhysicsBlock[1];
  609. flags.ExtraPhysics[0] = new ObjectFlagUpdatePacket.ExtraPhysicsBlock();
  610. flags.ExtraPhysics[0].PhysicsShapeType = (byte)physicsType;
  611. flags.ExtraPhysics[0].Density = density;
  612. flags.ExtraPhysics[0].Friction = friction;
  613. flags.ExtraPhysics[0].Restitution = restitution;
  614. flags.ExtraPhysics[0].GravityMultiplier = gravityMultiplier;
  615. Client.Network.SendPacket(flags, simulator);
  616. }
  617. /// <summary>
  618. /// Sets the sale properties of a single object
  619. /// </summary>
  620. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  621. /// <param name="localID">The Local ID of the object</param>
  622. /// <param name="saleType">One of the options from the <see cref="SaleType"/> enum</param>
  623. /// <param name="price">The price of the object</param>
  624. public void SetSaleInfo(Simulator simulator, uint localID, SaleType saleType, int price)
  625. {
  626. ObjectSaleInfoPacket sale = new ObjectSaleInfoPacket();
  627. sale.AgentData.AgentID = Client.Self.AgentID;
  628. sale.AgentData.SessionID = Client.Self.SessionID;
  629. sale.ObjectData = new ObjectSaleInfoPacket.ObjectDataBlock[1];
  630. sale.ObjectData[0] = new ObjectSaleInfoPacket.ObjectDataBlock();
  631. sale.ObjectData[0].LocalID = localID;
  632. sale.ObjectData[0].SalePrice = price;
  633. sale.ObjectData[0].SaleType = (byte)saleType;
  634. Client.Network.SendPacket(sale, simulator);
  635. }
  636. /// <summary>
  637. /// Sets the sale properties of multiple objects
  638. /// </summary>
  639. /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
  640. /// <param name="localIDs">An array containing the Local IDs of the objects</param>
  641. /// <param name="saleType">One of the options from the <see cref="SaleType"/> enum</param>
  642. /// <param name="price">The price of the object</param>
  643. public void SetSaleInfo(Simulator simulator, List<uint> localIDs, SaleType saleType, int price)
  644. {
  645. ObjectSaleInfoPacket sale = new ObjectSaleInfoPacket();
  646. sale.AgentData.AgentID = Client.Self.AgentID;
  647. sale.AgentData.SessionID = Client.Self.SessionID;
  648. sale.ObjectData = new ObjectSaleInfoPacket.ObjectDataBlock[localIDs.Count];
  649. for (int i = 0; i < localIDs.Count; i++)
  650. {
  651. sale.ObjectData[i] = new ObjectSaleInfoPacket.ObjectDataBlock();
  652. sale.ObjectData[i].LocalID = localIDs[i];
  653. sale.ObjectData[i].SalePrice = price;
  654. sale.ObjectData[i].SaleType = (byte)saleType;
  655. }
  656. Client.Network.SendPacket(sale, simulator);
  657. }
  658. /// <summary>
  659. /// Deselect a single object
  660. /// </summary>
  661. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  662. /// <param name="localID">The Local ID of the object</param>
  663. public void DeselectObject(Simulator simulator, uint localID)
  664. {
  665. ObjectDeselectPacket deselect = new ObjectDeselectPacket();
  666. deselect.AgentData.AgentID = Client.Self.AgentID;
  667. deselect.AgentData.SessionID = Client.Self.SessionID;
  668. deselect.ObjectData = new ObjectDeselectPacket.ObjectDataBlock[1];
  669. deselect.ObjectData[0] = new ObjectDeselectPacket.ObjectDataBlock();
  670. deselect.ObjectData[0].ObjectLocalID = localID;
  671. Client.Network.SendPacket(deselect, simulator);
  672. }
  673. /// <summary>
  674. /// Deselect multiple objects.
  675. /// </summary>
  676. /// <param name="simulator">The <see cref="Simulator"/> the objects are located</param>
  677. /// <param name="localIDs">An array containing the Local IDs of the objects</param>
  678. public void DeselectObjects(Simulator simulator, uint[] localIDs)
  679. {
  680. ObjectDeselectPacket deselect = new ObjectDeselectPacket();
  681. deselect.AgentData.AgentID = Client.Self.AgentID;
  682. deselect.AgentData.SessionID = Client.Self.SessionID;
  683. deselect.ObjectData = new ObjectDeselectPacket.ObjectDataBlock[localIDs.Length];
  684. for (int i = 0; i < localIDs.Length; i++)
  685. {
  686. deselect.ObjectData[i] = new ObjectDeselectPacket.ObjectDataBlock();
  687. deselect.ObjectData[i].ObjectLocalID = localIDs[i];
  688. }
  689. Client.Network.SendPacket(deselect, simulator);
  690. }
  691. /// <summary>
  692. /// Perform a click action on an object
  693. /// </summary>
  694. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  695. /// <param name="localID">The Local ID of the object</param>
  696. public void ClickObject(Simulator simulator, uint localID)
  697. {
  698. ClickObject(simulator, localID, Vector3.Zero, Vector3.Zero, 0, Vector3.Zero, Vector3.Zero, Vector3.Zero);
  699. }
  700. /// <summary>
  701. /// Perform a click action (Grab) on a single object
  702. /// </summary>
  703. /// <param name="simulator">The <see cref="Simulator"/> the object is located</param>
  704. /// <param name="localID">The Local ID of the object</param>
  705. /// <param name="uvCoord">The texture coordinates to touch</param>
  706. /// <param name="stCoord">The surface coordinates to touch</param>
  707. /// <param name="faceIndex">The face of the position to touch</param>
  708. /// <param name="position">The region coordinates of the position to touch</param>
  709. /// <param name="normal">The surface normal of the position to touch (A normal is a vector perpindicular to the surface)</param>
  710. /// <param name="binormal">The surface binormal of the position to touch (A binormal is a vector tangen to the surface
  711. /// pointing along the U direction of the tangent space</param>
  712. public void ClickObject(Simulator simulator, uint localID, Vector3 uvCoord, Vector3 stCoord, int faceIndex, Vector3 position,
  713. Vector3 normal, Vector3 binormal)
  714. {
  715. ObjectGrabPacket grab = new ObjectGrabPacket();
  716. grab.AgentData.AgentID = Client.Self.AgentID;
  717. grab.AgentData.SessionID = Client.Self.SessionID;
  718. grab.ObjectData.GrabOffset = Vector3.Zero;
  719. grab.ObjectData.LocalID = localID;
  720. grab.SurfaceInfo = new ObjectGrabPacket.SurfaceInfoBlock[1];
  721. grab.SurfaceInfo[0] = new ObjectGrabPacket.SurfaceInfoBlock();
  722. grab.SurfaceInfo[0].UVCoord = uvCoord;
  723. grab.SurfaceInfo[0].STCoord = stCoord;
  724. grab.SurfaceInfo[0].FaceIndex = faceIndex;
  725. grab.SurfaceInfo[0].Position = position;
  726. grab.SurfaceInfo[0].Normal = normal;
  727. grab.SurfaceInfo[0].Binormal = binormal;
  728. Client.Network.SendPacket(grab, simulator);
  729. // TODO: If these hit the server out of order the click will fail
  730. // and we'll be grabbing the object
  731. Thread.Sleep(50);
  732. ObjectDeGrabPacket degrab = new ObjectDeGrabPacket();
  733. degrab.AgentData.AgentID = Client.Self.AgentID;
  734. degrab.AgentData.SessionID = Client.Self.SessionID;
  735. degrab.ObjectData.LocalID = localID;
  736. degrab.SurfaceInfo = new ObjectDeGrabPacket.SurfaceInfoBlock[1];
  737. degrab.SurfaceInfo[0] = new ObjectDeGrabPacket.SurfaceInfoBlock();
  738. degrab.SurfaceInfo[0].UVCoord = uvCoord;
  739. degrab.SurfaceInfo[0].STCoord = stCoord;
  740. degrab.SurfaceInfo[0].FaceIndex = faceIndex;
  741. degrab.SurfaceInfo[0].Position = position;
  742. degrab.SurfaceInfo[0].Normal = normal;
  743. degrab.SurfaceInfo[0].Binormal = binormal;
  744. Client.Network.SendPacket(degrab, simulator);
  745. }
  746. /// <summary>
  747. /// Create (rez) a new prim object in a simulator
  748. /// </summary>
  749. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object to place the object in</param>
  750. /// <param name="prim">Data describing the prim object to rez</param>
  751. /// <param name="groupID">Group ID that this prim will be set to, or UUID.Zero if you
  752. /// do not want the object to be associated with a specific group</param>
  753. /// <param name="position">An approximation of the position at which to rez the prim</param>
  754. /// <param name="scale">Scale vector to size this prim</param>
  755. /// <param name="rotation">Rotation quaternion to rotate this prim</param>
  756. /// <remarks>Due to the way client prim rezzing is done on the server,
  757. /// the requested position for an object is only close to where the prim
  758. /// actually ends up. If you desire exact placement you'll need to
  759. /// follow up by moving the object after it has been created. This
  760. /// function will not set textures, light and flexible data, or other
  761. /// extended primitive properties</remarks>
  762. public void AddPrim(Simulator simulator, Primitive.ConstructionData prim, UUID groupID, Vector3 position,
  763. Vector3 scale, Quaternion rotation)
  764. {
  765. AddPrim(simulator, prim, groupID, position, scale, rotation, PrimFlags.CreateSelected);
  766. }
  767. /// <summary>
  768. /// Create (rez) a new prim object in a simulator
  769. /// </summary>
  770. /// <param name="simulator">A reference to the <seealso cref="Simulator"/> object to place the object in</param>
  771. /// <param name="prim">Data describing the prim object to rez</param>
  772. /// <param name="groupID">Group ID that this prim will be set to, or UUID.Zero if you
  773. /// do not want the object to be associated with a specific group</param>
  774. /// <param name="position">An approximation of the position at which to rez the prim</param>
  775. /// <param name="scale">Scale vector to size this prim</param>
  776. /// <param name="rotation">Rotation quaternion to rotate this prim</param>
  777. /// <param name="createFlags">Specify the <seealso cref="PrimFlags"/></param>
  778. /// <remarks>Due to the way client prim rezzing is done on the server,
  779. /// the requested position for an object is only close to where the prim
  780. /// actually ends up. If you desire exact placement you'll need to
  781. /// follow up by moving the object after it has been created. This
  782. /// function will not set textures, light and flexible data, or other
  783. /// extended primitive properties</remarks>
  784. public void AddPrim(Simulator simulator, Primitive.ConstructionData prim, UUID groupID, Vector3 position,
  785. Vector3 scale, Quaternion rotation, PrimFlags createFlags)
  786. {
  787. ObjectAddPacket packet = new ObjectAddPacket();
  788. packet.AgentData.AgentID = Client.Self.AgentID;
  789. packet.AgentData.SessionID = Client.Self.SessionID;
  790. packet.AgentData.GroupID = groupID;
  791. packet.ObjectData.State = prim.State;
  792. packet.ObjectData.AddFlags = (uint)createFlags;
  793. packet.ObjectData.PCode = (byte)PCode.Prim;
  794. packet.ObjectData.Material = (byte)prim.Material;
  795. packet.ObjectData.Scale = scale;
  796. packet.ObjectData.Rotation = rotation;
  797. packet.ObjectData.PathCurve = (byte)prim.PathCurve;
  798. packet.ObjectData.PathBegin = Primitive.PackBeginCut(prim.PathBegin);
  799. packet.ObjectData.PathEnd = Primitive.PackEndCut(prim.PathEnd);
  800. packet.ObjectData.PathRadiusOffset = Primitive.PackPathTwist(prim.PathRadiusOffset);
  801. packet.ObjectData.PathRevolutions = Primitive.PackPathRevolutions(prim.PathRevolutions);
  802. packet.ObjectData.PathScaleX = Primitive.PackPathScale(prim.PathScaleX);
  803. packet.ObjectData.PathScaleY = Primitive.PackPathScale(prim.PathScaleY);
  804. packet.ObjectData.PathShearX = (byte)Primitive.PackPathShear(prim.PathShearX);
  805. packet.ObjectData.PathShearY = (byte)Primitive.PackPathShear(prim.PathShearY);
  806. packet.ObjectData.PathSkew = Primitive.PackPathTwist(prim.PathSkew);
  807. packet.ObjectData.PathTaperX = Primitive.PackPathTaper(prim.PathTaperX);
  808. packet.ObjectData.PathTaperY = Primitive.PackPathTaper(prim.PathTaperY);
  809. packet.ObjectData.PathTwist = Primitive.PackPathTwist(prim.PathTwist);
  810. packet.ObjectData.PathTwistBegin = Primitive.PackPathTwist(prim.PathTwistBegin);
  811. packet.ObjectData.ProfileCurve = prim.profileCurve;
  812. packet.ObjectData.ProfileBegin = Primitive.PackBeginCut(prim.ProfileBegin);
  813. packet.ObjectData.ProfileEnd = Primitive.PackEndCut(prim.ProfileEnd);
  814. packet.ObjectData.ProfileHollow = Primitive.PackProfileHollow(prim.ProfileHollow);
  815. packet.ObjectData.RayStart = position;
  816. packet.ObjectData.RayEnd = position;
  817. packet.ObjectData.RayEndIsIntersection = 0;
  818. packet.ObjectData.RayTargetID = UUID.Zero;
  819. packet.ObjectData.BypassRaycast = 1;
  820. Client.Network.SendPacket(packet, simulator);
  821. }
  822. /// <summary>
  823. /// Rez a Linden tree
  824. /// </summary>
  825. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  826. /// <param name="scale">The size of the tree</param>
  827. /// <param name="rotation">The rotation of the tree</param>
  828. /// <param name="position">The position of the tree</param>
  829. /// <param name="treeType">The Type of tree</param>
  830. /// <param name="groupOwner">The <seealso cref="UUID"/> of the group to set the tree to,
  831. /// or UUID.Zero if no group is to be set</param>
  832. /// <param name="newTree">true to use the "new" Linden trees, false to use the old</param>
  833. public void AddTree(Simulator simulator, Vector3 scale, Quaternion rotation, Vector3 position,
  834. Tree treeType, UUID groupOwner, bool newTree)
  835. {
  836. ObjectAddPacket add = new ObjectAddPacket();
  837. add.AgentData.AgentID = Client.Self.AgentID;
  838. add.AgentData.SessionID = Client.Self.SessionID;
  839. add.AgentData.GroupID = groupOwner;
  840. add.ObjectData.BypassRaycast = 1;
  841. add.ObjectData.Material = 3;
  842. add.ObjectData.PathCurve = 16;
  843. add.ObjectData.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree;
  844. add.ObjectData.RayEnd = position;
  845. add.ObjectData.RayStart = position;
  846. add.ObjectData.RayTargetID = UUID.Zero;
  847. add.ObjectData.Rotation = rotation;
  848. add.ObjectData.Scale = scale;
  849. add.ObjectData.State = (byte)treeType;
  850. Client.Network.SendPacket(add, simulator);
  851. }
  852. /// <summary>
  853. /// Rez grass and ground cover
  854. /// </summary>
  855. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  856. /// <param name="scale">The size of the grass</param>
  857. /// <param name="rotation">The rotation of the grass</param>
  858. /// <param name="position">The position of the grass</param>
  859. /// <param name="grassType">The type of grass from the <seealso cref="Grass"/> enum</param>
  860. /// <param name="groupOwner">The <seealso cref="UUID"/> of the group to set the tree to,
  861. /// or UUID.Zero if no group is to be set</param>
  862. public void AddGrass(Simulator simulator, Vector3 scale, Quaternion rotation, Vector3 position,
  863. Grass grassType, UUID groupOwner)
  864. {
  865. ObjectAddPacket add = new ObjectAddPacket();
  866. add.AgentData.AgentID = Client.Self.AgentID;
  867. add.AgentData.SessionID = Client.Self.SessionID;
  868. add.AgentData.GroupID = groupOwner;
  869. add.ObjectData.BypassRaycast = 1;
  870. add.ObjectData.Material = 3;
  871. add.ObjectData.PathCurve = 16;
  872. add.ObjectData.PCode = (byte)PCode.Grass;
  873. add.ObjectData.RayEnd = position;
  874. add.ObjectData.RayStart = position;
  875. add.ObjectData.RayTargetID = UUID.Zero;
  876. add.ObjectData.Rotation = rotation;
  877. add.ObjectData.Scale = scale;
  878. add.ObjectData.State = (byte)grassType;
  879. Client.Network.SendPacket(add, simulator);
  880. }
  881. /// <summary>
  882. /// Set the textures to apply to the faces of an object
  883. /// </summary>
  884. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  885. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  886. /// <param name="textures">The texture data to apply</param>
  887. public void SetTextures(Simulator simulator, uint localID, Primitive.TextureEntry textures)
  888. {
  889. SetTextures(simulator, localID, textures, String.Empty);
  890. }
  891. /// <summary>
  892. /// Set the textures to apply to the faces of an object
  893. /// </summary>
  894. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  895. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  896. /// <param name="textures">The texture data to apply</param>
  897. /// <param name="mediaUrl">A media URL (not used)</param>
  898. public void SetTextures(Simulator simulator, uint localID, Primitive.TextureEntry textures, string mediaUrl)
  899. {
  900. ObjectImagePacket image = new ObjectImagePacket();
  901. image.AgentData.AgentID = Client.Self.AgentID;
  902. image.AgentData.SessionID = Client.Self.SessionID;
  903. image.ObjectData = new ObjectImagePacket.ObjectDataBlock[1];
  904. image.ObjectData[0] = new ObjectImagePacket.ObjectDataBlock();
  905. image.ObjectData[0].ObjectLocalID = localID;
  906. image.ObjectData[0].TextureEntry = textures.GetBytes();
  907. image.ObjectData[0].MediaURL = Utils.StringToBytes(mediaUrl);
  908. Client.Network.SendPacket(image, simulator);
  909. }
  910. /// <summary>
  911. /// Set the Light data on an object
  912. /// </summary>
  913. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  914. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  915. /// <param name="light">A <seealso cref="Primitive.LightData"/> object containing the data to set</param>
  916. public void SetLight(Simulator simulator, uint localID, Primitive.LightData light)
  917. {
  918. ObjectExtraParamsPacket extra = new ObjectExtraParamsPacket();
  919. extra.AgentData.AgentID = Client.Self.AgentID;
  920. extra.AgentData.SessionID = Client.Self.SessionID;
  921. extra.ObjectData = new ObjectExtraParamsPacket.ObjectDataBlock[1];
  922. extra.ObjectData[0] = new ObjectExtraParamsPacket.ObjectDataBlock();
  923. extra.ObjectData[0].ObjectLocalID = localID;
  924. extra.ObjectData[0].ParamType = (byte)ExtraParamType.Light;
  925. if (light.Intensity == 0.0f)
  926. {
  927. // Disables the light if intensity is 0
  928. extra.ObjectData[0].ParamInUse = false;
  929. }
  930. else
  931. {
  932. extra.ObjectData[0].ParamInUse = true;
  933. }
  934. extra.ObjectData[0].ParamData = light.GetBytes();
  935. extra.ObjectData[0].ParamSize = (uint)extra.ObjectData[0].ParamData.Length;
  936. Client.Network.SendPacket(extra, simulator);
  937. }
  938. /// <summary>
  939. /// Set the flexible data on an object
  940. /// </summary>
  941. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  942. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  943. /// <param name="flexible">A <seealso cref="Primitive.FlexibleData"/> object containing the data to set</param>
  944. public void SetFlexible(Simulator simulator, uint localID, Primitive.FlexibleData flexible)
  945. {
  946. ObjectExtraParamsPacket extra = new ObjectExtraParamsPacket();
  947. extra.AgentData.AgentID = Client.Self.AgentID;
  948. extra.AgentData.SessionID = Client.Self.SessionID;
  949. extra.ObjectData = new ObjectExtraParamsPacket.ObjectDataBlock[1];
  950. extra.ObjectData[0] = new ObjectExtraParamsPacket.ObjectDataBlock();
  951. extra.ObjectData[0].ObjectLocalID = localID;
  952. extra.ObjectData[0].ParamType = (byte)ExtraParamType.Flexible;
  953. extra.ObjectData[0].ParamInUse = true;
  954. extra.ObjectData[0].ParamData = flexible.GetBytes();
  955. extra.ObjectData[0].ParamSize = (uint)extra.ObjectData[0].ParamData.Length;
  956. Client.Network.SendPacket(extra, simulator);
  957. }
  958. /// <summary>
  959. /// Set the sculptie texture and data on an object
  960. /// </summary>
  961. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  962. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  963. /// <param name="sculpt">A <seealso cref="Primitive.SculptData"/> object containing the data to set</param>
  964. public void SetSculpt(Simulator simulator, uint localID, Primitive.SculptData sculpt)
  965. {
  966. ObjectExtraParamsPacket extra = new ObjectExtraParamsPacket();
  967. extra.AgentData.AgentID = Client.Self.AgentID;
  968. extra.AgentData.SessionID = Client.Self.SessionID;
  969. extra.ObjectData = new ObjectExtraParamsPacket.ObjectDataBlock[1];
  970. extra.ObjectData[0] = new ObjectExtraParamsPacket.ObjectDataBlock();
  971. extra.ObjectData[0].ObjectLocalID = localID;
  972. extra.ObjectData[0].ParamType = (byte)ExtraParamType.Sculpt;
  973. extra.ObjectData[0].ParamInUse = true;
  974. extra.ObjectData[0].ParamData = sculpt.GetBytes();
  975. extra.ObjectData[0].ParamSize = (uint)extra.ObjectData[0].ParamData.Length;
  976. Client.Network.SendPacket(extra, simulator);
  977. // Not sure why, but if you don't send this the sculpted prim disappears
  978. ObjectShapePacket shape = new ObjectShapePacket();
  979. shape.AgentData.AgentID = Client.Self.AgentID;
  980. shape.AgentData.SessionID = Client.Self.SessionID;
  981. shape.ObjectData = new OpenMetaverse.Packets.ObjectShapePacket.ObjectDataBlock[1];
  982. shape.ObjectData[0] = new OpenMetaverse.Packets.ObjectShapePacket.ObjectDataBlock();
  983. shape.ObjectData[0].ObjectLocalID = localID;
  984. shape.ObjectData[0].PathScaleX = 100;
  985. shape.ObjectData[0].PathScaleY = 150;
  986. shape.ObjectData[0].PathCurve = 32;
  987. Client.Network.SendPacket(shape, simulator);
  988. }
  989. /// <summary>
  990. /// Unset additional primitive parameters on an object
  991. /// </summary>
  992. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  993. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  994. /// <param name="type">The extra parameters to set</param>
  995. public void SetExtraParamOff(Simulator simulator, uint localID, ExtraParamType type)
  996. {
  997. ObjectExtraParamsPacket extra = new ObjectExtraParamsPacket();
  998. extra.AgentData.AgentID = Client.Self.AgentID;
  999. extra.AgentData.SessionID = Client.Self.SessionID;
  1000. extra.ObjectData = new ObjectExtraParamsPacket.ObjectDataBlock[1];
  1001. extra.ObjectData[0] = new ObjectExtraParamsPacket.ObjectDataBlock();
  1002. extra.ObjectData[0].ObjectLocalID = localID;
  1003. extra.ObjectData[0].ParamType = (byte)type;
  1004. extra.ObjectData[0].ParamInUse = false;
  1005. extra.ObjectData[0].ParamData = Utils.EmptyBytes;
  1006. extra.ObjectData[0].ParamSize = 0;
  1007. Client.Network.SendPacket(extra, simulator);
  1008. }
  1009. /// <summary>
  1010. /// Link multiple prims into a linkset
  1011. /// </summary>
  1012. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the objects reside</param>
  1013. /// <param name="localIDs">An array which contains the IDs of the objects to link</param>
  1014. /// <remarks>The last object in the array will be the root object of the linkset TODO: Is this true?</remarks>
  1015. public void LinkPrims(Simulator simulator, List<uint> localIDs)
  1016. {
  1017. ObjectLinkPacket packet = new ObjectLinkPacket();
  1018. packet.AgentData.AgentID = Client.Self.AgentID;
  1019. packet.AgentData.SessionID = Client.Self.SessionID;
  1020. packet.ObjectData = new ObjectLinkPacket.ObjectDataBlock[localIDs.Count];
  1021. for (int i = 0; i < localIDs.Count; i++)
  1022. {
  1023. packet.ObjectData[i] = new ObjectLinkPacket.ObjectDataBlock();
  1024. packet.ObjectData[i].ObjectLocalID = localIDs[i];
  1025. }
  1026. Client.Network.SendPacket(packet, simulator);
  1027. }
  1028. /// <summary>
  1029. /// Delink/Unlink multiple prims from a linkset
  1030. /// </summary>
  1031. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the objects reside</param>
  1032. /// <param name="localIDs">An array which contains the IDs of the objects to delink</param>
  1033. public void DelinkPrims(Simulator simulator, List<uint> localIDs)
  1034. {
  1035. ObjectDelinkPacket packet = new ObjectDelinkPacket();
  1036. packet.AgentData.AgentID = Client.Self.AgentID;
  1037. packet.AgentData.SessionID = Client.Self.SessionID;
  1038. packet.ObjectData = new ObjectDelinkPacket.ObjectDataBlock[localIDs.Count];
  1039. int i = 0;
  1040. foreach (uint localID in localIDs)
  1041. {
  1042. packet.ObjectData[i] = new ObjectDelinkPacket.ObjectDataBlock();
  1043. packet.ObjectData[i].ObjectLocalID = localID;
  1044. i++;
  1045. }
  1046. Client.Network.SendPacket(packet, simulator);
  1047. }
  1048. /// <summary>
  1049. /// Change the rotation of an object
  1050. /// </summary>
  1051. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1052. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1053. /// <param name="rotation">The new rotation of the object</param>
  1054. public void SetRotation(Simulator simulator, uint localID, Quaternion rotation)
  1055. {
  1056. ObjectRotationPacket objRotPacket = new ObjectRotationPacket();
  1057. objRotPacket.AgentData.AgentID = Client.Self.AgentID;
  1058. objRotPacket.AgentData.SessionID = Client.Self.SessionID;
  1059. objRotPacket.ObjectData = new ObjectRotationPacket.ObjectDataBlock[1];
  1060. objRotPacket.ObjectData[0] = new ObjectRotationPacket.ObjectDataBlock();
  1061. objRotPacket.ObjectData[0].ObjectLocalID = localID;
  1062. objRotPacket.ObjectData[0].Rotation = rotation;
  1063. Client.Network.SendPacket(objRotPacket, simulator);
  1064. }
  1065. /// <summary>
  1066. /// Set the name of an object
  1067. /// </summary>
  1068. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1069. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1070. /// <param name="name">A string containing the new name of the object</param>
  1071. public void SetName(Simulator simulator, uint localID, string name)
  1072. {
  1073. SetNames(simulator, new uint[] { localID }, new string[] { name });
  1074. }
  1075. /// <summary>
  1076. /// Set the name of multiple objects
  1077. /// </summary>
  1078. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the objects reside</param>
  1079. /// <param name="localIDs">An array which contains the IDs of the objects to change the name of</param>
  1080. /// <param name="names">An array which contains the new names of the objects</param>
  1081. public void SetNames(Simulator simulator, uint[] localIDs, string[] names)
  1082. {
  1083. ObjectNamePacket namePacket = new ObjectNamePacket();
  1084. namePacket.AgentData.AgentID = Client.Self.AgentID;
  1085. namePacket.AgentData.SessionID = Client.Self.SessionID;
  1086. namePacket.ObjectData = new ObjectNamePacket.ObjectDataBlock[localIDs.Length];
  1087. for (int i = 0; i < localIDs.Length; ++i)
  1088. {
  1089. namePacket.ObjectData[i] = new ObjectNamePacket.ObjectDataBlock();
  1090. namePacket.ObjectData[i].LocalID = localIDs[i];
  1091. namePacket.ObjectData[i].Name = Utils.StringToBytes(names[i]);
  1092. }
  1093. Client.Network.SendPacket(namePacket, simulator);
  1094. }
  1095. /// <summary>
  1096. /// Set the description of an object
  1097. /// </summary>
  1098. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1099. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1100. /// <param name="description">A string containing the new description of the object</param>
  1101. public void SetDescription(Simulator simulator, uint localID, string description)
  1102. {
  1103. SetDescriptions(simulator, new uint[] { localID }, new string[] { description });
  1104. }
  1105. /// <summary>
  1106. /// Set the descriptions of multiple objects
  1107. /// </summary>
  1108. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the objects reside</param>
  1109. /// <param name="localIDs">An array which contains the IDs of the objects to change the description of</param>
  1110. /// <param name="descriptions">An array which contains the new descriptions of the objects</param>
  1111. public void SetDescriptions(Simulator simulator, uint[] localIDs, string[] descriptions)
  1112. {
  1113. ObjectDescriptionPacket descPacket = new ObjectDescriptionPacket();
  1114. descPacket.AgentData.AgentID = Client.Self.AgentID;
  1115. descPacket.AgentData.SessionID = Client.Self.SessionID;
  1116. descPacket.ObjectData = new ObjectDescriptionPacket.ObjectDataBlock[localIDs.Length];
  1117. for (int i = 0; i < localIDs.Length; ++i)
  1118. {
  1119. descPacket.ObjectData[i] = new ObjectDescriptionPacket.ObjectDataBlock();
  1120. descPacket.ObjectData[i].LocalID = localIDs[i];
  1121. descPacket.ObjectData[i].Description = Utils.StringToBytes(descriptions[i]);
  1122. }
  1123. Client.Network.SendPacket(descPacket, simulator);
  1124. }
  1125. /// <summary>
  1126. /// Attach an object to this avatar
  1127. /// </summary>
  1128. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1129. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1130. /// <param name="attachPoint">The point on the avatar the object will be attached</param>
  1131. /// <param name="rotation">The rotation of the attached object</param>
  1132. public void AttachObject(Simulator simulator, uint localID, AttachmentPoint attachPoint, Quaternion rotation)
  1133. {
  1134. ObjectAttachPacket attach = new ObjectAttachPacket();
  1135. attach.AgentData.AgentID = Client.Self.AgentID;
  1136. attach.AgentData.SessionID = Client.Self.SessionID;
  1137. attach.AgentData.AttachmentPoint = (byte)attachPoint;
  1138. attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
  1139. attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
  1140. attach.ObjectData[0].ObjectLocalID = localID;
  1141. attach.ObjectData[0].Rotation = rotation;
  1142. Client.Network.SendPacket(attach, simulator);
  1143. }
  1144. /// <summary>
  1145. /// Drop an attached object from this avatar
  1146. /// </summary>
  1147. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/>
  1148. /// object where the objects reside. This will always be the simulator the avatar is currently in
  1149. /// </param>
  1150. /// <param name="localID">The object's ID which is local to the simulator the object is in</param>
  1151. public void DropObject(Simulator simulator, uint localID)
  1152. {
  1153. ObjectDropPacket dropit = new ObjectDropPacket();
  1154. dropit.AgentData.AgentID = Client.Self.AgentID;
  1155. dropit.AgentData.SessionID = Client.Self.SessionID;
  1156. dropit.ObjectData = new ObjectDropPacket.ObjectDataBlock[1];
  1157. dropit.ObjectData[0] = new ObjectDropPacket.ObjectDataBlock();
  1158. dropit.ObjectData[0].ObjectLocalID = localID;
  1159. Client.Network.SendPacket(dropit, simulator);
  1160. }
  1161. /// <summary>
  1162. /// Detach an object from yourself
  1163. /// </summary>
  1164. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/>
  1165. /// object where the objects reside
  1166. ///
  1167. /// This will always be the simulator the avatar is currently in
  1168. /// </param>
  1169. /// <param name="localIDs">An array which contains the IDs of the objects to detach</param>
  1170. public void DetachObjects(Simulator simulator, List<uint> localIDs)
  1171. {
  1172. ObjectDetachPacket detach = new ObjectDetachPacket();
  1173. detach.AgentData.AgentID = Client.Self.AgentID;
  1174. detach.AgentData.SessionID = Client.Self.SessionID;
  1175. detach.ObjectData = new ObjectDetachPacket.ObjectDataBlock[localIDs.Count];
  1176. for (int i = 0; i < localIDs.Count; i++)
  1177. {
  1178. detach.ObjectData[i] = new ObjectDetachPacket.ObjectDataBlock();
  1179. detach.ObjectData[i].ObjectLocalID = localIDs[i];
  1180. }
  1181. Client.Network.SendPacket(detach, simulator);
  1182. }
  1183. /// <summary>
  1184. /// Change the position of an object, Will change position of entire linkset
  1185. /// </summary>
  1186. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1187. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1188. /// <param name="position">The new position of the object</param>
  1189. public void SetPosition(Simulator simulator, uint localID, Vector3 position)
  1190. {
  1191. UpdateObject(simulator, localID, position, UpdateType.Position | UpdateType.Linked);
  1192. }
  1193. /// <summary>
  1194. /// Change the position of an object
  1195. /// </summary>
  1196. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1197. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1198. /// <param name="position">The new position of the object</param>
  1199. /// <param name="childOnly">if true, will change position of (this) child prim only, not entire linkset</param>
  1200. public void SetPosition(Simulator simulator, uint localID, Vector3 position, bool childOnly)
  1201. {
  1202. UpdateType type = UpdateType.Position;
  1203. if (!childOnly)
  1204. type |= UpdateType.Linked;
  1205. UpdateObject(simulator, localID, position, type);
  1206. }
  1207. /// <summary>
  1208. /// Change the Scale (size) of an object
  1209. /// </summary>
  1210. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1211. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1212. /// <param name="scale">The new scale of the object</param>
  1213. /// <param name="childOnly">If true, will change scale of this prim only, not entire linkset</param>
  1214. /// <param name="uniform">True to resize prims uniformly</param>
  1215. public void SetScale(Simulator simulator, uint localID, Vector3 scale, bool childOnly, bool uniform)
  1216. {
  1217. UpdateType type = UpdateType.Scale;
  1218. if (!childOnly)
  1219. type |= UpdateType.Linked;
  1220. if (uniform)
  1221. type |= UpdateType.Uniform;
  1222. UpdateObject(simulator, localID, scale, type);
  1223. }
  1224. /// <summary>
  1225. /// Change the Rotation of an object that is either a child or a whole linkset
  1226. /// </summary>
  1227. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1228. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1229. /// <param name="quat">The new scale of the object</param>
  1230. /// <param name="childOnly">If true, will change rotation of this prim only, not entire linkset</param>
  1231. public void SetRotation(Simulator simulator, uint localID, Quaternion quat, bool childOnly)
  1232. {
  1233. UpdateType type = UpdateType.Rotation;
  1234. if (!childOnly)
  1235. type |= UpdateType.Linked;
  1236. MultipleObjectUpdatePacket multiObjectUpdate = new MultipleObjectUpdatePacket();
  1237. multiObjectUpdate.AgentData.AgentID = Client.Self.AgentID;
  1238. multiObjectUpdate.AgentData.SessionID = Client.Self.SessionID;
  1239. multiObjectUpdate.ObjectData = new MultipleObjectUpdatePacket.ObjectDataBlock[1];
  1240. multiObjectUpdate.ObjectData[0] = new MultipleObjectUpdatePacket.ObjectDataBlock();
  1241. multiObjectUpdate.ObjectData[0].Type = (byte)type;
  1242. multiObjectUpdate.ObjectData[0].ObjectLocalID = localID;
  1243. multiObjectUpdate.ObjectData[0].Data = quat.GetBytes();
  1244. Client.Network.SendPacket(multiObjectUpdate, simulator);
  1245. }
  1246. /// <summary>
  1247. /// Send a Multiple Object Update packet to change the size, scale or rotation of a primitive
  1248. /// </summary>
  1249. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1250. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1251. /// <param name="data">The new rotation, size, or position of the target object</param>
  1252. /// <param name="type">The flags from the <seealso cref="UpdateType"/> Enum</param>
  1253. public void UpdateObject(Simulator simulator, uint localID, Vector3 data, UpdateType type)
  1254. {
  1255. MultipleObjectUpdatePacket multiObjectUpdate = new MultipleObjectUpdatePacket();
  1256. multiObjectUpdate.AgentData.AgentID = Client.Self.AgentID;
  1257. multiObjectUpdate.AgentData.SessionID = Client.Self.SessionID;
  1258. multiObjectUpdate.ObjectData = new MultipleObjectUpdatePacket.ObjectDataBlock[1];
  1259. multiObjectUpdate.ObjectData[0] = new MultipleObjectUpdatePacket.ObjectDataBlock();
  1260. multiObjectUpdate.ObjectData[0].Type = (byte)type;
  1261. multiObjectUpdate.ObjectData[0].ObjectLocalID = localID;
  1262. multiObjectUpdate.ObjectData[0].Data = data.GetBytes();
  1263. Client.Network.SendPacket(multiObjectUpdate, simulator);
  1264. }
  1265. /// <summary>
  1266. /// Deed an object (prim) to a group, Object must be shared with group which
  1267. /// can be accomplished with SetPermissions()
  1268. /// </summary>
  1269. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1270. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  1271. /// <param name="groupOwner">The <seealso cref="UUID"/> of the group to deed the object to</param>
  1272. public void DeedObject(Simulator simulator, uint localID, UUID groupOwner)
  1273. {
  1274. ObjectOwnerPacket objDeedPacket = new ObjectOwnerPacket();
  1275. objDeedPacket.AgentData.AgentID = Client.Self.AgentID;
  1276. objDeedPacket.AgentData.SessionID = Client.Self.SessionID;
  1277. // Can only be use in God mode
  1278. objDeedPacket.HeaderData.Override = false;
  1279. objDeedPacket.HeaderData.OwnerID = UUID.Zero;
  1280. objDeedPacket.HeaderData.GroupID = groupOwner;
  1281. objDeedPacket.ObjectData = new ObjectOwnerPacket.ObjectDataBlock[1];
  1282. objDeedPacket.ObjectData[0] = new ObjectOwnerPacket.ObjectDataBlock();
  1283. objDeedPacket.ObjectData[0].ObjectLocalID = localID;
  1284. Client.Network.SendPacket(objDeedPacket, simulator);
  1285. }
  1286. /// <summary>
  1287. /// Deed multiple objects (prims) to a group, Objects must be shared with group which
  1288. /// can be accomplished with SetPermissions()
  1289. /// </summary>
  1290. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1291. /// <param name="localIDs">An array which contains the IDs of the objects to deed</param>
  1292. /// <param name="groupOwner">The <seealso cref="UUID"/> of the group to deed the object to</param>
  1293. public void DeedObjects(Simulator simulator, List<uint> localIDs, UUID groupOwner)
  1294. {
  1295. ObjectOwnerPacket packet = new ObjectOwnerPacket();
  1296. packet.AgentData.AgentID = Client.Self.AgentID;
  1297. packet.AgentData.SessionID = Client.Self.SessionID;
  1298. // Can only be use in God mode
  1299. packet.HeaderData.Override = false;
  1300. packet.HeaderData.OwnerID = UUID.Zero;
  1301. packet.HeaderData.GroupID = groupOwner;
  1302. packet.ObjectData = new ObjectOwnerPacket.ObjectDataBlock[localIDs.Count];
  1303. for (int i = 0; i < localIDs.Count; i++)
  1304. {
  1305. packet.ObjectData[i] = new ObjectOwnerPacket.ObjectDataBlock();
  1306. packet.ObjectData[i].ObjectLocalID = localIDs[i];
  1307. }
  1308. Client.Network.SendPacket(packet, simulator);
  1309. }
  1310. /// <summary>
  1311. /// Set the permissions on multiple objects
  1312. /// </summary>
  1313. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the objects reside</param>
  1314. /// <param name="localIDs">An array which contains the IDs of the objects to set the permissions on</param>
  1315. /// <param name="who">The new Who mask to set</param>
  1316. /// <param name="permissions">Which permission to modify</param>
  1317. /// <param name="set">The new state of permission</param>
  1318. public void SetPermissions(Simulator simulator, List<uint> localIDs, PermissionWho who,
  1319. PermissionMask permissions, bool set)
  1320. {
  1321. ObjectPermissionsPacket packet = new ObjectPermissionsPacket();
  1322. packet.AgentData.AgentID = Client.Self.AgentID;
  1323. packet.AgentData.SessionID = Client.Self.SessionID;
  1324. // Override can only be used by gods
  1325. packet.HeaderData.Override = false;
  1326. packet.ObjectData = new ObjectPermissionsPacket.ObjectDataBlock[localIDs.Count];
  1327. for (int i = 0; i < localIDs.Count; i++)
  1328. {
  1329. packet.ObjectData[i] = new ObjectPermissionsPacket.ObjectDataBlock();
  1330. packet.ObjectData[i].ObjectLocalID = localIDs[i];
  1331. packet.ObjectData[i].Field = (byte)who;
  1332. packet.ObjectData[i].Mask = (uint)permissions;
  1333. packet.ObjectData[i].Set = Convert.ToByte(set);
  1334. }
  1335. Client.Network.SendPacket(packet, simulator);
  1336. }
  1337. /// <summary>
  1338. /// Request additional properties for an object
  1339. /// </summary>
  1340. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1341. /// <param name="objectID"></param>
  1342. public void RequestObjectPropertiesFamily(Simulator simulator, UUID objectID)
  1343. {
  1344. RequestObjectPropertiesFamily(simulator, objectID, true);
  1345. }
  1346. /// <summary>
  1347. /// Request additional properties for an object
  1348. /// </summary>
  1349. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  1350. /// <param name="objectID">Absolute UUID of the object</param>
  1351. /// <param name="reliable">Whether to require server acknowledgement of this request</param>
  1352. public void RequestObjectPropertiesFamily(Simulator simulator, UUID objectID, bool reliable)
  1353. {
  1354. RequestObjectPropertiesFamilyPacket properties = new RequestObjectPropertiesFamilyPacket();
  1355. properties.AgentData.AgentID = Client.Self.AgentID;
  1356. properties.AgentData.SessionID = Client.Self.SessionID;
  1357. properties.ObjectData.ObjectID = objectID;
  1358. // TODO: RequestFlags is typically only for bug report submissions, but we might be able to
  1359. // use it to pass an arbitrary uint back to the callback
  1360. properties.ObjectData.RequestFlags = 0;
  1361. properties.Header.Reliable = reliable;
  1362. Client.Network.SendPacket(properties, simulator);
  1363. }
  1364. /// <summary>
  1365. /// Set the ownership of a list of objects to the specified group
  1366. /// </summary>
  1367. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the objects reside</param>
  1368. /// <param name="localIds">An array which contains the IDs of the objects to set the group id on</param>
  1369. /// <param name="groupID">The Groups ID</param>
  1370. public void SetObjectsGroup(Simulator simulator, List<uint> localIds, UUID groupID)
  1371. {
  1372. ObjectGroupPacket packet = new ObjectGroupPacket();
  1373. packet.AgentData.AgentID = Client.Self.AgentID;
  1374. packet.AgentData.GroupID = groupID;
  1375. packet.AgentData.SessionID = Client.Self.SessionID;
  1376. packet.ObjectData = new ObjectGroupPacket.ObjectDataBlock[localIds.Count];
  1377. for (int i = 0; i < localIds.Count; i++)
  1378. {
  1379. packet.ObjectData[i] = new ObjectGroupPacket.ObjectDataBlock();
  1380. packet.ObjectData[i].ObjectLocalID = localIds[i];
  1381. }
  1382. Client.Network.SendPacket(packet, simulator);
  1383. }
  1384. /// <summary>
  1385. /// Update current URL of the previously set prim media
  1386. /// </summary>
  1387. /// <param name="primID">UUID of the prim</param>
  1388. /// <param name="newURL">Set current URL to this</param>
  1389. /// <param name="face">Prim face number</param>
  1390. /// <param name="sim">Simulator in which prim is located</param>
  1391. public void NavigateObjectMedia(UUID primID, int face, string newURL, Simulator sim)
  1392. {
  1393. Uri url;
  1394. if (sim.Caps != null && null != (url = sim.Caps.CapabilityURI("ObjectMediaNavigate")))
  1395. {
  1396. ObjectMediaNavigateMessage req = new ObjectMediaNavigateMessage();
  1397. req.PrimID = primID;
  1398. req.URL = newURL;
  1399. req.Face = face;
  1400. CapsClient request = new CapsClient(url);
  1401. request.OnComplete += (CapsClient client, OSD result, Exception error) =>
  1402. {
  1403. if (error != null)
  1404. {
  1405. Logger.Log("ObjectMediaNavigate: " + error.Message, Helpers.LogLevel.Error, Client);
  1406. }
  1407. };
  1408. request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
  1409. }
  1410. else
  1411. {
  1412. Logger.Log("ObjectMediaNavigate capability not available", Helpers.LogLevel.Error, Client);
  1413. }
  1414. }
  1415. /// <summary>
  1416. /// Set object media
  1417. /// </summary>
  1418. /// <param name="primID">UUID of the prim</param>
  1419. /// <param name="faceMedia">Array the length of prims number of faces. Null on face indexes where there is
  1420. /// no media, <seealso cref="MediaEntry"/> on faces which contain the media</param>
  1421. /// <param name="sim">Simulatior in which prim is located</param>
  1422. public void UpdateObjectMedia(UUID primID, MediaEntry[] faceMedia, Simulator sim)
  1423. {
  1424. Uri url;
  1425. if (sim.Caps != null && null != (url = sim.Caps.CapabilityURI("ObjectMedia")))
  1426. {
  1427. ObjectMediaUpdate req = new ObjectMediaUpdate();
  1428. req.PrimID = primID;
  1429. req.FaceMedia = faceMedia;
  1430. req.Verb = "UPDATE";
  1431. CapsClient request = new CapsClient(url);
  1432. request.OnComplete += (CapsClient client, OSD result, Exception error) =>
  1433. {
  1434. if (error != null)
  1435. {
  1436. Logger.Log("ObjectMediaUpdate: " + error.Message, Helpers.LogLevel.Error, Client);
  1437. }
  1438. };
  1439. request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
  1440. }
  1441. else
  1442. {
  1443. Logger.Log("ObjectMedia capability not available", Helpers.LogLevel.Error, Client);
  1444. }
  1445. }
  1446. /// <summary>
  1447. /// Retrieve information about object media
  1448. /// </summary>
  1449. /// <param name="primID">UUID of the primitive</param>
  1450. /// <param name="sim">Simulator where prim is located</param>
  1451. /// <param name="callback">Call this callback when done</param>
  1452. public void RequestObjectMedia(UUID primID, Simulator sim, ObjectMediaCallback callback)
  1453. {
  1454. Uri url;
  1455. if (sim.Caps != null && null != (url = sim.Caps.CapabilityURI("ObjectMedia")))
  1456. {
  1457. ObjectMediaRequest req = new ObjectMediaRequest();
  1458. req.PrimID = primID;
  1459. req.Verb = "GET";
  1460. CapsClient request = new CapsClient(url);
  1461. request.OnComplete += (CapsClient client, OSD result, Exception error) =>
  1462. {
  1463. if (result == null)
  1464. {
  1465. Logger.Log("Failed retrieving ObjectMedia data", Helpers.LogLevel.Error, Client);
  1466. try { callback(false, string.Empty, null); }
  1467. catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); }
  1468. return;
  1469. }
  1470. ObjectMediaMessage msg = new ObjectMediaMessage();
  1471. msg.Deserialize((OSDMap)result);
  1472. if (msg.Request is ObjectMediaResponse)
  1473. {
  1474. ObjectMediaResponse response = (ObjectMediaResponse)msg.Request;
  1475. if (Client.Settings.OBJECT_TRACKING)
  1476. {
  1477. Primitive prim = sim.ObjectsPrimitives.Find((Primitive p) => { return p.ID == primID; });
  1478. if (prim != null)
  1479. {
  1480. prim.MediaVersion = response.Version;
  1481. prim.FaceMedia = response.FaceMedia;
  1482. }
  1483. }
  1484. try { callback(true, response.Version, response.FaceMedia); }
  1485. catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); }
  1486. }
  1487. else
  1488. {
  1489. try { callback(false, string.Empty, null); }
  1490. catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); }
  1491. }
  1492. };
  1493. request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
  1494. }
  1495. else
  1496. {
  1497. Logger.Log("ObjectMedia capability not available", Helpers.LogLevel.Error, Client);
  1498. try { callback(false, string.Empty, null); }
  1499. catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); }
  1500. }
  1501. }
  1502. #endregion
  1503. #region Packet Handlers
  1504. /// <summary>Process an incoming packet and raise the appropriate events</summary>
  1505. /// <param name="sender">The sender</param>
  1506. /// <param name="e">The EventArgs object containing the packet data</param>
  1507. protected void ObjectUpdateHandler(object sender, PacketReceivedEventArgs e)
  1508. {
  1509. Packet packet = e.Packet;
  1510. Simulator simulator = e.Simulator;
  1511. ObjectUpdatePacket update = (ObjectUpdatePacket)packet;
  1512. UpdateDilation(e.Simulator, update.RegionData.TimeDilation);
  1513. for (int b = 0; b < update.ObjectData.Length; b++)
  1514. {
  1515. ObjectUpdatePacket.ObjectDataBlock block = update.ObjectData[b];
  1516. ObjectMovementUpdate objectupdate = new ObjectMovementUpdate();
  1517. //Vector4 collisionPlane = Vector4.Zero;
  1518. //Vector3 position;
  1519. //Vector3 velocity;
  1520. //Vector3 acceleration;
  1521. //Quaternion rotation;
  1522. //Vector3 angularVelocity;
  1523. NameValue[] nameValues;
  1524. bool attachment = false;
  1525. PCode pcode = (PCode)block.PCode;
  1526. #region Relevance check
  1527. // Check if we are interested in this object
  1528. if (!Client.Settings.ALWAYS_DECODE_OBJECTS)
  1529. {
  1530. switch (pcode)
  1531. {
  1532. case PCode.Grass:
  1533. case PCode.Tree:
  1534. case PCode.NewTree:
  1535. case PCode.Prim:
  1536. if (m_ObjectUpdate == null) continue;
  1537. break;
  1538. case PCode.Avatar:
  1539. // Make an exception for updates about our own agent
  1540. if (block.FullID != Client.Self.AgentID && m_AvatarUpdate == null) continue;
  1541. break;
  1542. case PCode.ParticleSystem:
  1543. continue; // TODO: Do something with these
  1544. }
  1545. }
  1546. #endregion Relevance check
  1547. #region NameValue parsing
  1548. string nameValue = Utils.BytesToString(block.NameValue);
  1549. if (nameValue.Length > 0)
  1550. {
  1551. string[] lines = nameValue.Split('\n');
  1552. nameValues = new NameValue[lines.Length];
  1553. for (int i = 0; i < lines.Length; i++)
  1554. {
  1555. if (!String.IsNullOrEmpty(lines[i]))
  1556. {
  1557. NameValue nv = new NameValue(lines[i]);
  1558. if (nv.Name == "AttachItemID") attachment = true;
  1559. nameValues[i] = nv;
  1560. }
  1561. }
  1562. }
  1563. else
  1564. {
  1565. nameValues = new NameValue[0];
  1566. }
  1567. #endregion NameValue parsing
  1568. #region Decode Object (primitive) parameters
  1569. Primitive.ConstructionData data = new Primitive.ConstructionData();
  1570. data.State = block.State;
  1571. data.Material = (Material)block.Material;
  1572. data.PathCurve = (PathCurve)block.PathCurve;
  1573. data.profileCurve = block.ProfileCurve;
  1574. data.PathBegin = Primitive.UnpackBeginCut(block.PathBegin);
  1575. data.PathEnd = Primitive.UnpackEndCut(block.PathEnd);
  1576. data.PathScaleX = Primitive.UnpackPathScale(block.PathScaleX);
  1577. data.PathScaleY = Primitive.UnpackPathScale(block.PathScaleY);
  1578. data.PathShearX = Primitive.UnpackPathShear((sbyte)block.PathShearX);
  1579. data.PathShearY = Primitive.UnpackPathShear((sbyte)block.PathShearY);
  1580. data.PathTwist = Primitive.UnpackPathTwist(block.PathTwist);
  1581. data.PathTwistBegin = Primitive.UnpackPathTwist(block.PathTwistBegin);
  1582. data.PathRadiusOffset = Primitive.UnpackPathTwist(block.PathRadiusOffset);
  1583. data.PathTaperX = Primitive.UnpackPathTaper(block.PathTaperX);
  1584. data.PathTaperY = Primitive.UnpackPathTaper(block.PathTaperY);
  1585. data.PathRevolutions = Primitive.UnpackPathRevolutions(block.PathRevolutions);
  1586. data.PathSkew = Primitive.UnpackPathTwist(block.PathSkew);
  1587. data.ProfileBegin = Primitive.UnpackBeginCut(block.ProfileBegin);
  1588. data.ProfileEnd = Primitive.UnpackEndCut(block.ProfileEnd);
  1589. data.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow);
  1590. data.PCode = pcode;
  1591. #endregion
  1592. #region Decode Additional packed parameters in ObjectData
  1593. int pos = 0;
  1594. switch (block.ObjectData.Length)
  1595. {
  1596. case 76:
  1597. // Collision normal for avatar
  1598. objectupdate.CollisionPlane = new Vector4(block.ObjectData, pos);
  1599. pos += 16;
  1600. goto case 60;
  1601. case 60:
  1602. // Position
  1603. objectupdate.Position = new Vector3(block.ObjectData, pos);
  1604. pos += 12;
  1605. // Velocity
  1606. objectupdate.Velocity = new Vector3(block.ObjectData, pos);
  1607. pos += 12;
  1608. // Acceleration
  1609. objectupdate.Acceleration = new Vector3(block.ObjectData, pos);
  1610. pos += 12;
  1611. // Rotation (theta)
  1612. objectupdate.Rotation = new Quaternion(block.ObjectData, pos, true);
  1613. pos += 12;
  1614. // Angular velocity (omega)
  1615. objectupdate.AngularVelocity = new Vector3(block.ObjectData, pos);
  1616. pos += 12;
  1617. break;
  1618. case 48:
  1619. // Collision normal for avatar
  1620. objectupdate.CollisionPlane = new Vector4(block.ObjectData, pos);
  1621. pos += 16;
  1622. goto case 32;
  1623. case 32:
  1624. // The data is an array of unsigned shorts
  1625. // Position
  1626. objectupdate.Position = new Vector3(
  1627. Utils.UInt16ToFloat(block.ObjectData, pos, -0.5f * 256.0f, 1.5f * 256.0f),
  1628. Utils.UInt16ToFloat(block.ObjectData, pos + 2, -0.5f * 256.0f, 1.5f * 256.0f),
  1629. Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 3.0f * 256.0f));
  1630. pos += 6;
  1631. // Velocity
  1632. objectupdate.Velocity = new Vector3(
  1633. Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f),
  1634. Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f),
  1635. Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f));
  1636. pos += 6;
  1637. // Acceleration
  1638. objectupdate.Acceleration = new Vector3(
  1639. Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f),
  1640. Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f),
  1641. Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f));
  1642. pos += 6;
  1643. // Rotation (theta)
  1644. objectupdate.Rotation = new Quaternion(
  1645. Utils.UInt16ToFloat(block.ObjectData, pos, -1.0f, 1.0f),
  1646. Utils.UInt16ToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f),
  1647. Utils.UInt16ToFloat(block.ObjectData, pos + 4, -1.0f, 1.0f),
  1648. Utils.UInt16ToFloat(block.ObjectData, pos + 6, -1.0f, 1.0f));
  1649. pos += 8;
  1650. // Angular velocity (omega)
  1651. objectupdate.AngularVelocity = new Vector3(
  1652. Utils.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f),
  1653. Utils.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f),
  1654. Utils.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f));
  1655. pos += 6;
  1656. break;
  1657. case 16:
  1658. // The data is an array of single bytes (8-bit numbers)
  1659. // Position
  1660. objectupdate.Position = new Vector3(
  1661. Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
  1662. Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
  1663. Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
  1664. pos += 3;
  1665. // Velocity
  1666. objectupdate.Velocity = new Vector3(
  1667. Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
  1668. Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
  1669. Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
  1670. pos += 3;
  1671. // Accleration
  1672. objectupdate.Acceleration = new Vector3(
  1673. Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
  1674. Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
  1675. Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
  1676. pos += 3;
  1677. // Rotation
  1678. objectupdate.Rotation = new Quaternion(
  1679. Utils.ByteToFloat(block.ObjectData, pos, -1.0f, 1.0f),
  1680. Utils.ByteToFloat(block.ObjectData, pos + 1, -1.0f, 1.0f),
  1681. Utils.ByteToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f),
  1682. Utils.ByteToFloat(block.ObjectData, pos + 3, -1.0f, 1.0f));
  1683. pos += 4;
  1684. // Angular Velocity
  1685. objectupdate.AngularVelocity = new Vector3(
  1686. Utils.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
  1687. Utils.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
  1688. Utils.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
  1689. pos += 3;
  1690. break;
  1691. default:
  1692. Logger.Log("Got an ObjectUpdate block with ObjectUpdate field length of " +
  1693. block.ObjectData.Length, Helpers.LogLevel.Warning, Client);
  1694. continue;
  1695. }
  1696. #endregion
  1697. // Determine the object type and create the appropriate class
  1698. switch (pcode)
  1699. {
  1700. #region Prim and Foliage
  1701. case PCode.Grass:
  1702. case PCode.Tree:
  1703. case PCode.NewTree:
  1704. case PCode.Prim:
  1705. bool isNewObject;
  1706. lock (simulator.ObjectsPrimitives.Dictionary)
  1707. isNewObject = !simulator.ObjectsPrimitives.ContainsKey(block.ID);
  1708. Primitive prim = GetPrimitive(simulator, block.ID, block.FullID);
  1709. // Textures
  1710. objectupdate.Textures = new Primitive.TextureEntry(block.TextureEntry, 0,
  1711. block.TextureEntry.Length);
  1712. OnObjectDataBlockUpdate(new ObjectDataBlockUpdateEventArgs(simulator, prim, data, block, objectupdate, nameValues));
  1713. #region Update Prim Info with decoded data
  1714. prim.Flags = (PrimFlags)block.UpdateFlags;
  1715. if ((prim.Flags & PrimFlags.ZlibCompressed) != 0)
  1716. {
  1717. Logger.Log("Got a ZlibCompressed ObjectUpdate, implement me!",
  1718. Helpers.LogLevel.Warning, Client);
  1719. continue;
  1720. }
  1721. // Automatically request ObjectProperties for prim if it was rezzed selected.
  1722. if ((prim.Flags & PrimFlags.CreateSelected) != 0)
  1723. {
  1724. SelectObject(simulator, prim.LocalID);
  1725. }
  1726. prim.NameValues = nameValues;
  1727. prim.LocalID = block.ID;
  1728. prim.ID = block.FullID;
  1729. prim.ParentID = block.ParentID;
  1730. prim.RegionHandle = update.RegionData.RegionHandle;
  1731. prim.Scale = block.Scale;
  1732. prim.ClickAction = (ClickAction)block.ClickAction;
  1733. prim.OwnerID = block.OwnerID;
  1734. prim.MediaURL = Utils.BytesToString(block.MediaURL);
  1735. prim.Text = Utils.BytesToString(block.Text);
  1736. prim.TextColor = new Color4(block.TextColor, 0, false, true);
  1737. prim.IsAttachment = attachment;
  1738. // Sound information
  1739. prim.Sound = block.Sound;
  1740. prim.SoundFlags = (SoundFlags)block.Flags;
  1741. prim.SoundGain = block.Gain;
  1742. prim.SoundRadius = block.Radius;
  1743. // Joint information
  1744. prim.Joint = (JointType)block.JointType;
  1745. prim.JointPivot = block.JointPivot;
  1746. prim.JointAxisOrAnchor = block.JointAxisOrAnchor;
  1747. // Object parameters
  1748. prim.PrimData = data;
  1749. // Textures, texture animations, particle system, and extra params
  1750. prim.Textures = objectupdate.Textures;
  1751. prim.TextureAnim = new Primitive.TextureAnimation(block.TextureAnim, 0);
  1752. prim.ParticleSys = new Primitive.ParticleSystem(block.PSBlock, 0);
  1753. prim.SetExtraParamsFromBytes(block.ExtraParams, 0);
  1754. // PCode-specific data
  1755. switch (pcode)
  1756. {
  1757. case PCode.Grass:
  1758. case PCode.Tree:
  1759. case PCode.NewTree:
  1760. if (block.Data.Length == 1)
  1761. prim.TreeSpecies = (Tree)block.Data[0];
  1762. else
  1763. Logger.Log("Got a foliage update with an invalid TreeSpecies field", Helpers.LogLevel.Warning);
  1764. // prim.ScratchPad = Utils.EmptyBytes;
  1765. // break;
  1766. //default:
  1767. // prim.ScratchPad = new byte[block.Data.Length];
  1768. // if (block.Data.Length > 0)
  1769. // Buffer.BlockCopy(block.Data, 0, prim.ScratchPad, 0, prim.ScratchPad.Length);
  1770. break;
  1771. }
  1772. prim.ScratchPad = Utils.EmptyBytes;
  1773. // Packed parameters
  1774. prim.CollisionPlane = objectupdate.CollisionPlane;
  1775. prim.Position = objectupdate.Position;
  1776. prim.Velocity = objectupdate.Velocity;
  1777. prim.Acceleration = objectupdate.Acceleration;
  1778. prim.Rotation = objectupdate.Rotation;
  1779. prim.AngularVelocity = objectupdate.AngularVelocity;
  1780. #endregion
  1781. EventHandler<PrimEventArgs> handler = m_ObjectUpdate;
  1782. if (handler != null)
  1783. {
  1784. ThreadPool.QueueUserWorkItem(delegate(object o)
  1785. { handler(this, new PrimEventArgs(simulator, prim, update.RegionData.TimeDilation, isNewObject, attachment)); });
  1786. }
  1787. break;
  1788. #endregion Prim and Foliage
  1789. #region Avatar
  1790. case PCode.Avatar:
  1791. bool isNewAvatar;
  1792. lock (simulator.ObjectsAvatars.Dictionary)
  1793. isNewAvatar = !simulator.ObjectsAvatars.ContainsKey(block.ID);
  1794. // Update some internals if this is our avatar
  1795. if (block.FullID == Client.Self.AgentID && simulator == Client.Network.CurrentSim)
  1796. {
  1797. #region Update Client.Self
  1798. // We need the local ID to recognize terse updates for our agent
  1799. Client.Self.localID = block.ID;
  1800. // Packed parameters
  1801. Client.Self.collisionPlane = objectupdate.CollisionPlane;
  1802. Client.Self.relativePosition = objectupdate.Position;
  1803. Client.Self.velocity = objectupdate.Velocity;
  1804. Client.Self.acceleration = objectupdate.Acceleration;
  1805. Client.Self.relativeRotation = objectupdate.Rotation;
  1806. Client.Self.angularVelocity = objectupdate.AngularVelocity;
  1807. #endregion
  1808. }
  1809. #region Create an Avatar from the decoded data
  1810. Avatar avatar = GetAvatar(simulator, block.ID, block.FullID);
  1811. objectupdate.Avatar = true;
  1812. // Textures
  1813. objectupdate.Textures = new Primitive.TextureEntry(block.TextureEntry, 0,
  1814. block.TextureEntry.Length);
  1815. OnObjectDataBlockUpdate(new ObjectDataBlockUpdateEventArgs(simulator, avatar, data, block, objectupdate, nameValues));
  1816. uint oldSeatID = avatar.ParentID;
  1817. avatar.ID = block.FullID;
  1818. avatar.LocalID = block.ID;
  1819. avatar.Scale = block.Scale;
  1820. avatar.CollisionPlane = objectupdate.CollisionPlane;
  1821. avatar.Position = objectupdate.Position;
  1822. avatar.Velocity = objectupdate.Velocity;
  1823. avatar.Acceleration = objectupdate.Acceleration;
  1824. avatar.Rotation = objectupdate.Rotation;
  1825. avatar.AngularVelocity = objectupdate.AngularVelocity;
  1826. avatar.NameValues = nameValues;
  1827. avatar.PrimData = data;
  1828. if (block.Data.Length > 0)
  1829. {
  1830. Logger.Log("Unexpected Data field for an avatar update, length " + block.Data.Length, Helpers.LogLevel.Warning);
  1831. }
  1832. avatar.ParentID = block.ParentID;
  1833. avatar.RegionHandle = update.RegionData.RegionHandle;
  1834. SetAvatarSittingOn(simulator, avatar, block.ParentID, oldSeatID);
  1835. // Textures
  1836. avatar.Textures = objectupdate.Textures;
  1837. #endregion Create an Avatar from the decoded data
  1838. OnAvatarUpdate(new AvatarUpdateEventArgs(simulator, avatar, update.RegionData.TimeDilation, isNewAvatar));
  1839. break;
  1840. #endregion Avatar
  1841. case PCode.ParticleSystem:
  1842. DecodeParticleUpdate(block);
  1843. // TODO: Create a callback for particle updates
  1844. break;
  1845. default:
  1846. Logger.DebugLog("Got an ObjectUpdate block with an unrecognized PCode " + pcode.ToString(), Client);
  1847. break;
  1848. }
  1849. }
  1850. }
  1851. protected void DecodeParticleUpdate(ObjectUpdatePacket.ObjectDataBlock block)
  1852. {
  1853. // TODO: Handle ParticleSystem ObjectUpdate blocks
  1854. // float bounce_b
  1855. // Vector4 scale_range
  1856. // Vector4 alpha_range
  1857. // Vector3 vel_offset
  1858. // float dist_begin_fadeout
  1859. // float dist_end_fadeout
  1860. // UUID image_uuid
  1861. // long flags
  1862. // byte createme
  1863. // Vector3 diff_eq_alpha
  1864. // Vector3 diff_eq_scale
  1865. // byte max_particles
  1866. // byte initial_particles
  1867. // float kill_plane_z
  1868. // Vector3 kill_plane_normal
  1869. // float bounce_plane_z
  1870. // Vector3 bounce_plane_normal
  1871. // float spawn_range
  1872. // float spawn_frequency
  1873. // float spawn_frequency_range
  1874. // Vector3 spawn_direction
  1875. // float spawn_direction_range
  1876. // float spawn_velocity
  1877. // float spawn_velocity_range
  1878. // float speed_limit
  1879. // float wind_weight
  1880. // Vector3 current_gravity
  1881. // float gravity_weight
  1882. // float global_lifetime
  1883. // float individual_lifetime
  1884. // float individual_lifetime_range
  1885. // float alpha_decay
  1886. // float scale_decay
  1887. // float distance_death
  1888. // float damp_motion_factor
  1889. // Vector3 wind_diffusion_factor
  1890. }
  1891. /// <summary>
  1892. /// A terse object update, used when a transformation matrix or
  1893. /// velocity/acceleration for an object changes but nothing else
  1894. /// (scale/position/rotation/acceleration/velocity)
  1895. /// </summary>
  1896. /// <param name="sender">The sender</param>
  1897. /// <param name="e">The EventArgs object containing the packet data</param>
  1898. protected void ImprovedTerseObjectUpdateHandler(object sender, PacketReceivedEventArgs e)
  1899. {
  1900. Packet packet = e.Packet;
  1901. Simulator simulator = e.Simulator;
  1902. ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)packet;
  1903. UpdateDilation(simulator, terse.RegionData.TimeDilation);
  1904. for (int i = 0; i < terse.ObjectData.Length; i++)
  1905. {
  1906. ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = terse.ObjectData[i];
  1907. try
  1908. {
  1909. int pos = 4;
  1910. uint localid = Utils.BytesToUInt(block.Data, 0);
  1911. // Check if we are interested in this update
  1912. if (!Client.Settings.ALWAYS_DECODE_OBJECTS
  1913. && localid != Client.Self.localID
  1914. && m_TerseObjectUpdate == null)
  1915. {
  1916. continue;
  1917. }
  1918. #region Decode update data
  1919. ObjectMovementUpdate update = new ObjectMovementUpdate();
  1920. // LocalID
  1921. update.LocalID = localid;
  1922. // State
  1923. update.State = block.Data[pos++];
  1924. // Avatar boolean
  1925. update.Avatar = (block.Data[pos++] != 0);
  1926. // Collision normal for avatar
  1927. if (update.Avatar)
  1928. {
  1929. update.CollisionPlane = new Vector4(block.Data, pos);
  1930. pos += 16;
  1931. }
  1932. // Position
  1933. update.Position = new Vector3(block.Data, pos);
  1934. pos += 12;
  1935. // Velocity
  1936. update.Velocity = new Vector3(
  1937. Utils.UInt16ToFloat(block.Data, pos, -128.0f, 128.0f),
  1938. Utils.UInt16ToFloat(block.Data, pos + 2, -128.0f, 128.0f),
  1939. Utils.UInt16ToFloat(block.Data, pos + 4, -128.0f, 128.0f));
  1940. pos += 6;
  1941. // Acceleration
  1942. update.Acceleration = new Vector3(
  1943. Utils.UInt16ToFloat(block.Data, pos, -64.0f, 64.0f),
  1944. Utils.UInt16ToFloat(block.Data, pos + 2, -64.0f, 64.0f),
  1945. Utils.UInt16ToFloat(block.Data, pos + 4, -64.0f, 64.0f));
  1946. pos += 6;
  1947. // Rotation (theta)
  1948. update.Rotation = new Quaternion(
  1949. Utils.UInt16ToFloat(block.Data, pos, -1.0f, 1.0f),
  1950. Utils.UInt16ToFloat(block.Data, pos + 2, -1.0f, 1.0f),
  1951. Utils.UInt16ToFloat(block.Data, pos + 4, -1.0f, 1.0f),
  1952. Utils.UInt16ToFloat(block.Data, pos + 6, -1.0f, 1.0f));
  1953. pos += 8;
  1954. // Angular velocity (omega)
  1955. update.AngularVelocity = new Vector3(
  1956. Utils.UInt16ToFloat(block.Data, pos, -64.0f, 64.0f),
  1957. Utils.UInt16ToFloat(block.Data, pos + 2, -64.0f, 64.0f),
  1958. Utils.UInt16ToFloat(block.Data, pos + 4, -64.0f, 64.0f));
  1959. pos += 6;
  1960. // Textures
  1961. // FIXME: Why are we ignoring the first four bytes here?
  1962. if (block.TextureEntry.Length != 0)
  1963. update.Textures = new Primitive.TextureEntry(block.TextureEntry, 4, block.TextureEntry.Length - 4);
  1964. #endregion Decode update data
  1965. Primitive obj = !Client.Settings.OBJECT_TRACKING ? null : (update.Avatar) ?
  1966. (Primitive)GetAvatar(simulator, update.LocalID, UUID.Zero) :
  1967. (Primitive)GetPrimitive(simulator, update.LocalID, UUID.Zero);
  1968. // Fire the pre-emptive notice (before we stomp the object)
  1969. EventHandler<TerseObjectUpdateEventArgs> handler = m_TerseObjectUpdate;
  1970. if (handler != null)
  1971. {
  1972. ThreadPool.QueueUserWorkItem(delegate(object o)
  1973. { handler(this, new TerseObjectUpdateEventArgs(simulator, obj, update, terse.RegionData.TimeDilation)); });
  1974. }
  1975. #region Update Client.Self
  1976. if (update.LocalID == Client.Self.localID)
  1977. {
  1978. Client.Self.collisionPlane = update.CollisionPlane;
  1979. Client.Self.relativePosition = update.Position;
  1980. Client.Self.velocity = update.Velocity;
  1981. Client.Self.acceleration = update.Acceleration;
  1982. Client.Self.relativeRotation = update.Rotation;
  1983. Client.Self.angularVelocity = update.AngularVelocity;
  1984. }
  1985. #endregion Update Client.Self
  1986. if (Client.Settings.OBJECT_TRACKING && obj != null)
  1987. {
  1988. obj.Position = update.Position;
  1989. obj.Rotation = update.Rotation;
  1990. obj.Velocity = update.Velocity;
  1991. obj.CollisionPlane = update.CollisionPlane;
  1992. obj.Acceleration = update.Acceleration;
  1993. obj.AngularVelocity = update.AngularVelocity;
  1994. obj.PrimData.State = update.State;
  1995. if (update.Textures != null)
  1996. obj.Textures = update.Textures;
  1997. }
  1998. }
  1999. catch (Exception ex)
  2000. {
  2001. Logger.Log(ex.Message, Helpers.LogLevel.Warning, Client, ex);
  2002. }
  2003. }
  2004. }
  2005. /// <summary>Process an incoming packet and raise the appropriate events</summary>
  2006. /// <param name="sender">The sender</param>
  2007. /// <param name="e">The EventArgs object containing the packet data</param>
  2008. protected void ObjectUpdateCompressedHandler(object sender, PacketReceivedEventArgs e)
  2009. {
  2010. Packet packet = e.Packet;
  2011. Simulator simulator = e.Simulator;
  2012. ObjectUpdateCompressedPacket update = (ObjectUpdateCompressedPacket)packet;
  2013. for (int b = 0; b < update.ObjectData.Length; b++)
  2014. {
  2015. ObjectUpdateCompressedPacket.ObjectDataBlock block = update.ObjectData[b];
  2016. int i = 0;
  2017. try
  2018. {
  2019. // UUID
  2020. UUID FullID = new UUID(block.Data, 0);
  2021. i += 16;
  2022. // Local ID
  2023. uint LocalID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
  2024. (block.Data[i++] << 16) + (block.Data[i++] << 24));
  2025. // PCode
  2026. PCode pcode = (PCode)block.Data[i++];
  2027. #region Relevance check
  2028. if (!Client.Settings.ALWAYS_DECODE_OBJECTS)
  2029. {
  2030. switch (pcode)
  2031. {
  2032. case PCode.Grass:
  2033. case PCode.Tree:
  2034. case PCode.NewTree:
  2035. case PCode.Prim:
  2036. if (m_ObjectUpdate == null) continue;
  2037. break;
  2038. }
  2039. }
  2040. #endregion Relevance check
  2041. bool isNew;
  2042. lock (simulator.ObjectsPrimitives.Dictionary)
  2043. isNew = !simulator.ObjectsPrimitives.ContainsKey(LocalID);
  2044. Primitive prim = GetPrimitive(simulator, LocalID, FullID);
  2045. prim.LocalID = LocalID;
  2046. prim.ID = FullID;
  2047. prim.Flags = (PrimFlags)block.UpdateFlags;
  2048. prim.PrimData.PCode = pcode;
  2049. #region Decode block and update Prim
  2050. // State
  2051. prim.PrimData.State = block.Data[i++];
  2052. // CRC
  2053. i += 4;
  2054. // Material
  2055. prim.PrimData.Material = (Material)block.Data[i++];
  2056. // Click action
  2057. prim.ClickAction = (ClickAction)block.Data[i++];
  2058. // Scale
  2059. prim.Scale = new Vector3(block.Data, i);
  2060. i += 12;
  2061. // Position
  2062. prim.Position = new Vector3(block.Data, i);
  2063. i += 12;
  2064. // Rotation
  2065. prim.Rotation = new Quaternion(block.Data, i, true);
  2066. i += 12;
  2067. // Compressed flags
  2068. CompressedFlags flags = (CompressedFlags)Utils.BytesToUInt(block.Data, i);
  2069. i += 4;
  2070. prim.OwnerID = new UUID(block.Data, i);
  2071. i += 16;
  2072. // Angular velocity
  2073. if ((flags & CompressedFlags.HasAngularVelocity) != 0)
  2074. {
  2075. prim.AngularVelocity = new Vector3(block.Data, i);
  2076. i += 12;
  2077. }
  2078. // Parent ID
  2079. if ((flags & CompressedFlags.HasParent) != 0)
  2080. {
  2081. prim.ParentID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
  2082. (block.Data[i++] << 16) + (block.Data[i++] << 24));
  2083. }
  2084. else
  2085. {
  2086. prim.ParentID = 0;
  2087. }
  2088. // Tree data
  2089. if ((flags & CompressedFlags.Tree) != 0)
  2090. {
  2091. prim.TreeSpecies = (Tree)block.Data[i++];
  2092. //prim.ScratchPad = Utils.EmptyBytes;
  2093. }
  2094. // Scratch pad
  2095. else if ((flags & CompressedFlags.ScratchPad) != 0)
  2096. {
  2097. prim.TreeSpecies = (Tree)0;
  2098. int size = block.Data[i++];
  2099. //prim.ScratchPad = new byte[size];
  2100. //Buffer.BlockCopy(block.Data, i, prim.ScratchPad, 0, size);
  2101. i += size;
  2102. }
  2103. prim.ScratchPad = Utils.EmptyBytes;
  2104. // Floating text
  2105. if ((flags & CompressedFlags.HasText) != 0)
  2106. {
  2107. string text = String.Empty;
  2108. while (block.Data[i] != 0)
  2109. {
  2110. text += (char)block.Data[i];
  2111. i++;
  2112. }
  2113. i++;
  2114. // Floating text
  2115. prim.Text = text;
  2116. // Text color
  2117. prim.TextColor = new Color4(block.Data, i, false);
  2118. i += 4;
  2119. }
  2120. else
  2121. {
  2122. prim.Text = String.Empty;
  2123. }
  2124. // Media URL
  2125. if ((flags & CompressedFlags.MediaURL) != 0)
  2126. {
  2127. string text = String.Empty;
  2128. while (block.Data[i] != 0)
  2129. {
  2130. text += (char)block.Data[i];
  2131. i++;
  2132. }
  2133. i++;
  2134. prim.MediaURL = text;
  2135. }
  2136. // Particle system
  2137. if ((flags & CompressedFlags.HasParticles) != 0)
  2138. {
  2139. prim.ParticleSys = new Primitive.ParticleSystem(block.Data, i);
  2140. i += 86;
  2141. }
  2142. // Extra parameters
  2143. i += prim.SetExtraParamsFromBytes(block.Data, i);
  2144. //Sound data
  2145. if ((flags & CompressedFlags.HasSound) != 0)
  2146. {
  2147. prim.Sound = new UUID(block.Data, i);
  2148. i += 16;
  2149. prim.SoundGain = Utils.BytesToFloat(block.Data, i);
  2150. i += 4;
  2151. prim.SoundFlags = (SoundFlags)block.Data[i++];
  2152. prim.SoundRadius = Utils.BytesToFloat(block.Data, i);
  2153. i += 4;
  2154. }
  2155. // Name values
  2156. if ((flags & CompressedFlags.HasNameValues) != 0)
  2157. {
  2158. string text = String.Empty;
  2159. while (block.Data[i] != 0)
  2160. {
  2161. text += (char)block.Data[i];
  2162. i++;
  2163. }
  2164. i++;
  2165. // Parse the name values
  2166. if (text.Length > 0)
  2167. {
  2168. string[] lines = text.Split('\n');
  2169. prim.NameValues = new NameValue[lines.Length];
  2170. for (int j = 0; j < lines.Length; j++)
  2171. {
  2172. if (!String.IsNullOrEmpty(lines[j]))
  2173. {
  2174. NameValue nv = new NameValue(lines[j]);
  2175. prim.NameValues[j] = nv;
  2176. }
  2177. }
  2178. }
  2179. }
  2180. prim.PrimData.PathCurve = (PathCurve)block.Data[i++];
  2181. ushort pathBegin = Utils.BytesToUInt16(block.Data, i); i += 2;
  2182. prim.PrimData.PathBegin = Primitive.UnpackBeginCut(pathBegin);
  2183. ushort pathEnd = Utils.BytesToUInt16(block.Data, i); i += 2;
  2184. prim.PrimData.PathEnd = Primitive.UnpackEndCut(pathEnd);
  2185. prim.PrimData.PathScaleX = Primitive.UnpackPathScale(block.Data[i++]);
  2186. prim.PrimData.PathScaleY = Primitive.UnpackPathScale(block.Data[i++]);
  2187. prim.PrimData.PathShearX = Primitive.UnpackPathShear((sbyte)block.Data[i++]);
  2188. prim.PrimData.PathShearY = Primitive.UnpackPathShear((sbyte)block.Data[i++]);
  2189. prim.PrimData.PathTwist = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
  2190. prim.PrimData.PathTwistBegin = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
  2191. prim.PrimData.PathRadiusOffset = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
  2192. prim.PrimData.PathTaperX = Primitive.UnpackPathTaper((sbyte)block.Data[i++]);
  2193. prim.PrimData.PathTaperY = Primitive.UnpackPathTaper((sbyte)block.Data[i++]);
  2194. prim.PrimData.PathRevolutions = Primitive.UnpackPathRevolutions(block.Data[i++]);
  2195. prim.PrimData.PathSkew = Primitive.UnpackPathTwist((sbyte)block.Data[i++]);
  2196. prim.PrimData.profileCurve = block.Data[i++];
  2197. ushort profileBegin = Utils.BytesToUInt16(block.Data, i); i += 2;
  2198. prim.PrimData.ProfileBegin = Primitive.UnpackBeginCut(profileBegin);
  2199. ushort profileEnd = Utils.BytesToUInt16(block.Data, i); i += 2;
  2200. prim.PrimData.ProfileEnd = Primitive.UnpackEndCut(profileEnd);
  2201. ushort profileHollow = Utils.BytesToUInt16(block.Data, i); i += 2;
  2202. prim.PrimData.ProfileHollow = Primitive.UnpackProfileHollow(profileHollow);
  2203. // TextureEntry
  2204. int textureEntryLength = (int)Utils.BytesToUInt(block.Data, i);
  2205. i += 4;
  2206. prim.Textures = new Primitive.TextureEntry(block.Data, i, textureEntryLength);
  2207. i += textureEntryLength;
  2208. // Texture animation
  2209. if ((flags & CompressedFlags.TextureAnimation) != 0)
  2210. {
  2211. //int textureAnimLength = (int)Utils.BytesToUIntBig(block.Data, i);
  2212. i += 4;
  2213. prim.TextureAnim = new Primitive.TextureAnimation(block.Data, i);
  2214. }
  2215. #endregion
  2216. prim.IsAttachment = (flags & CompressedFlags.HasNameValues) != 0 && prim.ParentID != 0;
  2217. #region Raise Events
  2218. EventHandler<PrimEventArgs> handler = m_ObjectUpdate;
  2219. if (handler != null)
  2220. handler(this, new PrimEventArgs(simulator, prim, update.RegionData.TimeDilation, isNew, prim.IsAttachment));
  2221. #endregion
  2222. }
  2223. catch (IndexOutOfRangeException ex)
  2224. {
  2225. Logger.Log("Error decoding an ObjectUpdateCompressed packet", Helpers.LogLevel.Warning, Client, ex);
  2226. Logger.Log(block, Helpers.LogLevel.Warning);
  2227. }
  2228. }
  2229. }
  2230. /// <summary>Process an incoming packet and raise the appropriate events</summary>
  2231. /// <param name="sender">The sender</param>
  2232. /// <param name="e">The EventArgs object containing the packet data</param>
  2233. protected void ObjectUpdateCachedHandler(object sender, PacketReceivedEventArgs e)
  2234. {
  2235. if (Client.Settings.ALWAYS_REQUEST_OBJECTS)
  2236. {
  2237. bool cachedPrimitives = Client.Settings.CACHE_PRIMITIVES;
  2238. Packet packet = e.Packet;
  2239. Simulator simulator = e.Simulator;
  2240. ObjectUpdateCachedPacket update = (ObjectUpdateCachedPacket)packet;
  2241. List<uint> ids = new List<uint>(update.ObjectData.Length);
  2242. // Object caching is implemented when Client.Settings.PRIMITIVES_FACTORY is True, otherwise request updates for all of these objects
  2243. for (int i = 0; i < update.ObjectData.Length; i++)
  2244. {
  2245. uint localID = update.ObjectData[i].ID;
  2246. if (cachedPrimitives)
  2247. {
  2248. if (!simulator.DataPool.NeedsRequest(localID))
  2249. {
  2250. continue;
  2251. }
  2252. }
  2253. ids.Add(localID);
  2254. }
  2255. RequestObjects(simulator, ids);
  2256. }
  2257. }
  2258. /// <summary>Process an incoming packet and raise the appropriate events</summary>
  2259. /// <param name="sender">The sender</param>
  2260. /// <param name="e">The EventArgs object containing the packet data</param>
  2261. protected void KillObjectHandler(object sender, PacketReceivedEventArgs e)
  2262. {
  2263. Packet packet = e.Packet;
  2264. Simulator simulator = e.Simulator;
  2265. KillObjectPacket kill = (KillObjectPacket)packet;
  2266. // Notify first, so that handler has a chance to get a
  2267. // reference from the ObjectTracker to the object being killed
  2268. for (int i = 0; i < kill.ObjectData.Length; i++)
  2269. {
  2270. OnKillObject(new KillObjectEventArgs(simulator, kill.ObjectData[i].ID));
  2271. }
  2272. lock (simulator.ObjectsPrimitives.Dictionary)
  2273. {
  2274. List<uint> removeAvatars = new List<uint>();
  2275. List<uint> removePrims = new List<uint>();
  2276. if (Client.Settings.OBJECT_TRACKING)
  2277. {
  2278. uint localID;
  2279. for (int i = 0; i < kill.ObjectData.Length; i++)
  2280. {
  2281. localID = kill.ObjectData[i].ID;
  2282. if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(localID))
  2283. removePrims.Add(localID);
  2284. foreach (KeyValuePair<uint, Primitive> prim in simulator.ObjectsPrimitives.Dictionary)
  2285. {
  2286. if (prim.Value.ParentID == localID)
  2287. {
  2288. OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
  2289. removePrims.Add(prim.Key);
  2290. }
  2291. }
  2292. }
  2293. }
  2294. if (Client.Settings.AVATAR_TRACKING)
  2295. {
  2296. lock (simulator.ObjectsAvatars.Dictionary)
  2297. {
  2298. uint localID;
  2299. for (int i = 0; i < kill.ObjectData.Length; i++)
  2300. {
  2301. localID = kill.ObjectData[i].ID;
  2302. if (simulator.ObjectsAvatars.Dictionary.ContainsKey(localID))
  2303. removeAvatars.Add(localID);
  2304. List<uint> rootPrims = new List<uint>();
  2305. foreach (KeyValuePair<uint, Primitive> prim in simulator.ObjectsPrimitives.Dictionary)
  2306. {
  2307. if (prim.Value.ParentID == localID)
  2308. {
  2309. OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
  2310. removePrims.Add(prim.Key);
  2311. rootPrims.Add(prim.Key);
  2312. }
  2313. }
  2314. foreach (KeyValuePair<uint, Primitive> prim in simulator.ObjectsPrimitives.Dictionary)
  2315. {
  2316. if (rootPrims.Contains(prim.Value.ParentID))
  2317. {
  2318. OnKillObject(new KillObjectEventArgs(simulator, prim.Key));
  2319. removePrims.Add(prim.Key);
  2320. }
  2321. }
  2322. }
  2323. //Do the actual removing outside of the loops but still inside the lock.
  2324. //This safely prevents the collection from being modified during a loop.
  2325. foreach (uint removeID in removeAvatars)
  2326. simulator.ObjectsAvatars.Dictionary.Remove(removeID);
  2327. }
  2328. }
  2329. if (Client.Settings.CACHE_PRIMITIVES)
  2330. {
  2331. simulator.DataPool.ReleasePrims(removePrims);
  2332. }
  2333. foreach (uint removeID in removePrims)
  2334. simulator.ObjectsPrimitives.Dictionary.Remove(removeID);
  2335. }
  2336. }
  2337. /// <summary>Process an incoming packet and raise the appropriate events</summary>
  2338. /// <param name="sender">The sender</param>
  2339. /// <param name="e">The EventArgs object containing the packet data</param>
  2340. protected void ObjectPropertiesHandler(object sender, PacketReceivedEventArgs e)
  2341. {
  2342. Packet packet = e.Packet;
  2343. Simulator simulator = e.Simulator;
  2344. ObjectPropertiesPacket op = (ObjectPropertiesPacket)packet;
  2345. ObjectPropertiesPacket.ObjectDataBlock[] datablocks = op.ObjectData;
  2346. for (int i = 0; i < datablocks.Length; ++i)
  2347. {
  2348. ObjectPropertiesPacket.ObjectDataBlock objectData = datablocks[i];
  2349. Primitive.ObjectProperties props = new Primitive.ObjectProperties();
  2350. props.ObjectID = objectData.ObjectID;
  2351. props.AggregatePerms = objectData.AggregatePerms;
  2352. props.AggregatePermTextures = objectData.AggregatePermTextures;
  2353. props.AggregatePermTexturesOwner = objectData.AggregatePermTexturesOwner;
  2354. props.Permissions = new Permissions(objectData.BaseMask, objectData.EveryoneMask, objectData.GroupMask,
  2355. objectData.NextOwnerMask, objectData.OwnerMask);
  2356. props.Category = (ObjectCategory)objectData.Category;
  2357. props.CreationDate = Utils.UnixTimeToDateTime((uint)objectData.CreationDate);
  2358. props.CreatorID = objectData.CreatorID;
  2359. props.Description = Utils.BytesToString(objectData.Description);
  2360. props.FolderID = objectData.FolderID;
  2361. props.FromTaskID = objectData.FromTaskID;
  2362. props.GroupID = objectData.GroupID;
  2363. props.InventorySerial = objectData.InventorySerial;
  2364. props.ItemID = objectData.ItemID;
  2365. props.LastOwnerID = objectData.LastOwnerID;
  2366. props.Name = Utils.BytesToString(objectData.Name);
  2367. props.OwnerID = objectData.OwnerID;
  2368. props.OwnershipCost = objectData.OwnershipCost;
  2369. props.SalePrice = objectData.SalePrice;
  2370. props.SaleType = (SaleType)objectData.SaleType;
  2371. props.SitName = Utils.BytesToString(objectData.SitName);
  2372. props.TouchName = Utils.BytesToString(objectData.TouchName);
  2373. int numTextures = objectData.TextureID.Length / 16;
  2374. props.TextureIDs = new UUID[numTextures];
  2375. for (int j = 0; j < numTextures; ++j)
  2376. props.TextureIDs[j] = new UUID(objectData.TextureID, j * 16);
  2377. if (Client.Settings.OBJECT_TRACKING)
  2378. {
  2379. Primitive findPrim = simulator.ObjectsPrimitives.Find(
  2380. delegate(Primitive prim) { return prim.ID == props.ObjectID; });
  2381. if (findPrim != null)
  2382. {
  2383. OnObjectPropertiesUpdated(new ObjectPropertiesUpdatedEventArgs(simulator, findPrim, props));
  2384. lock (simulator.ObjectsPrimitives.Dictionary)
  2385. {
  2386. if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(findPrim.LocalID))
  2387. simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties = props;
  2388. }
  2389. }
  2390. }
  2391. OnObjectProperties(new ObjectPropertiesEventArgs(simulator, props));
  2392. }
  2393. }
  2394. /// <summary>Process an incoming packet and raise the appropriate events</summary>
  2395. /// <param name="sender">The sender</param>
  2396. /// <param name="e">The EventArgs object containing the packet data</param>
  2397. protected void ObjectPropertiesFamilyHandler(object sender, PacketReceivedEventArgs e)
  2398. {
  2399. Packet packet = e.Packet;
  2400. Simulator simulator = e.Simulator;
  2401. ObjectPropertiesFamilyPacket op = (ObjectPropertiesFamilyPacket)packet;
  2402. Primitive.ObjectProperties props = new Primitive.ObjectProperties();
  2403. ReportType requestType = (ReportType)op.ObjectData.RequestFlags;
  2404. props.ObjectID = op.ObjectData.ObjectID;
  2405. props.Category = (ObjectCategory)op.ObjectData.Category;
  2406. props.Description = Utils.BytesToString(op.ObjectData.Description);
  2407. props.GroupID = op.ObjectData.GroupID;
  2408. props.LastOwnerID = op.ObjectData.LastOwnerID;
  2409. props.Name = Utils.BytesToString(op.ObjectData.Name);
  2410. props.OwnerID = op.ObjectData.OwnerID;
  2411. props.OwnershipCost = op.ObjectData.OwnershipCost;
  2412. props.SalePrice = op.ObjectData.SalePrice;
  2413. props.SaleType = (SaleType)op.ObjectData.SaleType;
  2414. props.Permissions.BaseMask = (PermissionMask)op.ObjectData.BaseMask;
  2415. props.Permissions.EveryoneMask = (PermissionMask)op.ObjectData.EveryoneMask;
  2416. props.Permissions.GroupMask = (PermissionMask)op.ObjectData.GroupMask;
  2417. props.Permissions.NextOwnerMask = (PermissionMask)op.ObjectData.NextOwnerMask;
  2418. props.Permissions.OwnerMask = (PermissionMask)op.ObjectData.OwnerMask;
  2419. if (Client.Settings.OBJECT_TRACKING)
  2420. {
  2421. Primitive findPrim = simulator.ObjectsPrimitives.Find(
  2422. delegate(Primitive prim) { return prim.ID == op.ObjectData.ObjectID; });
  2423. if (findPrim != null)
  2424. {
  2425. lock (simulator.ObjectsPrimitives.Dictionary)
  2426. {
  2427. if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(findPrim.LocalID))
  2428. {
  2429. if (simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties == null)
  2430. simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties = new Primitive.ObjectProperties();
  2431. simulator.ObjectsPrimitives.Dictionary[findPrim.LocalID].Properties.SetFamilyProperties(props);
  2432. }
  2433. }
  2434. }
  2435. }
  2436. OnObjectPropertiesFamily(new ObjectPropertiesFamilyEventArgs(simulator, props, requestType));
  2437. }
  2438. /// <summary>Process an incoming packet and raise the appropriate events</summary>
  2439. /// <param name="sender">The sender</param>
  2440. /// <param name="e">The EventArgs object containing the packet data</param>
  2441. protected void PayPriceReplyHandler(object sender, PacketReceivedEventArgs e)
  2442. {
  2443. if (m_PayPriceReply != null)
  2444. {
  2445. Packet packet = e.Packet;
  2446. Simulator simulator = e.Simulator;
  2447. PayPriceReplyPacket p = (PayPriceReplyPacket)packet;
  2448. UUID objectID = p.ObjectData.ObjectID;
  2449. int defaultPrice = p.ObjectData.DefaultPayPrice;
  2450. int[] buttonPrices = new int[p.ButtonData.Length];
  2451. for (int i = 0; i < p.ButtonData.Length; i++)
  2452. {
  2453. buttonPrices[i] = p.ButtonData[i].PayButton;
  2454. }
  2455. OnPayPriceReply(new PayPriceReplyEventArgs(simulator, objectID, defaultPrice, buttonPrices));
  2456. }
  2457. }
  2458. /// <summary>
  2459. ///
  2460. /// </summary>
  2461. /// <param name="capsKey"></param>
  2462. /// <param name="message"></param>
  2463. /// <param name="simulator"></param>
  2464. protected void ObjectPhysicsPropertiesHandler(string capsKey, IMessage message, Simulator simulator)
  2465. {
  2466. ObjectPhysicsPropertiesMessage msg = (ObjectPhysicsPropertiesMessage)message;
  2467. if (Client.Settings.OBJECT_TRACKING)
  2468. {
  2469. for (int i = 0; i < msg.ObjectPhysicsProperties.Length; i++)
  2470. {
  2471. lock (simulator.ObjectsPrimitives.Dictionary)
  2472. {
  2473. if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(msg.ObjectPhysicsProperties[i].LocalID))
  2474. {
  2475. simulator.ObjectsPrimitives.Dictionary[msg.ObjectPhysicsProperties[i].LocalID].PhysicsProps = msg.ObjectPhysicsProperties[i];
  2476. }
  2477. }
  2478. }
  2479. }
  2480. if (m_PhysicsProperties != null)
  2481. {
  2482. for (int i = 0; i < msg.ObjectPhysicsProperties.Length; i++)
  2483. {
  2484. OnPhysicsProperties(new PhysicsPropertiesEventArgs(simulator, msg.ObjectPhysicsProperties[i]));
  2485. }
  2486. }
  2487. }
  2488. #endregion Packet Handlers
  2489. #region Utility Functions
  2490. /// <summary>
  2491. /// Setup construction data for a basic primitive shape
  2492. /// </summary>
  2493. /// <param name="type">Primitive shape to construct</param>
  2494. /// <returns>Construction data that can be plugged into a <seealso cref="Primitive"/></returns>
  2495. public static Primitive.ConstructionData BuildBasicShape(PrimType type)
  2496. {
  2497. Primitive.ConstructionData prim = new Primitive.ConstructionData();
  2498. prim.PCode = PCode.Prim;
  2499. prim.Material = Material.Wood;
  2500. switch (type)
  2501. {
  2502. case PrimType.Box:
  2503. prim.ProfileCurve = ProfileCurve.Square;
  2504. prim.PathCurve = PathCurve.Line;
  2505. prim.ProfileEnd = 1f;
  2506. prim.PathEnd = 1f;
  2507. prim.PathScaleX = 1f;
  2508. prim.PathScaleY = 1f;
  2509. prim.PathRevolutions = 1f;
  2510. break;
  2511. case PrimType.Cylinder:
  2512. prim.ProfileCurve = ProfileCurve.Circle;
  2513. prim.PathCurve = PathCurve.Line;
  2514. prim.ProfileEnd = 1f;
  2515. prim.PathEnd = 1f;
  2516. prim.PathScaleX = 1f;
  2517. prim.PathScaleY = 1f;
  2518. prim.PathRevolutions = 1f;
  2519. break;
  2520. case PrimType.Prism:
  2521. prim.ProfileCurve = ProfileCurve.EqualTriangle;
  2522. prim.PathCurve = PathCurve.Line;
  2523. prim.ProfileEnd = 1f;
  2524. prim.PathEnd = 1f;
  2525. prim.PathScaleX = 0f;
  2526. prim.PathScaleY = 0f;
  2527. prim.PathRevolutions = 1f;
  2528. break;
  2529. case PrimType.Ring:
  2530. prim.ProfileCurve = ProfileCurve.EqualTriangle;
  2531. prim.PathCurve = PathCurve.Circle;
  2532. prim.ProfileEnd = 1f;
  2533. prim.PathEnd = 1f;
  2534. prim.PathScaleX = 1f;
  2535. prim.PathScaleY = 0.25f;
  2536. prim.PathRevolutions = 1f;
  2537. break;
  2538. case PrimType.Sphere:
  2539. prim.ProfileCurve = ProfileCurve.HalfCircle;
  2540. prim.PathCurve = PathCurve.Circle;
  2541. prim.ProfileEnd = 1f;
  2542. prim.PathEnd = 1f;
  2543. prim.PathScaleX = 1f;
  2544. prim.PathScaleY = 1f;
  2545. prim.PathRevolutions = 1f;
  2546. break;
  2547. case PrimType.Torus:
  2548. prim.ProfileCurve = ProfileCurve.Circle;
  2549. prim.PathCurve = PathCurve.Circle;
  2550. prim.ProfileEnd = 1f;
  2551. prim.PathEnd = 1f;
  2552. prim.PathScaleX = 1f;
  2553. prim.PathScaleY = 0.25f;
  2554. prim.PathRevolutions = 1f;
  2555. break;
  2556. case PrimType.Tube:
  2557. prim.ProfileCurve = ProfileCurve.Square;
  2558. prim.PathCurve = PathCurve.Circle;
  2559. prim.ProfileEnd = 1f;
  2560. prim.PathEnd = 1f;
  2561. prim.PathScaleX = 1f;
  2562. prim.PathScaleY = 0.25f;
  2563. prim.PathRevolutions = 1f;
  2564. break;
  2565. case PrimType.Sculpt:
  2566. prim.ProfileCurve = ProfileCurve.Circle;
  2567. prim.PathCurve = PathCurve.Circle;
  2568. prim.ProfileEnd = 1f;
  2569. prim.PathEnd = 1f;
  2570. prim.PathScaleX = 1f;
  2571. prim.PathScaleY = 0.5f;
  2572. prim.PathRevolutions = 1f;
  2573. break;
  2574. default:
  2575. throw new NotSupportedException("Unsupported shape: " + type.ToString());
  2576. }
  2577. return prim;
  2578. }
  2579. /// <summary>
  2580. ///
  2581. /// </summary>
  2582. /// <param name="sim"></param>
  2583. /// <param name="av"></param>
  2584. /// <param name="localid"></param>
  2585. /// <param name="oldSeatID"></param>
  2586. protected void SetAvatarSittingOn(Simulator sim, Avatar av, uint localid, uint oldSeatID)
  2587. {
  2588. if (Client.Network.CurrentSim == sim && av.LocalID == Client.Self.localID)
  2589. {
  2590. Client.Self.sittingOn = localid;
  2591. }
  2592. av.ParentID = localid;
  2593. if (m_AvatarSitChanged != null && oldSeatID != localid)
  2594. {
  2595. OnAvatarSitChanged(new AvatarSitChangedEventArgs(sim, av, localid, oldSeatID));
  2596. }
  2597. }
  2598. /// <summary>
  2599. ///
  2600. /// </summary>
  2601. /// <param name="s"></param>
  2602. /// <param name="dilation"></param>
  2603. protected void UpdateDilation(Simulator s, uint dilation)
  2604. {
  2605. s.Stats.Dilation = (float)dilation / 65535.0f;
  2606. }
  2607. /// <summary>
  2608. /// Set the Shape data of an object
  2609. /// </summary>
  2610. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  2611. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  2612. /// <param name="prim">Data describing the prim shape</param>
  2613. public void SetShape(Simulator simulator, uint localID, Primitive.ConstructionData prim)
  2614. {
  2615. ObjectShapePacket shape = new ObjectShapePacket();
  2616. shape.AgentData.AgentID = Client.Self.AgentID;
  2617. shape.AgentData.SessionID = Client.Self.SessionID;
  2618. shape.ObjectData = new OpenMetaverse.Packets.ObjectShapePacket.ObjectDataBlock[1];
  2619. shape.ObjectData[0] = new OpenMetaverse.Packets.ObjectShapePacket.ObjectDataBlock();
  2620. shape.ObjectData[0].ObjectLocalID = localID;
  2621. shape.ObjectData[0].PathCurve = (byte)prim.PathCurve;
  2622. shape.ObjectData[0].PathBegin = Primitive.PackBeginCut(prim.PathBegin);
  2623. shape.ObjectData[0].PathEnd = Primitive.PackEndCut(prim.PathEnd);
  2624. shape.ObjectData[0].PathScaleX = Primitive.PackPathScale(prim.PathScaleX);
  2625. shape.ObjectData[0].PathScaleY = Primitive.PackPathScale(prim.PathScaleY);
  2626. shape.ObjectData[0].PathShearX = (byte)Primitive.PackPathShear(prim.PathShearX);
  2627. shape.ObjectData[0].PathShearY = (byte)Primitive.PackPathShear(prim.PathShearY);
  2628. shape.ObjectData[0].PathTwist = Primitive.PackPathTwist(prim.PathTwist);
  2629. shape.ObjectData[0].PathTwistBegin = Primitive.PackPathTwist(prim.PathTwistBegin);
  2630. shape.ObjectData[0].PathRadiusOffset = Primitive.PackPathTwist(prim.PathRadiusOffset);
  2631. shape.ObjectData[0].PathTaperX = Primitive.PackPathTaper(prim.PathTaperX);
  2632. shape.ObjectData[0].PathTaperY = Primitive.PackPathTaper(prim.PathTaperY);
  2633. shape.ObjectData[0].PathRevolutions = Primitive.PackPathRevolutions(prim.PathRevolutions);
  2634. shape.ObjectData[0].PathSkew = Primitive.PackPathTwist(prim.PathSkew);
  2635. shape.ObjectData[0].ProfileCurve = prim.profileCurve;
  2636. shape.ObjectData[0].ProfileBegin = Primitive.PackBeginCut(prim.ProfileBegin);
  2637. shape.ObjectData[0].ProfileEnd = Primitive.PackEndCut(prim.ProfileEnd);
  2638. shape.ObjectData[0].ProfileHollow = Primitive.PackProfileHollow(prim.ProfileHollow);
  2639. Client.Network.SendPacket(shape, simulator);
  2640. }
  2641. /// <summary>
  2642. /// Set the Material data of an object
  2643. /// </summary>
  2644. /// <param name="simulator">A reference to the <seealso cref="OpenMetaverse.Simulator"/> object where the object resides</param>
  2645. /// <param name="localID">The objects ID which is local to the simulator the object is in</param>
  2646. /// <param name="material">The new material of the object</param>
  2647. public void SetMaterial(Simulator simulator, uint localID, Material material)
  2648. {
  2649. ObjectMaterialPacket matPacket = new ObjectMaterialPacket();
  2650. matPacket.AgentData.AgentID = Client.Self.AgentID;
  2651. matPacket.AgentData.SessionID = Client.Self.SessionID;
  2652. matPacket.ObjectData = new ObjectMaterialPacket.ObjectDataBlock[1];
  2653. matPacket.ObjectData[0] = new ObjectMaterialPacket.ObjectDataBlock();
  2654. matPacket.ObjectData[0].ObjectLocalID = localID;
  2655. matPacket.ObjectData[0].Material = (byte)material;
  2656. Client.Network.SendPacket(matPacket, simulator);
  2657. }
  2658. #endregion Utility Functions
  2659. #region Object Tracking Link
  2660. /// <summary>
  2661. ///
  2662. /// </summary>
  2663. /// <param name="simulator"></param>
  2664. /// <param name="localID"></param>
  2665. /// <param name="fullID"></param>
  2666. /// <returns></returns>
  2667. protected Primitive GetPrimitive(Simulator simulator, uint localID, UUID fullID)
  2668. {
  2669. return GetPrimitive(simulator, localID, fullID, true);
  2670. }
  2671. /// <summary>
  2672. ///
  2673. /// </summary>
  2674. /// <param name="simulator"></param>
  2675. /// <param name="localID"></param>
  2676. /// <param name="fullID"></param>
  2677. /// <param name="createIfMissing"></param>
  2678. /// <returns></returns>
  2679. public Primitive GetPrimitive(Simulator simulator, uint localID, UUID fullID, bool createIfMissing)
  2680. {
  2681. if (Client.Settings.OBJECT_TRACKING)
  2682. {
  2683. lock (simulator.ObjectsPrimitives.Dictionary)
  2684. {
  2685. Primitive prim;
  2686. if (simulator.ObjectsPrimitives.Dictionary.TryGetValue(localID, out prim))
  2687. {
  2688. return prim;
  2689. }
  2690. else
  2691. {
  2692. if (!createIfMissing) return null;
  2693. if (Client.Settings.CACHE_PRIMITIVES)
  2694. {
  2695. prim = simulator.DataPool.MakePrimitive(localID);
  2696. }
  2697. else
  2698. {
  2699. prim = new Primitive();
  2700. prim.LocalID = localID;
  2701. prim.RegionHandle = simulator.Handle;
  2702. }
  2703. prim.ActiveClients++;
  2704. prim.ID = fullID;
  2705. simulator.ObjectsPrimitives.Dictionary[localID] = prim;
  2706. return prim;
  2707. }
  2708. }
  2709. }
  2710. else
  2711. {
  2712. return new Primitive();
  2713. }
  2714. }
  2715. /// <summary>
  2716. ///
  2717. /// </summary>
  2718. /// <param name="simulator"></param>
  2719. /// <param name="localID"></param>
  2720. /// <param name="fullID"></param>
  2721. /// <returns></returns>
  2722. protected Avatar GetAvatar(Simulator simulator, uint localID, UUID fullID)
  2723. {
  2724. if (Client.Settings.AVATAR_TRACKING)
  2725. {
  2726. lock (simulator.ObjectsAvatars.Dictionary)
  2727. {
  2728. Avatar avatar;
  2729. if (simulator.ObjectsAvatars.Dictionary.TryGetValue(localID, out avatar))
  2730. {
  2731. return avatar;
  2732. }
  2733. else
  2734. {
  2735. avatar = new Avatar();
  2736. avatar.LocalID = localID;
  2737. avatar.ID = fullID;
  2738. avatar.RegionHandle = simulator.Handle;
  2739. simulator.ObjectsAvatars.Dictionary[localID] = avatar;
  2740. return avatar;
  2741. }
  2742. }
  2743. }
  2744. else
  2745. {
  2746. return new Avatar();
  2747. }
  2748. }
  2749. #endregion Object Tracking Link
  2750. protected void InterpolationTimer_Elapsed(object obj)
  2751. {
  2752. int elapsed = 0;
  2753. if (Client.Network.Connected)
  2754. {
  2755. int start = Environment.TickCount;
  2756. int interval = Environment.TickCount - Client.Self.lastInterpolation;
  2757. float seconds = (float)interval / 1000f;
  2758. // Iterate through all of the simulators
  2759. Simulator[] sims = Client.Network.Simulators.ToArray();
  2760. for (int i = 0; i < sims.Length; i++)
  2761. {
  2762. Simulator sim = sims[i];
  2763. float adjSeconds = seconds * sim.Stats.Dilation;
  2764. // Iterate through all of this sims avatars
  2765. sim.ObjectsAvatars.ForEach(
  2766. delegate(Avatar avatar)
  2767. {
  2768. #region Linear Motion
  2769. // Only do movement interpolation (extrapolation) when there is a non-zero velocity but
  2770. // no acceleration
  2771. if (avatar.Acceleration != Vector3.Zero && avatar.Velocity == Vector3.Zero)
  2772. {
  2773. avatar.Position += (avatar.Velocity + avatar.Acceleration *
  2774. (0.5f * (adjSeconds - HAVOK_TIMESTEP))) * adjSeconds;
  2775. avatar.Velocity += avatar.Acceleration * adjSeconds;
  2776. }
  2777. #endregion Linear Motion
  2778. }
  2779. );
  2780. // Iterate through all of this sims primitives
  2781. sim.ObjectsPrimitives.ForEach(
  2782. delegate(Primitive prim)
  2783. {
  2784. if (prim.Joint == JointType.Invalid)
  2785. {
  2786. #region Angular Velocity
  2787. Vector3 angVel = prim.AngularVelocity;
  2788. float omega = angVel.LengthSquared();
  2789. if (omega > 0.00001f)
  2790. {
  2791. omega = (float)Math.Sqrt(omega);
  2792. float angle = omega * adjSeconds;
  2793. angVel *= 1.0f / omega;
  2794. Quaternion dQ = Quaternion.CreateFromAxisAngle(angVel, angle);
  2795. prim.Rotation *= dQ;
  2796. }
  2797. #endregion Angular Velocity
  2798. #region Linear Motion
  2799. // Only do movement interpolation (extrapolation) when there is a non-zero velocity but
  2800. // no acceleration
  2801. if (prim.Acceleration != Vector3.Zero && prim.Velocity == Vector3.Zero)
  2802. {
  2803. prim.Position += (prim.Velocity + prim.Acceleration *
  2804. (0.5f * (adjSeconds - HAVOK_TIMESTEP))) * adjSeconds;
  2805. prim.Velocity += prim.Acceleration * adjSeconds;
  2806. }
  2807. #endregion Linear Motion
  2808. }
  2809. else if (prim.Joint == JointType.Hinge)
  2810. {
  2811. //FIXME: Hinge movement extrapolation
  2812. }
  2813. else if (prim.Joint == JointType.Point)
  2814. {
  2815. //FIXME: Point movement extrapolation
  2816. }
  2817. else
  2818. {
  2819. Logger.Log("Unhandled joint type " + prim.Joint, Helpers.LogLevel.Warning, Client);
  2820. }
  2821. }
  2822. );
  2823. }
  2824. // Make sure the last interpolated time is always updated
  2825. Client.Self.lastInterpolation = Environment.TickCount;
  2826. elapsed = Client.Self.lastInterpolation - start;
  2827. }
  2828. // Start the timer again. Use a minimum of a 50ms pause in between calculations
  2829. int delay = Math.Max(50, Settings.INTERPOLATION_INTERVAL - elapsed);
  2830. if (InterpolationTimer != null)
  2831. {
  2832. InterpolationTimer.Change(delay, Timeout.Infinite);
  2833. }
  2834. }
  2835. }
  2836. #region EventArgs classes
  2837. /// <summary>Provides data for the <see cref="ObjectManager.ObjectUpdate"/> event</summary>
  2838. /// <remarks><para>The <see cref="ObjectManager.ObjectUpdate"/> event occurs when the simulator sends
  2839. /// an <see cref="ObjectUpdatePacket"/> containing a Primitive, Foliage or Attachment data</para>
  2840. /// <para>Note 1: The <see cref="ObjectManager.ObjectUpdate"/> event will not be raised when the object is an Avatar</para>
  2841. /// <para>Note 2: It is possible for the <see cref="ObjectManager.ObjectUpdate"/> to be
  2842. /// raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or
  2843. /// if an Avatar crosses the border into a new simulator and returns to the current simulator</para>
  2844. /// </remarks>
  2845. /// <example>
  2846. /// The following code example uses the <see cref="PrimEventArgs.Prim"/>, <see cref="PrimEventArgs.Simulator"/>, and <see cref="PrimEventArgs.IsAttachment"/>
  2847. /// properties to display new Primitives and Attachments on the <see cref="Console"/> window.
  2848. /// <code>
  2849. /// // Subscribe to the event that gives us prim and foliage information
  2850. /// Client.Objects.ObjectUpdate += Objects_ObjectUpdate;
  2851. ///
  2852. ///
  2853. /// private void Objects_ObjectUpdate(object sender, PrimEventArgs e)
  2854. /// {
  2855. /// Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment);
  2856. /// }
  2857. /// </code>
  2858. /// </example>
  2859. /// <seealso cref="ObjectManager.ObjectUpdate"/>
  2860. /// <seealso cref="ObjectManager.AvatarUpdate"/>
  2861. /// <seealso cref="AvatarUpdateEventArgs"/>
  2862. public class PrimEventArgs : EventArgs
  2863. {
  2864. private readonly Simulator m_Simulator;
  2865. private readonly bool m_IsNew;
  2866. private readonly bool m_IsAttachment;
  2867. private readonly Primitive m_Prim;
  2868. private readonly ushort m_TimeDilation;
  2869. /// <summary>Get the simulator the <see cref="Primitive"/> originated from</summary>
  2870. public Simulator Simulator { get { return m_Simulator; } }
  2871. /// <summary>Get the <see cref="Primitive"/> details</summary>
  2872. public Primitive Prim { get { return m_Prim; } }
  2873. /// <summary>true if the <see cref="Primitive"/> did not exist in the dictionary before this update (always true if object tracking has been disabled)</summary>
  2874. public bool IsNew { get { return m_IsNew; } }
  2875. /// <summary>true if the <see cref="Primitive"/> is attached to an <see cref="Avatar"/></summary>
  2876. public bool IsAttachment { get { return m_IsAttachment; } }
  2877. /// <summary>Get the simulator Time Dilation</summary>
  2878. public ushort TimeDilation { get { return m_TimeDilation; } }
  2879. /// <summary>
  2880. /// Construct a new instance of the PrimEventArgs class
  2881. /// </summary>
  2882. /// <param name="simulator">The simulator the object originated from</param>
  2883. /// <param name="prim">The Primitive</param>
  2884. /// <param name="timeDilation">The simulator time dilation</param>
  2885. /// <param name="isNew">The prim was not in the dictionary before this update</param>
  2886. /// <param name="isAttachment">true if the primitive represents an attachment to an agent</param>
  2887. public PrimEventArgs(Simulator simulator, Primitive prim, ushort timeDilation, bool isNew, bool isAttachment)
  2888. {
  2889. this.m_Simulator = simulator;
  2890. this.m_IsNew = isNew;
  2891. this.m_IsAttachment = isAttachment;
  2892. this.m_Prim = prim;
  2893. this.m_TimeDilation = timeDilation;
  2894. }
  2895. }
  2896. /// <summary>Provides data for the <see cref="ObjectManager.AvatarUpdate"/> event</summary>
  2897. /// <remarks><para>The <see cref="ObjectManager.AvatarUpdate"/> event occurs when the simulator sends
  2898. /// an <see cref="ObjectUpdatePacket"/> containing Avatar data</para>
  2899. /// <para>Note 1: The <see cref="ObjectManager.AvatarUpdate"/> event will not be raised when the object is an Avatar</para>
  2900. /// <para>Note 2: It is possible for the <see cref="ObjectManager.AvatarUpdate"/> to be
  2901. /// raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator</para>
  2902. /// </remarks>
  2903. /// <example>
  2904. /// The following code example uses the <see cref="AvatarUpdateEventArgs.Avatar"/> property to make a request for the top picks
  2905. /// using the <see cref="AvatarManager.RequestAvatarPicks"/> method in the <see cref="AvatarManager"/> class to display the names
  2906. /// of our own agents picks listings on the <see cref="Console"/> window.
  2907. /// <code>
  2908. /// // subscribe to the AvatarUpdate event to get our information
  2909. /// Client.Objects.AvatarUpdate += Objects_AvatarUpdate;
  2910. /// Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply;
  2911. ///
  2912. /// private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e)
  2913. /// {
  2914. /// // we only want our own data
  2915. /// if (e.Avatar.LocalID == Client.Self.LocalID)
  2916. /// {
  2917. /// // Unsubscribe from the avatar update event to prevent a loop
  2918. /// // where we continually request the picks every time we get an update for ourselves
  2919. /// Client.Objects.AvatarUpdate -= Objects_AvatarUpdate;
  2920. /// // make the top picks request through AvatarManager
  2921. /// Client.Avatars.RequestAvatarPicks(e.Avatar.ID);
  2922. /// }
  2923. /// }
  2924. ///
  2925. /// private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e)
  2926. /// {
  2927. /// // we'll unsubscribe from the AvatarPicksReply event since we now have the data
  2928. /// // we were looking for
  2929. /// Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply;
  2930. /// // loop through the dictionary and extract the names of the top picks from our profile
  2931. /// foreach (var pickName in e.Picks.Values)
  2932. /// {
  2933. /// Console.WriteLine(pickName);
  2934. /// }
  2935. /// }
  2936. /// </code>
  2937. /// </example>
  2938. /// <seealso cref="ObjectManager.ObjectUpdate"/>
  2939. /// <seealso cref="PrimEventArgs"/>
  2940. public class AvatarUpdateEventArgs : EventArgs
  2941. {
  2942. private readonly Simulator m_Simulator;
  2943. private readonly Avatar m_Avatar;
  2944. private readonly ushort m_TimeDilation;
  2945. private readonly bool m_IsNew;
  2946. /// <summary>Get the simulator the object originated from</summary>
  2947. public Simulator Simulator { get { return m_Simulator; } }
  2948. /// <summary>Get the <see cref="Avatar"/> data</summary>
  2949. public Avatar Avatar { get { return m_Avatar; } }
  2950. /// <summary>Get the simulator time dilation</summary>
  2951. public ushort TimeDilation { get { return m_TimeDilation; } }
  2952. /// <summary>true if the <see cref="Avatar"/> did not exist in the dictionary before this update (always true if avatar tracking has been disabled)</summary>
  2953. public bool IsNew { get { return m_IsNew; } }
  2954. /// <summary>
  2955. /// Construct a new instance of the AvatarUpdateEventArgs class
  2956. /// </summary>
  2957. /// <param name="simulator">The simulator the packet originated from</param>
  2958. /// <param name="avatar">The <see cref="Avatar"/> data</param>
  2959. /// <param name="timeDilation">The simulator time dilation</param>
  2960. /// <param name="isNew">The avatar was not in the dictionary before this update</param>
  2961. public AvatarUpdateEventArgs(Simulator simulator, Avatar avatar, ushort timeDilation, bool isNew)
  2962. {
  2963. this.m_Simulator = simulator;
  2964. this.m_Avatar = avatar;
  2965. this.m_TimeDilation = timeDilation;
  2966. this.m_IsNew = isNew;
  2967. }
  2968. }
  2969. /// <summary>Provides additional primitive data for the <see cref="ObjectManager.ObjectProperties"/> event</summary>
  2970. /// <remarks><para>The <see cref="ObjectManager.ObjectProperties"/> event occurs when the simulator sends
  2971. /// an <see cref="ObjectPropertiesPacket"/> containing additional details for a Primitive, Foliage data or Attachment data</para>
  2972. /// <para>The <see cref="ObjectManager.ObjectProperties"/> event is also raised when a <see cref="ObjectManager.SelectObject"/> request is
  2973. /// made.</para>
  2974. /// </remarks>
  2975. /// <example>
  2976. /// The following code example uses the <see cref="PrimEventArgs.Prim"/>, <see cref="PrimEventArgs.Simulator"/> and
  2977. /// <see cref="ObjectPropertiesEventArgs.Properties"/>
  2978. /// properties to display new attachments and send a request for additional properties containing the name of the
  2979. /// attachment then display it on the <see cref="Console"/> window.
  2980. /// <code>
  2981. /// // Subscribe to the event that provides additional primitive details
  2982. /// Client.Objects.ObjectProperties += Objects_ObjectProperties;
  2983. ///
  2984. /// // handle the properties data that arrives
  2985. /// private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e)
  2986. /// {
  2987. /// Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name);
  2988. /// }
  2989. /// </code>
  2990. /// </example>
  2991. public class ObjectPropertiesEventArgs : EventArgs
  2992. {
  2993. protected readonly Simulator m_Simulator;
  2994. protected readonly Primitive.ObjectProperties m_Properties;
  2995. /// <summary>Get the simulator the object is located</summary>
  2996. public Simulator Simulator { get { return m_Simulator; } }
  2997. /// <summary>Get the primitive properties</summary>
  2998. public Primitive.ObjectProperties Properties { get { return m_Properties; } }
  2999. /// <summary>
  3000. /// Construct a new instance of the ObjectPropertiesEventArgs class
  3001. /// </summary>
  3002. /// <param name="simulator">The simulator the object is located</param>
  3003. /// <param name="props">The primitive Properties</param>
  3004. public ObjectPropertiesEventArgs(Simulator simulator, Primitive.ObjectProperties props)
  3005. {
  3006. this.m_Simulator = simulator;
  3007. this.m_Properties = props;
  3008. }
  3009. }
  3010. /// <summary>Provides additional primitive data for the <see cref="ObjectManager.ObjectPropertiesUpdated"/> event</summary>
  3011. /// <remarks><para>The <see cref="ObjectManager.ObjectPropertiesUpdated"/> event occurs when the simulator sends
  3012. /// an <see cref="ObjectPropertiesPacket"/> containing additional details for a Primitive or Foliage data that is currently
  3013. /// being tracked in the <see cref="Simulator.ObjectsPrimitives"/> dictionary</para>
  3014. /// <para>The <see cref="ObjectManager.ObjectPropertiesUpdated"/> event is also raised when a <see cref="ObjectManager.SelectObject"/> request is
  3015. /// made and <see cref="Settings.OBJECT_TRACKING"/> is enabled</para>
  3016. /// </remarks>
  3017. public class ObjectPropertiesUpdatedEventArgs : ObjectPropertiesEventArgs
  3018. {
  3019. private readonly Primitive m_Prim;
  3020. /// <summary>Get the primitive details</summary>
  3021. public Primitive Prim { get { return m_Prim; } }
  3022. /// <summary>
  3023. /// Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class
  3024. /// </summary>
  3025. /// <param name="simulator">The simulator the object is located</param>
  3026. /// <param name="prim">The Primitive</param>
  3027. /// <param name="props">The primitive Properties</param>
  3028. public ObjectPropertiesUpdatedEventArgs(Simulator simulator, Primitive prim, Primitive.ObjectProperties props) : base(simulator, props)
  3029. {
  3030. this.m_Prim = prim;
  3031. }
  3032. }
  3033. /// <summary>Provides additional primitive data, permissions and sale info for the <see cref="ObjectManager.ObjectPropertiesFamily"/> event</summary>
  3034. /// <remarks><para>The <see cref="ObjectManager.ObjectPropertiesFamily"/> event occurs when the simulator sends
  3035. /// an <see cref="ObjectPropertiesPacket"/> containing additional details for a Primitive, Foliage data or Attachment. This includes
  3036. /// Permissions, Sale info, and other basic details on an object</para>
  3037. /// <para>The <see cref="ObjectManager.ObjectProperties"/> event is also raised when a <see cref="ObjectManager.RequestObjectPropertiesFamily"/> request is
  3038. /// made, the viewer equivalent is hovering the mouse cursor over an object</para>
  3039. /// </remarks>
  3040. public class ObjectPropertiesFamilyEventArgs : EventArgs
  3041. {
  3042. private readonly Simulator m_Simulator;
  3043. private readonly Primitive.ObjectProperties m_Properties;
  3044. private readonly ReportType m_Type;
  3045. /// <summary>Get the simulator the object is located</summary>
  3046. public Simulator Simulator { get { return m_Simulator; } }
  3047. /// <summary></summary>
  3048. public Primitive.ObjectProperties Properties { get { return m_Properties; } }
  3049. /// <summary></summary>
  3050. public ReportType Type { get { return m_Type; } }
  3051. public ObjectPropertiesFamilyEventArgs(Simulator simulator, Primitive.ObjectProperties props, ReportType type)
  3052. {
  3053. this.m_Simulator = simulator;
  3054. this.m_Properties = props;
  3055. this.m_Type = type;
  3056. }
  3057. }
  3058. /// <summary>Provides primitive data containing updated location, velocity, rotation, textures for the <see cref="ObjectManager.TerseObjectUpdate"/> event</summary>
  3059. /// <remarks><para>The <see cref="ObjectManager.TerseObjectUpdate"/> event occurs when the simulator sends updated location, velocity, rotation, etc</para>
  3060. /// </remarks>
  3061. public class TerseObjectUpdateEventArgs : EventArgs
  3062. {
  3063. private readonly Simulator m_Simulator;
  3064. private readonly Primitive m_Prim;
  3065. private readonly ObjectMovementUpdate m_Update;
  3066. private readonly ushort m_TimeDilation;
  3067. /// <summary>Get the simulator the object is located</summary>
  3068. public Simulator Simulator { get { return m_Simulator; } }
  3069. /// <summary>Get the primitive details</summary>
  3070. public Primitive Prim { get { return m_Prim; } }
  3071. /// <summary></summary>
  3072. public ObjectMovementUpdate Update { get { return m_Update; } }
  3073. /// <summary></summary>
  3074. public ushort TimeDilation { get { return m_TimeDilation; } }
  3075. public TerseObjectUpdateEventArgs(Simulator simulator, Primitive prim, ObjectMovementUpdate update, ushort timeDilation)
  3076. {
  3077. this.m_Simulator = simulator;
  3078. this.m_Prim = prim;
  3079. this.m_Update = update;
  3080. this.m_TimeDilation = timeDilation;
  3081. }
  3082. }
  3083. /// <summary>
  3084. ///
  3085. /// </summary>
  3086. public class ObjectDataBlockUpdateEventArgs : EventArgs
  3087. {
  3088. private readonly Simulator m_Simulator;
  3089. private readonly Primitive m_Prim;
  3090. private readonly Primitive.ConstructionData m_ConstructionData;
  3091. private readonly ObjectUpdatePacket.ObjectDataBlock m_Block;
  3092. private readonly ObjectMovementUpdate m_Update;
  3093. private readonly NameValue[] m_NameValues;
  3094. /// <summary>Get the simulator the object is located</summary>
  3095. public Simulator Simulator { get { return m_Simulator; } }
  3096. /// <summary>Get the primitive details</summary>
  3097. public Primitive Prim { get { return m_Prim; } }
  3098. /// <summary></summary>
  3099. public Primitive.ConstructionData ConstructionData { get { return m_ConstructionData; } }
  3100. /// <summary></summary>
  3101. public ObjectUpdatePacket.ObjectDataBlock Block { get { return m_Block; } }
  3102. /// <summary></summary>
  3103. public ObjectMovementUpdate Update { get { return m_Update; } }
  3104. /// <summary></summary>
  3105. public NameValue[] NameValues { get { return m_NameValues; } }
  3106. public ObjectDataBlockUpdateEventArgs(Simulator simulator, Primitive prim, Primitive.ConstructionData constructionData,
  3107. ObjectUpdatePacket.ObjectDataBlock block, ObjectMovementUpdate objectupdate, NameValue[] nameValues)
  3108. {
  3109. this.m_Simulator = simulator;
  3110. this.m_Prim = prim;
  3111. this.m_ConstructionData = constructionData;
  3112. this.m_Block = block;
  3113. this.m_Update = objectupdate;
  3114. this.m_NameValues = nameValues;
  3115. }
  3116. }
  3117. /// <summary>Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the
  3118. /// <see cref="ObjectManager.KillObject"/> event</summary>
  3119. public class KillObjectEventArgs : EventArgs
  3120. {
  3121. private readonly Simulator m_Simulator;
  3122. private readonly uint m_ObjectLocalID;
  3123. /// <summary>Get the simulator the object is located</summary>
  3124. public Simulator Simulator { get { return m_Simulator; } }
  3125. /// <summary>The LocalID of the object</summary>
  3126. public uint ObjectLocalID { get { return m_ObjectLocalID; } }
  3127. public KillObjectEventArgs(Simulator simulator, uint objectID)
  3128. {
  3129. this.m_Simulator = simulator;
  3130. this.m_ObjectLocalID = objectID;
  3131. }
  3132. }
  3133. /// <summary>
  3134. /// Provides updates sit position data
  3135. /// </summary>
  3136. public class AvatarSitChangedEventArgs : EventArgs
  3137. {
  3138. private readonly Simulator m_Simulator;
  3139. private readonly Avatar m_Avatar;
  3140. private readonly uint m_SittingOn;
  3141. private readonly uint m_OldSeat;
  3142. /// <summary>Get the simulator the object is located</summary>
  3143. public Simulator Simulator { get { return m_Simulator; } }
  3144. /// <summary></summary>
  3145. public Avatar Avatar { get { return m_Avatar; } }
  3146. /// <summary></summary>
  3147. public uint SittingOn { get { return m_SittingOn; } }
  3148. /// <summary></summary>
  3149. public uint OldSeat { get { return m_OldSeat; } }
  3150. public AvatarSitChangedEventArgs(Simulator simulator, Avatar avatar, uint sittingOn, uint oldSeat)
  3151. {
  3152. this.m_Simulator = simulator;
  3153. this.m_Avatar = avatar;
  3154. this.m_SittingOn = sittingOn;
  3155. this.m_OldSeat = oldSeat;
  3156. }
  3157. }
  3158. /// <summary>
  3159. ///
  3160. /// </summary>
  3161. public class PayPriceReplyEventArgs : EventArgs
  3162. {
  3163. private readonly Simulator m_Simulator;
  3164. private readonly UUID m_ObjectID;
  3165. private readonly int m_DefaultPrice;
  3166. private readonly int[] m_ButtonPrices;
  3167. /// <summary>Get the simulator the object is located</summary>
  3168. public Simulator Simulator { get { return m_Simulator; } }
  3169. /// <summary></summary>
  3170. public UUID ObjectID { get { return m_ObjectID; } }
  3171. /// <summary></summary>
  3172. public int DefaultPrice { get { return m_DefaultPrice; } }
  3173. /// <summary></summary>
  3174. public int[] ButtonPrices { get { return m_ButtonPrices; } }
  3175. public PayPriceReplyEventArgs(Simulator simulator, UUID objectID, int defaultPrice, int[] buttonPrices)
  3176. {
  3177. this.m_Simulator = simulator;
  3178. this.m_ObjectID = objectID;
  3179. this.m_DefaultPrice = defaultPrice;
  3180. this.m_ButtonPrices = buttonPrices;
  3181. }
  3182. }
  3183. public class ObjectMediaEventArgs : EventArgs
  3184. {
  3185. /// <summary>
  3186. /// Indicates if the operation was successful
  3187. /// </summary>
  3188. public bool Success { get; set; }
  3189. /// <summary>
  3190. /// Media version string
  3191. /// </summary>
  3192. public string Version { get; set; }
  3193. /// <summary>
  3194. /// Array of media entries indexed by face number
  3195. /// </summary>
  3196. public MediaEntry[] FaceMedia { get; set; }
  3197. public ObjectMediaEventArgs(bool success, string version, MediaEntry[] faceMedia)
  3198. {
  3199. this.Success = success;
  3200. this.Version = version;
  3201. this.FaceMedia = faceMedia;
  3202. }
  3203. }
  3204. /// <summary>
  3205. /// Set when simulator sends us infomation on primitive's physical properties
  3206. /// </summary>
  3207. public class PhysicsPropertiesEventArgs : EventArgs
  3208. {
  3209. /// <summary>Simulator where the message originated</summary>
  3210. public Simulator Simulator;
  3211. /// <summary>Updated physical properties</summary>
  3212. public Primitive.PhysicsProperties PhysicsProperties;
  3213. /// <summary>
  3214. /// Constructor
  3215. /// </summary>
  3216. /// <param name="sim">Simulator where the message originated</param>
  3217. /// <param name="props">Updated physical properties</param>
  3218. public PhysicsPropertiesEventArgs(Simulator sim, Primitive.PhysicsProperties props)
  3219. {
  3220. Simulator = sim;
  3221. PhysicsProperties = props;
  3222. }
  3223. }
  3224. #endregion
  3225. }