PageRenderTime 72ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Region/SceneGraph.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 2314 lines | 1537 code | 221 blank | 556 comment | 276 complexity | 9b54046049b2fed1c55899ebd36e7387 MD5 | raw file
  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  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. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the Aurora-Sim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.Modules;
  31. using Aurora.Framework.Physics;
  32. using Aurora.Framework.PresenceInfo;
  33. using Aurora.Framework.SceneInfo;
  34. using Aurora.Framework.SceneInfo.Entities;
  35. using Aurora.Framework.Services;
  36. using Aurora.Framework.Utilities;
  37. using Nini.Config;
  38. using OpenMetaverse;
  39. using OpenMetaverse.Packets;
  40. using System;
  41. using System.Collections.Generic;
  42. using System.Linq;
  43. using System.Threading;
  44. namespace Aurora.Region
  45. {
  46. /// <summary>
  47. /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
  48. /// should be migrated out over time.
  49. /// </summary>
  50. public class SceneGraph : ISceneGraph
  51. {
  52. #region Declares
  53. protected internal EntityManager Entities = new EntityManager();
  54. protected RegionInfo m_regInfo;
  55. protected IScene m_parentScene;
  56. protected bool EnableFakeRaycasting = false;
  57. protected string m_DefaultObjectName = "Primitive";
  58. /// <summary>
  59. /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is
  60. /// dispensed.
  61. /// </summary>
  62. protected uint m_lastAllocatedLocalId = 720000;
  63. private readonly object _primAllocateLock = new object();
  64. protected internal object m_syncRoot = new object();
  65. protected internal PhysicsScene _PhyScene;
  66. private readonly Object m_updateLock = new Object();
  67. public PhysicsScene PhysicsScene
  68. {
  69. get { return _PhyScene; }
  70. set { _PhyScene = value; }
  71. }
  72. #endregion
  73. #region Constructor and close
  74. protected internal SceneGraph(IScene parent, RegionInfo regInfo)
  75. {
  76. Random random = new Random();
  77. m_lastAllocatedLocalId = (uint) (random.NextDouble()*(uint.MaxValue/2)) + uint.MaxValue/4;
  78. m_parentScene = parent;
  79. m_regInfo = regInfo;
  80. //Subscript to the scene events
  81. m_parentScene.EventManager.OnNewClient += SubscribeToClientEvents;
  82. m_parentScene.EventManager.OnClosingClient += UnSubscribeToClientEvents;
  83. IConfig aurorastartupConfig = parent.Config.Configs["AuroraStartup"];
  84. if (aurorastartupConfig != null)
  85. {
  86. m_DefaultObjectName = aurorastartupConfig.GetString("DefaultObjectName", m_DefaultObjectName);
  87. EnableFakeRaycasting = aurorastartupConfig.GetBoolean("EnableFakeRaycasting", false);
  88. }
  89. }
  90. protected internal void Close()
  91. {
  92. Entities.Clear();
  93. //Remove the events
  94. m_parentScene.EventManager.OnNewClient -= SubscribeToClientEvents;
  95. m_parentScene.EventManager.OnClosingClient -= UnSubscribeToClientEvents;
  96. }
  97. #endregion
  98. #region Update Methods
  99. protected internal void UpdatePreparePhysics()
  100. {
  101. // If we are using a threaded physics engine
  102. // grab the latest scene from the engine before
  103. // trying to process it.
  104. // PhysX does this (runs in the background).
  105. if (_PhyScene != null && _PhyScene.IsThreaded)
  106. {
  107. _PhyScene.GetResults();
  108. }
  109. }
  110. private readonly object m_taintedPresencesLock = new object();
  111. private readonly List<IScenePresence> m_taintedPresences = new List<IScenePresence>();
  112. public void TaintPresenceForUpdate(IScenePresence presence, PresenceTaint taint)
  113. {
  114. lock (m_taintedPresencesLock)
  115. {
  116. if (!presence.IsTainted) //We ONLY set the IsTainted under this lock, so we can trust it
  117. m_taintedPresences.Add(presence);
  118. presence.Taints |= taint;
  119. }
  120. }
  121. protected internal void UpdateEntities()
  122. {
  123. IScenePresence[] presences;
  124. lock (m_taintedPresencesLock)
  125. {
  126. presences = new IScenePresence[m_taintedPresences.Count];
  127. m_taintedPresences.CopyTo(presences);
  128. m_taintedPresences.Clear();
  129. }
  130. foreach (IScenePresence presence in presences)
  131. {
  132. presence.IsTainted = false;
  133. //We set this first so that it is cleared out, but also so that the method can re-taint us
  134. presence.Update();
  135. }
  136. }
  137. protected internal void UpdatePhysics(double elapsed)
  138. {
  139. if (_PhyScene == null)
  140. return;
  141. lock (m_syncRoot)
  142. {
  143. // Update DisableCollisions
  144. _PhyScene.DisableCollisions = m_regInfo.RegionSettings.DisableCollisions;
  145. // Here is where the Scene calls the PhysicsScene. This is a one-way
  146. // interaction; the PhysicsScene cannot access the calling Scene directly.
  147. // But with joints, we want a PhysicsActor to be able to influence a
  148. // non-physics SceneObjectPart. In particular, a PhysicsActor that is connected
  149. // with a joint should be able to move the SceneObjectPart which is the visual
  150. // representation of that joint (for editing and serialization purposes).
  151. // However the PhysicsActor normally cannot directly influence anything outside
  152. // of the PhysicsScene, and the non-physical SceneObjectPart which represents
  153. // the joint in the Scene does not exist in the PhysicsScene.
  154. //
  155. // To solve this, we have an event in the PhysicsScene that is fired when a joint
  156. // has changed position (because one of its associated PhysicsActors has changed
  157. // position).
  158. //
  159. // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
  160. _PhyScene.Simulate((float) elapsed);
  161. }
  162. }
  163. private List<Vector3> m_oldCoarseLocations = new List<Vector3>();
  164. private List<UUID> m_oldAvatarUUIDs = new List<UUID>();
  165. public bool GetCoarseLocations(out List<Vector3> coarseLocations, out List<UUID> avatarUUIDs, uint maxLocations)
  166. {
  167. coarseLocations = new List<Vector3>();
  168. avatarUUIDs = new List<UUID>();
  169. List<IScenePresence> presences = GetScenePresences();
  170. for (int i = 0; i < Math.Min(presences.Count, maxLocations); i++)
  171. {
  172. IScenePresence sp = presences[i];
  173. // If this presence is a child agent, we don't want its coarse locations
  174. if (sp.IsChildAgent)
  175. continue;
  176. if (sp.ParentID != UUID.Zero)
  177. {
  178. // sitting avatar
  179. ISceneChildEntity sop = m_parentScene.GetSceneObjectPart(sp.ParentID);
  180. if (sop != null)
  181. {
  182. coarseLocations.Add(sop.AbsolutePosition + sp.OffsetPosition);
  183. avatarUUIDs.Add(sp.UUID);
  184. }
  185. else
  186. {
  187. // we can't find the parent.. ! arg!
  188. MainConsole.Instance.Warn("Could not find parent prim for avatar " + sp.Name);
  189. coarseLocations.Add(sp.AbsolutePosition);
  190. avatarUUIDs.Add(sp.UUID);
  191. }
  192. }
  193. else
  194. {
  195. coarseLocations.Add(sp.AbsolutePosition);
  196. avatarUUIDs.Add(sp.UUID);
  197. }
  198. }
  199. if (m_oldCoarseLocations.Count == coarseLocations.Count)
  200. {
  201. List<UUID> foundAvies = new List<UUID>(m_oldAvatarUUIDs);
  202. foreach (UUID t in avatarUUIDs)
  203. {
  204. foundAvies.Remove(t);
  205. }
  206. if (foundAvies.Count == 0)
  207. {
  208. //All avies are still the same, check their locations now
  209. for (int i = 0; i < avatarUUIDs.Count; i++)
  210. {
  211. if (m_oldCoarseLocations[i].ApproxEquals(coarseLocations[i], 5))
  212. continue;
  213. m_oldCoarseLocations = coarseLocations;
  214. m_oldAvatarUUIDs = avatarUUIDs;
  215. return true;
  216. }
  217. //Things are still close enough to the same
  218. return false;
  219. }
  220. }
  221. m_oldCoarseLocations = coarseLocations;
  222. m_oldAvatarUUIDs = avatarUUIDs;
  223. //Its changed, tell it to send new
  224. return true;
  225. }
  226. #endregion
  227. #region Entity Methods
  228. protected internal void HandleUndo(IClientAPI remoteClient, UUID primId)
  229. {
  230. if (primId != UUID.Zero)
  231. {
  232. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(primId);
  233. if (part != null)
  234. if (m_parentScene.Permissions.CanEditObject(part.UUID, remoteClient.AgentId))
  235. part.Undo();
  236. }
  237. }
  238. protected internal void HandleRedo(IClientAPI remoteClient, UUID primId)
  239. {
  240. if (primId != UUID.Zero)
  241. {
  242. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(primId);
  243. if (part != null)
  244. if (m_parentScene.Permissions.CanEditObject(part.UUID, remoteClient.AgentId))
  245. part.Redo();
  246. }
  247. }
  248. protected internal void HandleObjectGroupUpdate(
  249. IClientAPI remoteClient, UUID GroupID, uint LocalID, UUID Garbage)
  250. {
  251. IEntity entity;
  252. if (TryGetEntity(LocalID, out entity))
  253. {
  254. if (m_parentScene.Permissions.CanEditObject(entity.UUID, remoteClient.AgentId))
  255. if (((ISceneEntity) entity).OwnerID == remoteClient.AgentId)
  256. ((ISceneEntity) entity).SetGroup(GroupID, remoteClient.AgentId, true);
  257. }
  258. }
  259. /// <summary>
  260. /// Add a presence to the scene
  261. /// </summary>
  262. /// <param name="presence"></param>
  263. protected internal void AddScenePresence(IScenePresence presence)
  264. {
  265. AddEntity(presence, true);
  266. }
  267. /// <summary>
  268. /// Remove a presence from the scene
  269. /// </summary>
  270. protected internal void RemoveScenePresence(IEntity agent)
  271. {
  272. if (!Entities.Remove(agent))
  273. {
  274. MainConsole.Instance.WarnFormat(
  275. "[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
  276. agent.UUID);
  277. return;
  278. }
  279. }
  280. #endregion
  281. #region Get Methods
  282. /// <summary>
  283. /// Get a reference to the scene presence list. Changes to the list will be done in a copy
  284. /// There is no guarantee that presences will remain in the scene after the list is returned.
  285. /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
  286. /// pass a delegate to ForEachScenePresence.
  287. /// </summary>
  288. /// <returns></returns>
  289. public List<IScenePresence> GetScenePresences()
  290. {
  291. return Entities.GetPresences();
  292. }
  293. /// <summary>
  294. /// Request a scene presence by UUID. Fast, indexed lookup.
  295. /// </summary>
  296. /// <param name="agentID"></param>
  297. /// <returns>null if the presence was not found</returns>
  298. protected internal IScenePresence GetScenePresence(UUID agentID)
  299. {
  300. IScenePresence sp;
  301. Entities.TryGetPresenceValue(agentID, out sp);
  302. return sp;
  303. }
  304. /// <summary>
  305. /// Request the scene presence by name.
  306. /// NOTE: Depricated, use the ScenePresence GetScenePresence (string Name) instead!
  307. /// </summary>
  308. /// <param name="firstName"></param>
  309. /// <param name="lastName"></param>
  310. /// <returns>null if the presence was not found</returns>
  311. public IScenePresence GetScenePresence(string firstName, string lastName)
  312. {
  313. List<IScenePresence> presences = GetScenePresences();
  314. #if (!ISWIN)
  315. foreach (IScenePresence presence in presences)
  316. {
  317. if (presence.Firstname == firstName && presence.Lastname == lastName) return presence;
  318. }
  319. return null;
  320. #else
  321. return presences.FirstOrDefault(presence => presence.Firstname == firstName && presence.Lastname == lastName);
  322. #endif
  323. }
  324. /// <summary>
  325. /// Request the scene presence by localID.
  326. /// </summary>
  327. /// <param name="localID"></param>
  328. /// <returns>null if the presence was not found</returns>
  329. public IScenePresence GetScenePresence(uint localID)
  330. {
  331. List<IScenePresence> presences = GetScenePresences();
  332. #if (!ISWIN)
  333. foreach (IScenePresence presence in presences)
  334. {
  335. if (presence.LocalId == localID) return presence;
  336. }
  337. return null;
  338. #else
  339. return presences.FirstOrDefault(presence => presence.LocalId == localID);
  340. #endif
  341. }
  342. protected internal bool TryGetScenePresence(UUID agentID, out IScenePresence avatar)
  343. {
  344. return Entities.TryGetPresenceValue(agentID, out avatar);
  345. }
  346. protected internal bool TryGetAvatarByName(string name, out IScenePresence avatar)
  347. {
  348. #if (!ISWIN)
  349. avatar = null;
  350. foreach (IScenePresence presence in GetScenePresences())
  351. {
  352. if (String.Compare(name, presence.ControllingClient.Name, true) == 0)
  353. {
  354. avatar = presence;
  355. break;
  356. }
  357. }
  358. #else
  359. avatar =
  360. GetScenePresences()
  361. .FirstOrDefault(presence => String.Compare(name, presence.ControllingClient.Name, true) == 0);
  362. #endif
  363. return (avatar != null);
  364. }
  365. /// <summary>
  366. /// Get a scene object group that contains the prim with the given uuid
  367. /// </summary>
  368. /// <param name="hray"></param>
  369. /// <param name="frontFacesOnly"></param>
  370. /// <param name="faceCenters"></param>
  371. /// <returns>null if no scene object group containing that prim is found</returns>
  372. protected internal EntityIntersection GetClosestIntersectingPrim(Ray hray, bool frontFacesOnly, bool faceCenters)
  373. {
  374. // Primitive Ray Tracing
  375. float closestDistance = 280f;
  376. EntityIntersection result = new EntityIntersection();
  377. ISceneEntity[] EntityList = Entities.GetEntities(hray.Origin, closestDistance);
  378. foreach (ISceneEntity ent in EntityList)
  379. {
  380. if (ent is SceneObjectGroup)
  381. {
  382. SceneObjectGroup reportingG = (SceneObjectGroup) ent;
  383. EntityIntersection inter = reportingG.TestIntersection(hray, frontFacesOnly, faceCenters);
  384. if (inter.HitTF && inter.distance < closestDistance)
  385. {
  386. closestDistance = inter.distance;
  387. result = inter;
  388. }
  389. }
  390. }
  391. return result;
  392. }
  393. /// <summary>
  394. /// Gets a list of scene object group that intersect with the given ray
  395. /// </summary>
  396. public List<EntityIntersection> GetIntersectingPrims(Ray hray, float length, int count,
  397. bool frontFacesOnly, bool faceCenters, bool getAvatars,
  398. bool getLand, bool getPrims)
  399. {
  400. // Primitive Ray Tracing
  401. List<EntityIntersection> result = new List<EntityIntersection>(count);
  402. if (getPrims)
  403. {
  404. ISceneEntity[] EntityList = Entities.GetEntities(hray.Origin, length);
  405. #if (!ISWIN)
  406. foreach (ISceneEntity ent in EntityList)
  407. {
  408. if (ent is SceneObjectGroup)
  409. {
  410. SceneObjectGroup reportingG = (SceneObjectGroup)ent;
  411. EntityIntersection inter = reportingG.TestIntersection(hray, frontFacesOnly, faceCenters);
  412. if (inter.HitTF)
  413. result.Add(inter);
  414. }
  415. }
  416. #else
  417. result.AddRange(
  418. EntityList.OfType<SceneObjectGroup>()
  419. .Select(reportingG => reportingG.TestIntersection(hray, frontFacesOnly, faceCenters))
  420. .Where(inter => inter.HitTF));
  421. #endif
  422. }
  423. if (getAvatars)
  424. {
  425. List<IScenePresence> presenceList = Entities.GetPresences();
  426. foreach (IScenePresence ent in presenceList)
  427. {
  428. //Do rough approximation and keep the # of loops down
  429. Vector3 newPos = hray.Origin;
  430. for (int i = 0; i < 100; i++)
  431. {
  432. newPos += ((Vector3.One*(length*(i/100)))*hray.Direction);
  433. if (ent.AbsolutePosition.ApproxEquals(newPos, ent.PhysicsActor.Size.X*2))
  434. {
  435. EntityIntersection intersection = new EntityIntersection();
  436. intersection.distance = length*(i/100);
  437. intersection.face = 0;
  438. intersection.HitTF = true;
  439. intersection.obj = ent;
  440. intersection.ipoint = newPos;
  441. intersection.normal = newPos;
  442. result.Add(intersection);
  443. break;
  444. }
  445. }
  446. }
  447. }
  448. if (getLand)
  449. {
  450. //TODO
  451. }
  452. #if (!ISWIN)
  453. result.Sort(delegate(EntityIntersection a, EntityIntersection b)
  454. {
  455. return a.distance.CompareTo(b.distance);
  456. });
  457. #else
  458. result.Sort((a, b) => a.distance.CompareTo(b.distance));
  459. #endif
  460. if (result.Count > count)
  461. result.RemoveRange(count, result.Count - count);
  462. return result;
  463. }
  464. #endregion
  465. #region ForEach* Methods
  466. /// <summary>
  467. /// Performs action on all scene object groups.
  468. /// </summary>
  469. /// <param name="action"></param>
  470. protected internal void ForEachSceneEntity(Action<ISceneEntity> action)
  471. {
  472. ISceneEntity[] objlist = Entities.GetEntities();
  473. foreach (ISceneEntity obj in objlist)
  474. {
  475. try
  476. {
  477. action(obj);
  478. }
  479. catch (Exception e)
  480. {
  481. // Catch it and move on. This includes situations where splist has inconsistent info
  482. MainConsole.Instance.WarnFormat("[SCENE]: Problem processing action in ForEachSOG: {0}",
  483. e.ToString());
  484. }
  485. }
  486. }
  487. /// <summary>
  488. /// Performs action on all scene presences. This can ultimately run the actions in parallel but
  489. /// any delegates passed in will need to implement their own locking on data they reference and
  490. /// modify outside of the scope of the delegate.
  491. /// </summary>
  492. /// <param name="action"></param>
  493. public void ForEachScenePresence(Action<IScenePresence> action)
  494. {
  495. // Once all callers have their delegates configured for parallelism, we can unleash this
  496. /*
  497. Action<ScenePresence> protectedAction = new Action<ScenePresence>(delegate(ScenePresence sp)
  498. {
  499. try
  500. {
  501. action(sp);
  502. }
  503. catch (Exception e)
  504. {
  505. MainConsole.Instance.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
  506. MainConsole.Instance.Info("[BUG] Stack Trace: " + e.StackTrace);
  507. }
  508. });
  509. Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
  510. */
  511. // For now, perform actions serially
  512. List<IScenePresence> presences = new List<IScenePresence>(GetScenePresences());
  513. foreach (IScenePresence sp in presences)
  514. {
  515. try
  516. {
  517. action(sp);
  518. }
  519. catch (Exception e)
  520. {
  521. MainConsole.Instance.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
  522. MainConsole.Instance.Info("[BUG] Stack Trace: " + e.StackTrace);
  523. }
  524. }
  525. }
  526. #endregion ForEach* Methods
  527. #region Client Event handlers
  528. public void SubscribeToClientEvents(IClientAPI client)
  529. {
  530. client.OnUpdatePrimGroupPosition += UpdatePrimPosition;
  531. client.OnUpdatePrimSinglePosition += UpdatePrimSinglePosition;
  532. client.OnUpdatePrimGroupRotation += UpdatePrimRotation;
  533. client.OnUpdatePrimGroupMouseRotation += UpdatePrimRotation;
  534. client.OnUpdatePrimSingleRotation += UpdatePrimSingleRotation;
  535. client.OnUpdatePrimSingleRotationPosition += UpdatePrimSingleRotationPosition;
  536. client.OnUpdatePrimScale += UpdatePrimScale;
  537. client.OnUpdatePrimGroupScale += UpdatePrimGroupScale;
  538. client.OnUpdateExtraParams += UpdateExtraParam;
  539. client.OnUpdatePrimShape += UpdatePrimShape;
  540. client.OnUpdatePrimTexture += UpdatePrimTexture;
  541. client.OnGrabUpdate += MoveObject;
  542. client.OnSpinStart += SpinStart;
  543. client.OnSpinUpdate += SpinObject;
  544. client.OnObjectName += PrimName;
  545. client.OnObjectClickAction += PrimClickAction;
  546. client.OnObjectMaterial += PrimMaterial;
  547. client.OnLinkObjects += LinkObjects;
  548. client.OnDelinkObjects += DelinkObjects;
  549. client.OnObjectDuplicate += DuplicateObject;
  550. client.OnUpdatePrimFlags += UpdatePrimFlags;
  551. client.OnRequestObjectPropertiesFamily += RequestObjectPropertiesFamily;
  552. client.OnObjectPermissions += HandleObjectPermissionsUpdate;
  553. client.OnGrabObject += ProcessObjectGrab;
  554. client.OnGrabUpdate += ProcessObjectGrabUpdate;
  555. client.OnDeGrabObject += ProcessObjectDeGrab;
  556. client.OnUndo += HandleUndo;
  557. client.OnRedo += HandleRedo;
  558. client.OnObjectDescription += PrimDescription;
  559. client.OnObjectIncludeInSearch += MakeObjectSearchable;
  560. client.OnObjectOwner += ObjectOwner;
  561. client.OnObjectGroupRequest += HandleObjectGroupUpdate;
  562. client.OnAddPrim += AddNewPrim;
  563. client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay;
  564. }
  565. public void UnSubscribeToClientEvents(IClientAPI client)
  566. {
  567. client.OnUpdatePrimGroupPosition -= UpdatePrimPosition;
  568. client.OnUpdatePrimSinglePosition -= UpdatePrimSinglePosition;
  569. client.OnUpdatePrimGroupRotation -= UpdatePrimRotation;
  570. client.OnUpdatePrimGroupMouseRotation -= UpdatePrimRotation;
  571. client.OnUpdatePrimSingleRotation -= UpdatePrimSingleRotation;
  572. client.OnUpdatePrimSingleRotationPosition -= UpdatePrimSingleRotationPosition;
  573. client.OnUpdatePrimScale -= UpdatePrimScale;
  574. client.OnUpdatePrimGroupScale -= UpdatePrimGroupScale;
  575. client.OnUpdateExtraParams -= UpdateExtraParam;
  576. client.OnUpdatePrimShape -= UpdatePrimShape;
  577. client.OnUpdatePrimTexture -= UpdatePrimTexture;
  578. client.OnGrabUpdate -= MoveObject;
  579. client.OnSpinStart -= SpinStart;
  580. client.OnSpinUpdate -= SpinObject;
  581. client.OnObjectName -= PrimName;
  582. client.OnObjectClickAction -= PrimClickAction;
  583. client.OnObjectMaterial -= PrimMaterial;
  584. client.OnLinkObjects -= LinkObjects;
  585. client.OnDelinkObjects -= DelinkObjects;
  586. client.OnObjectDuplicate -= DuplicateObject;
  587. client.OnUpdatePrimFlags -= UpdatePrimFlags;
  588. client.OnRequestObjectPropertiesFamily -= RequestObjectPropertiesFamily;
  589. client.OnObjectPermissions -= HandleObjectPermissionsUpdate;
  590. client.OnGrabObject -= ProcessObjectGrab;
  591. client.OnGrabUpdate -= ProcessObjectGrabUpdate;
  592. client.OnDeGrabObject -= ProcessObjectDeGrab;
  593. client.OnUndo -= HandleUndo;
  594. client.OnRedo -= HandleRedo;
  595. client.OnObjectDescription -= PrimDescription;
  596. client.OnObjectIncludeInSearch -= MakeObjectSearchable;
  597. client.OnObjectOwner -= ObjectOwner;
  598. client.OnObjectGroupRequest -= HandleObjectGroupUpdate;
  599. client.OnAddPrim -= AddNewPrim;
  600. client.OnObjectDuplicateOnRay -= doObjectDuplicateOnRay;
  601. }
  602. public virtual void ProcessObjectGrab(uint localID, Vector3 offsetPos, IClientAPI remoteClient,
  603. List<SurfaceTouchEventArgs> surfaceArgs)
  604. {
  605. SurfaceTouchEventArgs surfaceArg = null;
  606. if (surfaceArgs != null && surfaceArgs.Count > 0)
  607. surfaceArg = surfaceArgs[0];
  608. ISceneChildEntity childPrim;
  609. if (TryGetPart(localID, out childPrim))
  610. {
  611. SceneObjectPart part = childPrim as SceneObjectPart;
  612. if (part != null)
  613. {
  614. SceneObjectGroup obj = part.ParentGroup;
  615. if (obj.RootPart.BlockGrab || obj.RootPart.BlockGrabObject)
  616. return;
  617. // Currently only grab/touch for the single prim
  618. // the client handles rez correctly
  619. obj.ObjectGrabHandler(localID, offsetPos, remoteClient);
  620. // If the touched prim handles touches, deliver it
  621. // If not, deliver to root prim
  622. m_parentScene.EventManager.TriggerObjectGrab(part, part, part.OffsetPosition, remoteClient,
  623. surfaceArg);
  624. // Deliver to the root prim if the touched prim doesn't handle touches
  625. // or if we're meant to pass on touches anyway. Don't send to root prim
  626. // if prim touched is the root prim as we just did it
  627. if ((part.LocalId != obj.RootPart.LocalId))
  628. {
  629. const int PASS_IF_NOT_HANDLED = 0;
  630. const int PASS_ALWAYS = 1;
  631. const int PASS_NEVER = 2;
  632. if (part.PassTouch == PASS_NEVER)
  633. {
  634. }
  635. if (part.PassTouch == PASS_ALWAYS)
  636. {
  637. m_parentScene.EventManager.TriggerObjectGrab(obj.RootPart, part, part.OffsetPosition,
  638. remoteClient, surfaceArg);
  639. }
  640. else if (((part.ScriptEvents & scriptEvents.touch_start) == 0) &&
  641. part.PassTouch == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent
  642. {
  643. m_parentScene.EventManager.TriggerObjectGrab(obj.RootPart, part, part.OffsetPosition,
  644. remoteClient, surfaceArg);
  645. }
  646. }
  647. }
  648. }
  649. }
  650. public virtual void ProcessObjectGrabUpdate(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient,
  651. List<SurfaceTouchEventArgs> surfaceArgs)
  652. {
  653. SurfaceTouchEventArgs surfaceArg = null;
  654. if (surfaceArgs != null && surfaceArgs.Count > 0)
  655. surfaceArg = surfaceArgs[0];
  656. ISceneChildEntity childPrim;
  657. if (TryGetPart(objectID, out childPrim))
  658. {
  659. SceneObjectPart part = childPrim as SceneObjectPart;
  660. if (part != null)
  661. {
  662. SceneObjectGroup obj = part.ParentGroup;
  663. if (obj.RootPart.BlockGrab || obj.RootPart.BlockGrabObject)
  664. return;
  665. // If the touched prim handles touches, deliver it
  666. // If not, deliver to root prim
  667. m_parentScene.EventManager.TriggerObjectGrabbing(part, part, part.OffsetPosition, remoteClient,
  668. surfaceArg);
  669. // Deliver to the root prim if the touched prim doesn't handle touches
  670. // or if we're meant to pass on touches anyway. Don't send to root prim
  671. // if prim touched is the root prim as we just did it
  672. if ((part.LocalId != obj.RootPart.LocalId))
  673. {
  674. const int PASS_IF_NOT_HANDLED = 0;
  675. const int PASS_ALWAYS = 1;
  676. const int PASS_NEVER = 2;
  677. if (part.PassTouch == PASS_NEVER)
  678. {
  679. }
  680. if (part.PassTouch == PASS_ALWAYS)
  681. {
  682. m_parentScene.EventManager.TriggerObjectGrabbing(obj.RootPart, part, part.OffsetPosition,
  683. remoteClient, surfaceArg);
  684. }
  685. else if ((((part.ScriptEvents & scriptEvents.touch_start) == 0) ||
  686. ((part.ScriptEvents & scriptEvents.touch) == 0)) &&
  687. part.PassTouch == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent
  688. {
  689. m_parentScene.EventManager.TriggerObjectGrabbing(obj.RootPart, part, part.OffsetPosition,
  690. remoteClient, surfaceArg);
  691. }
  692. }
  693. }
  694. }
  695. }
  696. public virtual void ProcessObjectDeGrab(uint localID, IClientAPI remoteClient,
  697. List<SurfaceTouchEventArgs> surfaceArgs)
  698. {
  699. SurfaceTouchEventArgs surfaceArg = null;
  700. if (surfaceArgs != null && surfaceArgs.Count > 0)
  701. surfaceArg = surfaceArgs[0];
  702. ISceneChildEntity childPrim;
  703. if (TryGetPart(localID, out childPrim))
  704. {
  705. SceneObjectPart part = childPrim as SceneObjectPart;
  706. if (part != null)
  707. {
  708. SceneObjectGroup obj = part.ParentGroup;
  709. // If the touched prim handles touches, deliver it
  710. // If not, deliver to root prim
  711. m_parentScene.EventManager.TriggerObjectDeGrab(part, part, remoteClient, surfaceArg);
  712. if ((part.LocalId != obj.RootPart.LocalId))
  713. {
  714. const int PASS_IF_NOT_HANDLED = 0;
  715. const int PASS_ALWAYS = 1;
  716. const int PASS_NEVER = 2;
  717. if (part.PassTouch == PASS_NEVER)
  718. {
  719. }
  720. if (part.PassTouch == PASS_ALWAYS)
  721. {
  722. m_parentScene.EventManager.TriggerObjectDeGrab(obj.RootPart, part, remoteClient, surfaceArg);
  723. }
  724. else if ((((part.ScriptEvents & scriptEvents.touch_start) == 0) ||
  725. ((part.ScriptEvents & scriptEvents.touch_end) == 0)) &&
  726. part.PassTouch == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent
  727. {
  728. m_parentScene.EventManager.TriggerObjectDeGrab(obj.RootPart, part, remoteClient,
  729. surfaceArg);
  730. }
  731. }
  732. }
  733. }
  734. }
  735. /// <summary>
  736. /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
  737. /// </summary>
  738. /// <param name="RayStart"></param>
  739. /// <param name="RayEnd"></param>
  740. /// <param name="RayTargetID"></param>
  741. /// <param name="rot"></param>
  742. /// <param name="bypassRayCast"></param>
  743. /// <param name="RayEndIsIntersection"></param>
  744. /// <param name="frontFacesOnly"></param>
  745. /// <param name="scale"></param>
  746. /// <param name="FaceCenter"></param>
  747. /// <returns></returns>
  748. public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot,
  749. byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly,
  750. Vector3 scale, bool FaceCenter)
  751. {
  752. Vector3 pos = Vector3.Zero;
  753. if (RayEndIsIntersection == 1)
  754. {
  755. pos = RayEnd;
  756. return pos;
  757. }
  758. if (RayTargetID != UUID.Zero)
  759. {
  760. ISceneChildEntity target = m_parentScene.GetSceneObjectPart(RayTargetID);
  761. Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
  762. Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
  763. Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);
  764. if (target != null)
  765. {
  766. pos = target.AbsolutePosition;
  767. //MainConsole.Instance.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
  768. // TODO: Raytrace better here
  769. //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
  770. Ray NewRay = new Ray(AXOrigin, AXdirection);
  771. // Ray Trace against target here
  772. EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly,
  773. FaceCenter);
  774. // Un-comment out the following line to Get Raytrace results printed to the console.
  775. //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
  776. float ScaleOffset = 0.5f;
  777. // If we hit something
  778. if (ei.HitTF)
  779. {
  780. Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
  781. if (scaleComponent.X != 0) ScaleOffset = scale.X;
  782. if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
  783. if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
  784. ScaleOffset = Math.Abs(ScaleOffset);
  785. Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
  786. Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
  787. // Set the position to the intersection point
  788. Vector3 offset = (normal*(ScaleOffset/2f));
  789. pos = (intersectionpoint + offset);
  790. //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
  791. //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
  792. // Un-offset the prim (it gets offset later by the consumer method)
  793. //pos.Z -= 0.25F;
  794. }
  795. return pos;
  796. }
  797. else
  798. {
  799. // We don't have a target here, so we're going to raytrace all the objects in the scene.
  800. EntityIntersection ei = GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
  801. // Un-comment the following line to print the raytrace results to the console.
  802. //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
  803. pos = ei.HitTF ? new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z) : RayEnd;
  804. return pos;
  805. }
  806. }
  807. // fall back to our stupid functionality
  808. pos = RayEnd;
  809. //increase height so its above the ground.
  810. //should be getting the normal of the ground at the rez point and using that?
  811. pos.Z += scale.Z/2f;
  812. return pos;
  813. }
  814. public virtual void AddNewPrim(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot,
  815. PrimitiveBaseShape shape,
  816. byte bypassRaycast, Vector3 RayStart, UUID RayTargetID,
  817. byte RayEndIsIntersection)
  818. {
  819. Vector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection,
  820. true, new Vector3(0.5f, 0.5f, 0.5f), false);
  821. string reason;
  822. if (m_parentScene.Permissions.CanRezObject(1, ownerID, pos, out reason))
  823. {
  824. AddNewPrim(ownerID, groupID, pos, rot, shape);
  825. }
  826. else
  827. {
  828. GetScenePresence(ownerID)
  829. .ControllingClient.SendAlertMessage("You do not have permission to rez objects here: " + reason);
  830. }
  831. }
  832. /// <summary>
  833. /// Create a New SceneObjectGroup/Part by raycasting
  834. /// </summary>
  835. /// <param name="ownerID"></param>
  836. /// <param name="groupID"></param>
  837. /// <param name="pos"></param>
  838. /// <param name="rot"></param>
  839. /// <param name="shape"></param>
  840. public virtual ISceneEntity AddNewPrim(
  841. UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
  842. {
  843. SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape, m_DefaultObjectName,
  844. m_parentScene);
  845. // If an entity creator has been registered for this prim type then use that
  846. if (m_entityCreators.ContainsKey((PCode) shape.PCode))
  847. {
  848. sceneObject =
  849. (SceneObjectGroup)
  850. m_entityCreators[(PCode) shape.PCode].CreateEntity(sceneObject, ownerID, groupID, pos, rot, shape);
  851. }
  852. else
  853. {
  854. // Otherwise, use this default creation code;
  855. sceneObject.SetGroup(groupID, ownerID, false);
  856. AddPrimToScene(sceneObject);
  857. sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  858. }
  859. return sceneObject;
  860. }
  861. /// <summary>
  862. /// Duplicates object specified by localID at position raycasted against RayTargetObject using
  863. /// RayEnd and RayStart to determine what the angle of the ray is
  864. /// </summary>
  865. /// <param name="localID">ID of object to duplicate</param>
  866. /// <param name="dupeFlags"></param>
  867. /// <param name="AgentID">Agent doing the duplication</param>
  868. /// <param name="GroupID">Group of new object</param>
  869. /// <param name="RayTargetObj">The target of the Ray</param>
  870. /// <param name="RayEnd">The ending of the ray (farthest away point)</param>
  871. /// <param name="RayStart">The Beginning of the ray (closest point)</param>
  872. /// <param name="BypassRaycast">Bool to bypass raycasting</param>
  873. /// <param name="RayEndIsIntersection">The End specified is the place to add the object</param>
  874. /// <param name="CopyCenters">Position the object at the center of the face that it's colliding with</param>
  875. /// <param name="CopyRotates">Rotate the object the same as the localID object</param>
  876. public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID,
  877. UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart,
  878. bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters,
  879. bool CopyRotates)
  880. {
  881. const bool frontFacesOnly = true;
  882. //MainConsole.Instance.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString());
  883. ISceneChildEntity target = m_parentScene.GetSceneObjectPart(localID);
  884. ISceneChildEntity target2 = m_parentScene.GetSceneObjectPart(RayTargetObj);
  885. IScenePresence Sp = GetScenePresence(AgentID);
  886. if (target != null && target2 != null)
  887. {
  888. Vector3 pos;
  889. if (EnableFakeRaycasting)
  890. {
  891. RayStart = Sp.CameraPosition;
  892. RayEnd = pos = target2.AbsolutePosition;
  893. }
  894. Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
  895. Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
  896. Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);
  897. if (target2.ParentEntity != null)
  898. {
  899. pos = target2.AbsolutePosition;
  900. // TODO: Raytrace better here
  901. //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), false, false);
  902. Ray NewRay = new Ray(AXOrigin, AXdirection);
  903. // Ray Trace against target here
  904. EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly,
  905. CopyCenters);
  906. // Un-comment out the following line to Get Raytrace results printed to the console.
  907. //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
  908. float ScaleOffset = 0.5f;
  909. // If we hit something
  910. if (ei.HitTF)
  911. {
  912. Vector3 scale = target.Scale;
  913. Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
  914. if (scaleComponent.X != 0) ScaleOffset = scale.X;
  915. if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
  916. if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
  917. ScaleOffset = Math.Abs(ScaleOffset);
  918. Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
  919. Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
  920. Vector3 offset = normal*(ScaleOffset/2f);
  921. pos = intersectionpoint + offset;
  922. // stick in offset format from the original prim
  923. pos = pos - target.ParentEntity.AbsolutePosition;
  924. if (CopyRotates)
  925. {
  926. Quaternion worldRot = target2.GetWorldRotation();
  927. // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
  928. DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
  929. //obj.Rotation = worldRot;
  930. //obj.UpdateGroupRotationR(worldRot);
  931. }
  932. else
  933. {
  934. DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID,
  935. Quaternion.Identity);
  936. }
  937. }
  938. return;
  939. }
  940. return;
  941. }
  942. }
  943. /// <value>
  944. /// Registered classes that are capable of creating entities.
  945. /// </value>
  946. protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>();
  947. public void RegisterEntityCreatorModule(IEntityCreator entityCreator)
  948. {
  949. lock (m_entityCreators)
  950. {
  951. foreach (PCode pcode in entityCreator.CreationCapabilities)
  952. {
  953. m_entityCreators[pcode] = entityCreator;
  954. }
  955. }
  956. }
  957. /// <summary>
  958. /// Unregister a module commander and all its commands
  959. /// </summary>
  960. /// <param name="entityCreator"></param>
  961. public void UnregisterEntityCreatorCommander(IEntityCreator entityCreator)
  962. {
  963. lock (m_entityCreators)
  964. {
  965. foreach (PCode pcode in entityCreator.CreationCapabilities)
  966. {
  967. m_entityCreators[pcode] = null;
  968. }
  969. }
  970. }
  971. protected internal void ObjectOwner(IClientAPI remoteClient, UUID ownerID, UUID groupID, List<uint> localIDs)
  972. {
  973. if (!m_parentScene.Permissions.IsGod(remoteClient.AgentId))
  974. {
  975. if (ownerID != UUID.Zero)
  976. return;
  977. if (!m_parentScene.Permissions.CanDeedObject(remoteClient.AgentId, groupID))
  978. return;
  979. }
  980. List<ISceneEntity> groups = new List<ISceneEntity>();
  981. foreach (uint localID in localIDs)
  982. {
  983. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(localID);
  984. if (!groups.Contains(part.ParentEntity))
  985. groups.Add(part.ParentEntity);
  986. }
  987. foreach (ISceneEntity sog in groups)
  988. {
  989. if (ownerID != UUID.Zero)
  990. {
  991. sog.SetOwnerId(ownerID);
  992. sog.SetGroup(groupID, remoteClient.AgentId, true);
  993. sog.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  994. foreach (ISceneChildEntity child in sog.ChildrenEntities())
  995. child.Inventory.ChangeInventoryOwner(ownerID);
  996. }
  997. else
  998. {
  999. if (!m_parentScene.Permissions.CanEditObject(sog.UUID, remoteClient.AgentId))
  1000. continue;
  1001. if (sog.GroupID != groupID)
  1002. continue;
  1003. foreach (ISceneChildEntity child in sog.ChildrenEntities())
  1004. {
  1005. child.LastOwnerID = child.OwnerID;
  1006. child.Inventory.ChangeInventoryOwner(groupID);
  1007. }
  1008. sog.SetOwnerId(groupID);
  1009. sog.ApplyNextOwnerPermissions();
  1010. }
  1011. //Trigger the prim count event so that this parcel gets changed!
  1012. m_parentScene.AuroraEventManager.FireGenericEventHandler("ObjectChangedOwner", sog);
  1013. }
  1014. foreach (uint localID in localIDs)
  1015. {
  1016. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(localID);
  1017. part.GetProperties(remoteClient);
  1018. }
  1019. }
  1020. /// <summary>
  1021. /// </summary>
  1022. /// <param name="LocalID"></param>
  1023. /// <param name="scale"></param>
  1024. /// <param name="remoteClient"></param>
  1025. protected internal void UpdatePrimScale(uint LocalID, Vector3 scale, IClientAPI remoteClient)
  1026. {
  1027. IEntity entity;
  1028. if (TryGetEntity(LocalID, out entity))
  1029. {
  1030. if (m_parentScene.Permissions.CanEditObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId))
  1031. {
  1032. ((SceneObjectGroup) entity).Resize(scale, LocalID);
  1033. }
  1034. }
  1035. }
  1036. protected internal void UpdatePrimGroupScale(uint LocalID, Vector3 scale, IClientAPI remoteClient)
  1037. {
  1038. IEntity entity;
  1039. if (TryGetEntity(LocalID, out entity))
  1040. {
  1041. if (m_parentScene.Permissions.CanEditObject(entity.UUID, remoteClient.AgentId))
  1042. {
  1043. ((SceneObjectGroup) entity).GroupResize(scale, LocalID);
  1044. }
  1045. }
  1046. }
  1047. public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field,
  1048. uint localId, uint mask, byte set)
  1049. {
  1050. // Check for spoofing.. since this is permissions we're talking about here!
  1051. if ((controller.SessionId == sessionID) && (controller.AgentId == agentID))
  1052. {
  1053. // Tell the object to do permission update
  1054. if (localId != 0)
  1055. {
  1056. ISceneEntity chObjectGroup = m_parentScene.GetGroupByPrim(localId);
  1057. if (chObjectGroup != null)
  1058. {
  1059. if (m_parentScene.Permissions.CanEditObject(chObjectGroup.UUID, controller.AgentId))
  1060. chObjectGroup.UpdatePermissions(agentID, field, localId, mask, set);
  1061. }
  1062. }
  1063. }
  1064. }
  1065. /// <summary>
  1066. /// This handles the nifty little tool tip that you get when you drag your mouse over an object
  1067. /// Send to the Object Group to process. We don't know enough to service the request
  1068. /// </summary>
  1069. /// <param name="remoteClient"></param>
  1070. /// <param name="AgentID"></param>
  1071. /// <param name="RequestFlags"></param>
  1072. /// <param name="ObjectID"></param>
  1073. protected internal void RequestObjectPropertiesFamily(
  1074. IClientAPI remoteClient, UUID AgentID, uint RequestFlags, UUID ObjectID)
  1075. {
  1076. IEntity group;
  1077. if (TryGetEntity(ObjectID, out group))
  1078. {
  1079. if (group is SceneObjectGroup)
  1080. ((SceneObjectGroup) group).ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags);
  1081. }
  1082. }
  1083. /// <summary>
  1084. /// </summary>
  1085. /// <param name="LocalID"></param>
  1086. /// <param name="rot"></param>
  1087. /// <param name="remoteClient"></param>
  1088. protected internal void UpdatePrimSingleRotation(uint LocalID, Quaternion rot, IClientAPI remoteClient)
  1089. {
  1090. IEntity entity;
  1091. if (TryGetEntity(LocalID, out entity))
  1092. {
  1093. if (m_parentScene.Permissions.CanMoveObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId))
  1094. {
  1095. ((SceneObjectGroup) entity).UpdateSingleRotation(rot, LocalID);
  1096. }
  1097. }
  1098. }
  1099. /// <summary>
  1100. /// </summary>
  1101. /// <param name="LocalID"></param>
  1102. /// <param name="rot"></param>
  1103. /// <param name="pos"></param>
  1104. /// <param name="remoteClient"></param>
  1105. protected internal void UpdatePrimSingleRotationPosition(uint LocalID, Quaternion rot, Vector3 pos,
  1106. IClientAPI remoteClient)
  1107. {
  1108. IEntity entity;
  1109. if (TryGetEntity(LocalID, out entity))
  1110. {
  1111. if (m_parentScene.Permissions.CanMoveObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId))
  1112. {
  1113. ((SceneObjectGroup) entity).UpdateSingleRotation(rot, pos, LocalID);
  1114. }
  1115. }
  1116. }
  1117. /// <summary>
  1118. /// </summary>
  1119. /// <param name="LocalID"></param>
  1120. /// <param name="rot"></param>
  1121. /// <param name="remoteClient"></param>
  1122. protected internal void UpdatePrimRotation(uint LocalID, Quaternion rot, IClientAPI remoteClient)
  1123. {
  1124. IEntity entity;
  1125. if (TryGetEntity(LocalID, out entity))
  1126. {
  1127. if (m_parentScene.Permissions.CanMoveObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId))
  1128. {
  1129. ((SceneObjectGroup) entity).UpdateGroupRotationR(rot);
  1130. }
  1131. }
  1132. }
  1133. /// <summary>
  1134. /// </summary>
  1135. /// <param name="LocalID"></param>
  1136. /// <param name="pos"></param>
  1137. /// <param name="rot"></param>
  1138. /// <param name="remoteClient"></param>
  1139. protected internal void UpdatePrimRotation(uint LocalID, Vector3 pos, Quaternion rot, IClientAPI remoteClient)
  1140. {
  1141. IEntity entity;
  1142. if (TryGetEntity(LocalID, out entity))
  1143. {
  1144. if (m_parentScene.Permissions.CanMoveObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId))
  1145. {
  1146. ((SceneObjectGroup) entity).UpdateGroupRotationPR(pos, rot);
  1147. }
  1148. }
  1149. }
  1150. /// <summary>
  1151. /// Update the position of the given part
  1152. /// </summary>
  1153. /// <param name="LocalID"></param>
  1154. /// <param name="pos"></param>
  1155. /// <param name="remoteClient"></param>
  1156. /// <param name="SaveUpdate"></param>
  1157. protected internal void UpdatePrimSinglePosition(uint LocalID, Vector3 pos, IClientAPI remoteClient,
  1158. bool SaveUpdate)
  1159. {
  1160. IEntity entity;
  1161. if (TryGetEntity(LocalID, out entity))
  1162. {
  1163. if (m_parentScene.Permissions.CanMoveObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId) ||
  1164. ((SceneObjectGroup) entity).IsAttachment)
  1165. {
  1166. ((SceneObjectGroup) entity).UpdateSinglePosition(pos, LocalID, SaveUpdate);
  1167. }
  1168. }
  1169. }
  1170. /// <summary>
  1171. /// Update the position of the given part
  1172. /// </summary>
  1173. /// <param name="LocalID"></param>
  1174. /// <param name="pos"></param>
  1175. /// <param name="remoteClient"></param>
  1176. /// <param name="SaveUpdate"></param>
  1177. protected internal void UpdatePrimPosition(uint LocalID, Vector3 pos, IClientAPI remoteClient, bool SaveUpdate)
  1178. {
  1179. IEntity entity;
  1180. if (TryGetEntity(LocalID, out entity))
  1181. {
  1182. if (((SceneObjectGroup) entity).IsAttachment ||
  1183. (((SceneObjectGroup) entity).RootPart.Shape.PCode == 9 &&
  1184. ((SceneObjectGroup) entity).RootPart.Shape.State != 0))
  1185. {
  1186. //We don't deal with attachments, they handle themselves in the IAttachmentModule
  1187. }
  1188. else
  1189. {
  1190. //Move has edit permission as well
  1191. if (
  1192. m_parentScene.Permissions.CanMoveObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId) &&
  1193. m_parentScene.Permissions.CanObjectEntry(((SceneObjectGroup) entity).UUID, false, pos,
  1194. remoteClient.AgentId))
  1195. {
  1196. ((SceneObjectGroup) entity).UpdateGroupPosition(pos, SaveUpdate);
  1197. }
  1198. else
  1199. {
  1200. IScenePresence SP = GetScenePresence(remoteClient.AgentId);
  1201. ((SceneObjectGroup) entity).ScheduleGroupUpdateToAvatar(SP, PrimUpdateFlags.FullUpdate);
  1202. }
  1203. }
  1204. }
  1205. }
  1206. /// <summary>
  1207. /// Update the texture entry of the given prim.
  1208. /// </summary>
  1209. /// A texture entry is an object that contains details of all the textures of the prim's face. In this case,
  1210. /// the texture is given in its byte serialized form.
  1211. /// <param name="LocalID"></param>
  1212. /// <param name="texture"></param>
  1213. /// <param name="remoteClient"></param>
  1214. protected internal void UpdatePrimTexture(uint LocalID, byte[] texture, IClientAPI remoteClient)
  1215. {
  1216. IEntity entity;
  1217. if (TryGetEntity(LocalID, out entity))
  1218. {
  1219. if (m_parentScene.Permissions.CanEditObject(((SceneObjectGroup) entity).UUID, remoteClient.AgentId))
  1220. {
  1221. ((SceneObjectGroup) entity).UpdateTextureEntry(LocalID, texture, true);
  1222. }
  1223. }
  1224. }
  1225. /// <summary>
  1226. /// A user has changed an object setting
  1227. /// </summary>
  1228. /// <param name="LocalID"></param>
  1229. /// <param name="blocks"></param>
  1230. /// <param name="remoteClient"></param>
  1231. /// <param name="UsePhysics"></param>
  1232. /// <param name="IsTemporary"></param>
  1233. /// <param name="IsPhantom"></param>
  1234. protected internal void UpdatePrimFlags(uint LocalID, bool UsePhysics, bool IsTemporary, bool IsPhantom,
  1235. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks,
  1236. IClientAPI remoteClient)
  1237. {
  1238. IEntity entity;
  1239. if (TryGetEntity(LocalID, out entity))
  1240. {
  1241. if (m_parentScene.Permissions.CanEditObject(entity.UUID, remoteClient.AgentId))
  1242. {
  1243. ((SceneObjectGroup) entity).UpdatePrimFlags(LocalID, UsePhysics, IsTemporary, IsPhantom, false,
  1244. blocks);
  1245. // VolumeDetect can't be set via UI and will always be off when a change is made there
  1246. }
  1247. }
  1248. }
  1249. /// <summary>
  1250. /// Move the given object
  1251. /// </summary>
  1252. /// <param name="ObjectID"></param>
  1253. /// <param name="offset"></param>
  1254. /// <param name="pos"></param>
  1255. /// <param name="remoteClient"></param>
  1256. /// <param name="surfaceArgs"></param>
  1257. protected internal void MoveObject(UUID ObjectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient,
  1258. List<SurfaceTouchEventArgs> surfaceArgs)
  1259. {
  1260. IEntity group;
  1261. if (TryGetEntity(ObjectID, out group))
  1262. {
  1263. if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) // && PermissionsMngr.)
  1264. {
  1265. ((SceneObjectGroup) group).GrabMovement(offset, pos, remoteClient);
  1266. }
  1267. }
  1268. }
  1269. /// <summary>
  1270. /// Start spinning the given object
  1271. /// </summary>
  1272. /// <param name="ObjectID"></param>
  1273. /// <param name="remoteClient"></param>
  1274. protected internal void SpinStart(UUID ObjectID, IClientAPI remoteClient)
  1275. {
  1276. IEntity group;
  1277. if (TryGetEntity(ObjectID, out group))
  1278. {
  1279. if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) // && PermissionsMngr.)
  1280. {
  1281. ((SceneObjectGroup) group).SpinStart(remoteClient);
  1282. }
  1283. }
  1284. }
  1285. /// <summary>
  1286. /// Spin the given object
  1287. /// </summary>
  1288. /// <param name="ObjectID"></param>
  1289. /// <param name="rotation"></param>
  1290. /// <param name="remoteClient"></param>
  1291. protected internal void SpinObject(UUID ObjectID, Quaternion rotation, IClientAPI remoteClient)
  1292. {
  1293. IEntity group;
  1294. if (TryGetEntity(ObjectID, out group))
  1295. {
  1296. if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) // && PermissionsMngr.)
  1297. {
  1298. ((SceneObjectGroup) group).SpinMovement(rotation, remoteClient);
  1299. }
  1300. // This is outside the above permissions condition
  1301. // so that if the object is locked the client moving the object
  1302. // get's it's position on the simulator even if it was the same as before
  1303. // This keeps the moving user's client in sync with the rest of the world.
  1304. ((SceneObjectGroup) group).ScheduleGroupTerseUpdate();
  1305. }
  1306. }
  1307. /// <summary>
  1308. /// </summary>
  1309. /// <param name="remoteClient"></param>
  1310. /// <param name="LocalID"></param>
  1311. /// <param name="name"></param>
  1312. protected internal void PrimName(IClientAPI remoteClient, uint LocalID, string name)
  1313. {
  1314. IEntity group;
  1315. if (TryGetEntity(LocalID, out group))
  1316. {
  1317. if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
  1318. {
  1319. ((SceneObjectGroup) group).SetPartName(Util.CleanString(name), LocalID);
  1320. ((SceneObjectGroup) group).ScheduleGroupUpdate(PrimUpdateFlags.FindBest);
  1321. }
  1322. }
  1323. }
  1324. /// <summary>
  1325. /// </summary>
  1326. /// <param name="LocalID"></param>
  1327. /// <param name="description"></param>
  1328. /// <param name="remoteClient"></param>
  1329. protected internal void PrimDescription(IClientAPI remoteClient, uint LocalID, string description)
  1330. {
  1331. IEntity group;
  1332. if (TryGetEntity(LocalID, out group))
  1333. {
  1334. if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
  1335. {
  1336. ((SceneObjectGroup) group).SetPartDescription(Util.CleanString(description), LocalID);
  1337. ((SceneObjectGroup) group).ScheduleGroupUpdate(PrimUpdateFlags.ClickAction);
  1338. }
  1339. }
  1340. }
  1341. protected internal void PrimClickAction(IClientAPI remoteClient, uint LocalID, string clickAction)
  1342. {
  1343. IEntity group;
  1344. if (TryGetEntity(LocalID, out group))
  1345. {
  1346. if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
  1347. {
  1348. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(LocalID);
  1349. part.ClickAction = Convert.ToByte(clickAction);
  1350. ((ISceneEntity) group).ScheduleGroupUpdate(PrimUpdateFlags.ClickAction);
  1351. }
  1352. }
  1353. }
  1354. protected internal void PrimMaterial(IClientAPI remoteClient, uint LocalID, string material)
  1355. {
  1356. IEntity group;
  1357. if (TryGetEntity(LocalID, out group))
  1358. {
  1359. if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
  1360. {
  1361. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(LocalID);
  1362. part.UpdateMaterial(Convert.ToInt32(material));
  1363. //Update the client here as well... we changed restitution and friction in the physics engine probably
  1364. IEventQueueService eqs = m_parentScene.RequestModuleInterface<IEventQueueService>();
  1365. if (eqs != null)
  1366. eqs.ObjectPhysicsProperties(new[] {part}, remoteClient.AgentId,
  1367. m_parentScene.RegionInfo.RegionID);
  1368. ((ISceneEntity) group).ScheduleGroupUpdate(PrimUpdateFlags.ClickAction);
  1369. }
  1370. }
  1371. }
  1372. protected internal void UpdateExtraParam(UUID agentID, uint LocalID, ushort type, bool inUse, byte[] data)
  1373. {
  1374. ISceneChildEntity part;
  1375. if (TryGetPart(LocalID, out part))
  1376. {
  1377. if (m_parentScene.Permissions.CanEditObject(part.UUID, agentID))
  1378. {
  1379. ((SceneObjectPart) part).UpdateExtraParam(type, inUse, data);
  1380. }
  1381. }
  1382. }
  1383. /// <summary>
  1384. /// </summary>
  1385. /// <param name="LocalID"></param>
  1386. /// <param name="shapeBlock"></param>
  1387. /// <param name="agentID"></param>
  1388. protected internal void UpdatePrimShape(UUID agentID, uint LocalID, UpdateShapeArgs shapeBlock)
  1389. {
  1390. ISceneChildEntity part;
  1391. if (TryGetPart(LocalID, out part))
  1392. {
  1393. if (m_parentScene.Permissions.CanEditObject(part.UUID, agentID))
  1394. {
  1395. ObjectShapePacket.ObjectDataBlock shapeData = new ObjectShapePacket.ObjectDataBlock
  1396. {
  1397. ObjectLocalID = shapeBlock.ObjectLocalID,
  1398. PathBegin = shapeBlock.PathBegin,
  1399. PathCurve = shapeBlock.PathCurve,
  1400. PathEnd = shapeBlock.PathEnd,
  1401. PathRadiusOffset = shapeBlock.PathRadiusOffset,
  1402. PathRevolutions = shapeBlock.PathRevolutions,
  1403. PathScaleX = shapeBlock.PathScaleX,
  1404. PathScaleY = shapeBlock.PathScaleY,
  1405. PathShearX = shapeBlock.PathShearX,
  1406. PathShearY = shapeBlock.PathShearY,
  1407. PathSkew = shapeBlock.PathSkew,
  1408. PathTaperX = shapeBlock.PathTaperX,
  1409. PathTaperY = shapeBlock.PathTaperY,
  1410. PathTwist = shapeBlock.PathTwist,
  1411. PathTwistBegin = shapeBlock.PathTwistBegin,
  1412. ProfileBegin = shapeBlock.ProfileBegin,
  1413. ProfileCurve = shapeBlock.ProfileCurve,
  1414. ProfileEnd = shapeBlock.ProfileEnd,
  1415. ProfileHollow = shapeBlock.ProfileHollow
  1416. };
  1417. ((SceneObjectPart) part).UpdateShape(shapeData);
  1418. }
  1419. }
  1420. }
  1421. /// <summary>
  1422. /// Make this object be added to search
  1423. /// </summary>
  1424. /// <param name="remoteClient"></param>
  1425. /// <param name="IncludeInSearch"></param>
  1426. /// <param name="LocalID"></param>
  1427. protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint LocalID)
  1428. {
  1429. UUID user = remoteClient.AgentId;
  1430. UUID objid = UUID.Zero;
  1431. IEntity entity;
  1432. if (!TryGetEntity(LocalID, out entity))
  1433. return;
  1434. SceneObjectGroup grp = (SceneObjectGroup) entity;
  1435. //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints
  1436. //aka ObjectFlags.JointWheel = IncludeInSearch
  1437. //Permissions model: Object can be REMOVED from search IFF:
  1438. // * User owns object
  1439. //use CanEditObject
  1440. //Object can be ADDED to search IFF:
  1441. // * User owns object
  1442. // * Asset/DRM permission bit "modify" is enabled
  1443. //use CanEditObjectPosition
  1444. // libomv will complain about PrimFlags.JointWheel being
  1445. // deprecated, so we
  1446. #pragma warning disable 0612
  1447. if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(objid, user))
  1448. {
  1449. grp.RootPart.AddFlag(PrimFlags.JointWheel);
  1450. }
  1451. else if (!IncludeInSearch && m_parentScene.Permissions.CanEditObject(objid, user))
  1452. {
  1453. grp.RootPart.RemFlag(PrimFlags.JointWheel);
  1454. }
  1455. #pragma warning restore 0612
  1456. }
  1457. /// <summary>
  1458. /// Duplicate the given entity and add it to the world
  1459. /// </summary>
  1460. /// <param name="LocalID">LocalID of the object to duplicate</param>
  1461. /// <param name="offset">Duplicated objects position offset from the original entity</param>
  1462. /// <param name="flags">Flags to give the Duplicated object</param>
  1463. /// <param name="AgentID"></param>
  1464. /// <param name="GroupID"></param>
  1465. /// <param name="rot">Rotation to have the duplicated entity set to</param>
  1466. /// <returns></returns>
  1467. public bool DuplicateObject(uint LocalID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
  1468. {
  1469. //MainConsole.Instance.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
  1470. IEntity entity;
  1471. if (TryGetEntity(LocalID, out entity))
  1472. {
  1473. SceneObjectGroup original = (SceneObjectGroup) entity;
  1474. string reason = "You cannot duplicate this object.";
  1475. if (
  1476. m_parentScene.Permissions.CanDuplicateObject(original.ChildrenList.Count, original.UUID, AgentID,
  1477. original.AbsolutePosition) &&
  1478. m_parentScene.Permissions.CanRezObject(1, AgentID, original.AbsolutePosition + offset, out reason))
  1479. {
  1480. ISceneEntity duplicatedEntity = DuplicateEntity(original);
  1481. duplicatedEntity.AbsolutePosition = duplicatedEntity.AbsolutePosition + offset;
  1482. SceneObjectGroup duplicatedGroup = (SceneObjectGroup) duplicatedEntity;
  1483. if (original.OwnerID != AgentID)
  1484. {
  1485. duplicatedGroup.SetOwnerId(AgentID);
  1486. duplicatedGroup.SetRootPartOwner(duplicatedGroup.RootPart, AgentID, GroupID);
  1487. List<SceneObjectPart> partList =
  1488. new List<SceneObjectPart>(duplicatedGroup.ChildrenList);
  1489. if (m_parentScene.Permissions.PropagatePermissions())
  1490. {
  1491. foreach (SceneObjectPart child in partList)
  1492. {
  1493. child.Inventory.ChangeInventoryOwner(AgentID);
  1494. child.TriggerScriptChangedEvent(Changed.OWNER);
  1495. child.ApplyNextOwnerPermissions();
  1496. }
  1497. }
  1498. duplicatedGroup.RootPart.ObjectSaleType = 0;
  1499. duplicatedGroup.RootPart.SalePrice = 10;
  1500. }
  1501. // Since we copy from a source group that is in selected
  1502. // state, but the copy is shown deselected in the viewer,
  1503. // We need to clear the selection flag here, else that
  1504. // prim never gets persisted at all. The client doesn't
  1505. // think it's selected, so it will never send a deselect...
  1506. duplicatedGroup.IsSelected = false;
  1507. if (rot != Quaternion.Identity)
  1508. {
  1509. duplicatedGroup.UpdateGroupRotationR(rot);
  1510. }
  1511. duplicatedGroup.CreateScriptInstances(0, true, StateSource.NewRez, UUID.Zero, false);
  1512. duplicatedGroup.HasGroupChanged = true;
  1513. duplicatedGroup.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  1514. // required for physics to update it's position
  1515. duplicatedGroup.AbsolutePosition = duplicatedGroup.AbsolutePosition;
  1516. return true;
  1517. }
  1518. else
  1519. GetScenePresence(AgentID).ControllingClient.SendAlertMessage(reason);
  1520. }
  1521. return false;
  1522. }
  1523. #region Linking and Delinking
  1524. public void DelinkObjects(List<uint> primIds, IClientAPI client)
  1525. {
  1526. #if (!ISWIN)
  1527. List<ISceneChildEntity> parts = new List<ISceneChildEntity>();
  1528. foreach (uint localId in primIds)
  1529. {
  1530. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(localId);
  1531. if (part != null)
  1532. {
  1533. if (m_parentScene.Permissions.CanDelinkObject(client.AgentId, part.ParentEntity.UUID)) parts.Add(part);
  1534. }
  1535. }
  1536. #else
  1537. List<ISceneChildEntity> parts =
  1538. primIds.Select(localID => m_parentScene.GetSceneObjectPart(localID)).Where(part => part != null).Where(
  1539. part => m_parentScene.Permissions.CanDelinkObject(client.AgentId, part.ParentEntity.UUID)).ToList();
  1540. #endif
  1541. DelinkObjects(parts);
  1542. }
  1543. public void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds)
  1544. {
  1545. List<UUID> owners = new List<UUID>();
  1546. List<ISceneChildEntity> children = new List<ISceneChildEntity>();
  1547. ISceneChildEntity root = m_parentScene.GetSceneObjectPart(parentPrimId);
  1548. if (root == null)
  1549. {
  1550. MainConsole.Instance.DebugFormat("[LINK]: Can't find linkset root prim {0}", parentPrimId);
  1551. return;
  1552. }
  1553. if (!m_parentScene.Permissions.CanLinkObject(client.AgentId, root.ParentEntity.UUID))
  1554. {
  1555. MainConsole.Instance.DebugFormat("[LINK]: Refusing link. No permissions on root prim");
  1556. return;
  1557. }
  1558. foreach (uint localID in childPrimIds)
  1559. {
  1560. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(localID);
  1561. if (part == null)
  1562. continue;
  1563. if (!owners.Contains(part.OwnerID))
  1564. owners.Add(part.OwnerID);
  1565. if (m_parentScene.Permissions.CanLinkObject(client.AgentId, part.ParentEntity.UUID))
  1566. children.Add(part);
  1567. }
  1568. // Must be all one owner
  1569. //
  1570. if (owners.Count > 1)
  1571. {
  1572. MainConsole.Instance.DebugFormat("[LINK]: Refusing link. Too many owners");
  1573. client.SendAlertMessage("Permissions: Cannot link, too many owners.");
  1574. return;
  1575. }
  1576. if (children.Count == 0)
  1577. {
  1578. MainConsole.Instance.DebugFormat("[LINK]: Refusing link. No permissions to link any of the children");
  1579. client.SendAlertMessage("Permissions: Cannot link, not enough permissions.");
  1580. return;
  1581. }
  1582. #if (!ISWIN)
  1583. int LinkCount = 0;
  1584. foreach (SceneObjectPart part in children)
  1585. LinkCount += part.ParentGroup.ChildrenList.Count;
  1586. #else
  1587. int LinkCount = children.Cast<SceneObjectPart>().Sum(part => part.ParentGroup.ChildrenList.Count);
  1588. #endif
  1589. IOpenRegionSettingsModule module = m_parentScene.RequestModuleInterface<IOpenRegionSettingsModule>();
  1590. if (module != null)
  1591. {
  1592. if (LinkCount > module.MaximumLinkCount &&
  1593. module.MaximumLinkCount != -1)
  1594. {
  1595. client.SendAlertMessage("You cannot link more than " + module.MaximumLinkCount +
  1596. " prims. Please try again with fewer prims.");
  1597. return;
  1598. }
  1599. if ((root.Flags & PrimFlags.Physics) == PrimFlags.Physics)
  1600. {
  1601. //We only check the root here because if the root is physical, it will be applied to all during the link
  1602. if (LinkCount > module.MaximumLinkCountPhys &&
  1603. module.MaximumLinkCountPhys != -1)
  1604. {
  1605. client.SendAlertMessage("You cannot link more than " + module.MaximumLinkCountPhys +
  1606. " physical prims. Please try again with fewer prims.");
  1607. return;
  1608. }
  1609. }
  1610. }
  1611. LinkObjects(root, children);
  1612. }
  1613. /// <summary>
  1614. /// Initial method invoked when we receive a link objects request from the client.
  1615. /// </summary>
  1616. /// <param name="root"></param>
  1617. /// <param name="children"></param>
  1618. protected internal void LinkObjects(ISceneChildEntity root, List<ISceneChildEntity> children)
  1619. {
  1620. Monitor.Enter(m_updateLock);
  1621. try
  1622. {
  1623. ISceneEntity parentGroup = root.ParentEntity;
  1624. List<ISceneEntity> childGroups = new List<ISceneEntity>();
  1625. if (parentGroup != null)
  1626. {
  1627. // We do this in reverse to get the link order of the prims correct
  1628. for (int i = children.Count - 1; i >= 0; i--)
  1629. {
  1630. ISceneEntity child = children[i].ParentEntity;
  1631. if (child != null)
  1632. {
  1633. // Make sure no child prim is set for sale
  1634. // So that, on delink, no prims are unwittingly
  1635. // left for sale and sold off
  1636. child.RootChild.ObjectSaleType = 0;
  1637. child.RootChild.SalePrice = 10;
  1638. childGroups.Add(child);
  1639. }
  1640. }
  1641. }
  1642. else
  1643. {
  1644. return; // parent is null so not in this region
  1645. }
  1646. foreach (ISceneEntity child in childGroups)
  1647. {
  1648. parentGroup.LinkToGroup(child);
  1649. // this is here so physics gets updated!
  1650. // Don't remove! Bad juju! Stay away! or fix physics!
  1651. child.AbsolutePosition = child.AbsolutePosition;
  1652. }
  1653. // We need to explicitly resend the newly link prim's object properties since no other actions
  1654. // occur on link to invoke this elsewhere (such as object selection)
  1655. parentGroup.RootChild.CreateSelected = true;
  1656. parentGroup.HasGroupChanged = true;
  1657. //parentGroup.RootPart.SendFullUpdateToAllClients(PrimUpdateFlags.FullUpdate);
  1658. //parentGroup.ScheduleGroupForFullUpdate(PrimUpdateFlags.FullUpdate);
  1659. parentGroup.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  1660. parentGroup.TriggerScriptChangedEvent(Changed.LINK);
  1661. }
  1662. finally
  1663. {
  1664. Monitor.Exit(m_updateLock);
  1665. }
  1666. }
  1667. /// <summary>
  1668. /// Delink a linkset
  1669. /// </summary>
  1670. /// <param name="prims"></param>
  1671. protected internal void DelinkObjects(List<ISceneChildEntity> prims)
  1672. {
  1673. Monitor.Enter(m_updateLock);
  1674. try
  1675. {
  1676. List<ISceneChildEntity> childParts = new List<ISceneChildEntity>();
  1677. List<ISceneChildEntity> rootParts = new List<ISceneChildEntity>();
  1678. List<ISceneEntity> affectedGroups = new List<ISceneEntity>();
  1679. // Look them all up in one go, since that is comparatively expensive
  1680. //
  1681. foreach (ISceneChildEntity part in prims)
  1682. {
  1683. if (part != null)
  1684. {
  1685. if (part.ParentEntity.PrimCount != 1) // Skip single
  1686. {
  1687. if (part.LinkNum < 2) // Root
  1688. rootParts.Add(part);
  1689. else
  1690. childParts.Add(part);
  1691. ISceneEntity group = part.ParentEntity;
  1692. if (!affectedGroups.Contains(group))
  1693. affectedGroups.Add(group);
  1694. }
  1695. }
  1696. }
  1697. foreach (ISceneChildEntity child in childParts)
  1698. {
  1699. // Unlink all child parts from their groups
  1700. //
  1701. child.ParentEntity.DelinkFromGroup(child, true);
  1702. // These are not in affected groups and will not be
  1703. // handled further. Do the honors here.
  1704. child.ParentEntity.HasGroupChanged = true;
  1705. if (!affectedGroups.Contains(child.ParentEntity))
  1706. affectedGroups.Add(child.ParentEntity);
  1707. }
  1708. foreach (ISceneChildEntity root in rootParts)
  1709. {
  1710. // In most cases, this will run only one time, and the prim
  1711. // will be a solo prim
  1712. // However, editing linked parts and unlinking may be different
  1713. //
  1714. ISceneEntity group = root.ParentEntity;
  1715. List<ISceneChildEntity> newSet = new List<ISceneChildEntity>(group.ChildrenEntities());
  1716. int numChildren = group.PrimCount;
  1717. // If there are prims left in a link set, but the root is
  1718. // slated for unlink, we need to do this
  1719. //
  1720. if (numChildren != 1)
  1721. {
  1722. // Unlink the remaining set
  1723. //
  1724. bool sendEventsToRemainder = true;
  1725. if (numChildren > 1)
  1726. sendEventsToRemainder = false;
  1727. foreach (ISceneChildEntity p in newSet)
  1728. {
  1729. if (p != group.RootChild)
  1730. group.DelinkFromGroup(p, sendEventsToRemainder);
  1731. }
  1732. // If there is more than one prim remaining, we
  1733. // need to re-link
  1734. //
  1735. if (numChildren > 2)
  1736. {
  1737. // Remove old root
  1738. //
  1739. if (newSet.Contains(root))
  1740. newSet.Remove(root);
  1741. // Preserve link ordering
  1742. //
  1743. newSet.Sort(LinkSetSorter);
  1744. // Determine new root
  1745. //
  1746. ISceneChildEntity newRoot = newSet[0];
  1747. newSet.RemoveAt(0);
  1748. LinkObjects(newRoot, newSet);
  1749. if (!affectedGroups.Contains(newRoot.ParentEntity))
  1750. affectedGroups.Add(newRoot.ParentEntity);
  1751. }
  1752. }
  1753. }
  1754. // Finally, trigger events in the roots
  1755. //
  1756. foreach (ISceneEntity g in affectedGroups)
  1757. {
  1758. g.TriggerScriptChangedEvent(Changed.LINK);
  1759. g.HasGroupChanged = true; // Persist
  1760. g.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  1761. }
  1762. //Fix undo states now that the linksets have been changed
  1763. foreach (ISceneChildEntity part in prims)
  1764. {
  1765. part.StoreUndoState();
  1766. }
  1767. }
  1768. finally
  1769. {
  1770. Monitor.Exit(m_updateLock);
  1771. }
  1772. }
  1773. /// <summary>
  1774. /// Sorts a list of Parts by Link Number so they end up in the correct order
  1775. /// </summary>
  1776. /// <param name="a"></param>
  1777. /// <param name="b"></param>
  1778. /// <returns></returns>
  1779. public int LinkSetSorter(ISceneChildEntity a, ISceneChildEntity b)
  1780. {
  1781. return a.LinkNum.CompareTo(b.LinkNum);
  1782. }
  1783. #endregion
  1784. #endregion
  1785. #region New Scene Entity Manager Code
  1786. public bool LinkPartToSOG(ISceneEntity grp, ISceneChildEntity part, int linkNum)
  1787. {
  1788. part.SetParentLocalId(grp.RootChild.LocalId);
  1789. part.SetParent(grp);
  1790. // Insert in terms of link numbers, the new links
  1791. // before the current ones (with the exception of
  1792. // the root prim. Shuffle the old ones up
  1793. foreach (ISceneChildEntity otherPart in grp.ChildrenEntities())
  1794. {
  1795. if (otherPart.LinkNum >= linkNum)
  1796. {
  1797. // Don't update root prim link number
  1798. otherPart.LinkNum += 1;
  1799. }
  1800. }
  1801. part.LinkNum = linkNum;
  1802. return LinkPartToEntity(grp, part);
  1803. }
  1804. /// <summary>
  1805. /// Dupliate the entity and add it to the Scene
  1806. /// </summary>
  1807. /// <param name="entity"></param>
  1808. /// <returns></returns>
  1809. public ISceneEntity DuplicateEntity(ISceneEntity entity)
  1810. {
  1811. //Make an exact copy of the entity
  1812. ISceneEntity copiedEntity = entity.Copy(false);
  1813. //Add the entity to the scene and back it up
  1814. //Reset the entity IDs
  1815. ResetEntityIDs(copiedEntity);
  1816. //Force the prim to backup now that it has been added
  1817. copiedEntity.ForcePersistence();
  1818. //Tell the entity that they are being added to a scene
  1819. copiedEntity.AttachToScene(m_parentScene);
  1820. //Now save the entity that we have
  1821. AddEntity(copiedEntity, false);
  1822. //Fix physics representation now
  1823. // entity.RebuildPhysicalRepresentation();
  1824. return copiedEntity;
  1825. }
  1826. /// <summary>
  1827. /// Add the new part to the group in the EntityManager
  1828. /// </summary>
  1829. /// <param name="entity"></param>
  1830. /// <param name="part"></param>
  1831. /// <returns></returns>
  1832. public bool LinkPartToEntity(ISceneEntity entity, ISceneChildEntity part)
  1833. {
  1834. //Remove the entity so that we can rebuild
  1835. RemoveEntity(entity);
  1836. bool RetVal = entity.LinkChild(part);
  1837. AddEntity(entity, false);
  1838. //Now that everything is linked, destroy the undo states because it will fry the link otherwise
  1839. entity.ClearUndoState();
  1840. return RetVal;
  1841. }
  1842. /// <summary>
  1843. /// Delinks the object from the group in the EntityManager
  1844. /// </summary>
  1845. /// <param name="entity"></param>
  1846. /// <param name="part"></param>
  1847. /// <returns></returns>
  1848. public bool DeLinkPartFromEntity(ISceneEntity entity, ISceneChildEntity part)
  1849. {
  1850. //Remove the entity so that we can rebuild
  1851. RemoveEntity(entity);
  1852. bool RetVal = entity.RemoveChild(part);
  1853. AddEntity(entity, false);
  1854. //Now that everything is linked, destroy the undo states because it will fry the object otherwise
  1855. entity.ClearUndoState();
  1856. return RetVal;
  1857. }
  1858. /// <summary>
  1859. /// THIS IS TO ONLY BE CALLED WHEN AN OBJECT UUID IS UPDATED!!!
  1860. /// This method is HIGHLY unsafe and destroys the integrity of the checks above!
  1861. /// This is NOT to be used lightly! Do NOT use this unless you have to!
  1862. /// </summary>
  1863. /// <param name="entity"></param>
  1864. /// <param name="newID">new UUID to set the root part to</param>
  1865. public void UpdateEntity(ISceneEntity entity, UUID newID)
  1866. {
  1867. RemoveEntity(entity);
  1868. //Set it to the root so that we don't create an infinite loop as the ONLY place this should be being called is from the setter in SceneObjectGroup.UUID
  1869. entity.RootChild.UUID = newID;
  1870. AddEntity(entity, false);
  1871. }
  1872. #endregion
  1873. #region Public Methods
  1874. /// <summary>
  1875. /// Try to get an EntityBase as given by its UUID
  1876. /// </summary>
  1877. /// <param name="ID"></param>
  1878. /// <param name="entity"></param>
  1879. /// <returns></returns>
  1880. public bool TryGetEntity(UUID ID, out IEntity entity)
  1881. {
  1882. return Entities.TryGetValue(ID, out entity);
  1883. }
  1884. /// <summary>
  1885. /// Try to get an EntityBase as given by it's LocalID
  1886. /// </summary>
  1887. /// <param name="LocalID"></param>
  1888. /// <param name="entity"></param>
  1889. /// <returns></returns>
  1890. public bool TryGetEntity(uint LocalID, out IEntity entity)
  1891. {
  1892. return Entities.TryGetValue(LocalID, out entity);
  1893. }
  1894. /// <summary>
  1895. /// Get a part (SceneObjectPart) from the EntityManager by LocalID
  1896. /// </summary>
  1897. /// <param name="LocalID"></param>
  1898. /// <param name="entity"></param>
  1899. /// <returns></returns>
  1900. public bool TryGetPart(uint LocalID, out ISceneChildEntity entity)
  1901. {
  1902. return Entities.TryGetChildPrim(LocalID, out entity);
  1903. }
  1904. /// <summary>
  1905. /// Get a part (SceneObjectPart) from the EntityManager by UUID
  1906. /// </summary>
  1907. /// <param name="ID"></param>
  1908. /// <param name="entity"></param>
  1909. /// <returns></returns>
  1910. public bool TryGetPart(UUID ID, out ISceneChildEntity entity)
  1911. {
  1912. IEntity ent;
  1913. if (Entities.TryGetValue(ID, out ent))
  1914. {
  1915. if (ent is ISceneEntity)
  1916. {
  1917. ISceneEntity parent = (ISceneEntity) ent;
  1918. return parent.GetChildPrim(ID, out entity);
  1919. }
  1920. }
  1921. entity = null;
  1922. return false;
  1923. }
  1924. /// <summary>
  1925. /// Get this prim ready to add to the scene
  1926. /// </summary>
  1927. /// <param name="entity"></param>
  1928. public void PrepPrimForAdditionToScene(ISceneEntity entity)
  1929. {
  1930. ResetEntityIDs(entity);
  1931. }
  1932. /// <summary>
  1933. /// Add the Entity to the Scene and back it up
  1934. /// </summary>
  1935. /// <param name="entity"></param>
  1936. /// <returns></returns>
  1937. public bool AddPrimToScene(ISceneEntity entity)
  1938. {
  1939. //Reset the entity IDs
  1940. ResetEntityIDs(entity);
  1941. //Force the prim to backup now that it has been added
  1942. entity.ForcePersistence();
  1943. //Tell the entity that they are being added to a scene
  1944. entity.AttachToScene(m_parentScene);
  1945. //Now save the entity that we have
  1946. return AddEntity(entity, false);
  1947. }
  1948. /// <summary>
  1949. /// Add the Entity to the Scene and back it up, but do NOT reset its ID's
  1950. /// </summary>
  1951. /// <param name="entity"></param>
  1952. /// <param name="force"></param>
  1953. /// <returns></returns>
  1954. public bool RestorePrimToScene(ISceneEntity entity, bool force)
  1955. {
  1956. List<ISceneChildEntity> children = entity.ChildrenEntities();
  1957. //Sort so that we rebuild in the same order and the root being first
  1958. children.Sort(LinkSetSorter);
  1959. entity.ClearChildren();
  1960. foreach (ISceneChildEntity child in children)
  1961. {
  1962. if (child.LocalId == 0)
  1963. child.LocalId = AllocateLocalId();
  1964. if (((SceneObjectPart) child).PhysActor != null)
  1965. {
  1966. ((SceneObjectPart) child).PhysActor.LocalID = child.LocalId;
  1967. ((SceneObjectPart) child).PhysActor.UUID = child.UUID;
  1968. }
  1969. child.Flags &= ~PrimFlags.Scripted;
  1970. child.TrimPermissions();
  1971. entity.AddChild(child, child.LinkNum);
  1972. }
  1973. //Tell the entity that they are being added to a scene
  1974. entity.AttachToScene(m_parentScene);
  1975. //Now save the entity that we have
  1976. bool success = AddEntity(entity, false);
  1977. if (force && !success)
  1978. {
  1979. IBackupModule backup = m_parentScene.RequestModuleInterface<IBackupModule>();
  1980. backup.DeleteSceneObjects(new ISceneEntity[1] {entity}, false, true);
  1981. return RestorePrimToScene(entity, false);
  1982. }
  1983. return success;
  1984. }
  1985. /// <summary>
  1986. /// Move this group from inside of another group into the Scene as a full member
  1987. /// This does not reset IDs so that it is updated correctly in the client
  1988. /// </summary>
  1989. /// <param name="entity"></param>
  1990. public void DelinkPartToScene(ISceneEntity entity)
  1991. {
  1992. //Force the prim to backup now that it has been added
  1993. entity.ForcePersistence();
  1994. //Tell the entity that they are being added to a scene
  1995. entity.RebuildPhysicalRepresentation(true);
  1996. //Now save the entity that we have
  1997. AddEntity(entity, false);
  1998. }
  1999. /// <summary>
  2000. /// Destroy the entity and remove it from the scene
  2001. /// </summary>
  2002. /// <param name="entity"></param>
  2003. /// <returns></returns>
  2004. public bool DeleteEntity(IEntity entity)
  2005. {
  2006. return RemoveEntity(entity);
  2007. }
  2008. #endregion
  2009. #region Private Methods
  2010. /// These methods are UNSAFE to be accessed from outside this manager, if they are, BAD things WILL happen.
  2011. /// If these are changed so that they can be accessed from the outside, ghost prims and other nasty things will occur unless you are EXTREMELY careful.
  2012. /// If more changes need to occur in this area, you must use public methods to safely add/update/remove objects from the EntityManager
  2013. /// <summary>
  2014. /// Remove this entity fully from the EntityManager
  2015. /// </summary>
  2016. /// <param name="entity"></param>
  2017. /// <returns></returns>
  2018. private bool RemoveEntity(IEntity entity)
  2019. {
  2020. return Entities.Remove(entity);
  2021. }
  2022. /// <summary>
  2023. /// Add this entity to the EntityManager
  2024. /// </summary>
  2025. /// <param name="entity"></param>
  2026. /// <param name="AllowUpdate"></param>
  2027. /// <returns></returns>
  2028. private bool AddEntity(IEntity entity, bool AllowUpdate)
  2029. {
  2030. return Entities.Add(entity);
  2031. }
  2032. /// <summary>
  2033. /// Reset all of the UUID's, localID's, etc in this group (includes children)
  2034. /// </summary>
  2035. /// <param name="entity"></param>
  2036. private void ResetEntityIDs(ISceneEntity entity)
  2037. {
  2038. List<ISceneChildEntity> children = entity.ChildrenEntities();
  2039. //Sort so that we rebuild in the same order and the root being first
  2040. children.Sort(LinkSetSorter);
  2041. entity.ClearChildren();
  2042. foreach (ISceneChildEntity child in children)
  2043. {
  2044. UUID oldID = child.UUID;
  2045. child.ResetEntityIDs();
  2046. entity.AddChild(child, child.LinkNum);
  2047. }
  2048. //This clears the xml file, which will need rebuilt now that we have changed the UUIDs
  2049. entity.HasGroupChanged = true;
  2050. foreach (ISceneChildEntity child in children)
  2051. {
  2052. if (!child.IsRoot)
  2053. {
  2054. child.SetParentLocalId(entity.RootChild.LocalId);
  2055. }
  2056. }
  2057. }
  2058. /// <summary>
  2059. /// Returns a new unallocated local ID
  2060. /// </summary>
  2061. /// <returns>A brand new local ID</returns>
  2062. public uint AllocateLocalId()
  2063. {
  2064. lock (_primAllocateLock)
  2065. return ++m_lastAllocatedLocalId;
  2066. }
  2067. /// <summary>
  2068. /// Check all the localIDs in this group to make sure that they have not been used previously
  2069. /// </summary>
  2070. /// <param name="group"></param>
  2071. public void CheckAllocationOfLocalIds(ISceneEntity group)
  2072. {
  2073. foreach (ISceneChildEntity part in group.ChildrenEntities())
  2074. {
  2075. if (part.LocalId != 0)
  2076. CheckAllocationOfLocalId(part.LocalId);
  2077. }
  2078. }
  2079. /// <summary>
  2080. /// Make sure that this localID has not been used earlier in the Scene Startup
  2081. /// </summary>
  2082. /// <param name="LocalID"></param>
  2083. private void CheckAllocationOfLocalId(uint LocalID)
  2084. {
  2085. lock (_primAllocateLock)
  2086. {
  2087. if (LocalID > m_lastAllocatedLocalId)
  2088. m_lastAllocatedLocalId = LocalID + 1;
  2089. }
  2090. }
  2091. #endregion
  2092. }
  2093. }