2007-12-27 21:41:48 +00:00
/ *
2008-03-18 05:16:43 +00:00
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2007-12-11 01:26:06 +00:00
using System ;
2007-11-04 14:34:45 +00:00
using System.Collections.Generic ;
2008-04-21 07:09:17 +00:00
using System.Reflection ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse ;
using OpenMetaverse.Packets ;
2008-04-21 07:09:17 +00:00
using log4net ;
2007-11-04 14:34:45 +00:00
using OpenSim.Framework ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Scenes.Types ;
2007-11-04 14:34:45 +00:00
using OpenSim.Region.Physics.Manager ;
2009-02-06 16:55:34 +00:00
namespace OpenSim.Region.Framework.Scenes
2007-11-04 14:34:45 +00:00
{
2007-11-28 06:18:07 +00:00
public delegate void PhysicsCrash ( ) ;
2009-01-06 15:14:15 +00:00
public delegate void ObjectDuplicateDelegate ( EntityBase original , EntityBase clone ) ;
public delegate void ObjectCreateDelegate ( EntityBase obj ) ;
public delegate void ObjectDeleteDelegate ( EntityBase obj ) ;
2008-11-12 20:16:46 +00:00
/// <summary>
/// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
/// should be migrated out over time.
/// </summary>
public class SceneGraph
2007-11-04 14:34:45 +00:00
{
2008-04-21 07:09:17 +00:00
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2008-02-05 19:44:27 +00:00
2007-11-28 06:18:07 +00:00
#region Events
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal event PhysicsCrash UnRecoverableError ;
2008-05-01 18:04:42 +00:00
private PhysicsCrash handlerPhysicsCrash = null ;
2007-12-27 21:41:48 +00:00
2009-01-06 15:14:15 +00:00
public event ObjectDuplicateDelegate OnObjectDuplicate ;
public event ObjectCreateDelegate OnObjectCreate ;
public event ObjectDeleteDelegate OnObjectRemove ;
2007-11-28 06:18:07 +00:00
# endregion
2007-11-04 22:22:53 +00:00
#region Fields
2007-12-27 21:41:48 +00:00
2008-09-06 07:52:41 +00:00
protected internal Dictionary < UUID , ScenePresence > ScenePresences = new Dictionary < UUID , ScenePresence > ( ) ;
2008-01-07 02:33:22 +00:00
// SceneObjects is not currently populated or used.
2008-09-06 07:52:41 +00:00
//public Dictionary<UUID, SceneObjectGroup> SceneObjects;
2008-11-24 14:45:05 +00:00
protected internal EntityManager Entities = new EntityManager ( ) ;
// protected internal Dictionary<UUID, EntityBase> Entities = new Dictionary<UUID, EntityBase>();
2008-09-06 07:52:41 +00:00
protected internal Dictionary < UUID , ScenePresence > RestorePresences = new Dictionary < UUID , ScenePresence > ( ) ;
2008-05-01 18:04:42 +00:00
2008-05-26 01:06:50 +00:00
protected internal BasicQuadTreeNode QuadTree ;
2008-05-01 18:04:42 +00:00
2008-05-01 16:35:00 +00:00
protected RegionInfo m_regInfo ;
2008-05-01 18:04:42 +00:00
protected Scene m_parentScene ;
protected List < EntityBase > m_updateList = new List < EntityBase > ( ) ;
protected int m_numRootAgents = 0 ;
protected int m_numPrim = 0 ;
protected int m_numChildAgents = 0 ;
protected int m_physicalPrim = 0 ;
2007-11-04 22:22:53 +00:00
2008-05-01 18:04:42 +00:00
protected int m_activeScripts = 0 ;
protected int m_scriptLPS = 0 ;
2008-02-06 08:03:22 +00:00
2008-05-26 01:06:50 +00:00
protected internal object m_syncRoot = new object ( ) ;
2008-05-01 18:04:42 +00:00
2008-05-26 01:06:50 +00:00
protected internal PhysicsScene _PhyScene ;
2007-12-27 21:41:48 +00:00
2007-11-04 22:22:53 +00:00
# endregion
2007-11-04 14:34:45 +00:00
2008-11-12 20:16:46 +00:00
protected internal SceneGraph ( Scene parent , RegionInfo regInfo )
2007-11-04 14:34:45 +00:00
{
m_parentScene = parent ;
m_regInfo = regInfo ;
2008-05-01 18:04:42 +00:00
QuadTree = new BasicQuadTreeNode ( null , "/0/" , 0 , 0 , ( short ) Constants . RegionSize , ( short ) Constants . RegionSize ) ;
2007-11-04 14:34:45 +00:00
QuadTree . Subdivide ( ) ;
QuadTree . Subdivide ( ) ;
2007-11-28 06:18:07 +00:00
}
2007-12-06 18:17:44 +00:00
2007-11-29 15:27:57 +00:00
public PhysicsScene PhysicsScene
2007-11-28 06:18:07 +00:00
{
2007-12-27 21:41:48 +00:00
get { return _PhyScene ; }
2007-11-28 06:18:07 +00:00
set
{
// If we're not doing the initial set
2008-05-16 01:22:11 +00:00
// Then we've got to remove the previous
2007-11-28 06:18:07 +00:00
// event handler
2008-07-21 13:40:08 +00:00
2008-08-18 00:39:10 +00:00
if ( _PhyScene ! = null )
2007-12-27 21:41:48 +00:00
_PhyScene . OnPhysicsCrash - = physicsBasedCrash ;
2007-11-28 06:18:07 +00:00
_PhyScene = value ;
2007-12-27 21:41:48 +00:00
2008-07-21 13:40:08 +00:00
if ( _PhyScene ! = null )
_PhyScene . OnPhysicsCrash + = physicsBasedCrash ;
2007-11-28 06:18:07 +00:00
}
2007-11-04 14:34:45 +00:00
}
2008-05-26 01:06:50 +00:00
protected internal void Close ( )
2007-11-04 14:34:45 +00:00
{
2008-05-07 22:59:30 +00:00
lock ( ScenePresences )
{
ScenePresences . Clear ( ) ;
}
2008-05-16 01:22:11 +00:00
2008-11-24 15:09:25 +00:00
Entities . Clear ( ) ;
2007-11-04 14:34:45 +00:00
}
2007-11-04 22:22:53 +00:00
#region Update Methods
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal void UpdatePreparePhysics ( )
2007-11-04 22:22:53 +00:00
{
// If we are using a threaded physics engine
// grab the latest scene from the engine before
// trying to process it.
// PhysX does this (runs in the background).
2007-11-28 06:18:07 +00:00
if ( _PhyScene . IsThreaded )
2007-11-04 22:22:53 +00:00
{
2007-11-28 06:18:07 +00:00
_PhyScene . GetResults ( ) ;
2007-11-04 22:22:53 +00:00
}
}
2008-05-26 01:06:50 +00:00
protected internal void UpdateEntities ( )
2007-11-04 22:22:53 +00:00
{
2007-12-17 16:41:28 +00:00
List < EntityBase > updateEntities = GetEntities ( ) ;
2007-11-04 22:22:53 +00:00
foreach ( EntityBase entity in updateEntities )
2008-09-09 01:26:48 +00:00
{
2008-09-06 01:10:47 +00:00
entity . Update ( ) ;
2007-11-04 22:22:53 +00:00
}
}
2008-05-26 01:06:50 +00:00
protected internal void UpdatePresences ( )
2008-02-20 00:08:04 +00:00
{
List < ScenePresence > updateScenePresences = GetScenePresences ( ) ;
foreach ( ScenePresence pres in updateScenePresences )
{
pres . Update ( ) ;
}
}
2008-05-26 01:06:50 +00:00
protected internal float UpdatePhysics ( double elapsed )
2007-11-04 22:22:53 +00:00
{
lock ( m_syncRoot )
{
2008-12-26 12:58:02 +00:00
// Here is where the Scene calls the PhysicsScene. This is a one-way
// interaction; the PhysicsScene cannot access the calling Scene directly.
// But with joints, we want a PhysicsActor to be able to influence a
// non-physics SceneObjectPart. In particular, a PhysicsActor that is connected
// with a joint should be able to move the SceneObjectPart which is the visual
// representation of that joint (for editing and serialization purposes).
// However the PhysicsActor normally cannot directly influence anything outside
// of the PhysicsScene, and the non-physical SceneObjectPart which represents
// the joint in the Scene does not exist in the PhysicsScene.
/ /
// To solve this, we have an event in the PhysicsScene that is fired when a joint
// has changed position (because one of its associated PhysicsActors has changed
// position).
/ /
// Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
2008-05-01 18:04:42 +00:00
return _PhyScene . Simulate ( ( float ) elapsed ) ;
2007-11-04 22:22:53 +00:00
}
}
2008-05-26 01:06:50 +00:00
protected internal void UpdateEntityMovement ( )
2007-11-04 22:22:53 +00:00
{
2007-12-17 16:41:28 +00:00
List < EntityBase > moveEntities = GetEntities ( ) ;
2007-11-04 22:22:53 +00:00
foreach ( EntityBase entity in moveEntities )
{
2008-06-08 17:36:41 +00:00
//cfk. This throws occaisional exceptions on a heavily used region
//and I added this null check to try to preclude the exception.
2008-06-09 08:46:33 +00:00
if ( entity ! = null )
entity . UpdateMovement ( ) ;
2007-11-04 22:22:53 +00:00
}
}
2007-12-27 21:41:48 +00:00
2007-11-04 22:22:53 +00:00
# endregion
#region Entity Methods
2007-12-27 21:41:48 +00:00
2008-05-24 22:10:14 +00:00
/// <summary>
/// Add an object into the scene that has come from storage
/// </summary>
/// <param name="sceneObject"></param>
2008-06-27 14:15:14 +00:00
/// <param name="attachToBackup">
/// If true, changes to the object will be reflected in its persisted data
/// If false, the persisted data will not be changed even if the object in the scene is changed
/// </param>
2008-07-13 00:18:29 +00:00
/// <param name="alreadyPersisted">
/// If true, we won't persist this object until it changes
/// If false, we'll persist this object immediately
/// </param>
2008-07-12 22:14:38 +00:00
/// <returns>
/// true if the object was added, false if an object with the same uuid was already in the scene
2008-08-18 00:39:10 +00:00
/// </returns>
2008-07-13 00:18:29 +00:00
protected internal bool AddRestoredSceneObject (
SceneObjectGroup sceneObject , bool attachToBackup , bool alreadyPersisted )
2007-11-04 14:34:45 +00:00
{
2008-07-13 00:18:29 +00:00
if ( ! alreadyPersisted )
{
sceneObject . ForceInventoryPersistence ( ) ;
sceneObject . HasGroupChanged = true ;
}
2008-08-18 00:39:10 +00:00
2008-07-12 22:14:38 +00:00
return AddSceneObject ( sceneObject , attachToBackup ) ;
2007-11-04 14:34:45 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-27 14:25:36 +00:00
/// <summary>
/// Add a newly created object to the scene. This will both update the scene, and send information about the
/// new object to all clients interested in the scene.
/// </summary>
/// <param name="sceneObject"></param>
/// <param name="attachToBackup">
/// If true, the object is made persistent into the scene.
/// If false, the object will not persist over server restarts
/// </param>
2008-07-12 22:14:38 +00:00
/// <returns>
/// true if the object was added, false if an object with the same uuid was already in the scene
2008-08-18 00:39:10 +00:00
/// </returns>
2008-07-12 22:14:38 +00:00
protected internal bool AddNewSceneObject ( SceneObjectGroup sceneObject , bool attachToBackup )
2008-08-18 00:39:10 +00:00
{
2008-06-27 14:46:44 +00:00
// Ensure that we persist this new scene object
sceneObject . HasGroupChanged = true ;
2008-08-18 00:39:10 +00:00
2008-07-12 22:14:38 +00:00
return AddSceneObject ( sceneObject , attachToBackup ) ;
2008-06-27 14:25:36 +00:00
}
2007-11-04 14:34:45 +00:00
2008-05-24 22:10:14 +00:00
/// <summary>
2008-06-17 20:36:21 +00:00
/// Add an object to the scene. This will both update the scene, and send information about the
/// new object to all clients interested in the scene.
2008-05-24 22:10:14 +00:00
/// </summary>
/// <param name="sceneObject"></param>
2008-06-12 17:49:08 +00:00
/// <param name="attachToBackup">
2008-06-13 00:21:53 +00:00
/// If true, the object is made persistent into the scene.
2008-06-12 17:49:08 +00:00
/// If false, the object will not persist over server restarts
/// </param>
2008-05-24 23:11:07 +00:00
/// <returns>true if the object was added, false if an object with the same uuid was already in the scene
/// </returns>
2008-06-27 14:25:36 +00:00
protected bool AddSceneObject ( SceneObjectGroup sceneObject , bool attachToBackup )
2007-11-04 14:34:45 +00:00
{
2008-10-13 20:45:13 +00:00
if ( sceneObject = = null | | sceneObject . RootPart = = null | | sceneObject . RootPart . UUID = = UUID . Zero )
2008-10-11 16:23:15 +00:00
return false ;
2008-11-06 22:21:25 +00:00
2008-11-12 01:40:38 +00:00
if ( m_parentScene . m_clampPrimSize )
{
foreach ( SceneObjectPart part in sceneObject . Children . Values )
{
Vector3 scale = part . Shape . Scale ;
if ( scale . X > m_parentScene . m_maxNonphys )
scale . X = m_parentScene . m_maxNonphys ;
if ( scale . Y > m_parentScene . m_maxNonphys )
scale . Y = m_parentScene . m_maxNonphys ;
if ( scale . Z > m_parentScene . m_maxNonphys )
scale . Z = m_parentScene . m_maxNonphys ;
part . Shape . Scale = scale ;
}
}
2008-11-06 22:21:25 +00:00
sceneObject . AttachToScene ( m_parentScene ) ;
2008-08-18 00:39:10 +00:00
2008-11-24 15:09:25 +00:00
lock ( sceneObject )
2007-11-04 14:34:45 +00:00
{
2008-05-24 23:11:07 +00:00
if ( ! Entities . ContainsKey ( sceneObject . UUID ) )
2007-12-17 16:41:28 +00:00
{
2008-11-24 15:09:25 +00:00
Entities . Add ( sceneObject ) ;
2008-06-06 23:20:02 +00:00
m_numPrim + = sceneObject . Children . Count ;
2008-06-13 00:21:53 +00:00
2008-08-18 00:39:10 +00:00
if ( attachToBackup )
sceneObject . AttachToBackup ( ) ;
2008-05-28 03:44:49 +00:00
2009-01-06 15:14:15 +00:00
if ( OnObjectCreate ! = null )
OnObjectCreate ( sceneObject ) ;
2008-05-24 23:11:07 +00:00
return true ;
2007-12-17 16:41:28 +00:00
}
2007-11-04 14:34:45 +00:00
}
2008-11-24 15:09:25 +00:00
return false ;
2007-11-04 14:34:45 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-24 23:11:07 +00:00
/// <summary>
/// Delete an object from the scene
/// </summary>
/// <returns>true if the object was deleted, false if there was no object to delete</returns>
2009-02-06 16:55:34 +00:00
public bool DeleteSceneObject ( UUID uuid , bool resultOfObjectLinked )
2008-05-24 23:11:07 +00:00
{
2008-11-24 15:09:25 +00:00
if ( Entities . ContainsKey ( uuid ) )
2008-05-24 23:11:07 +00:00
{
2008-11-24 15:09:25 +00:00
if ( ! resultOfObjectLinked )
2008-05-24 23:11:07 +00:00
{
2008-11-24 15:09:25 +00:00
m_numPrim - = ( ( SceneObjectGroup ) Entities [ uuid ] ) . Children . Count ;
2009-01-03 03:30:03 +00:00
if ( ( ( ( SceneObjectGroup ) Entities [ uuid ] ) . RootPart . Flags & PrimFlags . Physics ) = = PrimFlags . Physics )
{
RemovePhysicalPrim ( ( ( SceneObjectGroup ) Entities [ uuid ] ) . Children . Count ) ;
}
2008-05-24 23:11:07 +00:00
}
2009-01-03 03:30:03 +00:00
2009-01-06 15:14:15 +00:00
if ( OnObjectRemove ! = null )
OnObjectRemove ( Entities [ uuid ] ) ;
2009-01-03 03:30:03 +00:00
2008-11-24 15:09:25 +00:00
Entities . Remove ( uuid ) ;
2009-01-03 03:30:03 +00:00
//SceneObjectGroup part;
//((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
2008-11-24 15:09:25 +00:00
return true ;
2008-05-24 23:11:07 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-24 23:11:07 +00:00
return false ;
}
2007-12-27 21:41:48 +00:00
2008-03-13 00:22:38 +00:00
/// <summary>
/// Add an entity to the list of prims to process on the next update
/// </summary>
/// <param name="obj">
/// A <see cref="EntityBase"/>
/// </param>
2008-05-26 01:06:50 +00:00
protected internal void AddToUpdateList ( EntityBase obj )
2008-02-20 00:08:04 +00:00
{
lock ( m_updateList )
{
if ( ! m_updateList . Contains ( obj ) )
{
m_updateList . Add ( obj ) ;
}
}
}
2008-03-12 18:11:08 +00:00
/// <summary>
/// Process all pending updates
/// </summary>
2008-05-26 01:06:50 +00:00
protected internal void ProcessUpdates ( )
2008-02-20 00:08:04 +00:00
{
lock ( m_updateList )
{
for ( int i = 0 ; i < m_updateList . Count ; i + + )
{
2008-03-12 18:11:08 +00:00
EntityBase entity = m_updateList [ i ] ;
2008-05-16 01:22:11 +00:00
2008-03-12 18:11:08 +00:00
// Don't abort the whole update if one entity happens to give us an exception.
try
{
2008-09-09 01:26:48 +00:00
m_updateList [ i ] . Update ( ) ;
2008-03-12 18:11:08 +00:00
}
catch ( Exception e )
{
2008-06-21 19:56:19 +00:00
m_log . ErrorFormat (
"[INNER SCENE]: Failed to update {0}, {1} - {2}" , entity . Name , entity . UUID , e ) ;
2008-03-12 18:11:08 +00:00
}
2008-02-20 00:08:04 +00:00
}
2008-08-18 00:39:10 +00:00
2008-02-20 00:08:04 +00:00
m_updateList . Clear ( ) ;
}
}
2008-05-26 01:06:50 +00:00
protected internal void AddPhysicalPrim ( int number )
2007-12-14 00:49:40 +00:00
{
m_physicalPrim + + ;
}
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal void RemovePhysicalPrim ( int number )
2007-12-14 00:49:40 +00:00
{
m_physicalPrim - - ;
}
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal void AddToScriptLPS ( int number )
2008-02-06 08:03:22 +00:00
{
m_scriptLPS + = number ;
}
2008-05-26 01:06:50 +00:00
protected internal void AddActiveScripts ( int number )
2008-02-06 08:03:22 +00:00
{
m_activeScripts + = number ;
}
2008-05-28 03:44:49 +00:00
2009-03-20 13:57:22 +00:00
public void DropObject ( uint objectLocalID , IClientAPI remoteClient )
2008-10-04 01:09:22 +00:00
{
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase obj in EntityList )
{
if ( obj is SceneObjectGroup )
{
if ( ( ( SceneObjectGroup ) obj ) . LocalId = = objectLocalID )
{
SceneObjectGroup group = ( SceneObjectGroup ) obj ;
m_parentScene . DetachSingleAttachmentToGround ( group . UUID , remoteClient ) ;
}
}
}
}
2008-05-26 01:06:50 +00:00
protected internal void DetachObject ( uint objectLocalID , IClientAPI remoteClient )
2008-04-24 11:32:41 +00:00
{
List < EntityBase > EntityList = GetEntities ( ) ;
2007-11-04 14:34:45 +00:00
2008-04-24 11:32:41 +00:00
foreach ( EntityBase obj in EntityList )
{
if ( obj is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) obj ) . LocalId = = objectLocalID )
2008-04-24 11:32:41 +00:00
{
2008-05-01 18:04:42 +00:00
SceneObjectGroup group = ( SceneObjectGroup ) obj ;
2008-04-27 20:10:28 +00:00
//group.DetachToGround();
2008-08-19 02:12:40 +00:00
m_parentScene . DetachSingleAttachmentToInv ( group . GetFromAssetID ( ) , remoteClient ) ;
2008-04-24 11:32:41 +00:00
}
}
}
}
2008-04-28 01:48:21 +00:00
2008-09-06 07:52:41 +00:00
protected internal void HandleUndo ( IClientAPI remoteClient , UUID primId )
2008-04-28 01:48:21 +00:00
{
2008-09-06 07:52:41 +00:00
if ( primId ! = UUID . Zero )
2008-04-28 01:48:21 +00:00
{
2008-05-01 18:04:42 +00:00
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( primId ) ;
2008-04-28 01:48:21 +00:00
if ( part ! = null )
part . Undo ( ) ;
2008-05-28 03:44:49 +00:00
}
2008-04-28 01:48:21 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-26 01:06:50 +00:00
protected internal void HandleObjectGroupUpdate (
2008-09-06 07:52:41 +00:00
IClientAPI remoteClient , UUID GroupID , uint objectLocalID , UUID Garbage )
2008-05-18 03:21:22 +00:00
{
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase obj in EntityList )
{
if ( obj is SceneObjectGroup )
{
if ( ( ( SceneObjectGroup ) obj ) . LocalId = = objectLocalID )
{
SceneObjectGroup group = ( SceneObjectGroup ) obj ;
2008-11-28 09:54:27 +00:00
if ( group . OwnerID = = remoteClient . AgentId )
2008-05-18 03:21:22 +00:00
group . SetGroup ( GroupID , remoteClient ) ;
}
}
}
}
2008-05-28 03:44:49 +00:00
2008-04-26 17:36:30 +00:00
/// <summary>
/// Event Handling routine for Attach Object
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="objectLocalID"></param>
/// <param name="AttachmentPt"></param>
/// <param name="rot"></param>
2008-11-07 05:48:44 +00:00
protected internal void AttachObject ( IClientAPI remoteClient , uint objectLocalID , uint AttachmentPt , Quaternion rot , bool silent )
2008-04-24 11:32:41 +00:00
{
2008-10-03 21:44:33 +00:00
// If we can't take it, we can't attach it!
/ /
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( objectLocalID ) ;
if ( part = = null )
return ;
2008-05-16 01:22:11 +00:00
2008-11-21 22:14:57 +00:00
if ( ! m_parentScene . Permissions . CanTakeObject (
2008-10-03 21:44:33 +00:00
part . UUID , remoteClient . AgentId ) )
return ;
// Calls attach with a Zero position
/ /
2008-11-07 05:48:44 +00:00
AttachObject ( remoteClient , objectLocalID , AttachmentPt , rot , Vector3 . Zero , false ) ;
2008-04-26 17:36:30 +00:00
}
2008-05-28 03:44:49 +00:00
2008-08-19 02:12:40 +00:00
public SceneObjectGroup RezSingleAttachment (
2008-10-04 15:54:21 +00:00
IClientAPI remoteClient , UUID itemID , uint AttachmentPt )
2008-04-27 14:37:51 +00:00
{
2008-10-04 16:45:38 +00:00
SceneObjectGroup objatt = m_parentScene . RezObject ( remoteClient ,
itemID , Vector3 . Zero , Vector3 . Zero , UUID . Zero , ( byte ) 1 , true ,
2008-10-04 15:54:21 +00:00
false , false , remoteClient . AgentId , true ) ;
2008-04-27 14:37:51 +00:00
2008-10-04 16:45:38 +00:00
2008-04-27 14:37:51 +00:00
if ( objatt ! = null )
{
2008-10-04 16:58:34 +00:00
bool tainted = false ;
if ( AttachmentPt ! = 0 & & AttachmentPt ! = objatt . GetAttachmentPoint ( ) )
tainted = true ;
2008-11-07 05:48:44 +00:00
AttachObject ( remoteClient , objatt . LocalId , AttachmentPt , Quaternion . Identity , objatt . AbsolutePosition , false ) ;
2008-04-27 14:37:51 +00:00
objatt . ScheduleGroupForFullUpdate ( ) ;
2008-10-04 16:58:34 +00:00
if ( tainted )
objatt . HasGroupChanged = true ;
2008-11-29 14:16:09 +00:00
// Fire after attach, so we don't get messy perms dialogs
/ /
objatt . CreateScriptInstances ( 0 , true , m_parentScene . DefaultScriptEngine , 0 ) ;
2008-04-27 14:37:51 +00:00
}
2008-08-19 02:12:40 +00:00
return objatt ;
2008-04-27 14:37:51 +00:00
}
2008-04-25 21:41:55 +00:00
2008-09-06 07:52:41 +00:00
// What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
// To LocalId or UUID, *THAT* is the question. How now Brown UUID??
public void DetachSingleAttachmentToInv ( UUID itemID , IClientAPI remoteClient )
2008-04-27 20:10:28 +00:00
{
2008-09-06 07:52:41 +00:00
if ( itemID = = UUID . Zero ) // If this happened, someone made a mistake....
2008-04-27 20:10:28 +00:00
return ;
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase obj in EntityList )
{
if ( obj is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) obj ) . GetFromAssetID ( ) = = itemID )
2008-04-27 20:10:28 +00:00
{
2008-05-01 18:04:42 +00:00
SceneObjectGroup group = ( SceneObjectGroup ) obj ;
2008-04-27 20:10:28 +00:00
group . DetachToInventoryPrep ( ) ;
2008-05-01 18:04:42 +00:00
m_log . Debug ( "[DETACH]: Saving attachpoint: " + ( ( uint ) group . GetAttachmentPoint ( ) ) . ToString ( ) ) ;
2008-06-23 18:01:58 +00:00
m_parentScene . updateKnownAsset ( remoteClient , group , group . GetFromAssetID ( ) , group . OwnerID ) ;
2008-11-07 05:48:44 +00:00
m_parentScene . DeleteSceneObject ( group , false ) ;
2008-04-27 20:10:28 +00:00
}
}
}
}
2008-05-26 01:06:50 +00:00
protected internal void AttachObject (
2008-11-07 05:48:44 +00:00
IClientAPI remoteClient , uint objectLocalID , uint AttachmentPt , Quaternion rot , Vector3 attachPos , bool silent )
2008-04-26 17:36:30 +00:00
{
List < EntityBase > EntityList = GetEntities ( ) ;
2008-04-24 11:32:41 +00:00
foreach ( EntityBase obj in EntityList )
{
if ( obj is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) obj ) . LocalId = = objectLocalID )
2008-04-24 11:32:41 +00:00
{
2008-05-01 18:04:42 +00:00
SceneObjectGroup group = ( SceneObjectGroup ) obj ;
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanTakeObject ( obj . UUID , remoteClient . AgentId ) )
2008-04-27 20:10:28 +00:00
{
2008-05-08 19:22:20 +00:00
// If the attachment point isn't the same as the one previously used
// set it's offset position = 0 so that it appears on the attachment point
// and not in a weird location somewhere unknown.
if ( AttachmentPt ! = 0 & & AttachmentPt ! = ( uint ) group . GetAttachmentPoint ( ) )
{
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
attachPos = Vector3 . Zero ;
2008-05-08 19:22:20 +00:00
}
2008-04-27 20:10:28 +00:00
2008-05-08 19:22:20 +00:00
// AttachmentPt 0 means the client chose to 'wear' the attachment.
if ( AttachmentPt = = 0 )
{
2008-05-01 18:04:42 +00:00
2008-05-08 19:22:20 +00:00
// Check object for stored attachment point
AttachmentPt = ( uint ) group . GetAttachmentPoint ( ) ;
2008-04-27 14:37:51 +00:00
2008-05-08 19:22:20 +00:00
}
// if we still didn't find a suitable attachment point.......
if ( AttachmentPt = = 0 )
{
// Stick it on left hand with Zero Offset from the attachment point.
AttachmentPt = ( uint ) AttachmentPoint . LeftHand ;
2008-09-06 07:52:41 +00:00
attachPos = Vector3 . Zero ;
2008-05-08 19:22:20 +00:00
}
2008-04-27 14:37:51 +00:00
2008-10-04 16:45:38 +00:00
group . SetAttachmentPoint ( Convert . ToByte ( AttachmentPt ) ) ;
2008-11-06 06:23:58 +00:00
group . AbsolutePosition = attachPos ;
2008-05-08 19:22:20 +00:00
// Saves and gets assetID
2008-11-06 06:23:58 +00:00
UUID itemId ;
2009-02-09 22:27:27 +00:00
2008-09-06 07:52:41 +00:00
if ( group . GetFromAssetID ( ) = = UUID . Zero )
2008-05-08 19:22:20 +00:00
{
2008-11-06 06:23:58 +00:00
m_parentScene . attachObjectAssetStore ( remoteClient , group , remoteClient . AgentId , out itemId ) ;
2008-05-08 19:22:20 +00:00
}
2008-11-06 06:23:58 +00:00
else
{
itemId = group . GetFromAssetID ( ) ;
}
m_parentScene . AttachObject ( remoteClient , AttachmentPt , itemId , group ) ;
2008-11-07 05:48:44 +00:00
group . AttachToAgent ( remoteClient . AgentId , AttachmentPt , attachPos , silent ) ;
2008-10-03 13:45:54 +00:00
// In case it is later dropped again, don't let
// it get cleaned up
/ /
group . RootPart . RemFlag ( PrimFlags . TemporaryOnRez ) ;
2008-10-04 16:52:42 +00:00
group . HasGroupChanged = false ;
2008-05-08 19:22:20 +00:00
}
else
{
remoteClient . SendAgentAlertMessage ( "You don't have sufficient permissions to attach this object" , false ) ;
2008-04-27 14:37:51 +00:00
}
2008-05-16 01:22:11 +00:00
2008-04-24 11:32:41 +00:00
}
}
}
2008-05-01 18:04:42 +00:00
}
2008-05-16 01:22:11 +00:00
2008-11-28 20:11:17 +00:00
protected internal ScenePresence CreateAndAddChildScenePresence ( IClientAPI client , AvatarAppearance appearance )
2007-11-04 14:34:45 +00:00
{
ScenePresence newAvatar = null ;
2007-12-07 17:23:11 +00:00
newAvatar = new ScenePresence ( client , m_parentScene , m_regInfo , appearance ) ;
2008-11-28 20:11:17 +00:00
newAvatar . IsChildAgent = true ;
2007-11-04 14:34:45 +00:00
2008-05-26 00:47:36 +00:00
AddScenePresence ( newAvatar ) ;
2008-05-28 03:44:49 +00:00
2007-11-04 14:34:45 +00:00
return newAvatar ;
}
2007-12-27 21:41:48 +00:00
2008-05-26 00:38:04 +00:00
/// <summary>
/// Add a presence to the scene
/// </summary>
/// <param name="presence"></param>
2008-05-26 00:47:36 +00:00
protected internal void AddScenePresence ( ScenePresence presence )
2008-03-04 05:31:54 +00:00
{
bool child = presence . IsChildAgent ;
2008-08-18 00:39:10 +00:00
2008-03-04 05:31:54 +00:00
if ( child )
{
m_numChildAgents + + ;
}
else
{
m_numRootAgents + + ;
2009-02-15 05:00:58 +00:00
presence . AddToPhysicalScene ( false ) ;
2008-03-04 05:31:54 +00:00
}
2008-11-24 15:09:25 +00:00
Entities [ presence . UUID ] = presence ;
2008-03-14 15:28:34 +00:00
2008-03-04 05:31:54 +00:00
lock ( ScenePresences )
{
2008-03-14 15:28:34 +00:00
ScenePresences [ presence . UUID ] = presence ;
2008-03-04 05:31:54 +00:00
}
2008-03-14 15:28:34 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-26 00:38:04 +00:00
/// <summary>
/// Remove a presence from the scene
/// </summary>
2008-09-06 07:52:41 +00:00
protected internal void RemoveScenePresence ( UUID agentID )
2008-05-26 00:38:04 +00:00
{
2008-11-24 15:09:25 +00:00
if ( ! Entities . Remove ( agentID ) )
2008-05-26 00:38:04 +00:00
{
2008-11-24 15:09:25 +00:00
m_log . WarnFormat (
"[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene Entities list" ,
agentID ) ;
2008-05-26 00:38:04 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-26 00:38:04 +00:00
lock ( ScenePresences )
2008-05-28 03:44:49 +00:00
{
2008-08-12 19:00:13 +00:00
if ( ! ScenePresences . Remove ( agentID ) )
2008-05-26 00:38:04 +00:00
{
2008-08-18 00:39:10 +00:00
m_log . WarnFormat ( "[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list" , agentID ) ;
2008-05-26 00:38:04 +00:00
}
2008-08-12 19:00:13 +00:00
// else
// {
// m_log.InfoFormat("[SCENE] Removed scene presence {0} from scene presences list", agentID);
// }
2008-05-28 03:44:49 +00:00
}
2008-05-26 00:38:04 +00:00
}
2008-03-04 05:31:54 +00:00
2008-05-26 01:06:50 +00:00
protected internal void SwapRootChildAgent ( bool direction_RC_CR_T_F )
2007-12-12 06:58:55 +00:00
{
if ( direction_RC_CR_T_F )
{
m_numRootAgents - - ;
m_numChildAgents + + ;
}
else
{
m_numChildAgents - - ;
m_numRootAgents + + ;
}
}
2007-12-27 21:41:48 +00:00
2009-03-30 18:20:41 +00:00
public void removeUserCount ( bool TypeRCTF )
2007-12-12 06:58:55 +00:00
{
if ( TypeRCTF )
{
m_numRootAgents - - ;
}
2007-12-27 21:41:48 +00:00
else
2007-12-12 06:58:55 +00:00
{
m_numChildAgents - - ;
}
}
2007-12-27 21:41:48 +00:00
2009-01-06 00:07:24 +00:00
public void RecalculateStats ( )
{
List < ScenePresence > SPList = GetScenePresences ( ) ;
int rootcount = 0 ;
int childcount = 0 ;
foreach ( ScenePresence user in SPList )
{
if ( user . IsChildAgent )
childcount + + ;
else
rootcount + + ;
}
m_numRootAgents = rootcount ;
m_numChildAgents = childcount ;
}
2008-06-06 23:20:02 +00:00
public int GetChildAgentCount ( )
2007-12-12 06:58:55 +00:00
{
2008-02-07 08:28:48 +00:00
// some network situations come in where child agents get closed twice.
if ( m_numChildAgents < 0 )
2008-02-16 13:01:42 +00:00
{
m_numChildAgents = 0 ;
2008-02-07 08:28:48 +00:00
}
2007-12-12 06:58:55 +00:00
return m_numChildAgents ;
}
2008-06-06 23:20:02 +00:00
public int GetRootAgentCount ( )
2007-12-12 06:58:55 +00:00
{
return m_numRootAgents ;
}
2007-12-12 14:07:26 +00:00
2008-06-06 23:20:02 +00:00
public int GetTotalObjectsCount ( )
2007-12-12 14:07:26 +00:00
{
return m_numPrim ;
}
2008-06-06 23:20:02 +00:00
public int GetActiveObjectsCount ( )
2007-12-14 00:49:40 +00:00
{
return m_physicalPrim ;
}
2008-06-06 23:20:02 +00:00
public int GetActiveScriptsCount ( )
2008-02-06 08:03:22 +00:00
{
return m_activeScripts ;
}
2008-06-06 23:20:02 +00:00
public int GetScriptLPS ( )
2008-02-06 08:03:22 +00:00
{
int returnval = m_scriptLPS ;
m_scriptLPS = 0 ;
return returnval ;
}
2008-05-28 03:44:49 +00:00
2007-11-04 22:22:53 +00:00
# endregion
#region Get Methods
2007-11-04 14:34:45 +00:00
/// <summary>
2008-06-04 09:59:27 +00:00
/// Request a List of all scene presences in this scene. This is a new list, so no
2008-06-03 08:11:04 +00:00
/// locking is required to iterate over it.
2007-11-04 14:34:45 +00:00
/// </summary>
/// <returns></returns>
2008-05-26 01:06:50 +00:00
protected internal List < ScenePresence > GetScenePresences ( )
2007-11-04 14:34:45 +00:00
{
2009-01-15 23:37:49 +00:00
lock ( ScenePresences )
{
return new List < ScenePresence > ( ScenePresences . Values ) ;
}
2007-11-04 14:34:45 +00:00
}
2008-05-26 01:06:50 +00:00
protected internal List < ScenePresence > GetAvatars ( )
2007-11-04 14:34:45 +00:00
{
List < ScenePresence > result =
GetScenePresences ( delegate ( ScenePresence scenePresence ) { return ! scenePresence . IsChildAgent ; } ) ;
return result ;
}
2008-05-16 01:22:11 +00:00
2008-04-14 18:43:23 +00:00
/// <summary>
/// Get the controlling client for the given avatar, if there is one.
2008-05-16 01:22:11 +00:00
///
/// FIXME: The only user of the method right now is Caps.cs, in order to resolve a client API since it can't
2008-04-14 18:43:23 +00:00
/// use the ScenePresence. This could be better solved in a number of ways - we could establish an
2008-05-16 01:22:11 +00:00
/// OpenSim.Framework.IScenePresence, or move the caps code into a region package (which might be the more
2008-04-14 18:43:23 +00:00
/// suitable solution).
/// </summary>
/// <param name="agentId"></param>
2009-02-06 16:55:34 +00:00
/// <returns>null if either the avatar wasn't in the scene, or
/// they do not have a controlling client</returns>
/// <remarks>this used to be protected internal, but that
/// prevents CapabilitiesModule from accessing it</remarks>
public IClientAPI GetControllingClient ( UUID agentId )
2008-04-14 18:43:23 +00:00
{
ScenePresence presence = GetScenePresence ( agentId ) ;
2008-05-16 01:22:11 +00:00
2008-04-14 18:43:23 +00:00
if ( presence ! = null )
{
return presence . ControllingClient ;
}
2008-05-16 01:22:11 +00:00
2008-04-14 18:43:23 +00:00
return null ;
}
2007-11-04 14:34:45 +00:00
/// <summary>
/// Request a filtered list of m_scenePresences in this World
/// </summary>
/// <returns></returns>
2008-05-26 01:06:50 +00:00
protected internal List < ScenePresence > GetScenePresences ( FilterAvatarList filter )
2007-11-04 14:34:45 +00:00
{
2008-05-07 22:59:30 +00:00
// No locking of scene presences here since we're passing back a list...
2008-05-16 01:22:11 +00:00
2007-11-04 14:34:45 +00:00
List < ScenePresence > result = new List < ScenePresence > ( ) ;
2007-12-17 16:41:28 +00:00
List < ScenePresence > ScenePresencesList = GetScenePresences ( ) ;
2007-11-04 14:34:45 +00:00
2007-12-17 16:41:28 +00:00
foreach ( ScenePresence avatar in ScenePresencesList )
2007-11-04 14:34:45 +00:00
{
if ( filter ( avatar ) )
{
result . Add ( avatar ) ;
}
}
return result ;
}
/// <summary>
2008-04-14 18:43:23 +00:00
/// Request a scene presence by UUID
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="avatarID"></param>
2008-04-14 18:43:23 +00:00
/// <returns>null if the agent was not found</returns>
2008-09-06 07:52:41 +00:00
protected internal ScenePresence GetScenePresence ( UUID agentID )
2007-11-04 14:34:45 +00:00
{
2008-05-13 18:40:36 +00:00
ScenePresence sp ;
2009-01-07 19:33:20 +00:00
lock ( ScenePresences )
{
ScenePresences . TryGetValue ( agentID , out sp ) ;
}
2008-05-16 01:22:11 +00:00
2008-05-13 18:40:36 +00:00
return sp ;
2007-11-04 14:34:45 +00:00
}
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a scene object group that contains the prim with the given local id
/// </summary>
/// <param name="localID"></param>
/// <returns>null if no scene object group containing that prim is found</returns>
2007-11-07 02:42:18 +00:00
private SceneObjectGroup GetGroupByPrim ( uint localID )
2007-11-04 14:34:45 +00:00
{
2009-04-09 10:07:40 +00:00
if ( Entities . ContainsKey ( localID ) )
return Entities [ localID ] as SceneObjectGroup ;
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID);
2007-12-17 16:41:28 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase ent in EntityList )
2007-11-04 14:34:45 +00:00
{
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Looking at entity {0}", ent.UUID);
2007-11-04 14:34:45 +00:00
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) ent ) . HasChildPrim ( localID ) )
return ( SceneObjectGroup ) ent ;
2007-11-04 14:34:45 +00:00
}
}
return null ;
}
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a scene object group that contains the prim with the given uuid
/// </summary>
/// <param name="fullID"></param>
2008-08-18 00:39:10 +00:00
/// <returns>null if no scene object group containing that prim is found</returns>
2008-09-06 07:52:41 +00:00
private SceneObjectGroup GetGroupByPrim ( UUID fullID )
2007-11-04 14:34:45 +00:00
{
2007-12-17 16:41:28 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase ent in EntityList )
2007-11-04 14:34:45 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) ent ) . HasChildPrim ( fullID ) )
return ( SceneObjectGroup ) ent ;
2007-11-04 14:34:45 +00:00
}
}
return null ;
}
2008-05-26 01:06:50 +00:00
protected internal EntityIntersection GetClosestIntersectingPrim ( Ray hray , bool frontFacesOnly , bool faceCenters )
2007-11-23 05:56:35 +00:00
{
// Primitive Ray Tracing
float closestDistance = 280f ;
EntityIntersection returnResult = new EntityIntersection ( ) ;
2008-06-25 12:21:51 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase ent in EntityList )
2007-11-23 05:56:35 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
SceneObjectGroup reportingG = ( SceneObjectGroup ) ent ;
2008-05-01 15:17:49 +00:00
EntityIntersection result = reportingG . TestIntersection ( hray , frontFacesOnly , faceCenters ) ;
2007-11-23 05:56:35 +00:00
if ( result . HitTF )
{
if ( result . distance < closestDistance )
{
closestDistance = result . distance ;
returnResult = result ;
}
}
}
}
return returnResult ;
2008-02-16 13:01:42 +00:00
}
2007-11-23 05:56:35 +00:00
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a part contained in this scene.
/// </summary>
/// <param name="localID"></param>
/// <returns>null if the part was not found</returns>
2008-05-26 01:06:50 +00:00
protected internal SceneObjectPart GetSceneObjectPart ( uint localID )
2007-11-07 02:42:18 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
2008-08-18 00:39:10 +00:00
2007-11-07 02:42:18 +00:00
if ( group ! = null )
return group . GetChildPart ( localID ) ;
else
return null ;
}
2008-10-05 14:15:39 +00:00
2008-10-01 06:39:36 +00:00
/// <summary>
/// Get a named prim contained in this scene (will return the first
/// found, if there are more than one prim with the same name)
/// </summary>
/// <param name="name"></param>
/// <returns>null if the part was not found</returns>
protected internal SceneObjectPart GetSceneObjectPart ( string name )
{
List < EntityBase > EntityList = GetEntities ( ) ;
2008-12-26 12:58:02 +00:00
// FIXME: use a dictionary here
2008-10-01 06:39:36 +00:00
foreach ( EntityBase ent in EntityList )
{
if ( ent is SceneObjectGroup )
{
2008-10-05 14:15:39 +00:00
foreach ( SceneObjectPart p in ( ( SceneObjectGroup ) ent ) . GetParts ( ) )
{
if ( p . Name = = name )
{
return p ;
}
}
2008-10-01 06:39:36 +00:00
}
}
return null ;
}
2007-11-07 02:42:18 +00:00
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a part contained in this scene.
/// </summary>
/// <param name="fullID"></param>
2008-08-18 00:39:10 +00:00
/// <returns>null if the part was not found</returns>
2008-09-06 07:52:41 +00:00
protected internal SceneObjectPart GetSceneObjectPart ( UUID fullID )
2007-11-07 02:42:18 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( fullID ) ;
2008-11-10 18:10:00 +00:00
2007-11-07 02:42:18 +00:00
if ( group ! = null )
return group . GetChildPart ( fullID ) ;
else
return null ;
}
2008-09-06 07:52:41 +00:00
protected internal bool TryGetAvatar ( UUID avatarId , out ScenePresence avatar )
2007-11-04 14:34:45 +00:00
{
ScenePresence presence ;
2009-01-07 19:33:20 +00:00
lock ( ScenePresences )
2007-11-04 14:34:45 +00:00
{
2009-01-07 19:33:20 +00:00
if ( ScenePresences . TryGetValue ( avatarId , out presence ) )
{
avatar = presence ;
return true ;
2008-12-14 02:17:12 +00:00
2009-01-07 19:33:20 +00:00
//if (!presence.IsChildAgent)
//{
// avatar = presence;
// return true;
//}
//else
//{
// m_log.WarnFormat(
// "[INNER SCENE]: Requested avatar {0} could not be found in scene {1} since it is only registered as a child agent!",
// avatarId, m_parentScene.RegionInfo.RegionName);
//}
}
2007-11-04 14:34:45 +00:00
}
avatar = null ;
return false ;
}
2008-05-26 01:06:50 +00:00
protected internal bool TryGetAvatarByName ( string avatarName , out ScenePresence avatar )
2007-11-04 14:34:45 +00:00
{
2008-05-07 22:59:30 +00:00
lock ( ScenePresences )
2007-11-04 14:34:45 +00:00
{
2008-05-07 22:59:30 +00:00
foreach ( ScenePresence presence in ScenePresences . Values )
2007-11-04 14:34:45 +00:00
{
2008-05-07 22:59:30 +00:00
if ( ! presence . IsChildAgent )
2007-11-04 14:34:45 +00:00
{
2008-05-14 04:06:33 +00:00
string name = presence . ControllingClient . Name ;
2008-05-07 22:59:30 +00:00
if ( String . Compare ( avatarName , name , true ) = = 0 )
{
avatar = presence ;
return true ;
}
2007-11-04 14:34:45 +00:00
}
}
}
avatar = null ;
return false ;
}
2008-05-24 21:57:00 +00:00
/// <summary>
2008-06-03 08:34:38 +00:00
/// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over
/// it
2008-05-24 21:57:00 +00:00
/// </summary>
/// <returns></returns>
2008-05-26 01:06:50 +00:00
protected internal List < EntityBase > GetEntities ( )
2007-12-17 16:41:28 +00:00
{
2008-11-24 14:45:05 +00:00
return Entities . GetEntities ( ) ;
2007-12-17 16:41:28 +00:00
}
2009-02-06 16:55:34 +00:00
public Dictionary < uint , float > GetTopScripts ( )
2008-05-25 20:50:45 +00:00
{
Dictionary < uint , float > topScripts = new Dictionary < uint , float > ( ) ;
List < EntityBase > EntityList = GetEntities ( ) ;
int limit = 0 ;
foreach ( EntityBase ent in EntityList )
{
if ( ent is SceneObjectGroup )
{
SceneObjectGroup grp = ( SceneObjectGroup ) ent ;
2008-09-06 07:52:41 +00:00
if ( ( grp . RootPart . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Scripted ) ! = 0 )
2008-05-25 20:50:45 +00:00
{
if ( grp . scriptScore > = 0.01 )
{
topScripts . Add ( grp . LocalId , grp . scriptScore ) ;
limit + + ;
if ( limit > = 100 )
{
break ;
}
}
grp . scriptScore = 0 ;
}
}
}
return topScripts ;
}
2007-11-04 22:22:53 +00:00
# endregion
#region Other Methods
2008-05-26 01:06:50 +00:00
protected internal void physicsBasedCrash ( )
2007-11-28 06:18:07 +00:00
{
2008-03-02 22:28:48 +00:00
handlerPhysicsCrash = UnRecoverableError ;
if ( handlerPhysicsCrash ! = null )
2007-11-28 06:18:07 +00:00
{
2008-03-02 22:28:48 +00:00
handlerPhysicsCrash ( ) ;
2007-11-28 06:18:07 +00:00
}
}
2008-09-06 07:52:41 +00:00
protected internal UUID ConvertLocalIDToFullID ( uint localID )
2007-11-04 22:22:53 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
return group . GetPartsFullID ( localID ) ;
else
2008-09-06 07:52:41 +00:00
return UUID . Zero ;
2007-11-04 22:22:53 +00:00
}
2008-05-26 01:06:50 +00:00
protected internal void ForEachClient ( Action < IClientAPI > action )
2007-11-04 14:34:45 +00:00
{
2009-01-15 23:37:49 +00:00
List < ScenePresence > splist = GetScenePresences ( ) ;
foreach ( ScenePresence presence in splist )
2007-11-04 14:34:45 +00:00
{
2009-01-15 23:37:49 +00:00
try
2008-05-07 22:59:30 +00:00
{
action ( presence . ControllingClient ) ;
}
2009-01-15 23:37:49 +00:00
catch ( Exception e )
{
// Catch it and move on. This includes situations where splist has inconsistent info
m_log . WarnFormat ( "[SCENE]: Problem processing action in ForEachClient: " , e . Message ) ;
}
2007-11-04 14:34:45 +00:00
}
}
2007-12-27 21:41:48 +00:00
2007-11-04 22:22:53 +00:00
# endregion
2007-11-04 14:34:45 +00:00
#region Client Event handlers
2007-12-27 21:41:48 +00:00
2007-11-04 14:34:45 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="scale"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimScale ( uint localID , Vector3 scale , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
group . Resize ( scale , localID ) ;
}
}
2007-11-04 14:34:45 +00:00
}
2008-05-28 03:44:49 +00:00
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimGroupScale ( uint localID , Vector3 scale , IClientAPI remoteClient )
2008-04-19 21:01:26 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2008-04-19 21:01:26 +00:00
{
group . GroupResize ( scale , localID ) ;
}
}
}
2007-11-04 14:34:45 +00:00
2007-11-15 07:32:24 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
/// This handles the nifty little tool tip that you get when you drag your mouse over an object
2007-11-15 07:32:24 +00:00
/// Send to the Object Group to process. We don't know enough to service the request
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="AgentID"></param>
/// <param name="RequestFlags"></param>
/// <param name="ObjectID"></param>
2008-05-26 01:06:50 +00:00
protected internal void RequestObjectPropertiesFamily (
2008-09-06 07:52:41 +00:00
IClientAPI remoteClient , UUID AgentID , uint RequestFlags , UUID ObjectID )
2007-11-15 07:32:24 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( ObjectID ) ;
if ( group ! = null )
2008-02-12 11:21:23 +00:00
{
2007-11-15 07:32:24 +00:00
group . ServiceObjectPropertiesFamilyRequest ( remoteClient , AgentID , RequestFlags ) ;
2008-02-12 11:21:23 +00:00
}
2007-11-15 07:32:24 +00:00
}
2007-11-04 14:34:45 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="rot"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimSingleRotation ( uint localID , Quaternion rot , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
group . UpdateSingleRotation ( rot , localID ) ;
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="rot"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimRotation ( uint localID , Quaternion rot , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
group . UpdateGroupRotation ( rot ) ;
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="pos"></param>
/// <param name="rot"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimRotation ( uint localID , Vector3 pos , Quaternion rot , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
group . UpdateGroupRotation ( pos , rot ) ;
}
}
2007-11-04 14:34:45 +00:00
}
2008-06-27 14:39:21 +00:00
/// <summary>
/// Update the position of the given part
/// </summary>
/// <param name="localID"></param>
/// <param name="pos"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimSinglePosition ( uint localID , Vector3 pos , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) | | group . IsAttachment )
2007-12-07 07:42:03 +00:00
{
group . UpdateSinglePosition ( pos , localID ) ;
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-06-27 14:39:21 +00:00
/// Update the position of the given part
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="pos"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimPosition ( uint localID , Vector3 pos , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-05-16 01:22:11 +00:00
2008-09-06 07:52:41 +00:00
// Vector3 oldPos = group.AbsolutePosition;
2008-11-22 16:09:58 +00:00
if ( group . IsAttachment | | ( group . RootPart . Shape . PCode = = 9 & & group . RootPart . Shape . State ! = 0 ) )
2008-04-23 13:22:06 +00:00
{
2009-03-10 06:14:29 +00:00
// If this is an attachment, then we need to save the modified
// object back into the avatar's inventory. First we save the
// attachment point information, then we update the relative
// positioning (which caused this method to get driven in the
// first place. Then we have to mark the object as NOT an
// attachment. This is necessary in order to correctly save
// and retrieve GroupPosition information for the attachment.
// Then we save the asset back into the appropriate inventory
// entry. Finally, we restore the object's attachment status.
byte attachmentPoint = group . GetAttachmentPoint ( ) ;
2008-04-24 11:32:41 +00:00
group . UpdateGroupPosition ( pos ) ;
2009-03-10 06:14:29 +00:00
group . RootPart . IsAttachment = false ;
group . AbsolutePosition = group . RootPart . AttachedPos ;
m_parentScene . updateKnownAsset ( remoteClient , group , group . GetFromAssetID ( ) , group . OwnerID ) ;
group . SetAttachmentPoint ( attachmentPoint ) ;
2008-04-23 13:22:06 +00:00
}
2008-05-16 01:22:11 +00:00
else
2007-12-07 07:42:03 +00:00
{
2008-11-22 15:58:52 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) & & m_parentScene . Permissions . CanObjectEntry ( group . UUID , false , pos ) )
2008-04-24 11:32:41 +00:00
{
group . UpdateGroupPosition ( pos ) ;
}
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="texture"></param>
/// <param name="remoteClient"></param>
2008-05-26 01:06:50 +00:00
protected internal void UpdatePrimTexture ( uint localID , byte [ ] texture , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
group . UpdateTextureEntry ( localID , texture ) ;
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="packet"></param>
/// <param name="remoteClient"></param>
2008-12-20 21:36:42 +00:00
/// This routine seems to get called when a user changes object settings in the viewer.
/// If some one can confirm that, please change the comment according.
2008-11-07 22:57:32 +00:00
protected internal void UpdatePrimFlags ( uint localID , bool UsePhysics , bool IsTemporary , bool IsPhantom , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2008-12-20 21:36:42 +00:00
group . UpdatePrimFlags ( localID , UsePhysics , IsTemporary , IsPhantom , false ) ; // VolumeDetect can't be set via UI and will always be off when a change is made there
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
2008-06-27 14:39:21 +00:00
/// <summary>
/// Move the given object
/// </summary>
/// <param name="objectID"></param>
/// <param name="offset"></param>
/// <param name="pos"></param>
/// <param name="remoteClient"></param>
2008-10-10 16:01:59 +00:00
protected internal void MoveObject ( UUID objectID , Vector3 offset , Vector3 pos , IClientAPI remoteClient , List < SurfaceTouchEventArgs > surfaceArgs )
2007-11-04 14:34:45 +00:00
{
2007-12-07 07:42:03 +00:00
SceneObjectGroup group = GetGroupByPrim ( objectID ) ;
if ( group ! = null )
2007-11-04 14:34:45 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) ) // && PermissionsMngr.)
2007-12-07 07:42:03 +00:00
{
2007-11-07 02:42:18 +00:00
group . GrabMovement ( offset , pos , remoteClient ) ;
2007-12-07 07:42:03 +00:00
}
2008-02-12 15:47:37 +00:00
// This is outside the above permissions condition
// so that if the object is locked the client moving the object
// get's it's position on the simulator even if it was the same as before
// This keeps the moving user's client in sync with the rest of the world.
2008-02-10 21:27:32 +00:00
group . SendGroupTerseUpdate ( ) ;
2007-11-04 14:34:45 +00:00
}
}
2009-04-10 06:39:52 +00:00
/// <summary>
/// Start spinning the given object
/// </summary>
/// <param name="objectID"></param>
/// <param name="rotation"></param>
/// <param name="remoteClient"></param>
protected internal void SpinStart ( UUID objectID , IClientAPI remoteClient )
{
SceneObjectGroup group = GetGroupByPrim ( objectID ) ;
if ( group ! = null )
{
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) ) // && PermissionsMngr.)
{
group . SpinStart ( remoteClient ) ;
}
}
}
/// <summary>
/// Spin the given object
/// </summary>
/// <param name="objectID"></param>
/// <param name="rotation"></param>
/// <param name="remoteClient"></param>
protected internal void SpinObject ( UUID objectID , Quaternion rotation , IClientAPI remoteClient )
{
SceneObjectGroup group = GetGroupByPrim ( objectID ) ;
if ( group ! = null )
{
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) ) // && PermissionsMngr.)
{
group . SpinMovement ( rotation , remoteClient ) ;
}
// This is outside the above permissions condition
// so that if the object is locked the client moving the object
// get's it's position on the simulator even if it was the same as before
// This keeps the moving user's client in sync with the rest of the world.
group . SendGroupTerseUpdate ( ) ;
}
}
2007-11-04 14:34:45 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="primLocalID"></param>
/// <param name="description"></param>
2008-05-26 01:06:50 +00:00
protected internal void PrimName ( IClientAPI remoteClient , uint primLocalID , string name )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2007-12-28 23:19:03 +00:00
group . SetPartName ( Util . CleanString ( name ) , primLocalID ) ;
2008-08-15 16:51:26 +00:00
group . HasGroupChanged = true ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="primLocalID"></param>
/// <param name="description"></param>
2008-05-26 01:06:50 +00:00
protected internal void PrimDescription ( IClientAPI remoteClient , uint primLocalID , string description )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2007-12-28 23:19:03 +00:00
group . SetPartDescription ( Util . CleanString ( description ) , primLocalID ) ;
2008-08-15 16:51:26 +00:00
group . HasGroupChanged = true ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
2008-09-12 20:42:04 +00:00
protected internal void PrimClickAction ( IClientAPI remoteClient , uint primLocalID , string clickAction )
{
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2008-09-12 20:42:04 +00:00
{
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( primLocalID ) ;
part . ClickAction = Convert . ToByte ( clickAction ) ;
group . HasGroupChanged = true ;
}
}
}
2008-10-03 12:00:13 +00:00
protected internal void PrimMaterial ( IClientAPI remoteClient , uint primLocalID , string material )
{
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2008-10-03 12:00:13 +00:00
{
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( primLocalID ) ;
part . Material = Convert . ToByte ( material ) ;
group . HasGroupChanged = true ;
}
}
}
2008-09-12 20:42:04 +00:00
2008-09-06 07:52:41 +00:00
protected internal void UpdateExtraParam ( UUID agentID , uint primLocalID , ushort type , bool inUse , byte [ ] data )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
2007-12-27 21:41:48 +00:00
2007-12-07 07:42:03 +00:00
if ( group ! = null )
2007-11-29 15:24:31 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , agentID ) )
2007-12-07 07:42:03 +00:00
{
2007-11-29 15:24:31 +00:00
group . UpdateExtraParam ( primLocalID , type , inUse , data ) ;
2007-12-07 07:42:03 +00:00
}
2007-11-29 15:24:31 +00:00
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="primLocalID"></param>
/// <param name="shapeBlock"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimShape ( UUID agentID , uint primLocalID , UpdateShapeArgs shapeBlock )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
2007-12-07 07:42:03 +00:00
if ( group ! = null )
2007-11-29 15:24:31 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . GetPartsFullID ( primLocalID ) , agentID ) )
2007-12-07 07:42:03 +00:00
{
2008-05-07 20:31:48 +00:00
ObjectShapePacket . ObjectDataBlock shapeData = new ObjectShapePacket . ObjectDataBlock ( ) ;
shapeData . ObjectLocalID = shapeBlock . ObjectLocalID ;
shapeData . PathBegin = shapeBlock . PathBegin ;
shapeData . PathCurve = shapeBlock . PathCurve ;
shapeData . PathEnd = shapeBlock . PathEnd ;
shapeData . PathRadiusOffset = shapeBlock . PathRadiusOffset ;
shapeData . PathRevolutions = shapeBlock . PathRevolutions ;
shapeData . PathScaleX = shapeBlock . PathScaleX ;
shapeData . PathScaleY = shapeBlock . PathScaleY ;
shapeData . PathShearX = shapeBlock . PathShearX ;
shapeData . PathShearY = shapeBlock . PathShearY ;
shapeData . PathSkew = shapeBlock . PathSkew ;
shapeData . PathTaperX = shapeBlock . PathTaperX ;
shapeData . PathTaperY = shapeBlock . PathTaperY ;
shapeData . PathTwist = shapeBlock . PathTwist ;
shapeData . PathTwistBegin = shapeBlock . PathTwistBegin ;
shapeData . ProfileBegin = shapeBlock . ProfileBegin ;
shapeData . ProfileCurve = shapeBlock . ProfileCurve ;
shapeData . ProfileEnd = shapeBlock . ProfileEnd ;
shapeData . ProfileHollow = shapeBlock . ProfileHollow ;
group . UpdateShape ( shapeData , primLocalID ) ;
2007-12-07 07:42:03 +00:00
}
2007-11-29 15:24:31 +00:00
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-04-03 13:33:46 +00:00
/// Initial method invoked when we receive a link objects request from the client.
2007-11-04 14:34:45 +00:00
/// </summary>
2008-04-03 13:33:46 +00:00
/// <param name="client"></param>
2007-11-04 14:34:45 +00:00
/// <param name="parentPrim"></param>
/// <param name="childPrims"></param>
2008-05-26 01:06:50 +00:00
protected internal void LinkObjects ( IClientAPI client , uint parentPrim , List < uint > childPrims )
2007-11-04 14:34:45 +00:00
{
2007-12-17 16:41:28 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
2007-11-04 14:34:45 +00:00
SceneObjectGroup parenPrim = null ;
2007-12-17 16:41:28 +00:00
foreach ( EntityBase ent in EntityList )
2007-11-04 14:34:45 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) ent ) . LocalId = = parentPrim )
2007-11-04 14:34:45 +00:00
{
2008-05-01 18:04:42 +00:00
parenPrim = ( SceneObjectGroup ) ent ;
2007-11-04 14:34:45 +00:00
break ;
}
}
}
List < SceneObjectGroup > children = new List < SceneObjectGroup > ( ) ;
if ( parenPrim ! = null )
{
2008-10-29 03:22:54 +00:00
// We do this in reverse to get the link order of the prims correct
2008-10-28 11:26:23 +00:00
for ( int i = childPrims . Count - 1 ; i > = 0 ; i - - )
2007-11-04 14:34:45 +00:00
{
2007-12-17 16:41:28 +00:00
foreach ( EntityBase ent in EntityList )
2007-11-04 14:34:45 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) ent ) . LocalId = = childPrims [ i ] )
2007-11-04 14:34:45 +00:00
{
2008-08-24 06:39:54 +00:00
// Make sure no child prim is set for sale
// So that, on delink, no prims are unwittingly
// left for sale and sold off
( ( SceneObjectGroup ) ent ) . RootPart . ObjectSaleType = 0 ;
( ( SceneObjectGroup ) ent ) . RootPart . SalePrice = 10 ;
2008-05-01 18:04:42 +00:00
children . Add ( ( SceneObjectGroup ) ent ) ;
2007-11-04 14:34:45 +00:00
}
}
}
}
}
2008-11-30 21:19:53 +00:00
else
{
return ; // parent is null so not in this region
}
2007-11-04 14:34:45 +00:00
foreach ( SceneObjectGroup sceneObj in children )
{
parenPrim . LinkToGroup ( sceneObj ) ;
2008-12-07 04:03:09 +00:00
// this is here so physics gets updated!
// Don't remove! Bad juju! Stay away! or fix physics!
sceneObj . AbsolutePosition = sceneObj . AbsolutePosition ;
2007-11-04 14:34:45 +00:00
}
2008-05-16 01:22:11 +00:00
2008-04-03 13:33:46 +00:00
// We need to explicitly resend the newly link prim's object properties since no other actions
// occur on link to invoke this elsewhere (such as object selection)
2009-01-07 19:33:20 +00:00
parenPrim . RootPart . AddFlag ( PrimFlags . CreateSelected ) ;
2008-07-19 04:05:34 +00:00
parenPrim . TriggerScriptChangedEvent ( Changed . LINK ) ;
2009-02-03 17:50:25 +00:00
2008-07-23 13:24:25 +00:00
if ( client ! = null )
2009-02-03 17:50:25 +00:00
{
2008-07-19 04:05:34 +00:00
parenPrim . GetProperties ( client ) ;
2009-02-03 17:50:25 +00:00
}
2008-07-19 04:05:34 +00:00
else
{
2009-01-07 19:33:20 +00:00
foreach ( ScenePresence p in GetScenePresences ( ) )
2008-07-19 04:05:34 +00:00
{
parenPrim . GetProperties ( p . ControllingClient ) ;
}
}
2007-11-04 14:34:45 +00:00
}
2007-11-18 11:11:44 +00:00
2007-11-13 19:57:11 +00:00
/// <summary>
/// Delink a linkset
/// </summary>
2008-05-16 01:22:11 +00:00
/// <param name="prims"></param>
2008-05-26 01:06:50 +00:00
protected internal void DelinkObjects ( List < uint > primIds )
2008-07-19 04:05:34 +00:00
{
DelinkObjects ( primIds , true ) ;
}
protected internal void DelinkObjects ( List < uint > primIds , bool sendEvents )
2007-11-13 19:57:11 +00:00
{
SceneObjectGroup parenPrim = null ;
// Need a list of the SceneObjectGroup local ids
// XXX I'm anticipating that building this dictionary once is more efficient than
// repeated scanning of the Entity.Values for a large number of primIds. However, it might
// be more efficient yet to keep this dictionary permanently on hand.
2007-12-17 16:41:28 +00:00
2007-11-18 11:11:44 +00:00
Dictionary < uint , SceneObjectGroup > sceneObjects = new Dictionary < uint , SceneObjectGroup > ( ) ;
2008-02-16 13:01:42 +00:00
2008-05-20 16:19:35 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase ent in EntityList )
2007-11-13 19:57:11 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
SceneObjectGroup obj = ( SceneObjectGroup ) ent ;
2008-11-28 03:28:39 +00:00
// Nasty one. Can't unlink anything in the sim
// If a duplicate local ID sneaks in
// So, check it here!
/ /
if ( ! sceneObjects . ContainsKey ( obj . LocalId ) )
sceneObjects . Add ( obj . LocalId , obj ) ;
2008-05-01 18:04:42 +00:00
2007-11-13 19:57:11 +00:00
}
2007-11-18 11:11:44 +00:00
}
2007-11-13 19:57:11 +00:00
// Find the root prim among the prim ids we've been given
for ( int i = 0 ; i < primIds . Count ; i + + )
2007-11-18 11:11:44 +00:00
{
2008-05-01 18:04:42 +00:00
2007-11-13 19:57:11 +00:00
if ( sceneObjects . ContainsKey ( primIds [ i ] ) )
{
parenPrim = sceneObjects [ primIds [ i ] ] ;
primIds . RemoveAt ( i ) ;
break ;
2007-11-18 11:11:44 +00:00
}
2007-11-13 19:57:11 +00:00
}
if ( parenPrim ! = null )
{
foreach ( uint childPrimId in primIds )
{
2008-07-19 04:05:34 +00:00
parenPrim . DelinkFromGroup ( childPrimId , sendEvents ) ;
}
2008-07-23 13:24:25 +00:00
if ( parenPrim . Children . Count = = 1 )
2008-07-19 04:05:34 +00:00
{
// The link set has been completely torn down
// This is the case if you select a link set and delink
/ /
2008-07-27 19:32:43 +00:00
parenPrim . RootPart . LinkNum = 0 ;
2008-07-23 13:24:25 +00:00
if ( sendEvents )
2008-07-19 04:05:34 +00:00
parenPrim . TriggerScriptChangedEvent ( Changed . LINK ) ;
}
2008-08-18 00:39:10 +00:00
else
2008-07-19 04:05:34 +00:00
{
// The link set has prims remaining. This path is taken
// when a subset of a link set's prims are selected
// and the root prim is part of that selection
/ /
List < SceneObjectPart > parts = new List < SceneObjectPart > ( parenPrim . Children . Values ) ;
2008-08-18 00:39:10 +00:00
2008-07-19 04:05:34 +00:00
List < uint > unlink_ids = new List < uint > ( ) ;
foreach ( SceneObjectPart unlink_part in parts )
unlink_ids . Add ( unlink_part . LocalId ) ;
// Tear down the remaining link set
/ /
2008-07-23 13:24:25 +00:00
if ( unlink_ids . Count = = 2 )
2008-07-19 04:05:34 +00:00
{
DelinkObjects ( unlink_ids , true ) ;
return ;
}
DelinkObjects ( unlink_ids , false ) ;
// Send event to root prim, then we're done with it
parenPrim . TriggerScriptChangedEvent ( Changed . LINK ) ;
unlink_ids . Remove ( parenPrim . RootPart . LocalId ) ;
foreach ( uint localId in unlink_ids )
{
SceneObjectPart nr = GetSceneObjectPart ( localId ) ;
nr . UpdateFlag = 0 ;
}
uint newRoot = unlink_ids [ 0 ] ;
unlink_ids . Remove ( newRoot ) ;
LinkObjects ( null , newRoot , unlink_ids ) ;
2007-11-18 11:11:44 +00:00
}
2007-11-13 19:57:11 +00:00
}
else
{
2008-07-19 04:05:34 +00:00
// The selected prims were all child prims. Edit linked parts
// without the root prim selected will get us here
/ /
List < SceneObjectGroup > parents = new List < SceneObjectGroup > ( ) ;
2008-02-10 18:56:34 +00:00
// If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow
2008-05-16 01:22:11 +00:00
// We know that this is not the root prim now essentially, so we don't have to worry about remapping
2008-02-10 18:56:34 +00:00
// which one is the root prim
bool delinkedSomething = false ;
for ( int i = 0 ; i < primIds . Count ; i + + )
{
foreach ( SceneObjectGroup grp in sceneObjects . Values )
{
SceneObjectPart gPart = grp . GetChildPart ( primIds [ i ] ) ;
if ( gPart ! = null )
{
grp . DelinkFromGroup ( primIds [ i ] ) ;
delinkedSomething = true ;
2008-07-23 13:24:25 +00:00
if ( ! parents . Contains ( grp ) )
2008-07-19 04:05:34 +00:00
parents . Add ( grp ) ;
2008-02-10 18:56:34 +00:00
}
2008-05-01 18:04:42 +00:00
2008-02-10 18:56:34 +00:00
}
}
if ( ! delinkedSomething )
{
m_log . InfoFormat ( "[SCENE]: " +
2008-05-01 18:04:42 +00:00
"DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!" ,
primIds ) ;
2008-02-10 18:56:34 +00:00
}
2008-07-19 04:05:34 +00:00
else
{
foreach ( SceneObjectGroup g in parents )
{
g . TriggerScriptChangedEvent ( Changed . LINK ) ;
}
}
2007-11-13 19:57:11 +00:00
}
}
2007-11-04 14:34:45 +00:00
2008-05-26 01:06:50 +00:00
protected internal void MakeObjectSearchable ( IClientAPI remoteClient , bool IncludeInSearch , uint localID )
2008-04-16 03:55:21 +00:00
{
2008-09-06 07:52:41 +00:00
UUID user = remoteClient . AgentId ;
2008-09-26 17:25:22 +00:00
UUID objid = UUID . Zero ;
2008-04-16 03:55:21 +00:00
SceneObjectPart obj = null ;
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase ent in EntityList )
{
if ( ent is SceneObjectGroup )
{
2008-09-06 07:52:41 +00:00
foreach ( KeyValuePair < UUID , SceneObjectPart > subent in ( ( SceneObjectGroup ) ent ) . Children )
2008-04-16 03:55:21 +00:00
{
if ( subent . Value . LocalId = = localID )
{
objid = subent . Key ;
obj = subent . Value ;
}
}
}
}
2008-05-16 01:22:11 +00:00
2008-04-16 03:55:21 +00:00
//Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints
//aka ObjectFlags.JointWheel = IncludeInSearch
//Permissions model: Object can be REMOVED from search IFF:
// * User owns object
//use CanEditObject
//Object can be ADDED to search IFF:
// * User owns object
// * Asset/DRM permission bit "modify" is enabled
//use CanEditObjectPosition
2008-09-08 10:28:59 +00:00
// libomv will complain about PrimFlags.JointWheel being
// deprecated, so we
#pragma warning disable 0612
2008-11-21 22:14:57 +00:00
if ( IncludeInSearch & & m_parentScene . Permissions . CanEditObject ( objid , user ) )
2008-04-16 03:55:21 +00:00
{
2008-09-06 07:52:41 +00:00
obj . ParentGroup . RootPart . AddFlag ( PrimFlags . JointWheel ) ;
2008-10-04 03:04:00 +00:00
obj . ParentGroup . HasGroupChanged = true ;
2008-04-16 03:55:21 +00:00
}
2008-11-21 22:14:57 +00:00
else if ( ! IncludeInSearch & & m_parentScene . Permissions . CanMoveObject ( objid , user ) )
2008-04-16 03:55:21 +00:00
{
2008-09-06 07:52:41 +00:00
obj . ParentGroup . RootPart . RemFlag ( PrimFlags . JointWheel ) ;
2008-10-04 03:04:00 +00:00
obj . ParentGroup . HasGroupChanged = true ;
2008-04-16 03:55:21 +00:00
}
2008-09-08 10:28:59 +00:00
#pragma warning restore 0612
2008-04-16 03:55:21 +00:00
}
2007-11-04 14:34:45 +00:00
/// <summary>
2008-06-10 00:18:00 +00:00
/// Duplicate the given object, Fire and Forget, No rotation, no return wrapper
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="originalPrim"></param>
/// <param name="offset"></param>
/// <param name="flags"></param>
2008-09-06 07:52:41 +00:00
protected internal void DuplicateObject ( uint originalPrim , Vector3 offset , uint flags , UUID AgentID , UUID GroupID )
2007-11-04 14:34:45 +00:00
{
2008-05-24 21:57:00 +00:00
//m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
2008-05-16 01:22:11 +00:00
2008-06-27 19:57:06 +00:00
// SceneObjectGroup dupe = DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Zero);
2008-09-06 07:52:41 +00:00
DuplicateObject ( originalPrim , offset , flags , AgentID , GroupID , Quaternion . Identity ) ;
2008-06-10 00:18:00 +00:00
}
2009-02-03 17:50:25 +00:00
2008-06-10 00:18:00 +00:00
/// <summary>
/// Duplicate the given object.
/// </summary>
/// <param name="originalPrim"></param>
/// <param name="offset"></param>
/// <param name="flags"></param>
2008-09-06 07:52:41 +00:00
protected internal SceneObjectGroup DuplicateObject ( uint originalPrim , Vector3 offset , uint flags , UUID AgentID , UUID GroupID , Quaternion rot )
2008-06-10 00:18:00 +00:00
{
//m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
2009-01-06 15:14:15 +00:00
2007-12-17 16:41:28 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
2007-11-04 14:34:45 +00:00
SceneObjectGroup originPrim = null ;
2007-12-17 16:41:28 +00:00
foreach ( EntityBase ent in EntityList )
2007-11-04 14:34:45 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) ent ) . LocalId = = originalPrim )
2007-11-04 14:34:45 +00:00
{
2008-05-01 18:04:42 +00:00
originPrim = ( SceneObjectGroup ) ent ;
2007-11-04 14:34:45 +00:00
break ;
}
}
}
if ( originPrim ! = null )
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanDuplicateObject ( originPrim . Children . Count , originPrim . UUID , AgentID , originPrim . AbsolutePosition ) )
2007-11-18 11:11:44 +00:00
{
2008-05-21 21:22:56 +00:00
SceneObjectGroup copy = originPrim . Copy ( AgentID , GroupID , true ) ;
2007-11-18 11:11:44 +00:00
copy . AbsolutePosition = copy . AbsolutePosition + offset ;
2008-02-16 13:01:42 +00:00
2008-11-24 15:09:25 +00:00
Entities . Add ( copy ) ;
2008-02-16 13:01:42 +00:00
2008-05-25 23:27:38 +00:00
// Since we copy from a source group that is in selected
// state, but the copy is shown deselected in the viewer,
// We need to clear the selection flag here, else that
// prim never gets persisted at all. The client doesn't
// think it's selected, so it will never send a deselect...
copy . IsSelected = false ;
2008-05-25 19:21:21 +00:00
2008-06-06 23:20:02 +00:00
m_numPrim + = copy . Children . Count ;
2008-02-16 13:01:42 +00:00
2008-09-06 07:52:41 +00:00
if ( rot ! = Quaternion . Identity )
2008-06-10 00:18:00 +00:00
{
2008-09-06 07:52:41 +00:00
copy . UpdateGroupRotation ( rot ) ;
2008-06-10 00:18:00 +00:00
}
2008-11-09 19:30:40 +00:00
copy . CreateScriptInstances ( 0 , false , m_parentScene . DefaultScriptEngine , 0 ) ;
2008-06-27 16:36:19 +00:00
copy . HasGroupChanged = true ;
2007-11-18 11:11:44 +00:00
copy . ScheduleGroupForFullUpdate ( ) ;
2008-12-21 14:50:58 +00:00
// required for physics to update it's position
copy . AbsolutePosition = copy . AbsolutePosition ;
2009-01-06 15:14:15 +00:00
if ( OnObjectDuplicate ! = null )
OnObjectDuplicate ( originPrim , copy ) ;
2008-06-10 00:18:00 +00:00
return copy ;
2007-11-18 11:11:44 +00:00
}
2007-11-04 14:34:45 +00:00
}
else
{
2008-02-10 01:57:59 +00:00
m_log . WarnFormat ( "[SCENE]: Attempted to duplicate nonexistant prim id {0}" , GroupID ) ;
2007-11-04 14:34:45 +00:00
}
2009-02-03 17:50:25 +00:00
2008-06-10 00:18:00 +00:00
return null ;
2007-11-18 11:11:44 +00:00
}
2008-11-12 20:16:46 +00:00
2007-12-06 18:17:44 +00:00
/// <summary>
/// Calculates the distance between two Vector3s
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
2008-05-26 01:06:50 +00:00
protected internal float Vector3Distance ( Vector3 v1 , Vector3 v2 )
2007-11-22 01:32:13 +00:00
{
2008-05-16 01:22:11 +00:00
// We don't really need the double floating point precision...
2007-11-22 01:32:13 +00:00
// so casting it to a single
2007-11-04 14:34:45 +00:00
2007-12-27 21:41:48 +00:00
return
( float )
2008-09-06 07:52:41 +00:00
Math . Sqrt ( ( v1 . X - v2 . X ) * ( v1 . X - v2 . X ) + ( v1 . Y - v2 . Y ) * ( v1 . Y - v2 . Y ) + ( v1 . Z - v2 . Z ) * ( v1 . Z - v2 . Z ) ) ;
2007-11-22 01:32:13 +00:00
}
2007-12-27 21:41:48 +00:00
2007-11-04 14:34:45 +00:00
# endregion
2009-01-06 00:07:24 +00:00
2007-11-04 14:34:45 +00:00
}
2008-05-01 18:04:42 +00:00
}