PageRenderTime 63ms CodeModel.GetById 22ms 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

Large files files are truncated, but you can click here to view the full 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. {

Large files files are truncated, but you can click here to view the full file