2007-07-16 15:40:11 +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 .
2008-12-19 17:57:03 +00:00
* * Redistributions in binary form must reproduce the above copyrightD
2008-03-18 05:16:43 +00:00
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-03-18 05:16:43 +00:00
* 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-07-16 15:40:11 +00:00
using System ;
using System.Collections.Generic ;
2010-03-08 07:19:45 +00:00
using System.Diagnostics ;
2007-12-27 21:41:48 +00:00
using System.Drawing ;
using System.Drawing.Imaging ;
2008-08-15 07:20:38 +00:00
using System.IO ;
2009-02-12 09:53:12 +00:00
using System.Text ;
2007-07-16 15:40:11 +00:00
using System.Threading ;
using System.Timers ;
2009-02-12 09:53:12 +00:00
using System.Xml ;
using Nini.Config ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse ;
2009-11-05 20:01:40 +00:00
using OpenMetaverse.Packets ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse.Imaging ;
2007-07-16 15:40:11 +00:00
using OpenSim.Framework ;
2012-07-25 22:27:00 +00:00
using OpenSim.Framework.Monitoring ;
2009-05-11 21:04:27 +00:00
using OpenSim.Services.Interfaces ;
2007-07-16 15:40:11 +00:00
using OpenSim.Framework.Communications ;
2009-02-12 09:53:12 +00:00
using OpenSim.Framework.Console ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Interfaces ;
using OpenSim.Region.Framework.Scenes.Scripting ;
2009-05-08 18:05:54 +00:00
using OpenSim.Region.Framework.Scenes.Serialization ;
2007-09-19 00:30:55 +00:00
using OpenSim.Region.Physics.Manager ;
2009-02-12 09:53:12 +00:00
using Timer = System . Timers . Timer ;
2008-10-04 18:46:34 +00:00
using TPFlags = OpenSim . Framework . Constants . TeleportFlags ;
2009-09-26 14:48:21 +00:00
using GridRegion = OpenSim . Services . Interfaces . GridRegion ;
2013-03-26 03:40:06 +00:00
using PermissionMask = OpenSim . Framework . PermissionMask ;
2007-07-16 18:45:19 +00:00
2009-02-06 16:55:34 +00:00
namespace OpenSim.Region.Framework.Scenes
2007-07-16 15:40:11 +00:00
{
2007-11-03 19:14:22 +00:00
public delegate bool FilterAvatarList ( ScenePresence avatar ) ;
2007-08-10 17:22:54 +00:00
public partial class Scene : SceneBase
2007-07-16 15:40:11 +00:00
{
2008-11-15 17:52:00 +00:00
private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L ;
private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L ;
2010-09-12 06:41:48 +00:00
public delegate void SynchronizeSceneHandler ( Scene scene ) ;
2007-12-12 06:58:55 +00:00
2010-09-12 06:41:48 +00:00
#region Fields
2007-11-03 19:14:22 +00:00
2011-02-08 20:06:14 +00:00
public bool EmergencyMonitoring = false ;
2012-03-21 01:27:09 +00:00
2013-01-18 23:22:02 +00:00
/// <summary>
/// Show debug information about animations.
/// </summary>
public bool DebugAnimations { get ; set ; }
2012-03-21 01:27:09 +00:00
/// <summary>
/// Show debug information about teleports.
/// </summary>
2013-01-10 23:49:48 +00:00
public bool DebugTeleporting { get ; set ; }
2011-02-08 20:06:14 +00:00
2012-03-21 01:27:09 +00:00
/// <summary>
/// Show debug information about the scene loop.
/// </summary>
2013-01-10 23:49:48 +00:00
public bool DebugUpdates { get ; set ; }
2011-02-08 20:06:14 +00:00
2013-01-10 22:38:48 +00:00
/// <summary>
/// If true then the scene is saved to persistent storage periodically, every m_update_backup frames and
/// if objects meet required conditions (m_dontPersistBefore and m_dontPersistAfter).
/// </summary>
/// <remarks>
/// Even if false, the scene will still be saved on clean shutdown.
/// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels.
/// This needs to be fixed.
/// </remarks>
2013-01-10 23:49:48 +00:00
public bool PeriodicBackup { get ; set ; }
2013-01-10 22:38:48 +00:00
/// <summary>
/// If false then the scene is never saved to persistence storage even if PeriodicBackup == true and even
/// if the scene is being shut down for the final time.
/// </summary>
2013-01-10 23:49:48 +00:00
public bool UseBackup { get ; set ; }
/// <summary>
/// If false then physical objects are disabled, though collisions will continue as normal.
/// </summary>
public bool PhysicsEnabled { get ; set ; }
/// <summary>
/// If false then scripts are not enabled on the smiulator
/// </summary>
public bool ScriptsEnabled
{
get { return m_scripts_enabled ; }
set
{
if ( m_scripts_enabled ! = value )
{
if ( ! value )
{
m_log . Info ( "Stopping all Scripts in Scene" ) ;
EntityBase [ ] entities = Entities . GetEntities ( ) ;
foreach ( EntityBase ent in entities )
{
if ( ent is SceneObjectGroup )
( ( SceneObjectGroup ) ent ) . RemoveScriptInstances ( false ) ;
}
}
else
{
m_log . Info ( "Starting all Scripts in Scene" ) ;
EntityBase [ ] entities = Entities . GetEntities ( ) ;
foreach ( EntityBase ent in entities )
{
if ( ent is SceneObjectGroup )
{
SceneObjectGroup sog = ( SceneObjectGroup ) ent ;
sog . CreateScriptInstances ( 0 , false , DefaultScriptEngine , 0 ) ;
sog . ResumeScripts ( ) ;
}
}
}
m_scripts_enabled = value ;
}
}
}
private bool m_scripts_enabled ;
2013-01-10 22:38:48 +00:00
2010-09-12 06:41:48 +00:00
public SynchronizeSceneHandler SynchronizeScene ;
2012-05-23 03:10:45 +00:00
2012-10-09 23:26:43 +00:00
/// <summary>
/// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other.
/// </summary>
private object m_removeClientLock = new object ( ) ;
2012-05-23 03:10:45 +00:00
/// <summary>
/// Statistical information for this scene.
/// </summary>
public SimStatsReporter StatsReporter { get ; private set ; }
2009-08-20 23:24:31 +00:00
public List < Border > NorthBorders = new List < Border > ( ) ;
public List < Border > EastBorders = new List < Border > ( ) ;
public List < Border > SouthBorders = new List < Border > ( ) ;
public List < Border > WestBorders = new List < Border > ( ) ;
2011-10-15 01:54:43 +00:00
/// <summary>
/// Controls whether physics can be applied to prims. Even if false, prims still have entries in a
/// PhysicsScene in order to perform collision detection
/// </summary>
2011-12-22 19:57:50 +00:00
public bool PhysicalPrims { get ; private set ; }
2011-10-15 01:54:43 +00:00
2011-12-22 19:44:52 +00:00
/// <summary>
/// Controls whether prims can be collided with.
/// </summary>
/// <remarks>
/// If this is set to false then prims cannot be subject to physics either.
/// </summary>
public bool CollidablePrims { get ; private set ; }
2012-08-06 14:35:40 +00:00
/// <summary>
/// Minimum value of the size of a non-physical prim in each axis
/// </summary>
2012-09-18 14:09:32 +00:00
public float m_minNonphys = 0.001f ;
2012-08-06 14:35:40 +00:00
/// <summary>
/// Maximum value of the size of a non-physical prim in each axis
/// </summary>
2009-03-11 09:31:02 +00:00
public float m_maxNonphys = 256 ;
2012-08-06 14:35:40 +00:00
/// <summary>
/// Minimum value of the size of a physical prim in each axis
/// </summary>
2012-09-18 14:09:32 +00:00
public float m_minPhys = 0.01f ;
2012-08-06 14:35:40 +00:00
/// <summary>
/// Maximum value of the size of a physical prim in each axis
/// </summary>
2008-07-23 13:24:25 +00:00
public float m_maxPhys = 10 ;
2012-08-06 14:35:40 +00:00
2012-09-08 12:48:07 +00:00
/// <summary>
/// Max prims an object will hold
/// </summary>
public int m_linksetCapacity = 0 ;
2009-10-26 23:33:04 +00:00
public bool m_clampPrimSize ;
public bool m_trustBinaries ;
public bool m_allowScriptCrossings ;
public bool m_useFlySlow ;
2012-04-25 18:54:57 +00:00
public bool m_useTrashOnDelete = true ;
2011-02-22 21:23:54 +00:00
2012-03-23 03:33:07 +00:00
/// <summary>
/// Temporarily setting to trigger appearance resends at 60 second intervals.
/// </summary>
public bool SendPeriodicAppearanceUpdates { get ; set ; }
2011-02-22 21:23:54 +00:00
protected float m_defaultDrawDistance = 255.0f ;
public float DefaultDrawDistance
{
get { return m_defaultDrawDistance ; }
}
2012-07-02 17:12:10 +00:00
private List < string > m_AllowedViewers = new List < string > ( ) ;
2012-07-03 22:26:02 +00:00
private List < string > m_BannedViewers = new List < string > ( ) ;
2011-02-22 21:23:54 +00:00
2009-05-11 07:46:12 +00:00
// TODO: need to figure out how allow client agents but deny
// root agents when ACL denies access to root agent
public bool m_strictAccessControl = true ;
2012-09-26 21:49:44 +00:00
public int MaxUndoCount { get ; set ; }
2012-07-18 23:09:22 +00:00
2013-07-24 18:23:19 +00:00
public bool SeeIntoRegion { get ; set ; }
2011-05-27 23:05:16 +00:00
// Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
public bool LoginLock = false ;
2012-07-18 23:09:22 +00:00
2011-05-27 23:05:16 +00:00
public bool StartDisabled = false ;
2010-09-12 06:41:48 +00:00
public bool LoadingPrims ;
public IXfer XferManager ;
// the minimum time that must elapse before a changed object will be considered for persisted
public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L ;
// the maximum time that must elapse before a changed object will be considered for persisted
public long m_persistAfter = DEFAULT_MAX_TIME_FOR_PERSISTENCE * 10000000L ;
protected int m_splitRegionID ;
protected Timer m_restartWaitTimer = new Timer ( ) ;
protected List < RegionInfo > m_regionRestartNotifyList = new List < RegionInfo > ( ) ;
protected List < RegionInfo > m_neighbours = new List < RegionInfo > ( ) ;
protected string m_simulatorVersion = "OpenSimulator Server" ;
protected AgentCircuitManager m_authenticateHandler ;
protected SceneCommunicationService m_sceneGridService ;
2010-09-12 21:20:26 +00:00
protected ISimulationDataService m_SimulationDataService ;
protected IEstateDataService m_EstateDataService ;
2010-09-12 06:41:48 +00:00
protected IAssetService m_AssetService ;
protected IAuthorizationService m_AuthorizationService ;
protected IInventoryService m_InventoryService ;
protected IGridService m_GridService ;
protected ILibraryService m_LibraryService ;
protected ISimulationService m_simulationService ;
protected IAuthenticationService m_AuthenticationService ;
protected IPresenceService m_PresenceService ;
protected IUserAccountService m_UserAccountService ;
protected IAvatarService m_AvatarService ;
protected IGridUserService m_GridUserService ;
protected IXMLRPC m_xmlrpcModule ;
protected IWorldComm m_worldCommModule ;
2011-10-19 21:41:44 +00:00
protected IAvatarFactoryModule m_AvatarFactory ;
2010-09-12 06:41:48 +00:00
protected IConfigSource m_config ;
protected IRegionSerialiserModule m_serialiser ;
protected IDialogModule m_dialogModule ;
protected ICapabilitiesModule m_capsModule ;
2011-12-19 23:03:45 +00:00
protected IGroupsModule m_groupsModule ;
2011-02-18 21:54:44 +00:00
2012-08-15 01:06:22 +00:00
private Dictionary < string , string > m_extraSettings ;
2011-02-18 21:54:44 +00:00
/// <summary>
/// Current scene frame number
/// </summary>
public uint Frame
{
get ;
protected set ;
}
2012-03-23 02:49:29 +00:00
/// <summary>
/// Current maintenance run number
/// </summary>
public uint MaintenanceRun { get ; private set ; }
2011-10-05 21:08:56 +00:00
/// <summary>
/// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we
/// will sleep for the remaining period.
/// </summary>
/// <remarks>
/// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
/// occur too quickly (viewer 1) or with even more slide (viewer 2).
/// </remarks>
2011-10-13 21:07:55 +00:00
public float MinFrameTime { get ; private set ; }
2011-10-05 21:08:56 +00:00
2012-03-23 02:49:29 +00:00
/// <summary>
/// The minimum length of time in seconds that will be taken for a maintenance run.
/// </summary>
public float MinMaintenanceTime { get ; private set ; }
2010-09-12 06:41:48 +00:00
private int m_update_physics = 1 ;
private int m_update_entitymovement = 1 ;
2011-10-13 21:28:42 +00:00
private int m_update_objects = 1 ;
private int m_update_temp_cleaning = 1000 ;
2010-09-12 06:41:48 +00:00
private int m_update_presences = 1 ; // Update scene presence movements
private int m_update_events = 1 ;
private int m_update_backup = 200 ;
private int m_update_terrain = 50 ;
2010-12-17 22:35:08 +00:00
// private int m_update_land = 1;
2010-12-20 03:29:07 +00:00
private int m_update_coarse_locations = 50 ;
2008-05-01 18:04:42 +00:00
2011-10-05 23:45:25 +00:00
private int agentMS ;
2010-09-12 06:41:48 +00:00
private int frameMS ;
private int physicsMS2 ;
private int physicsMS ;
private int otherMS ;
private int tempOnRezMS ;
private int eventMS ;
private int backupMS ;
private int terrainMS ;
private int landMS ;
2012-06-04 23:17:55 +00:00
private int spareMS ;
2012-03-21 00:02:08 +00:00
/// <summary>
/// Tick at which the last frame was processed.
/// </summary>
private int m_lastFrameTick ;
2008-05-22 22:31:42 +00:00
2012-03-23 02:49:29 +00:00
/// <summary>
/// Tick at which the last maintenance run occurred.
/// </summary>
private int m_lastMaintenanceTick ;
2008-05-22 22:31:42 +00:00
2011-10-13 22:47:37 +00:00
/// <summary>
/// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
/// asynchronously from the update loop.
/// </summary>
private bool m_cleaningTemps = false ;
2012-03-23 01:21:43 +00:00
// private Object m_heartbeatLock = new Object();
2011-10-13 22:47:37 +00:00
// TODO: Possibly stop other classes being able to manipulate this directly.
private SceneGraph m_sceneGraph ;
private volatile int m_bordersLocked ;
private readonly Timer m_restartTimer = new Timer ( 15000 ) ; // Wait before firing
private volatile bool m_backingup ;
private Dictionary < UUID , ReturnInfo > m_returns = new Dictionary < UUID , ReturnInfo > ( ) ;
private Dictionary < UUID , SceneObjectGroup > m_groupsWithTargets = new Dictionary < UUID , SceneObjectGroup > ( ) ;
2010-09-12 06:41:48 +00:00
private string m_defaultScriptEngine ;
2012-03-23 01:03:10 +00:00
/// <summary>
/// Tick at which the last login occurred.
/// </summary>
2010-09-12 06:41:48 +00:00
private int m_LastLogin ;
2012-03-23 01:46:11 +00:00
/// <summary>
/// Thread that runs the scene loop.
/// </summary>
private Thread m_heartbeatThread ;
2007-07-16 15:40:11 +00:00
2012-03-23 01:46:11 +00:00
/// <summary>
/// True if these scene is in the process of shutting down or is shutdown.
/// </summary>
public bool ShuttingDown
{
get { return m_shuttingDown ; }
}
private volatile bool m_shuttingDown ;
2010-09-12 06:41:48 +00:00
2012-10-12 01:52:08 +00:00
/// <summary>
/// Is the scene active?
/// </summary>
/// <remarks>
2012-10-12 02:19:12 +00:00
/// If false, maintenance and update loops are not being run. Updates can still be triggered manually if
/// the scene is not active.
2012-10-12 01:52:08 +00:00
/// </remarks>
public bool Active
{
get { return m_active ; }
set
{
if ( value )
{
if ( ! m_active )
2013-05-03 17:48:50 +00:00
Start ( false ) ;
2012-10-12 01:52:08 +00:00
}
else
{
2013-05-03 17:48:50 +00:00
// This appears assymetric with Start() above but is not - setting m_active = false stops the loops
// XXX: Possibly this should be in an explicit Stop() method for symmetry.
2012-10-12 01:52:08 +00:00
m_active = false ;
}
}
}
private volatile bool m_active ;
2012-03-23 01:03:10 +00:00
// private int m_lastUpdate;
// private bool m_firstHeartbeat = true;
2010-12-15 02:44:26 +00:00
2010-09-12 06:41:48 +00:00
private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes . Time ;
private bool m_reprioritizationEnabled = true ;
private double m_reprioritizationInterval = 5000.0 ;
private double m_rootReprioritizationDistance = 10.0 ;
private double m_childReprioritizationDistance = 20.0 ;
private Timer m_mapGenerationTimer = new Timer ( ) ;
private bool m_generateMaptiles ;
#endregion Fields
#region Properties
/* Used by the loadbalancer plugin on GForge */
public int SplitRegionID
{
get { return m_splitRegionID ; }
set { m_splitRegionID = value ; }
}
public bool BordersLocked
{
get { return m_bordersLocked = = 1 ; }
set
{
if ( value = = true )
m_bordersLocked = 1 ;
else
m_bordersLocked = 0 ;
}
}
2009-10-28 21:44:05 +00:00
public new float TimeDilation
2009-10-27 23:24:43 +00:00
{
get { return m_sceneGraph . PhysicsScene . TimeDilation ; }
}
2008-06-25 19:33:19 +00:00
public SceneCommunicationService SceneGridService
{
get { return m_sceneGridService ; }
}
2010-09-12 21:20:26 +00:00
public ISimulationDataService SimulationDataService
{
get
{
if ( m_SimulationDataService = = null )
{
m_SimulationDataService = RequestModuleInterface < ISimulationDataService > ( ) ;
if ( m_SimulationDataService = = null )
{
throw new Exception ( "No ISimulationDataService available." ) ;
}
}
return m_SimulationDataService ;
}
}
public IEstateDataService EstateDataService
{
get
{
if ( m_EstateDataService = = null )
{
m_EstateDataService = RequestModuleInterface < IEstateDataService > ( ) ;
if ( m_EstateDataService = = null )
{
throw new Exception ( "No IEstateDataService available." ) ;
}
}
return m_EstateDataService ;
}
}
2009-05-11 21:04:27 +00:00
public IAssetService AssetService
{
get
{
if ( m_AssetService = = null )
2009-06-03 17:29:21 +00:00
{
2009-05-11 21:04:27 +00:00
m_AssetService = RequestModuleInterface < IAssetService > ( ) ;
2009-06-09 18:07:35 +00:00
if ( m_AssetService = = null )
2009-06-03 17:29:21 +00:00
{
throw new Exception ( "No IAssetService available." ) ;
}
}
2009-05-11 21:04:27 +00:00
return m_AssetService ;
}
}
2009-09-09 18:42:53 +00:00
public IAuthorizationService AuthorizationService
{
get
{
if ( m_AuthorizationService = = null )
{
m_AuthorizationService = RequestModuleInterface < IAuthorizationService > ( ) ;
2010-01-14 03:25:33 +00:00
//if (m_AuthorizationService == null)
//{
// // don't throw an exception if no authorization service is set for the time being
// m_log.InfoFormat("[SCENE]: No Authorization service is configured");
//}
2009-09-09 18:42:53 +00:00
}
return m_AuthorizationService ;
}
}
2009-05-11 21:04:27 +00:00
2009-06-10 13:18:32 +00:00
public IInventoryService InventoryService
{
get
{
if ( m_InventoryService = = null )
{
m_InventoryService = RequestModuleInterface < IInventoryService > ( ) ;
if ( m_InventoryService = = null )
{
2009-07-10 21:47:54 +00:00
throw new Exception ( "No IInventoryService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example." ) ;
2009-06-10 13:18:32 +00:00
}
}
return m_InventoryService ;
}
}
2009-09-26 14:48:21 +00:00
public IGridService GridService
{
get
{
if ( m_GridService = = null )
{
m_GridService = RequestModuleInterface < IGridService > ( ) ;
if ( m_GridService = = null )
{
throw new Exception ( "No IGridService available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. Please also check that you have the correct version of your inventory service dll. Sometimes old versions of this dll will still exist. Do a clean checkout and re-create the opensim.ini from the opensim.ini.example." ) ;
}
}
return m_GridService ;
}
}
2010-01-02 05:12:46 +00:00
public ILibraryService LibraryService
{
get
{
if ( m_LibraryService = = null )
m_LibraryService = RequestModuleInterface < ILibraryService > ( ) ;
return m_LibraryService ;
}
}
2010-01-07 23:53:55 +00:00
public ISimulationService SimulationService
{
get
{
if ( m_simulationService = = null )
m_simulationService = RequestModuleInterface < ISimulationService > ( ) ;
2012-04-26 23:58:54 +00:00
2010-01-07 23:53:55 +00:00
return m_simulationService ;
}
}
public IAuthenticationService AuthenticationService
{
get
{
if ( m_AuthenticationService = = null )
m_AuthenticationService = RequestModuleInterface < IAuthenticationService > ( ) ;
return m_AuthenticationService ;
}
}
public IPresenceService PresenceService
{
get
{
if ( m_PresenceService = = null )
m_PresenceService = RequestModuleInterface < IPresenceService > ( ) ;
return m_PresenceService ;
}
}
2010-09-12 06:41:48 +00:00
2010-01-07 23:53:55 +00:00
public IUserAccountService UserAccountService
{
get
{
if ( m_UserAccountService = = null )
m_UserAccountService = RequestModuleInterface < IUserAccountService > ( ) ;
return m_UserAccountService ;
}
}
2010-09-12 06:41:48 +00:00
public IAvatarService AvatarService
2010-01-08 18:43:34 +00:00
{
get
{
if ( m_AvatarService = = null )
2010-01-12 01:30:05 +00:00
m_AvatarService = RequestModuleInterface < IAvatarService > ( ) ;
2010-01-08 18:43:34 +00:00
return m_AvatarService ;
}
}
2010-05-08 04:29:56 +00:00
public IGridUserService GridUserService
{
get
{
if ( m_GridUserService = = null )
m_GridUserService = RequestModuleInterface < IGridUserService > ( ) ;
return m_GridUserService ;
}
}
2010-03-05 23:18:47 +00:00
public IAttachmentsModule AttachmentsModule { get ; set ; }
2012-05-23 23:31:14 +00:00
public IEntityTransferModule EntityTransferModule { get ; private set ; }
2012-06-07 22:51:04 +00:00
public IAgentAssetTransactions AgentTransactionsModule { get ; private set ; }
2012-06-25 21:48:13 +00:00
public IUserManagement UserManagementModule { get ; private set ; }
2010-09-12 06:41:48 +00:00
2011-10-19 21:41:44 +00:00
public IAvatarFactoryModule AvatarFactory
2010-10-29 20:37:13 +00:00
{
get { return m_AvatarFactory ; }
}
2009-02-06 16:55:34 +00:00
public ICapabilitiesModule CapsModule
{
get { return m_capsModule ; }
}
2009-05-29 21:12:55 +00:00
2009-11-01 08:37:40 +00:00
public int MonitorFrameTime { get { return frameMS ; } }
public int MonitorPhysicsUpdateTime { get { return physicsMS ; } }
public int MonitorPhysicsSyncTime { get { return physicsMS2 ; } }
public int MonitorOtherTime { get { return otherMS ; } }
public int MonitorTempOnRezTime { get { return tempOnRezMS ; } }
public int MonitorEventTime { get { return eventMS ; } } // This may need to be divided into each event?
public int MonitorBackupTime { get { return backupMS ; } }
public int MonitorTerrainTime { get { return terrainMS ; } }
public int MonitorLandTime { get { return landMS ; } }
2012-03-21 00:02:08 +00:00
public int MonitorLastFrameTick { get { return m_lastFrameTick ; } }
2008-05-01 18:04:42 +00:00
2010-05-21 20:55:36 +00:00
public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return m_priorityScheme ; } }
public bool IsReprioritizationEnabled { get { return m_reprioritizationEnabled ; } }
public double ReprioritizationInterval { get { return m_reprioritizationInterval ; } }
public double RootReprioritizationDistance { get { return m_rootReprioritizationDistance ; } }
public double ChildReprioritizationDistance { get { return m_childReprioritizationDistance ; } }
2009-10-15 23:35:27 +00:00
2007-08-09 12:59:42 +00:00
public AgentCircuitManager AuthenticateHandler
{
2007-11-04 13:48:15 +00:00
get { return m_authenticateHandler ; }
2007-08-09 12:59:42 +00:00
}
2007-09-19 00:30:55 +00:00
2007-12-10 21:12:38 +00:00
// an instance to the physics plugin's Scene object.
2007-11-29 15:27:57 +00:00
public PhysicsScene PhysicsScene
2007-11-03 19:14:22 +00:00
{
2008-11-20 16:58:40 +00:00
get { return m_sceneGraph . PhysicsScene ; }
2008-12-26 12:58:02 +00:00
set
{
// If we're not doing the initial set
// Then we've got to remove the previous
// event handler
if ( PhysicsScene ! = null & & PhysicsScene . SupportsNINJAJoints )
{
PhysicsScene . OnJointMoved - = jointMoved ;
PhysicsScene . OnJointDeactivated - = jointDeactivated ;
PhysicsScene . OnJointErrorMessage - = jointErrorMessage ;
}
m_sceneGraph . PhysicsScene = value ;
if ( PhysicsScene ! = null & & m_sceneGraph . PhysicsScene . SupportsNINJAJoints )
{
// register event handlers to respond to joint movement/deactivation
PhysicsScene . OnJointMoved + = jointMoved ;
PhysicsScene . OnJointDeactivated + = jointDeactivated ;
PhysicsScene . OnJointErrorMessage + = jointErrorMessage ;
}
}
2007-09-20 23:28:08 +00:00
}
2007-12-27 21:41:48 +00:00
2008-09-21 21:47:00 +00:00
public string DefaultScriptEngine
{
get { return m_defaultScriptEngine ; }
}
2008-11-24 14:45:05 +00:00
public EntityManager Entities
{
get { return m_sceneGraph . Entities ; }
}
2008-05-16 01:22:11 +00:00
2012-05-18 23:56:46 +00:00
2012-05-13 21:11:44 +00:00
// used in sequence see: SpawnPoint()
private int m_SpawnPoint ;
2012-05-18 23:56:46 +00:00
// can be closest/random/sequence
2012-05-13 21:11:44 +00:00
public string SpawnPointRouting
{
2012-05-18 23:56:46 +00:00
get ; private set ;
2012-05-13 21:11:44 +00:00
}
2012-05-18 21:47:00 +00:00
// allow landmarks to pass
public bool TelehubAllowLandmarks
{
2012-05-18 23:56:46 +00:00
get ; private set ;
2012-05-18 21:47:00 +00:00
}
2012-05-13 21:11:44 +00:00
2010-09-12 06:41:48 +00:00
#endregion Properties
2007-07-16 15:40:11 +00:00
#region Constructors
2007-07-17 17:47:23 +00:00
2008-05-05 20:14:53 +00:00
public Scene ( RegionInfo regInfo , AgentCircuitManager authen ,
2010-01-11 15:45:47 +00:00
SceneCommunicationService sceneGridService ,
2010-09-12 21:20:26 +00:00
ISimulationDataService simDataService , IEstateDataService estateDataService ,
2011-10-15 02:03:05 +00:00
IConfigSource config , string simulatorVersion )
2011-10-13 21:21:03 +00:00
: this ( regInfo )
2007-07-16 15:40:11 +00:00
{
2008-05-14 23:15:25 +00:00
m_config = config ;
2011-10-13 21:07:55 +00:00
MinFrameTime = 0.089f ;
2012-03-23 02:49:29 +00:00
MinMaintenanceTime = 1 ;
2008-10-14 09:40:05 +00:00
2008-11-29 13:17:21 +00:00
Random random = new Random ( ) ;
2009-08-20 23:24:31 +00:00
2012-05-13 21:11:44 +00:00
m_lastAllocatedLocalId = ( uint ) ( random . NextDouble ( ) * ( double ) ( uint . MaxValue / 2 ) ) + ( uint ) ( uint . MaxValue / 4 ) ;
2007-11-04 13:48:15 +00:00
m_authenticateHandler = authen ;
2007-11-03 19:14:22 +00:00
m_sceneGridService = sceneGridService ;
2010-09-12 21:20:26 +00:00
m_SimulationDataService = simDataService ;
m_EstateDataService = estateDataService ;
2012-06-28 23:03:22 +00:00
m_regionHandle = RegionInfo . RegionHandle ;
2007-07-16 15:40:11 +00:00
2008-10-14 09:40:05 +00:00
m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter ( this ) ;
2008-11-11 20:33:29 +00:00
m_asyncSceneObjectDeleter . Enabled = true ;
2007-12-17 03:49:13 +00:00
2011-07-01 20:25:40 +00:00
m_asyncInventorySender = new AsyncInventorySender ( this ) ;
2010-05-21 20:55:36 +00:00
#region Region Settings
2008-06-30 14:09:19 +00:00
// Load region settings
2011-09-08 23:29:59 +00:00
// LoadRegionSettings creates new region settings in persistence if they don't already exist for this region.
// However, in this case, the default textures are not set in memory properly, so we need to do it here and
// resave.
// FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new
// region is set up and avoid these gyrations.
2012-06-28 23:03:22 +00:00
RegionSettings rs = simDataService . LoadRegionSettings ( RegionInfo . RegionID ) ;
2012-08-15 01:06:22 +00:00
m_extraSettings = simDataService . GetExtra ( RegionInfo . RegionID ) ;
2011-09-08 23:29:59 +00:00
bool updatedTerrainTextures = false ;
if ( rs . TerrainTexture1 = = UUID . Zero )
{
rs . TerrainTexture1 = RegionSettings . DEFAULT_TERRAIN_TEXTURE_1 ;
updatedTerrainTextures = true ;
}
if ( rs . TerrainTexture2 = = UUID . Zero )
{
rs . TerrainTexture2 = RegionSettings . DEFAULT_TERRAIN_TEXTURE_2 ;
updatedTerrainTextures = true ;
}
if ( rs . TerrainTexture3 = = UUID . Zero )
{
rs . TerrainTexture3 = RegionSettings . DEFAULT_TERRAIN_TEXTURE_3 ;
updatedTerrainTextures = true ;
}
if ( rs . TerrainTexture4 = = UUID . Zero )
{
rs . TerrainTexture4 = RegionSettings . DEFAULT_TERRAIN_TEXTURE_4 ;
updatedTerrainTextures = true ;
}
if ( updatedTerrainTextures )
rs . Save ( ) ;
2012-06-28 23:03:22 +00:00
RegionInfo . RegionSettings = rs ;
2011-09-08 23:29:59 +00:00
2010-09-12 21:20:26 +00:00
if ( estateDataService ! = null )
2012-06-28 23:03:22 +00:00
RegionInfo . EstateSettings = estateDataService . LoadEstateSettings ( RegionInfo . RegionID , false ) ;
2008-07-18 02:40:47 +00:00
2010-05-21 20:55:36 +00:00
#endregion Region Settings
2007-12-17 03:49:13 +00:00
//Bind Storage Manager functions to some land manager functions for this scene
2007-12-27 21:41:48 +00:00
EventManager . OnLandObjectAdded + =
2010-09-12 21:20:26 +00:00
new EventManager . LandObjectAdded ( simDataService . StoreLandObject ) ;
2007-12-27 21:41:48 +00:00
EventManager . OnLandObjectRemoved + =
2010-09-12 21:20:26 +00:00
new EventManager . LandObjectRemoved ( simDataService . RemoveLandObject ) ;
2007-12-27 21:41:48 +00:00
2011-09-12 21:51:56 +00:00
m_sceneGraph = new SceneGraph ( this ) ;
2007-12-12 17:15:37 +00:00
2008-11-12 20:16:46 +00:00
// If the scene graph has an Unrecoverable error, restart this sim.
2007-11-28 06:18:07 +00:00
// Currently the only thing that causes it to happen is two kinds of specific
// Physics based crashes.
/ /
// Out of memory
// Operating system has killed the plugin
2012-11-23 04:06:48 +00:00
m_sceneGraph . UnRecoverableError
+ = ( ) = >
{
m_log . ErrorFormat ( "[SCENE]: Restarting region {0} due to unrecoverable physics crash" , Name ) ;
RestartNow ( ) ;
} ;
2007-11-28 06:18:07 +00:00
2007-11-18 11:11:44 +00:00
RegisterDefaultSceneEvents ( ) ;
2007-08-15 14:10:26 +00:00
2013-01-10 23:49:48 +00:00
// XXX: Don't set the public property since we don't want to activate here. This needs to be handled
// better in the future.
2008-07-14 01:27:47 +00:00
m_scripts_enabled = ! RegionInfo . RegionSettings . DisableScripts ;
2013-01-10 23:49:48 +00:00
PhysicsEnabled = ! RegionInfo . RegionSettings . DisablePhysics ;
2008-02-06 09:38:14 +00:00
2009-12-12 16:04:16 +00:00
m_simulatorVersion = simulatorVersion + " (" + Util . GetRuntimeInformation ( ) + ")" ;
2008-07-20 15:19:26 +00:00
2010-05-21 20:55:36 +00:00
#region Region Config
2012-03-07 00:31:18 +00:00
// Region config overrides global config
/ /
if ( m_config . Configs [ "Startup" ] ! = null )
2008-07-23 13:24:25 +00:00
{
IConfig startupConfig = m_config . Configs [ "Startup" ] ;
2009-04-06 18:02:12 +00:00
2012-07-18 22:35:05 +00:00
StartDisabled = startupConfig . GetBoolean ( "StartDisabled" , false ) ;
2012-05-13 21:11:44 +00:00
m_defaultDrawDistance = startupConfig . GetFloat ( "DefaultDrawDistance" , m_defaultDrawDistance ) ;
2013-01-10 22:38:48 +00:00
UseBackup = startupConfig . GetBoolean ( "UseSceneBackup" , UseBackup ) ;
if ( ! UseBackup )
2011-05-24 01:37:25 +00:00
m_log . InfoFormat ( "[SCENE]: Backup has been disabled for {0}" , RegionInfo . RegionName ) ;
2011-02-22 21:23:54 +00:00
2009-04-06 18:02:12 +00:00
//Animation states
m_useFlySlow = startupConfig . GetBoolean ( "enableflyslow" , false ) ;
2013-07-24 18:23:19 +00:00
SeeIntoRegion = startupConfig . GetBoolean ( "see_into_region" , true ) ;
2012-09-26 23:12:34 +00:00
MaxUndoCount = startupConfig . GetInt ( "MaxPrimUndos" , 20 ) ;
2012-04-22 18:51:51 +00:00
PhysicalPrims = startupConfig . GetBoolean ( "physical_prim" , PhysicalPrims ) ;
CollidablePrims = startupConfig . GetBoolean ( "collidable_prim" , CollidablePrims ) ;
2011-10-15 01:54:43 +00:00
2012-09-18 13:47:15 +00:00
m_minNonphys = startupConfig . GetFloat ( "NonPhysicalPrimMin" , m_minNonphys ) ;
2012-08-06 14:35:40 +00:00
if ( RegionInfo . NonphysPrimMin > 0 )
{
m_minNonphys = RegionInfo . NonphysPrimMin ;
}
2012-09-18 13:47:15 +00:00
m_maxNonphys = startupConfig . GetFloat ( "NonPhysicalPrimMax" , m_maxNonphys ) ;
2009-01-02 17:41:12 +00:00
if ( RegionInfo . NonphysPrimMax > 0 )
2009-07-24 06:59:27 +00:00
{
2009-01-02 17:41:12 +00:00
m_maxNonphys = RegionInfo . NonphysPrimMax ;
2009-07-24 06:59:27 +00:00
}
2009-01-02 17:41:12 +00:00
2012-08-06 14:35:40 +00:00
m_minPhys = startupConfig . GetFloat ( "PhysicalPrimMin" , m_minPhys ) ;
if ( RegionInfo . PhysPrimMin > 0 )
{
m_minPhys = RegionInfo . PhysPrimMin ;
}
2009-01-02 17:41:12 +00:00
2012-08-06 14:35:40 +00:00
m_maxPhys = startupConfig . GetFloat ( "PhysicalPrimMax" , m_maxPhys ) ;
2009-01-02 17:41:12 +00:00
if ( RegionInfo . PhysPrimMax > 0 )
2009-07-24 06:59:27 +00:00
{
2009-01-02 17:41:12 +00:00
m_maxPhys = RegionInfo . PhysPrimMax ;
2009-07-24 06:59:27 +00:00
}
2009-01-02 17:41:12 +00:00
// Here, if clamping is requested in either global or
// local config, it will be used
/ /
2009-03-11 09:31:02 +00:00
m_clampPrimSize = startupConfig . GetBoolean ( "ClampPrimSize" , m_clampPrimSize ) ;
2009-01-02 17:41:12 +00:00
if ( RegionInfo . ClampPrimSize )
2009-07-24 06:59:27 +00:00
{
2009-01-02 17:41:12 +00:00
m_clampPrimSize = true ;
2009-07-24 06:59:27 +00:00
}
2009-01-02 17:41:12 +00:00
2012-09-08 12:48:07 +00:00
m_linksetCapacity = startupConfig . GetInt ( "LinksetPrims" , m_linksetCapacity ) ;
if ( RegionInfo . LinksetCapacity > 0 )
{
m_linksetCapacity = RegionInfo . LinksetCapacity ;
}
2012-05-13 21:11:44 +00:00
m_useTrashOnDelete = startupConfig . GetBoolean ( "UseTrashOnDelete" , m_useTrashOnDelete ) ;
2009-03-11 09:31:02 +00:00
m_trustBinaries = startupConfig . GetBoolean ( "TrustBinaries" , m_trustBinaries ) ;
m_allowScriptCrossings = startupConfig . GetBoolean ( "AllowScriptCrossing" , m_allowScriptCrossings ) ;
2008-11-15 17:52:00 +00:00
m_dontPersistBefore =
2008-11-15 18:00:34 +00:00
startupConfig . GetLong ( "MinimumTimeBeforePersistenceConsidered" , DEFAULT_MIN_TIME_FOR_PERSISTENCE ) ;
2008-11-15 17:52:00 +00:00
m_dontPersistBefore * = 10000000 ;
m_persistAfter =
2008-11-15 18:00:34 +00:00
startupConfig . GetLong ( "MaximumTimeBeforePersistenceConsidered" , DEFAULT_MAX_TIME_FOR_PERSISTENCE ) ;
2008-11-15 17:52:00 +00:00
m_persistAfter * = 10000000 ;
2008-09-21 21:47:00 +00:00
2009-11-26 17:03:09 +00:00
m_defaultScriptEngine = startupConfig . GetString ( "DefaultScriptEngine" , "XEngine" ) ;
2009-05-01 19:33:18 +00:00
2012-05-18 23:32:26 +00:00
SpawnPointRouting = startupConfig . GetString ( "SpawnPointRouting" , "closest" ) ;
TelehubAllowLandmarks = startupConfig . GetBoolean ( "TelehubAllowLandmark" , false ) ;
2012-05-13 21:11:44 +00:00
2009-05-11 07:46:12 +00:00
m_strictAccessControl = startupConfig . GetBoolean ( "StrictAccessControl" , m_strictAccessControl ) ;
2010-08-20 07:36:23 +00:00
2013-02-25 23:04:38 +00:00
string [ ] possibleMapConfigSections = new string [ ] { "Map" , "Startup" } ;
m_generateMaptiles
= Util . GetConfigVarFromSections < bool > ( config , "GenerateMaptiles" , possibleMapConfigSections , true ) ;
2010-08-20 07:36:23 +00:00
if ( m_generateMaptiles )
{
int maptileRefresh = startupConfig . GetInt ( "MaptileRefresh" , 0 ) ;
if ( maptileRefresh ! = 0 )
{
m_mapGenerationTimer . Interval = maptileRefresh * 1000 ;
2011-12-31 05:32:28 +00:00
m_mapGenerationTimer . Elapsed + = RegenerateMaptileAndReregister ;
2010-08-20 07:36:23 +00:00
m_mapGenerationTimer . AutoReset = true ;
m_mapGenerationTimer . Start ( ) ;
}
}
else
{
2013-02-25 23:04:38 +00:00
string tile
= Util . GetConfigVarFromSections < string > (
config , "MaptileStaticUUID" , possibleMapConfigSections , UUID . Zero . ToString ( ) ) ;
2010-08-20 07:36:23 +00:00
UUID tileID ;
2013-01-31 20:46:41 +00:00
if ( tile ! = UUID . Zero . ToString ( ) & & UUID . TryParse ( tile , out tileID ) )
2010-08-20 07:36:23 +00:00
{
RegionInfo . RegionSettings . TerrainImageID = tileID ;
}
2013-01-30 21:43:35 +00:00
else
{
RegionInfo . RegionSettings . TerrainImageID = RegionInfo . MaptileStaticUUID ;
m_log . InfoFormat ( "[SCENE]: Region {0}, maptile set to {1}" , RegionInfo . RegionName , RegionInfo . MaptileStaticUUID . ToString ( ) ) ;
}
2010-08-20 07:36:23 +00:00
}
2011-10-13 22:47:37 +00:00
2013-03-02 01:43:54 +00:00
string [ ] possibleAccessControlConfigSections = new string [ ] { "AccessControl" , "Startup" } ;
string grant
= Util . GetConfigVarFromSections < string > (
config , "AllowedClients" , possibleAccessControlConfigSections , "" ) ;
2012-07-02 17:12:10 +00:00
if ( grant . Length > 0 )
{
2012-07-12 22:18:30 +00:00
foreach ( string viewer in grant . Split ( '|' ) )
2012-07-02 17:12:10 +00:00
{
m_AllowedViewers . Add ( viewer . Trim ( ) . ToLower ( ) ) ;
}
}
2013-03-02 01:43:54 +00:00
grant
= Util . GetConfigVarFromSections < string > (
config , "BannedClients" , possibleAccessControlConfigSections , "" ) ;
2012-07-02 17:12:10 +00:00
if ( grant . Length > 0 )
{
2012-07-12 22:18:30 +00:00
foreach ( string viewer in grant . Split ( '|' ) )
2012-07-02 17:12:10 +00:00
{
2012-07-03 22:26:02 +00:00
m_BannedViewers . Add ( viewer . Trim ( ) . ToLower ( ) ) ;
2012-07-02 17:12:10 +00:00
}
}
2011-10-13 22:47:37 +00:00
MinFrameTime = startupConfig . GetFloat ( "MinFrameTime" , MinFrameTime ) ;
m_update_backup = startupConfig . GetInt ( "UpdateStorageEveryNFrames" , m_update_backup ) ;
m_update_coarse_locations = startupConfig . GetInt ( "UpdateCoarseLocationsEveryNFrames" , m_update_coarse_locations ) ;
m_update_entitymovement = startupConfig . GetInt ( "UpdateEntityMovementEveryNFrames" , m_update_entitymovement ) ;
m_update_events = startupConfig . GetInt ( "UpdateEventsEveryNFrames" , m_update_events ) ;
m_update_objects = startupConfig . GetInt ( "UpdateObjectsEveryNFrames" , m_update_objects ) ;
m_update_physics = startupConfig . GetInt ( "UpdatePhysicsEveryNFrames" , m_update_physics ) ;
m_update_presences = startupConfig . GetInt ( "UpdateAgentsEveryNFrames" , m_update_presences ) ;
m_update_terrain = startupConfig . GetInt ( "UpdateTerrainEveryNFrames" , m_update_terrain ) ;
m_update_temp_cleaning = startupConfig . GetInt ( "UpdateTempCleaningEveryNFrames" , m_update_temp_cleaning ) ;
2012-08-03 20:36:00 +00:00
}
2012-03-23 03:33:07 +00:00
2012-08-03 20:36:00 +00:00
// FIXME: Ultimately this should be in a module.
2012-09-20 00:40:05 +00:00
SendPeriodicAppearanceUpdates = true ;
2012-08-03 20:36:00 +00:00
IConfig appearanceConfig = m_config . Configs [ "Appearance" ] ;
if ( appearanceConfig ! = null )
{
SendPeriodicAppearanceUpdates
= appearanceConfig . GetBoolean ( "ResendAppearanceUpdates" , SendPeriodicAppearanceUpdates ) ;
2008-07-23 13:24:25 +00:00
}
2010-05-21 20:55:36 +00:00
#endregion Region Config
#region Interest Management
2012-03-07 00:31:18 +00:00
IConfig interestConfig = m_config . Configs [ "InterestManagement" ] ;
if ( interestConfig ! = null )
2010-05-21 20:55:36 +00:00
{
2012-03-07 00:31:18 +00:00
string update_prioritization_scheme = interestConfig . GetString ( "UpdatePrioritizationScheme" , "Time" ) . Trim ( ) . ToLower ( ) ;
2010-05-21 20:55:36 +00:00
2012-03-07 00:31:18 +00:00
try
{
m_priorityScheme = ( UpdatePrioritizationSchemes ) Enum . Parse ( typeof ( UpdatePrioritizationSchemes ) , update_prioritization_scheme , true ) ;
2010-05-21 21:17:03 +00:00
}
2012-03-07 00:31:18 +00:00
catch ( Exception )
{
m_log . Warn ( "[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time" ) ;
m_priorityScheme = UpdatePrioritizationSchemes . Time ;
2010-05-21 21:17:03 +00:00
}
2012-03-07 00:31:18 +00:00
m_reprioritizationEnabled = interestConfig . GetBoolean ( "ReprioritizationEnabled" , true ) ;
m_reprioritizationInterval = interestConfig . GetDouble ( "ReprioritizationInterval" , 5000.0 ) ;
m_rootReprioritizationDistance = interestConfig . GetDouble ( "RootReprioritizationDistance" , 10.0 ) ;
m_childReprioritizationDistance = interestConfig . GetDouble ( "ChildReprioritizationDistance" , 20.0 ) ;
2010-05-21 20:55:36 +00:00
}
2012-03-07 00:31:18 +00:00
m_log . DebugFormat ( "[SCENE]: Using the {0} prioritization scheme" , m_priorityScheme ) ;
2010-05-21 20:55:36 +00:00
#endregion Interest Management
2011-10-13 22:47:37 +00:00
StatsReporter = new SimStatsReporter ( this ) ;
StatsReporter . OnSendStatsResult + = SendSimStatsPackets ;
2012-03-07 00:31:18 +00:00
StatsReporter . OnStatsIncorrect + = m_sceneGraph . RecalculateStats ;
2007-07-16 15:40:11 +00:00
}
2007-07-17 17:47:23 +00:00
2012-06-28 23:03:22 +00:00
public Scene ( RegionInfo regInfo ) : base ( regInfo )
2009-01-11 18:24:16 +00:00
{
2012-04-22 18:51:51 +00:00
PhysicalPrims = true ;
CollidablePrims = true ;
2013-01-10 23:49:48 +00:00
PhysicsEnabled = true ;
2013-01-10 22:38:48 +00:00
PeriodicBackup = true ;
UseBackup = true ;
2012-04-22 18:51:51 +00:00
2009-08-29 07:36:41 +00:00
BordersLocked = true ;
2009-08-20 23:24:31 +00:00
Border northBorder = new Border ( ) ;
2009-09-02 08:39:00 +00:00
northBorder . BorderLine = new Vector3 ( float . MinValue , float . MaxValue , ( int ) Constants . RegionSize ) ; //<---
2009-08-20 23:24:31 +00:00
northBorder . CrossDirection = Cardinals . N ;
NorthBorders . Add ( northBorder ) ;
Border southBorder = new Border ( ) ;
2009-09-02 08:39:00 +00:00
southBorder . BorderLine = new Vector3 ( float . MinValue , float . MaxValue , 0 ) ; //--->
2009-08-20 23:24:31 +00:00
southBorder . CrossDirection = Cardinals . S ;
SouthBorders . Add ( southBorder ) ;
Border eastBorder = new Border ( ) ;
2009-09-02 17:04:17 +00:00
eastBorder . BorderLine = new Vector3 ( float . MinValue , float . MaxValue , ( int ) Constants . RegionSize ) ; //<---
2009-08-20 23:24:31 +00:00
eastBorder . CrossDirection = Cardinals . E ;
EastBorders . Add ( eastBorder ) ;
Border westBorder = new Border ( ) ;
2009-09-02 08:39:00 +00:00
westBorder . BorderLine = new Vector3 ( float . MinValue , float . MaxValue , 0 ) ; //--->
2009-08-20 23:24:31 +00:00
westBorder . CrossDirection = Cardinals . W ;
WestBorders . Add ( westBorder ) ;
2009-08-29 07:36:41 +00:00
BordersLocked = false ;
2009-08-20 23:24:31 +00:00
2009-01-11 18:24:16 +00:00
m_eventManager = new EventManager ( ) ;
2009-11-29 10:06:25 +00:00
2011-05-06 16:08:24 +00:00
m_permissions = new ScenePermissions ( this ) ;
2009-01-11 18:24:16 +00:00
}
2007-07-16 15:40:11 +00:00
# endregion
2007-11-03 19:14:22 +00:00
#region Startup / Close Methods
2007-11-18 11:11:44 +00:00
2009-02-20 17:18:07 +00:00
/// <value>
/// The scene graph for this scene
/// </value>
/// TODO: Possibly stop other classes being able to manipulate this directly.
public SceneGraph SceneGraph
{
get { return m_sceneGraph ; }
}
2007-11-18 11:11:44 +00:00
protected virtual void RegisterDefaultSceneEvents ( )
{
2009-01-07 20:09:37 +00:00
IDialogModule dm = RequestModuleInterface < IDialogModule > ( ) ;
2009-02-04 00:01:36 +00:00
2009-01-07 20:09:37 +00:00
if ( dm ! = null )
m_eventManager . OnPermissionError + = dm . SendAlertToUser ;
2011-09-21 22:56:11 +00:00
m_eventManager . OnSignificantClientMovement + = HandleOnSignificantClientMovement ;
2007-11-18 11:11:44 +00:00
}
2008-02-09 07:53:01 +00:00
public override string GetSimulatorVersion ( )
{
return m_simulatorVersion ;
}
2008-10-14 09:40:05 +00:00
/// <summary>
2011-10-15 02:17:58 +00:00
/// Process the fact that a neighbouring region has come up.
/// </summary>
/// <remarks>
2008-10-14 09:40:05 +00:00
/// We only add it to the neighbor list if it's within 1 region from here.
/// Agents may have draw distance values that cross two regions though, so
/// we add it to the notify list regardless of distance. We'll check
/// the agent's draw distance before notifying them though.
2011-10-15 02:17:58 +00:00
/// </remarks>
2008-10-14 09:40:05 +00:00
/// <param name="otherRegion">RegionInfo handle for the new region.</param>
/// <returns>True after all operations complete, throws exceptions otherwise.</returns>
2009-09-27 17:14:10 +00:00
public override void OtherRegionUp ( GridRegion otherRegion )
2007-11-25 04:52:14 +00:00
{
2009-09-27 17:14:10 +00:00
uint xcell = ( uint ) ( ( int ) otherRegion . RegionLocX / ( int ) Constants . RegionSize ) ;
uint ycell = ( uint ) ( ( int ) otherRegion . RegionLocY / ( int ) Constants . RegionSize ) ;
2010-12-29 15:36:39 +00:00
//m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
// RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
2009-02-14 16:37:55 +00:00
2007-11-27 13:46:52 +00:00
if ( RegionInfo . RegionHandle ! = otherRegion . RegionHandle )
2007-11-25 04:52:14 +00:00
{
2008-10-14 09:40:05 +00:00
// If these are cast to INT because long + negative values + abs returns invalid data
2009-09-27 17:14:10 +00:00
int resultX = Math . Abs ( ( int ) xcell - ( int ) RegionInfo . RegionLocX ) ;
int resultY = Math . Abs ( ( int ) ycell - ( int ) RegionInfo . RegionLocY ) ;
2008-08-28 14:41:54 +00:00
if ( resultX < = 1 & & resultY < = 1 )
2007-12-11 21:43:17 +00:00
{
2009-09-27 20:43:57 +00:00
// Let the grid service module know, so this can be cached
m_eventManager . TriggerOnRegionUp ( otherRegion ) ;
2007-12-12 00:38:57 +00:00
try
2007-11-29 02:07:19 +00:00
{
2011-11-04 00:53:51 +00:00
ForEachRootScenePresence ( delegate ( ScenePresence agent )
2012-02-21 01:57:19 +00:00
{
//agent.ControllingClient.new
//this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo());
List < ulong > old = new List < ulong > ( ) ;
old . Add ( otherRegion . RegionHandle ) ;
agent . DropOldNeighbours ( old ) ;
2012-05-23 23:31:14 +00:00
if ( EntityTransferModule ! = null & & agent . PresenceType ! = PresenceType . Npc )
EntityTransferModule . EnableChildAgent ( agent , otherRegion ) ;
2012-02-21 01:57:19 +00:00
} ) ;
2007-12-12 00:38:57 +00:00
}
2007-12-27 21:41:48 +00:00
catch ( NullReferenceException )
2007-12-12 00:38:57 +00:00
{
// This means that we're not booted up completely yet.
// This shouldn't happen too often anymore.
2008-02-05 19:44:27 +00:00
m_log . Error ( "[SCENE]: Couldn't inform client of regionup because we got a null reference exception" ) ;
2007-11-29 02:07:19 +00:00
}
}
else
{
2011-12-09 23:21:54 +00:00
m_log . InfoFormat (
2012-06-07 23:18:25 +00:00
"[SCENE]: Got notice about far away Region: {0} at ({1}, {2})" ,
2011-12-09 23:21:54 +00:00
otherRegion . RegionName , otherRegion . RegionLocX , otherRegion . RegionLocY ) ;
2007-11-25 04:52:14 +00:00
}
2007-12-08 17:25:34 +00:00
}
2007-11-25 04:52:14 +00:00
}
2007-11-28 12:36:09 +00:00
2008-05-13 06:05:45 +00:00
public void AddNeighborRegion ( RegionInfo region )
{
lock ( m_neighbours )
{
if ( ! CheckNeighborRegion ( region ) )
{
m_neighbours . Add ( region ) ;
}
}
}
2007-12-10 21:12:38 +00:00
2008-05-13 06:05:45 +00:00
public bool CheckNeighborRegion ( RegionInfo region )
{
bool found = false ;
lock ( m_neighbours )
{
foreach ( RegionInfo reg in m_neighbours )
{
if ( reg . RegionHandle = = region . RegionHandle )
{
found = true ;
break ;
}
}
}
return found ;
}
2008-06-18 03:50:39 +00:00
2011-10-19 22:38:25 +00:00
/// <summary>
/// Checks whether this region has a neighbour in the given direction.
/// </summary>
/// <param name="car"></param>
/// <param name="fix"></param>
/// <returns>
/// An integer which represents a compass point. N == 1, going clockwise until we reach NW == 8.
/// Returns a positive integer if there is a region in that direction, a negative integer if not.
/// </returns>
public int HaveNeighbor ( Cardinals car , ref int [ ] fix )
{
uint neighbourx = RegionInfo . RegionLocX ;
uint neighboury = RegionInfo . RegionLocY ;
int dir = ( int ) car ;
if ( dir > 1 & & dir < 5 ) //Heading East
neighbourx + + ;
else if ( dir > 5 ) // Heading West
neighbourx - - ;
if ( dir < 3 | | dir = = 8 ) // Heading North
neighboury + + ;
else if ( dir > 3 & & dir < 7 ) // Heading Sout
neighboury - - ;
int x = ( int ) ( neighbourx * Constants . RegionSize ) ;
int y = ( int ) ( neighboury * Constants . RegionSize ) ;
GridRegion neighbourRegion = GridService . GetRegionByPosition ( RegionInfo . ScopeID , x , y ) ;
if ( neighbourRegion = = null )
{
fix [ 0 ] = ( int ) ( RegionInfo . RegionLocX - neighbourx ) ;
fix [ 1 ] = ( int ) ( RegionInfo . RegionLocY - neighboury ) ;
return dir * ( - 1 ) ;
}
else
return dir ;
}
2009-02-14 16:37:55 +00:00
// Alias IncomingHelloNeighbour OtherRegionUp, for now
2009-09-27 17:14:10 +00:00
public GridRegion IncomingHelloNeighbour ( RegionInfo neighbour )
2009-02-14 16:37:55 +00:00
{
2009-09-27 17:14:10 +00:00
OtherRegionUp ( new GridRegion ( neighbour ) ) ;
return new GridRegion ( RegionInfo ) ;
2009-02-14 16:37:55 +00:00
}
2007-12-10 21:12:38 +00:00
// This causes the region to restart immediatley.
2007-11-29 15:27:57 +00:00
public void RestartNow ( )
2007-11-28 06:18:07 +00:00
{
2009-12-14 00:31:15 +00:00
IConfig startupConfig = m_config . Configs [ "Startup" ] ;
if ( startupConfig ! = null )
{
if ( startupConfig . GetBoolean ( "InworldRestartShutsDown" , false ) )
{
MainConsole . Instance . RunCommand ( "shutdown" ) ;
return ;
}
}
2012-11-23 02:22:30 +00:00
m_log . InfoFormat ( "[REGION]: Restarting region {0}" , Name ) ;
2009-12-14 00:31:15 +00:00
2012-11-23 02:22:30 +00:00
Close ( ) ;
2010-11-25 03:16:52 +00:00
base . Restart ( ) ;
2007-11-28 06:18:07 +00:00
}
2007-11-28 12:36:09 +00:00
2007-12-10 21:12:38 +00:00
// This is a helper function that notifies root agents in this region that a new sim near them has come up
2008-05-16 01:22:11 +00:00
// This is in the form of a timer because when an instance of OpenSim.exe is started,
2007-12-10 21:12:38 +00:00
// Even though the sims initialize, they don't listen until 'all of the sims are initialized'
// If we tell an agent about a sim that's not listening yet, the agent will not be able to connect to it.
// subsequently the agent will never see the region come back online.
2007-11-29 15:27:57 +00:00
public void RestartNotifyWaitElapsed ( object sender , ElapsedEventArgs e )
2007-12-12 17:15:37 +00:00
{
2007-11-27 13:46:52 +00:00
m_restartWaitTimer . Stop ( ) ;
2007-12-11 21:43:17 +00:00
lock ( m_regionRestartNotifyList )
2007-11-27 13:46:52 +00:00
{
2007-12-11 21:43:17 +00:00
foreach ( RegionInfo region in m_regionRestartNotifyList )
2007-11-29 07:25:58 +00:00
{
2010-01-15 23:11:58 +00:00
GridRegion r = new GridRegion ( region ) ;
2007-12-11 21:43:17 +00:00
try
2007-11-29 07:25:58 +00:00
{
2011-11-04 00:53:51 +00:00
ForEachRootScenePresence ( delegate ( ScenePresence agent )
2012-02-21 01:57:19 +00:00
{
2012-05-23 23:31:14 +00:00
if ( EntityTransferModule ! = null & & agent . PresenceType ! = PresenceType . Npc )
EntityTransferModule . EnableChildAgent ( agent , r ) ;
2012-02-21 01:57:19 +00:00
} ) ;
2007-12-11 21:43:17 +00:00
}
2007-12-27 21:41:48 +00:00
catch ( NullReferenceException )
2007-12-11 21:43:17 +00:00
{
// This means that we're not booted up completely yet.
// This shouldn't happen too often anymore.
}
2007-11-29 07:25:58 +00:00
}
2007-12-10 21:12:38 +00:00
2007-12-11 21:43:17 +00:00
// Reset list to nothing.
m_regionRestartNotifyList . Clear ( ) ;
}
2007-11-27 13:46:52 +00:00
}
2007-11-28 12:36:09 +00:00
2008-05-13 06:05:45 +00:00
public int GetInaccurateNeighborCount ( )
{
2010-03-06 01:04:20 +00:00
return m_neighbours . Count ;
2008-05-13 06:05:45 +00:00
}
2008-05-28 03:44:49 +00:00
2007-12-10 21:12:38 +00:00
// This is the method that shuts down the scene.
2007-11-03 19:14:22 +00:00
public override void Close ( )
2007-08-28 14:21:17 +00:00
{
2012-10-25 22:47:13 +00:00
if ( m_shuttingDown )
{
m_log . WarnFormat ( "[SCENE]: Ignoring close request because already closing {0}" , Name ) ;
return ;
}
2008-07-13 00:21:23 +00:00
m_log . InfoFormat ( "[SCENE]: Closing down the single simulator: {0}" , RegionInfo . RegionName ) ;
2008-08-18 00:39:10 +00:00
2012-03-06 19:05:32 +00:00
StatsReporter . Close ( ) ;
2009-10-23 21:22:21 +00:00
m_restartTimer . Stop ( ) ;
m_restartTimer . Close ( ) ;
2007-12-10 21:12:38 +00:00
// Kick all ROOT agents with the message, 'The simulator is going down'
2007-11-13 12:23:05 +00:00
ForEachScenePresence ( delegate ( ScenePresence avatar )
2011-10-07 06:20:51 +00:00
{
2011-10-07 05:47:33 +00:00
avatar . RemoveNeighbourRegion ( RegionInfo . RegionHandle ) ;
2007-11-25 04:52:14 +00:00
2008-05-01 18:04:42 +00:00
if ( ! avatar . IsChildAgent )
avatar . ControllingClient . Kick ( "The simulator is going down." ) ;
2007-11-25 04:52:14 +00:00
2008-05-10 13:11:09 +00:00
avatar . ControllingClient . SendShutdownConnectionNotice ( ) ;
2008-05-01 18:04:42 +00:00
} ) ;
2007-12-10 21:12:38 +00:00
2012-07-27 22:58:53 +00:00
// Stop updating the scene objects and agents.
m_shuttingDown = true ;
2007-12-10 21:12:38 +00:00
// Wait here, or the kick messages won't actually get to the agents before the scene terminates.
2012-07-27 22:58:53 +00:00
// We also need to wait to avoid a race condition with the scene update loop which might not yet
// have checked ShuttingDown.
2007-11-25 04:52:14 +00:00
Thread . Sleep ( 500 ) ;
2007-12-10 21:12:38 +00:00
// Stop all client threads.
2009-10-13 21:50:03 +00:00
ForEachScenePresence ( delegate ( ScenePresence avatar ) { avatar . ControllingClient . Close ( ) ; } ) ;
2009-02-04 00:01:36 +00:00
2008-11-13 04:23:31 +00:00
m_log . Debug ( "[SCENE]: Persisting changed objects" ) ;
2011-05-23 22:53:28 +00:00
EventManager . TriggerSceneShuttingDown ( this ) ;
2013-01-10 22:59:40 +00:00
Backup ( false ) ;
2008-11-12 20:16:46 +00:00
m_sceneGraph . Close ( ) ;
2009-02-04 00:01:36 +00:00
2012-10-25 21:55:29 +00:00
if ( ! GridService . DeregisterRegion ( RegionInfo . RegionID ) )
m_log . WarnFormat ( "[SCENE]: Deregister from grid failed for region {0}" , Name ) ;
base . Close ( ) ;
// XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence.
// Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can
// attempt to reference a null or disposed physics scene.
2012-07-26 22:27:18 +00:00
if ( PhysicsScene ! = null )
{
PhysicsScene phys = PhysicsScene ;
// remove the physics engine from both Scene and SceneGraph
PhysicsScene = null ;
phys . Dispose ( ) ;
phys = null ;
}
2007-07-16 15:40:11 +00:00
}
2013-05-03 17:48:50 +00:00
public override void Start ( )
{
Start ( true ) ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
2012-03-23 01:21:43 +00:00
/// Start the scene
2007-07-16 15:40:11 +00:00
/// </summary>
2013-05-03 17:48:50 +00:00
/// <param name='startScripts'>
/// Start the scripts within the scene.
/// </param>
public void Start ( bool startScripts )
2007-07-16 15:40:11 +00:00
{
2012-10-12 01:52:08 +00:00
m_active = true ;
2011-10-20 19:48:51 +00:00
// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
2008-10-11 11:43:42 +00:00
//m_heartbeatTimer.Enabled = true;
//m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
//m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
2012-03-23 01:46:11 +00:00
if ( m_heartbeatThread ! = null )
2009-09-06 14:55:14 +00:00
{
2012-03-23 01:46:11 +00:00
m_heartbeatThread . Abort ( ) ;
m_heartbeatThread = null ;
2009-09-06 14:55:14 +00:00
}
2012-03-23 01:03:10 +00:00
// m_lastUpdate = Util.EnvironmentTickCount();
2009-10-22 19:33:23 +00:00
2012-03-23 01:46:11 +00:00
m_heartbeatThread
2011-11-15 23:34:28 +00:00
= Watchdog . StartThread (
2012-02-24 05:02:33 +00:00
Heartbeat , string . Format ( "Heartbeat ({0})" , RegionInfo . RegionName ) , ThreadPriority . Normal , false , false ) ;
2013-05-03 17:48:50 +00:00
StartScripts ( ) ;
2007-07-16 15:40:11 +00:00
}
2008-05-05 20:14:53 +00:00
/// <summary>
2008-05-22 22:21:58 +00:00
/// Sets up references to modules required by the scene
2008-05-05 20:14:53 +00:00
/// </summary>
2007-11-03 19:14:22 +00:00
public void SetModuleInterfaces ( )
{
m_xmlrpcModule = RequestModuleInterface < IXMLRPC > ( ) ;
m_worldCommModule = RequestModuleInterface < IWorldComm > ( ) ;
XferManager = RequestModuleInterface < IXfer > ( ) ;
2011-10-19 21:41:44 +00:00
m_AvatarFactory = RequestModuleInterface < IAvatarFactoryModule > ( ) ;
2010-03-05 23:18:47 +00:00
AttachmentsModule = RequestModuleInterface < IAttachmentsModule > ( ) ;
2008-12-19 19:07:11 +00:00
m_serialiser = RequestModuleInterface < IRegionSerialiserModule > ( ) ;
2009-01-07 20:29:09 +00:00
m_dialogModule = RequestModuleInterface < IDialogModule > ( ) ;
2009-02-06 16:55:34 +00:00
m_capsModule = RequestModuleInterface < ICapabilitiesModule > ( ) ;
2012-05-23 23:31:14 +00:00
EntityTransferModule = RequestModuleInterface < IEntityTransferModule > ( ) ;
2011-12-19 23:03:45 +00:00
m_groupsModule = RequestModuleInterface < IGroupsModule > ( ) ;
2012-06-07 22:51:04 +00:00
AgentTransactionsModule = RequestModuleInterface < IAgentAssetTransactions > ( ) ;
2012-06-25 21:48:13 +00:00
UserManagementModule = RequestModuleInterface < IUserManagement > ( ) ;
2007-11-03 19:14:22 +00:00
}
# endregion
2007-07-16 15:40:11 +00:00
#region Update Methods
/// <summary>
2012-10-12 01:52:08 +00:00
/// Activate the various loops necessary to continually update the scene.
2007-07-16 15:40:11 +00:00
/// </summary>
2009-10-22 19:33:23 +00:00
private void Heartbeat ( )
2007-07-16 15:40:11 +00:00
{
2012-03-23 01:21:43 +00:00
// if (!Monitor.TryEnter(m_heartbeatLock))
// {
// Watchdog.RemoveThread();
// return;
// }
2009-10-06 14:28:38 +00:00
2012-03-23 01:21:43 +00:00
// try
// {
2012-02-24 05:02:33 +00:00
2012-03-23 01:21:43 +00:00
m_eventManager . TriggerOnRegionStarted ( this ) ;
2012-02-24 05:02:33 +00:00
2012-03-23 01:21:43 +00:00
// The first frame can take a very long time due to physics actors being added on startup. Therefore,
// don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false
// alarms for scenes with many objects.
Update ( 1 ) ;
2009-04-15 20:16:18 +00:00
2012-03-23 02:49:29 +00:00
Watchdog . StartThread (
Maintenance , string . Format ( "Maintenance ({0})" , RegionInfo . RegionName ) , ThreadPriority . Normal , false , true ) ;
2012-03-23 01:21:43 +00:00
Watchdog . GetCurrentThreadInfo ( ) . AlarmIfTimeout = true ;
2012-03-23 01:46:11 +00:00
Update ( - 1 ) ;
2009-04-15 20:16:18 +00:00
2012-03-23 01:03:10 +00:00
// m_lastUpdate = Util.EnvironmentTickCount();
// m_firstHeartbeat = false;
2012-03-23 01:21:43 +00:00
// }
// finally
// {
// Monitor.Pulse(m_heartbeatLock);
// Monitor.Exit(m_heartbeatLock);
// }
2009-10-22 19:33:23 +00:00
Watchdog . RemoveThread ( ) ;
2007-07-16 15:40:11 +00:00
}
2012-03-23 02:49:29 +00:00
private void Maintenance ( )
2011-10-20 18:44:59 +00:00
{
2012-03-23 02:49:29 +00:00
DoMaintenance ( - 1 ) ;
2011-10-20 19:48:51 +00:00
2012-03-23 02:49:29 +00:00
Watchdog . RemoveThread ( ) ;
}
2011-10-31 06:39:39 +00:00
2012-03-23 02:49:29 +00:00
public void DoMaintenance ( int runs )
{
long? endRun = null ;
int runtc ;
int previousMaintenanceTick ;
2011-10-05 23:45:25 +00:00
2012-03-23 02:49:29 +00:00
if ( runs > = 0 )
endRun = MaintenanceRun + runs ;
2009-12-01 15:48:11 +00:00
2012-03-23 02:49:29 +00:00
List < Vector3 > coarseLocations ;
List < UUID > avatarUUIDs ;
2009-10-29 06:10:16 +00:00
2012-10-12 02:19:12 +00:00
while ( ! m_shuttingDown & & ( ( endRun = = null & & Active ) | | MaintenanceRun < endRun ) )
2012-03-23 02:49:29 +00:00
{
runtc = Util . EnvironmentTickCount ( ) ;
+ + MaintenanceRun ;
2009-10-26 21:41:27 +00:00
2011-02-18 21:54:44 +00:00
// Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
2012-03-23 02:49:29 +00:00
if ( MaintenanceRun % ( m_update_coarse_locations / 10 ) = = 0 )
2008-03-04 05:31:54 +00:00
{
2011-02-18 21:54:44 +00:00
SceneGraph . GetCoarseLocations ( out coarseLocations , out avatarUUIDs , 60 ) ;
2012-03-23 02:49:29 +00:00
// Send coarse locations to clients
2011-02-18 21:54:44 +00:00
ForEachScenePresence ( delegate ( ScenePresence presence )
{
presence . SendCoarseLocations ( coarseLocations , avatarUUIDs ) ;
} ) ;
}
2009-05-29 21:12:55 +00:00
2012-03-23 03:33:07 +00:00
if ( SendPeriodicAppearanceUpdates & & MaintenanceRun % 60 = = 0 )
2011-02-18 21:54:44 +00:00
{
2012-03-23 03:39:39 +00:00
// m_log.DebugFormat("[SCENE]: Sending periodic appearance updates");
2009-12-01 15:48:11 +00:00
2012-03-23 03:33:07 +00:00
if ( AvatarFactory ! = null )
{
ForEachRootScenePresence ( sp = > AvatarFactory . SendAppearance ( sp . UUID ) ) ;
}
2011-10-03 22:25:09 +00:00
}
2008-05-16 01:22:11 +00:00
2012-03-23 02:49:29 +00:00
Watchdog . UpdateThread ( ) ;
2007-09-24 16:39:26 +00:00
2012-03-23 02:49:29 +00:00
previousMaintenanceTick = m_lastMaintenanceTick ;
m_lastMaintenanceTick = Util . EnvironmentTickCount ( ) ;
runtc = Util . EnvironmentTickCountSubtract ( m_lastMaintenanceTick , runtc ) ;
runtc = ( int ) ( MinMaintenanceTime * 1000 ) - runtc ;
if ( runtc > 0 )
Thread . Sleep ( runtc ) ;
// Optionally warn if a frame takes double the amount of time that it should.
if ( DebugUpdates
& & Util . EnvironmentTickCountSubtract (
m_lastMaintenanceTick , previousMaintenanceTick ) > ( int ) ( MinMaintenanceTime * 1000 * 2 ) )
m_log . WarnFormat (
"[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}" ,
Util . EnvironmentTickCountSubtract ( m_lastMaintenanceTick , previousMaintenanceTick ) ,
MinMaintenanceTime * 1000 ,
RegionInfo . RegionName ) ;
}
}
2012-03-20 23:12:21 +00:00
public override void Update ( int frames )
2011-10-20 18:44:59 +00:00
{
2012-03-20 23:12:21 +00:00
long? endFrame = null ;
2009-10-29 06:10:16 +00:00
2012-03-20 23:12:21 +00:00
if ( frames > = 0 )
endFrame = Frame + frames ;
2008-10-11 11:43:42 +00:00
2012-03-20 23:12:21 +00:00
float physicsFPS = 0f ;
2012-06-04 23:17:55 +00:00
int previousFrameTick , tmpMS ;
int maintc = Util . EnvironmentTickCount ( ) ;
2011-10-20 19:48:51 +00:00
2012-10-12 02:19:12 +00:00
while ( ! m_shuttingDown & & ( ( endFrame = = null & & Active ) | | Frame < endFrame ) )
2011-10-31 06:43:17 +00:00
{
2012-03-20 23:12:21 +00:00
+ + Frame ;
2011-10-05 23:45:25 +00:00
2012-03-20 23:12:21 +00:00
// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
2009-10-29 06:10:16 +00:00
2012-06-04 23:17:55 +00:00
agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0 ;
2009-10-26 21:41:27 +00:00
2012-03-20 23:12:21 +00:00
try
2011-02-18 21:54:44 +00:00
{
2013-05-30 16:21:58 +00:00
EventManager . TriggerRegionHeartbeatStart ( this ) ;
2012-05-10 21:42:46 +00:00
// Apply taints in terrain module to terrain in physics scene
if ( Frame % m_update_terrain = = 0 )
{
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2012-05-10 21:42:46 +00:00
UpdateTerrain ( ) ;
2012-06-04 23:17:55 +00:00
terrainMS = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2012-05-10 21:42:46 +00:00
}
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2013-01-10 23:49:48 +00:00
if ( PhysicsEnabled & & Frame % m_update_physics = = 0 )
2012-03-20 23:12:21 +00:00
m_sceneGraph . UpdatePreparePhysics ( ) ;
2012-06-04 23:17:55 +00:00
physicsMS2 = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2012-03-20 23:12:21 +00:00
// Apply any pending avatar force input to the avatar's velocity
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2012-03-20 23:12:21 +00:00
if ( Frame % m_update_entitymovement = = 0 )
m_sceneGraph . UpdateScenePresenceMovement ( ) ;
2012-06-04 23:17:55 +00:00
agentMS = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2012-03-20 23:12:21 +00:00
// Perform the main physics update. This will do the actual work of moving objects and avatars according to their
// velocity
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2012-03-20 23:12:21 +00:00
if ( Frame % m_update_physics = = 0 )
2011-02-18 21:54:44 +00:00
{
2013-01-10 23:49:48 +00:00
if ( PhysicsEnabled )
2012-03-20 23:12:21 +00:00
physicsFPS = m_sceneGraph . UpdatePhysics ( MinFrameTime ) ;
if ( SynchronizeScene ! = null )
SynchronizeScene ( this ) ;
}
2012-06-04 23:17:55 +00:00
physicsMS = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2011-10-20 19:48:51 +00:00
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2012-03-20 23:12:21 +00:00
// Check if any objects have reached their targets
CheckAtTargets ( ) ;
// Update SceneObjectGroups that have scheduled themselves for updates
// Objects queue their updates onto all scene presences
if ( Frame % m_update_objects = = 0 )
m_sceneGraph . UpdateObjectGroups ( ) ;
// Run through all ScenePresences looking for updates
// Presence updates and queued object updates for each presence are sent to clients
if ( Frame % m_update_presences = = 0 )
m_sceneGraph . UpdatePresences ( ) ;
2012-06-04 23:17:55 +00:00
agentMS + = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2012-03-20 23:12:21 +00:00
// Delete temp-on-rez stuff
if ( Frame % m_update_temp_cleaning = = 0 & & ! m_cleaningTemps )
{
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2012-03-20 23:12:21 +00:00
m_cleaningTemps = true ;
Util . FireAndForget ( delegate { CleanTempObjects ( ) ; m_cleaningTemps = false ; } ) ;
2012-06-04 23:17:55 +00:00
tempOnRezMS = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2012-03-20 23:12:21 +00:00
}
if ( Frame % m_update_events = = 0 )
{
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2012-03-20 23:12:21 +00:00
UpdateEvents ( ) ;
2012-06-04 23:17:55 +00:00
eventMS = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2012-03-20 23:12:21 +00:00
}
2013-01-10 22:38:48 +00:00
if ( PeriodicBackup & & Frame % m_update_backup = = 0 )
2012-03-20 23:12:21 +00:00
{
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCount ( ) ;
2012-03-20 23:12:21 +00:00
UpdateStorageBackup ( ) ;
2012-06-04 23:17:55 +00:00
backupMS = Util . EnvironmentTickCountSubtract ( tmpMS ) ;
2012-03-20 23:12:21 +00:00
}
//if (Frame % m_update_land == 0)
//{
// int ldMS = Util.EnvironmentTickCount();
// UpdateLand();
// landMS = Util.EnvironmentTickCountSubtract(ldMS);
//}
2012-07-18 23:09:22 +00:00
if ( ! LoginsEnabled & & Frame = = 20 )
2009-10-16 20:22:10 +00:00
{
2012-03-20 23:12:21 +00:00
// m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
// In 99.9% of cases it is a bad idea to manually force garbage collection. However,
// this is a rare case where we know we have just went through a long cycle of heap
// allocations, and there is no more work to be done until someone logs in
GC . Collect ( ) ;
2012-07-18 22:35:05 +00:00
if ( ! LoginLock )
2011-05-27 23:05:16 +00:00
{
2012-07-18 22:35:05 +00:00
if ( ! StartDisabled )
2012-03-20 23:12:21 +00:00
{
2012-06-19 23:07:03 +00:00
m_log . InfoFormat ( "[REGION]: Enabling logins for {0}" , RegionInfo . RegionName ) ;
2012-07-18 23:09:22 +00:00
LoginsEnabled = true ;
2012-03-20 23:12:21 +00:00
}
2012-07-18 21:09:20 +00:00
2012-07-18 22:37:41 +00:00
m_sceneGridService . InformNeighborsThatRegionisUp (
RequestModuleInterface < INeighbourService > ( ) , RegionInfo ) ;
2012-07-25 20:00:59 +00:00
// Region ready should always be set
Ready = true ;
2011-05-27 23:05:16 +00:00
}
2012-03-20 23:12:21 +00:00
else
2011-05-27 23:05:16 +00:00
{
2012-07-18 22:35:05 +00:00
// This handles a case of a region having no scripts for the RegionReady module
if ( m_sceneGraph . GetActiveScriptsCount ( ) = = 0 )
{
// In this case, we leave it to the IRegionReadyModule to enable logins
// LoginLock can currently only be set by a region module implementation.
// If somehow this hasn't been done then the quickest way to bugfix is to see the
// NullReferenceException
IRegionReadyModule rrm = RequestModuleInterface < IRegionReadyModule > ( ) ;
rrm . TriggerRegionReady ( this ) ;
}
2011-05-27 23:05:16 +00:00
}
}
2008-10-11 11:43:42 +00:00
}
2012-03-20 23:12:21 +00:00
catch ( Exception e )
{
m_log . ErrorFormat (
"[SCENE]: Failed on region {0} with exception {1}{2}" ,
RegionInfo . RegionName , e . Message , e . StackTrace ) ;
}
EventManager . TriggerRegionHeartbeatEnd ( this ) ;
2008-10-14 09:40:05 +00:00
2012-03-20 23:12:21 +00:00
Watchdog . UpdateThread ( ) ;
2012-02-02 00:27:20 +00:00
2012-03-21 01:27:09 +00:00
previousFrameTick = m_lastFrameTick ;
2012-03-21 00:02:08 +00:00
m_lastFrameTick = Util . EnvironmentTickCount ( ) ;
2012-06-04 23:17:55 +00:00
tmpMS = Util . EnvironmentTickCountSubtract ( m_lastFrameTick , maintc ) ;
tmpMS = ( int ) ( MinFrameTime * 1000 ) - tmpMS ;
2009-10-22 19:33:23 +00:00
2012-06-04 23:17:55 +00:00
if ( tmpMS > 0 )
{
Thread . Sleep ( tmpMS ) ;
spareMS + = tmpMS ;
}
2007-12-27 21:41:48 +00:00
2012-06-04 23:17:55 +00:00
frameMS = Util . EnvironmentTickCountSubtract ( maintc ) ;
maintc = Util . EnvironmentTickCount ( ) ;
otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS ;
// if (Frame%m_update_avatars == 0)
// UpdateInWorldTime();
StatsReporter . AddPhysicsFPS ( physicsFPS ) ;
StatsReporter . AddTimeDilation ( TimeDilation ) ;
StatsReporter . AddFPS ( 1 ) ;
StatsReporter . addFrameMS ( frameMS ) ;
StatsReporter . addAgentMS ( agentMS ) ;
StatsReporter . addPhysicsMS ( physicsMS + physicsMS2 ) ;
StatsReporter . addOtherMS ( otherMS ) ;
StatsReporter . AddSpareMS ( spareMS ) ;
StatsReporter . addScriptLines ( m_sceneGraph . GetScriptLPS ( ) ) ;
// Optionally warn if a frame takes double the amount of time that it should.
2012-03-21 01:27:09 +00:00
if ( DebugUpdates
& & Util . EnvironmentTickCountSubtract (
m_lastFrameTick , previousFrameTick ) > ( int ) ( MinFrameTime * 1000 * 2 ) )
m_log . WarnFormat (
"[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}" ,
Util . EnvironmentTickCountSubtract ( m_lastFrameTick , previousFrameTick ) ,
MinFrameTime * 1000 ,
RegionInfo . RegionName ) ;
2012-03-20 23:12:21 +00:00
}
2011-02-18 21:54:44 +00:00
}
2009-10-14 02:13:06 +00:00
public void AddGroupTarget ( SceneObjectGroup grp )
{
2009-10-18 23:58:03 +00:00
lock ( m_groupsWithTargets )
2009-10-14 02:13:06 +00:00
m_groupsWithTargets [ grp . UUID ] = grp ;
}
public void RemoveGroupTarget ( SceneObjectGroup grp )
{
2009-10-18 23:58:03 +00:00
lock ( m_groupsWithTargets )
2009-10-14 02:13:06 +00:00
m_groupsWithTargets . Remove ( grp . UUID ) ;
}
private void CheckAtTargets ( )
{
2012-10-30 01:48:05 +00:00
List < SceneObjectGroup > objs = null ;
2009-10-14 02:13:06 +00:00
lock ( m_groupsWithTargets )
2012-10-28 18:41:47 +00:00
{
2012-10-30 01:48:05 +00:00
if ( m_groupsWithTargets . Count ! = 0 )
objs = new List < SceneObjectGroup > ( m_groupsWithTargets . Values ) ;
2012-10-28 18:41:47 +00:00
}
2010-12-15 04:15:26 +00:00
2012-10-30 01:48:05 +00:00
if ( objs ! = null )
{
foreach ( SceneObjectGroup entry in objs )
entry . checkAtTargets ( ) ;
}
2009-10-14 02:13:06 +00:00
}
2009-08-15 04:01:58 +00:00
/// <summary>
/// Send out simstats data to all clients
/// </summary>
/// <param name="stats">Stats on the Simulator's performance</param>
2008-10-06 19:52:54 +00:00
private void SendSimStatsPackets ( SimStats stats )
2007-12-12 06:58:55 +00:00
{
2011-11-04 00:06:08 +00:00
ForEachRootClient ( delegate ( IClientAPI client )
{
client . SendSimStats ( stats ) ;
} ) ;
2007-12-12 06:58:55 +00:00
}
2007-12-27 21:41:48 +00:00
2009-08-15 04:01:58 +00:00
/// <summary>
/// Update the terrain if it needs to be updated.
/// </summary>
2007-09-24 15:46:03 +00:00
private void UpdateTerrain ( )
{
2008-03-06 15:49:53 +00:00
EventManager . TriggerTerrainTick ( ) ;
2008-02-05 15:03:08 +00:00
}
2009-08-15 04:01:58 +00:00
/// <summary>
/// Back up queued up changes
/// </summary>
2007-09-24 15:46:03 +00:00
private void UpdateStorageBackup ( )
{
2008-05-21 21:22:56 +00:00
if ( ! m_backingup )
{
m_backingup = true ;
2009-10-23 20:14:29 +00:00
Util . FireAndForget ( BackupWaitCallback ) ;
2008-05-21 21:22:56 +00:00
}
2007-09-24 15:46:03 +00:00
}
2007-08-19 13:35:20 +00:00
2009-08-15 04:01:58 +00:00
/// <summary>
/// Sends out the OnFrame event to the modules
/// </summary>
2007-09-24 15:46:03 +00:00
private void UpdateEvents ( )
{
m_eventManager . TriggerOnFrame ( ) ;
}
2007-09-20 13:04:51 +00:00
2009-10-23 20:14:29 +00:00
/// <summary>
/// Wrapper for Backup() that can be called with Util.FireAndForget()
/// </summary>
private void BackupWaitCallback ( object o )
2010-09-06 22:00:24 +00:00
{
Backup ( false ) ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
2008-06-16 15:36:01 +00:00
/// Backup the scene. This acts as the main method of the backup thread.
2007-07-16 15:40:11 +00:00
/// </summary>
2010-09-06 22:00:24 +00:00
/// <param name="forced">
/// If true, then any changes that have not yet been persisted are persisted. If false,
/// then the persistence decision is left to the backup code (in some situations, such as object persistence,
/// it's much more efficient to backup multiple changes at once rather than every single one).
2007-07-16 15:40:11 +00:00
/// <returns></returns>
2010-09-06 22:00:24 +00:00
public void Backup ( bool forced )
2007-07-16 15:40:11 +00:00
{
2008-11-21 18:44:48 +00:00
lock ( m_returns )
2008-10-18 05:51:36 +00:00
{
2010-09-12 21:20:26 +00:00
EventManager . TriggerOnBackup ( SimulationDataService , forced ) ;
2008-11-21 07:33:13 +00:00
m_backingup = false ;
2008-10-18 05:51:36 +00:00
2008-11-21 07:33:13 +00:00
foreach ( KeyValuePair < UUID , ReturnInfo > ret in m_returns )
{
UUID transaction = UUID . Random ( ) ;
GridInstantMessage msg = new GridInstantMessage ( ) ;
msg . fromAgentID = new Guid ( UUID . Zero . ToString ( ) ) ; // From server
msg . toAgentID = new Guid ( ret . Key . ToString ( ) ) ;
msg . imSessionID = new Guid ( transaction . ToString ( ) ) ;
msg . timestamp = ( uint ) Util . UnixTimeSinceEpoch ( ) ;
msg . fromAgentName = "Server" ;
msg . dialog = ( byte ) 19 ; // Object msg
msg . fromGroup = false ;
2011-11-02 23:50:47 +00:00
msg . offline = ( byte ) 0 ;
2008-11-21 07:33:13 +00:00
msg . ParentEstateID = RegionInfo . EstateSettings . ParentEstateID ;
msg . Position = Vector3 . Zero ;
msg . RegionID = RegionInfo . RegionID . Guid ;
2011-09-13 16:13:42 +00:00
// We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
msg . binaryBucket = Util . StringToBytes256 ( "\0" ) ;
2008-11-21 07:33:13 +00:00
if ( ret . Value . count > 1 )
msg . message = string . Format ( "Your {0} objects were returned from {1} in region {2} due to {3}" , ret . Value . count , ret . Value . location . ToString ( ) , RegionInfo . RegionName , ret . Value . reason ) ;
else
msg . message = string . Format ( "Your object {0} was returned from {1} in region {2} due to {3}" , ret . Value . objectName , ret . Value . location . ToString ( ) , RegionInfo . RegionName , ret . Value . reason ) ;
IMessageTransferModule tr = RequestModuleInterface < IMessageTransferModule > ( ) ;
if ( tr ! = null )
2009-06-09 18:07:35 +00:00
tr . SendInstantMessage ( msg , delegate ( bool success ) { } ) ;
2008-11-21 07:33:13 +00:00
}
m_returns . Clear ( ) ;
2008-10-18 05:51:36 +00:00
}
}
2009-08-15 04:01:58 +00:00
/// <summary>
/// Synchronous force backup. For deletes and links/unlinks
/// </summary>
/// <param name="group">Object to be backed up</param>
2009-02-04 16:00:39 +00:00
public void ForceSceneObjectBackup ( SceneObjectGroup group )
{
if ( group ! = null )
{
2010-09-12 21:20:26 +00:00
group . ProcessBackup ( SimulationDataService , true ) ;
2009-02-04 16:00:39 +00:00
}
}
2009-08-15 04:01:58 +00:00
/// <summary>
2011-04-05 21:25:00 +00:00
/// Tell an agent that their object has been returned.
2009-08-15 04:01:58 +00:00
/// </summary>
2011-04-05 21:25:00 +00:00
/// <remarks>
/// The actual return is handled by the caller.
/// </remarks>
2009-08-15 04:01:58 +00:00
/// <param name="agentID">Avatar Unique Id</param>
/// <param name="objectName">Name of object returned</param>
/// <param name="location">Location of object returned</param>
/// <param name="reason">Reasion for object return</param>
2008-11-21 07:33:13 +00:00
public void AddReturn ( UUID agentID , string objectName , Vector3 location , string reason )
2008-10-18 05:51:36 +00:00
{
2008-11-21 18:44:48 +00:00
lock ( m_returns )
2008-10-18 05:51:36 +00:00
{
2008-11-21 07:33:13 +00:00
if ( m_returns . ContainsKey ( agentID ) )
{
ReturnInfo info = m_returns [ agentID ] ;
info . count + + ;
m_returns [ agentID ] = info ;
}
else
{
ReturnInfo info = new ReturnInfo ( ) ;
info . count = 1 ;
info . objectName = objectName ;
info . location = location ;
info . reason = reason ;
m_returns [ agentID ] = info ;
}
2008-10-18 05:51:36 +00:00
}
2007-07-16 15:40:11 +00:00
}
2007-07-17 17:47:23 +00:00
2007-07-16 15:40:11 +00:00
# endregion
#region Load Terrain
2007-07-17 17:47:23 +00:00
2009-08-15 04:01:58 +00:00
/// <summary>
/// Store the terrain in the persistant data store
/// </summary>
2008-03-06 15:49:53 +00:00
public void SaveTerrain ( )
2008-01-12 03:17:28 +00:00
{
2010-09-12 21:20:26 +00:00
SimulationDataService . StoreTerrain ( Heightmap . GetDoubles ( ) , RegionInfo . RegionID ) ;
2008-01-12 03:17:28 +00:00
}
2010-03-31 03:20:20 +00:00
public void StoreWindlightProfile ( RegionLightShareData wl )
{
2012-06-28 23:03:22 +00:00
RegionInfo . WindlightSettings = wl ;
2010-09-12 21:20:26 +00:00
SimulationDataService . StoreRegionWindlightSettings ( wl ) ;
2010-03-31 03:20:20 +00:00
m_eventManager . TriggerOnSaveNewWindlightProfile ( ) ;
}
public void LoadWindlightProfile ( )
{
2012-06-28 23:03:22 +00:00
RegionInfo . WindlightSettings = SimulationDataService . LoadRegionWindlightSettings ( RegionInfo . RegionID ) ;
2010-03-31 03:20:20 +00:00
m_eventManager . TriggerOnSaveNewWindlightProfile ( ) ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
/// Loads the World heightmap
/// </summary>
public override void LoadWorldMap ( )
{
try
{
2010-09-12 21:20:26 +00:00
double [ , ] map = SimulationDataService . LoadTerrain ( RegionInfo . RegionID ) ;
2007-07-16 15:40:11 +00:00
if ( map = = null )
{
2012-03-16 20:08:05 +00:00
// This should be in the Terrain module, but it isn't because
// the heightmap is needed _way_ before the modules are initialized...
IConfig terrainConfig = m_config . Configs [ "Terrain" ] ;
String m_InitialTerrain = "pinhead-island" ;
if ( terrainConfig ! = null )
m_InitialTerrain = terrainConfig . GetString ( "InitialTerrain" , m_InitialTerrain ) ;
m_log . InfoFormat ( "[TERRAIN]: No default terrain. Generating a new terrain {0}." , m_InitialTerrain ) ;
Heightmap = new TerrainChannel ( m_InitialTerrain ) ;
2007-07-16 15:40:11 +00:00
2010-09-12 21:20:26 +00:00
SimulationDataService . StoreTerrain ( Heightmap . GetDoubles ( ) , RegionInfo . RegionID ) ;
2007-07-16 15:40:11 +00:00
}
else
{
2008-04-21 07:09:17 +00:00
Heightmap = new TerrainChannel ( map ) ;
2007-07-16 15:40:11 +00:00
}
}
2009-08-07 22:40:56 +00:00
catch ( IOException e )
{
2011-12-09 23:21:54 +00:00
m_log . WarnFormat (
"[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}" ,
e . Message , e . StackTrace ) ;
2009-08-07 22:40:56 +00:00
// Non standard region size. If there's an old terrain in the database, it might read past the buffer
2009-09-09 17:09:23 +00:00
#pragma warning disable 0162
2009-08-07 22:40:56 +00:00
if ( ( int ) Constants . RegionSize ! = 256 )
{
Heightmap = new TerrainChannel ( ) ;
2010-09-12 21:20:26 +00:00
SimulationDataService . StoreTerrain ( Heightmap . GetDoubles ( ) , RegionInfo . RegionID ) ;
2009-08-07 22:40:56 +00:00
}
}
2007-07-16 15:40:11 +00:00
catch ( Exception e )
{
2011-12-09 23:21:54 +00:00
m_log . WarnFormat (
"[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}" , e . Message , e . StackTrace ) ;
2007-07-16 15:40:11 +00:00
}
}
2008-05-12 16:57:56 +00:00
/// <summary>
/// Register this region with a grid service
/// </summary>
/// <exception cref="System.Exception">Thrown if registration of the region itself fails.</exception>
2007-11-28 12:36:09 +00:00
public void RegisterRegionWithGrid ( )
{
2010-06-14 02:06:22 +00:00
m_sceneGridService . SetScene ( this ) ;
2011-12-31 05:32:28 +00:00
//// Unfortunately this needs to be here and it can't be async.
//// The map tile image is stored in RegionSettings, but it also needs to be
//// stored in the GridService, because that's what the world map module uses
//// to send the map image UUIDs (of other regions) to the viewer...
if ( m_generateMaptiles )
RegenerateMaptile ( ) ;
2011-07-22 08:33:00 +00:00
GridRegion region = new GridRegion ( RegionInfo ) ;
string error = GridService . RegisterRegion ( RegionInfo . ScopeID , region ) ;
if ( error ! = String . Empty )
throw new Exception ( error ) ;
2007-11-28 12:36:09 +00:00
}
2007-07-16 15:40:11 +00:00
# endregion
2007-12-17 03:49:13 +00:00
#region Load Land
2009-08-15 04:01:58 +00:00
/// <summary>
/// Loads all Parcel data from the datastore for region identified by regionID
/// </summary>
/// <param name="regionID">Unique Identifier of the Region to load parcel data for</param>
2008-09-06 07:52:41 +00:00
public void loadAllLandObjectsFromStorage ( UUID regionID )
2007-12-17 03:49:13 +00:00
{
2008-02-10 14:27:21 +00:00
m_log . Info ( "[SCENE]: Loading land objects from storage" ) ;
2010-09-12 21:20:26 +00:00
List < LandData > landData = SimulationDataService . LoadLandObjects ( regionID ) ;
2008-01-19 19:49:08 +00:00
2008-05-13 16:22:57 +00:00
if ( LandChannel ! = null )
2008-02-10 14:27:21 +00:00
{
2008-05-13 16:22:57 +00:00
if ( landData . Count = = 0 )
{
2008-05-23 15:12:15 +00:00
EventManager . TriggerNoticeNoLandDataFromStorage ( ) ;
2008-05-13 16:22:57 +00:00
}
else
{
2008-05-23 15:12:15 +00:00
EventManager . TriggerIncomingLandDataFromStorage ( landData ) ;
2008-05-13 16:22:57 +00:00
}
2008-02-10 14:27:21 +00:00
}
else
{
2008-05-13 16:22:57 +00:00
m_log . Error ( "[SCENE]: Land Channel is not defined. Cannot load from storage!" ) ;
2008-02-10 14:27:21 +00:00
}
2007-12-17 03:49:13 +00:00
}
2007-12-27 21:41:48 +00:00
2007-12-17 03:49:13 +00:00
# endregion
2007-07-16 15:40:11 +00:00
#region Primitives Methods
/// <summary>
/// Loads the World's objects
/// </summary>
2011-07-11 02:13:59 +00:00
/// <param name="regionID"></param>
2008-09-06 07:52:41 +00:00
public virtual void LoadPrimsFromStorage ( UUID regionID )
2007-07-16 15:40:11 +00:00
{
2010-07-17 06:19:58 +00:00
LoadingPrims = true ;
2008-02-05 19:44:27 +00:00
m_log . Info ( "[SCENE]: Loading objects from datastore" ) ;
2008-02-10 14:27:21 +00:00
2010-09-12 21:20:26 +00:00
List < SceneObjectGroup > PrimsFromDB = SimulationDataService . LoadObjects ( regionID ) ;
2009-10-06 21:07:04 +00:00
2011-12-09 23:21:54 +00:00
m_log . InfoFormat ( "[SCENE]: Loaded {0} objects from the datastore" , PrimsFromDB . Count ) ;
2009-10-06 21:07:04 +00:00
2008-01-07 02:12:06 +00:00
foreach ( SceneObjectGroup group in PrimsFromDB )
2007-07-19 00:42:59 +00:00
{
2008-07-13 00:18:29 +00:00
AddRestoredSceneObject ( group , true , true ) ;
2012-03-27 19:50:58 +00:00
EventManager . TriggerOnSceneObjectLoaded ( group ) ;
2012-03-31 00:52:06 +00:00
SceneObjectPart rootPart = group . GetPart ( group . UUID ) ;
2010-08-13 19:23:53 +00:00
rootPart . Flags & = ~ PrimFlags . Scripted ;
2008-01-22 15:07:30 +00:00
rootPart . TrimPermissions ( ) ;
2011-07-12 01:33:09 +00:00
// Don't do this here - it will get done later on when sculpt data is loaded.
// group.CheckSculptAndLoad();
2007-07-19 00:42:59 +00:00
}
2008-02-10 14:27:21 +00:00
2010-07-17 06:19:58 +00:00
LoadingPrims = false ;
2011-06-08 22:18:14 +00:00
EventManager . TriggerPrimsLoaded ( this ) ;
2007-07-16 15:40:11 +00:00
}
2013-01-23 21:03:24 +00:00
public bool SupportsRayCastFiltered ( )
{
if ( PhysicsScene = = null )
return false ;
return PhysicsScene . SupportsRaycastWorldFiltered ( ) ;
}
public object RayCastFiltered ( Vector3 position , Vector3 direction , float length , int Count , RayFilterFlags filter )
{
if ( PhysicsScene = = null )
return null ;
return PhysicsScene . RaycastWorld ( position , direction , length , Count , filter ) ;
}
2009-08-15 04:01:58 +00:00
/// <summary>
/// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
/// </summary>
/// <param name="RayStart"></param>
/// <param name="RayEnd"></param>
/// <param name="RayTargetID"></param>
/// <param name="rot"></param>
/// <param name="bypassRayCast"></param>
/// <param name="RayEndIsIntersection"></param>
/// <param name="frontFacesOnly"></param>
/// <param name="scale"></param>
/// <param name="FaceCenter"></param>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public Vector3 GetNewRezLocation ( Vector3 RayStart , Vector3 RayEnd , UUID RayTargetID , Quaternion rot , byte bypassRayCast , byte RayEndIsIntersection , bool frontFacesOnly , Vector3 scale , bool FaceCenter )
2007-07-16 15:40:11 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 pos = Vector3 . Zero ;
2008-05-01 18:04:42 +00:00
if ( RayEndIsIntersection = = ( byte ) 1 )
2007-08-26 17:57:25 +00:00
{
2007-12-28 05:25:21 +00:00
pos = RayEnd ;
return pos ;
}
2008-08-28 14:41:54 +00:00
2008-09-06 07:52:41 +00:00
if ( RayTargetID ! = UUID . Zero )
2007-12-28 05:25:21 +00:00
{
SceneObjectPart target = GetSceneObjectPart ( RayTargetID ) ;
2008-05-16 01:22:11 +00:00
2008-09-06 07:52:41 +00:00
Vector3 direction = Vector3 . Normalize ( RayEnd - RayStart ) ;
2008-03-23 06:24:59 +00:00
Vector3 AXOrigin = new Vector3 ( RayStart . X , RayStart . Y , RayStart . Z ) ;
Vector3 AXdirection = new Vector3 ( direction . X , direction . Y , direction . Z ) ;
2007-12-28 05:25:21 +00:00
if ( target ! = null )
2007-12-12 17:15:37 +00:00
{
2007-12-28 05:25:21 +00:00
pos = target . AbsolutePosition ;
2008-03-21 05:54:56 +00:00
//m_log.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());
2008-05-16 01:22:11 +00:00
2008-03-23 06:24:59 +00:00
// TODO: Raytrace better here
2008-05-16 01:22:11 +00:00
2008-11-12 20:16:46 +00:00
//EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
2008-03-23 06:24:59 +00:00
Ray NewRay = new Ray ( AXOrigin , AXdirection ) ;
// Ray Trace against target here
2008-09-06 07:52:41 +00:00
EntityIntersection ei = target . TestIntersectionOBB ( NewRay , Quaternion . Identity , frontFacesOnly , FaceCenter ) ;
2008-03-23 06:24:59 +00:00
// Un-comment out the following line to Get Raytrace results printed to the console.
2008-05-01 18:04:42 +00:00
// m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2008-05-01 06:31:12 +00:00
float ScaleOffset = 0.5f ;
2008-03-23 06:24:59 +00:00
// If we hit something
if ( ei . HitTF )
2008-03-21 05:54:56 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 scaleComponent = new Vector3 ( ei . AAfaceNormal . X , ei . AAfaceNormal . Y , ei . AAfaceNormal . Z ) ;
2008-05-01 06:31:12 +00:00
if ( scaleComponent . X ! = 0 ) ScaleOffset = scale . X ;
if ( scaleComponent . Y ! = 0 ) ScaleOffset = scale . Y ;
if ( scaleComponent . Z ! = 0 ) ScaleOffset = scale . Z ;
ScaleOffset = Math . Abs ( ScaleOffset ) ;
2008-09-06 07:52:41 +00:00
Vector3 intersectionpoint = new Vector3 ( ei . ipoint . X , ei . ipoint . Y , ei . ipoint . Z ) ;
Vector3 normal = new Vector3 ( ei . normal . X , ei . normal . Y , ei . normal . Z ) ;
2008-03-23 06:24:59 +00:00
// Set the position to the intersection point
2008-09-06 07:52:41 +00:00
Vector3 offset = ( normal * ( ScaleOffset / 2f ) ) ;
2008-05-01 04:58:15 +00:00
pos = ( intersectionpoint + offset ) ;
2008-05-16 01:22:11 +00:00
2009-07-13 12:08:14 +00:00
//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
//And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2008-03-25 17:28:09 +00:00
// Un-offset the prim (it gets offset later by the consumer method)
2009-07-13 12:08:14 +00:00
//pos.Z -= 0.25F;
2008-05-16 01:22:11 +00:00
}
2007-12-28 05:25:21 +00:00
return pos ;
2007-11-23 05:56:35 +00:00
}
2007-11-25 17:53:16 +00:00
else
{
2008-03-23 06:24:59 +00:00
// We don't have a target here, so we're going to raytrace all the objects in the scene.
2008-11-12 20:16:46 +00:00
EntityIntersection ei = m_sceneGraph . GetClosestIntersectingPrim ( new Ray ( AXOrigin , AXdirection ) , true , false ) ;
2008-03-23 06:24:59 +00:00
// Un-comment the following line to print the raytrace results to the console.
//m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
if ( ei . HitTF )
{
2008-09-06 07:52:41 +00:00
pos = new Vector3 ( ei . ipoint . X , ei . ipoint . Y , ei . ipoint . Z ) ;
2008-09-30 14:42:25 +00:00
} else
{
// fall back to our stupid functionality
pos = RayEnd ;
2008-05-16 01:22:11 +00:00
}
2007-12-28 05:25:21 +00:00
return pos ;
}
}
else
{
// fall back to our stupid functionality
pos = RayEnd ;
2009-07-13 12:08:14 +00:00
//increase height so its above the ground.
//should be getting the normal of the ground at the rez point and using that?
2009-07-13 14:42:46 +00:00
pos . Z + = scale . Z / 2f ;
2007-12-28 05:25:21 +00:00
return pos ;
}
}
2009-08-15 04:01:58 +00:00
/// <summary>
/// Create a New SceneObjectGroup/Part by raycasting
/// </summary>
/// <param name="ownerID"></param>
/// <param name="groupID"></param>
/// <param name="RayEnd"></param>
/// <param name="rot"></param>
/// <param name="shape"></param>
/// <param name="bypassRaycast"></param>
/// <param name="RayStart"></param>
/// <param name="RayTargetID"></param>
/// <param name="RayEndIsIntersection"></param>
2008-11-17 23:43:46 +00:00
public virtual void AddNewPrim ( UUID ownerID , UUID groupID , Vector3 RayEnd , Quaternion rot , PrimitiveBaseShape shape ,
2008-09-06 07:52:41 +00:00
byte bypassRaycast , Vector3 RayStart , UUID RayTargetID ,
2008-02-05 19:44:27 +00:00
byte RayEndIsIntersection )
2008-02-10 14:27:21 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 pos = GetNewRezLocation ( RayStart , RayEnd , RayTargetID , rot , bypassRaycast , RayEndIsIntersection , true , new Vector3 ( 0.5f , 0.5f , 0.5f ) , false ) ;
2008-05-16 01:22:11 +00:00
2008-11-21 22:14:57 +00:00
if ( Permissions . CanRezObject ( 1 , ownerID , pos ) )
2007-12-28 05:25:21 +00:00
{
2007-12-30 16:00:55 +00:00
// rez ON the ground, not IN the ground
2012-03-14 22:33:22 +00:00
// pos.Z += 0.25F; The rez point should now be correct so that its not in the ground
2007-12-30 16:00:55 +00:00
2008-11-17 23:43:46 +00:00
AddNewPrim ( ownerID , groupID , pos , rot , shape ) ;
2007-12-30 16:00:55 +00:00
}
2012-03-14 22:33:22 +00:00
else
{
IClientAPI client = null ;
2012-03-31 00:07:14 +00:00
if ( TryGetClient ( ownerID , out client ) )
2012-03-14 22:33:22 +00:00
client . SendAlertMessage ( "You cannot create objects here." ) ;
}
2007-12-30 16:00:55 +00:00
}
2008-12-19 17:57:03 +00:00
public virtual SceneObjectGroup AddNewPrim (
UUID ownerID , UUID groupID , Vector3 pos , Quaternion rot , PrimitiveBaseShape shape )
2007-12-30 16:00:55 +00:00
{
2008-06-17 20:36:21 +00:00
//m_log.DebugFormat(
2008-12-19 17:57:03 +00:00
// "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName);
2009-02-04 00:01:36 +00:00
2010-03-03 22:14:06 +00:00
SceneObjectGroup sceneObject = null ;
2008-12-19 17:57:03 +00:00
// If an entity creator has been registered for this prim type then use that
if ( m_entityCreators . ContainsKey ( ( PCode ) shape . PCode ) )
2010-03-03 22:14:06 +00:00
{
sceneObject = m_entityCreators [ ( PCode ) shape . PCode ] . CreateEntity ( ownerID , groupID , pos , rot , shape ) ;
}
else
{
// Otherwise, use this default creation code;
sceneObject = new SceneObjectGroup ( ownerID , pos , rot , shape ) ;
AddNewSceneObject ( sceneObject , true ) ;
sceneObject . SetGroup ( groupID , null ) ;
}
2008-06-18 03:50:39 +00:00
2012-06-25 21:48:13 +00:00
if ( UserManagementModule ! = null )
sceneObject . RootPart . CreatorIdentification = UserManagementModule . GetUserUUI ( ownerID ) ;
2011-06-08 23:01:33 +00:00
2010-03-03 22:14:06 +00:00
sceneObject . ScheduleGroupForFullUpdate ( ) ;
2008-02-04 10:39:30 +00:00
2008-11-07 21:07:14 +00:00
return sceneObject ;
2010-09-12 17:43:49 +00:00
}
2010-06-08 14:07:57 +00:00
/// <summary>
/// Add an object into the scene that has come from storage
/// </summary>
///
/// <param name="sceneObject"></param>
/// <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>
/// <param name="alreadyPersisted">
/// If true, we won't persist this object until it changes
/// If false, we'll persist this object immediately
/// </param>
/// <param name="sendClientUpdates">
/// If true, we send updates to the client to tell it about this object
/// If false, we leave it up to the caller to do this
/// </param>
/// <returns>
/// true if the object was added, false if an object with the same uuid was already in the scene
/// </returns>
public bool AddRestoredSceneObject (
SceneObjectGroup sceneObject , bool attachToBackup , bool alreadyPersisted , bool sendClientUpdates )
{
2012-10-06 00:30:27 +00:00
if ( m_sceneGraph . AddRestoredSceneObject ( sceneObject , attachToBackup , alreadyPersisted , sendClientUpdates ) )
{
EventManager . TriggerObjectAddedToScene ( sceneObject ) ;
return true ;
}
return false ;
2007-07-16 15:40:11 +00:00
}
2010-06-08 14:07:57 +00:00
2008-05-24 22:10:14 +00:00
/// <summary>
/// Add an object into the scene that has come from storage
/// </summary>
2009-05-29 21:12:55 +00:00
///
2008-05-25 23:27:38 +00:00
/// <param name="sceneObject"></param>
2008-07-13 00:18:29 +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>
/// <param name="alreadyPersisted">
/// If true, we won't persist this object until it changes
/// If false, we'll persist this object immediately
/// </param>
/// <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
public bool AddRestoredSceneObject (
SceneObjectGroup sceneObject , bool attachToBackup , bool alreadyPersisted )
2007-08-10 13:59:19 +00:00
{
2010-06-08 14:07:57 +00:00
return AddRestoredSceneObject ( sceneObject , attachToBackup , alreadyPersisted , true ) ;
2007-08-10 13:59:19 +00:00
}
2008-05-24 22:10:14 +00:00
/// <summary>
2010-03-03 22:14:06 +00:00
/// Add a newly created object to the scene. Updates are also sent to viewers.
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>
2012-01-31 19:56:37 +00:00
/// <returns>true if the object was added. false if not</returns>
2008-07-12 22:14:38 +00:00
public bool AddNewSceneObject ( SceneObjectGroup sceneObject , bool attachToBackup )
2007-07-16 15:40:11 +00:00
{
2010-03-03 22:14:06 +00:00
return AddNewSceneObject ( sceneObject , attachToBackup , true ) ;
2008-05-25 23:27:38 +00:00
}
2010-03-03 22:14:06 +00:00
/// <summary>
/// Add a newly created object to 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>
/// <param name="sendClientUpdates">
/// If true, updates for the new scene object are sent to all viewers in range.
/// If false, it is left to the caller to schedule the update
/// </param>
2012-01-31 19:56:37 +00:00
/// <returns>true if the object was added. false if not</returns>
2010-03-03 22:14:06 +00:00
public bool AddNewSceneObject ( SceneObjectGroup sceneObject , bool attachToBackup , bool sendClientUpdates )
2011-03-23 21:50:56 +00:00
{
if ( m_sceneGraph . AddNewSceneObject ( sceneObject , attachToBackup , sendClientUpdates ) )
{
EventManager . TriggerObjectAddedToScene ( sceneObject ) ;
return true ;
}
return false ;
2010-03-10 04:15:36 +00:00
}
2010-08-24 22:25:19 +00:00
/// <summary>
/// Add a newly created object to the scene.
/// </summary>
2011-05-20 22:22:27 +00:00
/// <remarks>
2010-08-24 22:25:19 +00:00
/// This method does not send updates to the client - callers need to handle this themselves.
2011-05-20 22:22:27 +00:00
/// </remarks>
2010-08-24 22:25:19 +00:00
/// <param name="sceneObject"></param>
/// <param name="attachToBackup"></param>
2011-05-20 23:02:53 +00:00
/// <param name="pos">Position of the object. If null then the position stored in the object is used.</param>
/// <param name="rot">Rotation of the object. If null then the rotation stored in the object is used.</param>
2010-08-24 22:25:19 +00:00
/// <param name="vel">Velocity of the object. This parameter only has an effect if the object is physical</param>
/// <returns></returns>
public bool AddNewSceneObject (
2011-05-20 23:02:53 +00:00
SceneObjectGroup sceneObject , bool attachToBackup , Vector3 ? pos , Quaternion ? rot , Vector3 vel )
2010-09-12 17:43:49 +00:00
{
2011-03-23 21:50:56 +00:00
if ( m_sceneGraph . AddNewSceneObject ( sceneObject , attachToBackup , pos , rot , vel ) )
{
EventManager . TriggerObjectAddedToScene ( sceneObject ) ;
return true ;
}
return false ;
2010-08-24 22:25:19 +00:00
}
2007-07-16 15:40:11 +00:00
2008-07-14 16:23:59 +00:00
/// <summary>
2010-05-28 17:49:32 +00:00
/// Delete every object from the scene. This does not include attachments worn by avatars.
2008-07-14 16:23:59 +00:00
/// </summary>
public void DeleteAllSceneObjects ( )
{
lock ( Entities )
{
2010-09-10 19:04:12 +00:00
EntityBase [ ] entities = Entities . GetEntities ( ) ;
2008-07-14 16:23:59 +00:00
foreach ( EntityBase e in entities )
{
if ( e is SceneObjectGroup )
2010-05-28 17:49:32 +00:00
{
SceneObjectGroup sog = ( SceneObjectGroup ) e ;
if ( ! sog . IsAttachment )
DeleteSceneObject ( ( SceneObjectGroup ) e , false ) ;
}
2008-07-14 16:23:59 +00:00
}
2008-08-18 00:39:10 +00:00
}
2008-07-14 16:23:59 +00:00
}
2008-08-18 00:39:10 +00:00
2008-05-24 22:10:14 +00:00
/// <summary>
2008-11-12 20:35:35 +00:00
/// Synchronously delete the given object from the scene.
2008-05-24 22:10:14 +00:00
/// </summary>
2012-07-10 21:41:11 +00:00
/// <remarks>
/// Scripts are also removed.
/// </remarks>
2009-02-02 14:57:01 +00:00
/// <param name="group">Object Id</param>
/// <param name="silent">Suppress broadcasting changes to other clients.</param>
2008-11-07 05:48:44 +00:00
public void DeleteSceneObject ( SceneObjectGroup group , bool silent )
2012-07-10 21:41:11 +00:00
{
DeleteSceneObject ( group , silent , true ) ;
}
/// <summary>
/// Synchronously delete the given object from the scene.
/// </summary>
/// <param name="group">Object Id</param>
/// <param name="silent">Suppress broadcasting changes to other clients.</param>
/// <param name="removeScripts">If true, then scripts are removed. If false, then they are only stopped.</para>
public void DeleteSceneObject ( SceneObjectGroup group , bool silent , bool removeScripts )
2010-12-03 00:08:58 +00:00
{
2010-01-25 21:51:58 +00:00
// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
2008-05-25 23:27:38 +00:00
2012-07-10 21:41:11 +00:00
if ( removeScripts )
group . RemoveScriptInstances ( true ) ;
else
group . StopScriptInstances ( ) ;
2008-09-17 22:00:56 +00:00
2010-09-17 00:30:46 +00:00
SceneObjectPart [ ] partList = group . Parts ;
2010-08-27 23:40:33 +00:00
foreach ( SceneObjectPart part in partList )
2008-05-24 23:11:07 +00:00
{
2013-06-06 02:03:05 +00:00
if ( part . KeyframeMotion ! = null )
{
part . KeyframeMotion . Delete ( ) ;
part . KeyframeMotion = null ;
}
2010-08-27 23:40:33 +00:00
if ( part . IsJoint ( ) & & ( ( part . Flags & PrimFlags . Physics ) ! = 0 ) )
2008-12-26 12:58:02 +00:00
{
2010-08-27 23:40:33 +00:00
PhysicsScene . RequestJointDeletion ( part . Name ) ; // FIXME: what if the name changed?
}
else if ( part . PhysActor ! = null )
{
2011-10-15 01:02:39 +00:00
part . RemoveFromPhysics ( ) ;
2008-08-27 19:06:07 +00:00
}
2008-05-25 23:27:38 +00:00
}
2008-05-24 23:11:07 +00:00
2010-09-06 23:34:06 +00:00
if ( UnlinkSceneObject ( group , false ) )
2007-07-16 15:40:11 +00:00
{
2008-05-24 23:11:07 +00:00
EventManager . TriggerObjectBeingRemovedFromScene ( group ) ;
2008-05-23 15:12:15 +00:00
EventManager . TriggerParcelPrimCountTainted ( ) ;
2008-05-25 23:27:38 +00:00
}
2008-05-25 00:09:08 +00:00
2010-09-15 21:29:58 +00:00
group . DeleteGroupFromScene ( silent ) ;
2010-01-25 21:51:58 +00:00
2010-12-03 00:08:58 +00:00
// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2008-05-25 23:27:38 +00:00
}
2008-05-25 00:09:08 +00:00
/// <summary>
/// Unlink the given object from the scene. Unlike delete, this just removes the record of the object - the
/// object itself is not destroyed.
/// </summary>
2010-09-06 23:34:06 +00:00
/// <param name="so">The scene object.</param>
/// <param name="softDelete">If true, only deletes from scene, but keeps the object in the database.</param>
2008-05-25 00:09:08 +00:00
/// <returns>true if the object was in the scene, false if it was not</returns>
2010-09-06 23:34:06 +00:00
public bool UnlinkSceneObject ( SceneObjectGroup so , bool softDelete )
2008-05-25 23:27:38 +00:00
{
2010-09-06 23:34:06 +00:00
if ( m_sceneGraph . DeleteSceneObject ( so . UUID , softDelete ) )
2008-05-25 00:09:08 +00:00
{
2009-02-02 14:57:01 +00:00
if ( ! softDelete )
{
2010-09-06 23:34:06 +00:00
// Force a database update so that the scene object group ID is accurate. It's possible that the
// group has recently been delinked from another group but that this change has not been persisted
// to the DB.
2010-12-03 00:08:58 +00:00
// This is an expensive thing to do so only do it if absolutely necessary.
if ( so . HasGroupChangedDueToDelink )
ForceSceneObjectBackup ( so ) ;
2010-09-12 21:20:26 +00:00
so . DetachFromBackup ( ) ;
2012-06-28 23:03:22 +00:00
SimulationDataService . RemoveObject ( so . UUID , RegionInfo . RegionID ) ;
2009-02-02 14:57:01 +00:00
}
2010-09-06 23:34:06 +00:00
// We need to keep track of this state in case this group is still queued for further backup.
2010-09-12 21:20:26 +00:00
so . IsDeleted = true ;
2009-02-02 14:57:01 +00:00
2008-05-25 00:09:08 +00:00
return true ;
}
2008-05-25 23:27:38 +00:00
2008-05-25 00:09:08 +00:00
return false ;
}
2007-07-16 15:40:11 +00:00
2008-04-25 21:41:55 +00:00
/// <summary>
2008-10-14 09:40:05 +00:00
/// Move the given scene object into a new region depending on which region its absolute position has moved
/// into.
///
2008-04-25 21:41:55 +00:00
/// </summary>
2008-09-12 00:37:59 +00:00
/// <param name="attemptedPosition">the attempted out of region position of the scene object</param>
/// <param name="grp">the scene object that we're crossing</param>
2008-11-07 05:48:44 +00:00
public void CrossPrimGroupIntoNewRegion ( Vector3 attemptedPosition , SceneObjectGroup grp , bool silent )
2008-02-11 01:43:54 +00:00
{
2008-05-04 22:55:52 +00:00
if ( grp = = null )
return ;
2008-11-17 15:40:27 +00:00
if ( grp . IsDeleted )
2008-05-04 22:55:52 +00:00
return ;
if ( grp . RootPart . DIE_AT_EDGE )
{
// We remove the object here
try
{
2008-11-07 05:48:44 +00:00
DeleteSceneObject ( grp , false ) ;
2008-05-04 22:55:52 +00:00
}
catch ( Exception )
{
2010-09-06 23:34:06 +00:00
m_log . Warn ( "[SCENE]: exception when trying to remove the prim that crossed the border." ) ;
2008-05-04 22:55:52 +00:00
}
return ;
}
2008-10-14 09:40:05 +00:00
2010-02-14 21:41:57 +00:00
if ( grp . RootPart . RETURN_AT_EDGE )
{
// We remove the object here
try
{
List < SceneObjectGroup > objects = new List < SceneObjectGroup > ( ) ;
objects . Add ( grp ) ;
SceneObjectGroup [ ] objectsArray = objects . ToArray ( ) ;
returnObjects ( objectsArray , UUID . Zero ) ;
}
catch ( Exception )
{
2010-09-06 23:34:06 +00:00
m_log . Warn ( "[SCENE]: exception when trying to return the prim that crossed the border." ) ;
2010-02-14 21:41:57 +00:00
}
return ;
}
2012-05-23 23:31:14 +00:00
if ( EntityTransferModule ! = null )
EntityTransferModule . Cross ( grp , attemptedPosition , silent ) ;
2008-05-01 18:04:42 +00:00
}
2008-06-04 09:59:27 +00:00
2009-08-28 18:45:17 +00:00
public Border GetCrossedBorder ( Vector3 position , Cardinals gridline )
{
2009-08-29 07:36:41 +00:00
if ( BordersLocked )
{
switch ( gridline )
{
case Cardinals . N :
lock ( NorthBorders )
{
foreach ( Border b in NorthBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
}
break ;
case Cardinals . S :
lock ( SouthBorders )
{
foreach ( Border b in SouthBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
}
2009-08-28 18:45:17 +00:00
2009-08-29 07:36:41 +00:00
break ;
case Cardinals . E :
lock ( EastBorders )
{
foreach ( Border b in EastBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
}
break ;
case Cardinals . W :
lock ( WestBorders )
{
foreach ( Border b in WestBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
}
break ;
}
}
else
2009-08-28 18:45:17 +00:00
{
2009-08-29 07:36:41 +00:00
switch ( gridline )
{
case Cardinals . N :
2009-08-28 18:45:17 +00:00
foreach ( Border b in NorthBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
2009-08-29 07:36:41 +00:00
break ;
case Cardinals . S :
2009-08-28 18:45:17 +00:00
foreach ( Border b in SouthBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
2009-08-29 07:36:41 +00:00
break ;
case Cardinals . E :
2009-08-28 18:45:17 +00:00
foreach ( Border b in EastBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
2009-08-29 07:36:41 +00:00
break ;
case Cardinals . W :
2009-08-28 18:45:17 +00:00
foreach ( Border b in WestBorders )
{
if ( b . TestCross ( position ) )
return b ;
}
2009-08-29 07:36:41 +00:00
break ;
2009-08-28 18:45:17 +00:00
2009-08-29 07:36:41 +00:00
}
2009-08-28 18:45:17 +00:00
}
return null ;
}
2009-08-20 23:24:31 +00:00
public bool TestBorderCross ( Vector3 position , Cardinals border )
{
2009-08-29 07:36:41 +00:00
if ( BordersLocked )
2009-08-20 23:24:31 +00:00
{
2009-08-29 07:36:41 +00:00
switch ( border )
{
case Cardinals . N :
lock ( NorthBorders )
{
foreach ( Border b in NorthBorders )
{
if ( b . TestCross ( position ) )
return true ;
}
}
break ;
case Cardinals . E :
lock ( EastBorders )
{
foreach ( Border b in EastBorders )
{
if ( b . TestCross ( position ) )
return true ;
}
}
break ;
case Cardinals . S :
lock ( SouthBorders )
{
foreach ( Border b in SouthBorders )
{
if ( b . TestCross ( position ) )
return true ;
}
}
break ;
case Cardinals . W :
lock ( WestBorders )
{
foreach ( Border b in WestBorders )
{
if ( b . TestCross ( position ) )
return true ;
}
}
break ;
}
}
else
{
switch ( border )
{
case Cardinals . N :
foreach ( Border b in NorthBorders )
2009-08-20 23:24:31 +00:00
{
if ( b . TestCross ( position ) )
return true ;
}
2009-08-29 07:36:41 +00:00
break ;
case Cardinals . E :
2009-08-20 23:24:31 +00:00
foreach ( Border b in EastBorders )
{
if ( b . TestCross ( position ) )
return true ;
}
2009-08-29 07:36:41 +00:00
break ;
case Cardinals . S :
2009-08-20 23:24:31 +00:00
foreach ( Border b in SouthBorders )
{
if ( b . TestCross ( position ) )
return true ;
}
2009-08-29 07:36:41 +00:00
break ;
2009-09-30 16:00:09 +00:00
case Cardinals . W :
2009-08-20 23:24:31 +00:00
foreach ( Border b in WestBorders )
{
if ( b . TestCross ( position ) )
return true ;
2009-09-30 16:00:09 +00:00
}
2009-08-29 07:36:41 +00:00
break ;
}
2009-08-20 23:24:31 +00:00
}
return false ;
}
2010-02-08 19:02:20 +00:00
/// <summary>
2010-06-12 18:11:13 +00:00
/// Called when objects or attachments cross the border, or teleport, between regions.
2010-02-08 19:02:20 +00:00
/// </summary>
/// <param name="sog"></param>
/// <returns></returns>
2012-02-23 01:40:30 +00:00
public bool IncomingCreateObject ( Vector3 newPosition , ISceneObject sog )
2009-02-09 22:27:27 +00:00
{
2011-04-29 03:19:54 +00:00
//m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition,
// ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment);
2009-02-09 22:27:27 +00:00
SceneObjectGroup newObject ;
try
{
newObject = ( SceneObjectGroup ) sog ;
}
catch ( Exception e )
{
2012-07-06 21:33:16 +00:00
m_log . WarnFormat ( "[INTERREGION]: Problem casting object, exception {0}{1}" , e . Message , e . StackTrace ) ;
return false ;
}
// If the user is banned, we won't let any of their objects
// enter. Period.
/ /
if ( RegionInfo . EstateSettings . IsBanned ( newObject . OwnerID ) )
{
m_log . InfoFormat ( "[INTERREGION]: Denied prim crossing for banned avatar {0}" , newObject . OwnerID ) ;
2009-02-09 22:27:27 +00:00
return false ;
}
2012-02-23 01:40:30 +00:00
if ( newPosition ! = Vector3 . Zero )
newObject . RootPart . GroupPosition = newPosition ;
2009-05-29 21:01:18 +00:00
if ( ! AddSceneObject ( newObject ) )
2009-02-09 22:27:27 +00:00
{
2012-07-06 21:33:16 +00:00
m_log . DebugFormat (
"[INTERREGION]: Problem adding scene object {0} in {1} " , newObject . UUID , RegionInfo . RegionName ) ;
2009-02-09 22:27:27 +00:00
return false ;
}
2010-11-26 21:46:48 +00:00
2011-04-30 00:09:48 +00:00
if ( ! newObject . IsAttachment )
{
2012-07-06 21:33:16 +00:00
// FIXME: It would be better to never add the scene object at all rather than add it and then delete
// it
if ( ! Permissions . CanObjectEntry ( newObject . UUID , true , newObject . AbsolutePosition ) )
{
// Deny non attachments based on parcel settings
/ /
m_log . Info ( "[INTERREGION]: Denied prim crossing because of parcel settings" ) ;
DeleteSceneObject ( newObject , false ) ;
return false ;
}
// For attachments, we need to wait until the agent is root
// before we restart the scripts, or else some functions won't work.
2011-04-30 00:09:48 +00:00
newObject . RootPart . ParentGroup . CreateScriptInstances ( 0 , false , DefaultScriptEngine , GetStateSource ( newObject ) ) ;
newObject . ResumeScripts ( ) ;
2013-06-06 02:03:05 +00:00
if ( newObject . RootPart . KeyframeMotion ! = null )
newObject . RootPart . KeyframeMotion . UpdateSceneObject ( newObject ) ;
2011-04-30 00:09:48 +00:00
}
2010-06-06 22:09:22 +00:00
2010-02-08 19:02:20 +00:00
// Do this as late as possible so that listeners have full access to the incoming object
EventManager . TriggerOnIncomingSceneObject ( newObject ) ;
2010-06-12 18:11:13 +00:00
2009-02-09 22:27:27 +00:00
return true ;
}
2009-08-15 04:01:58 +00:00
/// <summary>
/// Adds a Scene Object group to the Scene.
/// Verifies that the creator of the object is not banned from the simulator.
/// Checks if the item is an Attachment
/// </summary>
/// <param name="sceneObject"></param>
/// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2009-05-29 21:01:18 +00:00
public bool AddSceneObject ( SceneObjectGroup sceneObject )
2009-02-09 22:27:27 +00:00
{
// Force allocation of new LocalId
/ /
2010-09-17 00:30:46 +00:00
SceneObjectPart [ ] parts = sceneObject . Parts ;
for ( int i = 0 ; i < parts . Length ; i + + )
parts [ i ] . LocalId = 0 ;
2009-02-09 22:27:27 +00:00
2010-02-08 19:10:54 +00:00
if ( sceneObject . IsAttachmentCheckFull ( ) ) // Attachment
2009-02-09 22:27:27 +00:00
{
2009-10-11 20:46:19 +00:00
sceneObject . RootPart . AddFlag ( PrimFlags . TemporaryOnRez ) ;
sceneObject . RootPart . AddFlag ( PrimFlags . Phantom ) ;
2010-06-08 14:07:57 +00:00
// Don't sent a full update here because this will cause full updates to be sent twice for
2010-09-12 17:43:49 +00:00
// attachments on region crossings, resulting in viewer glitches.
2010-06-08 14:07:57 +00:00
AddRestoredSceneObject ( sceneObject , false , false , false ) ;
2009-02-10 22:54:05 +00:00
2009-10-11 20:46:19 +00:00
// Handle attachment special case
SceneObjectPart RootPrim = sceneObject . RootPart ;
2009-02-10 22:54:05 +00:00
2009-10-11 20:46:19 +00:00
// Fix up attachment Parent Local ID
ScenePresence sp = GetScenePresence ( sceneObject . OwnerID ) ;
2009-05-29 21:12:55 +00:00
2009-10-11 20:46:19 +00:00
if ( sp ! = null )
{
SceneObjectGroup grp = sceneObject ;
2012-05-14 17:48:40 +00:00
// m_log.DebugFormat(
// "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID);
// m_log.DebugFormat(
// "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition);
2010-03-05 23:18:47 +00:00
2010-06-08 14:07:57 +00:00
RootPrim . RemFlag ( PrimFlags . TemporaryOnRez ) ;
2013-03-29 02:21:38 +00:00
// We must currently not resume scripts at this stage since AttachmentsModule does not have the
// information that this is due to a teleport/border cross rather than an ordinary attachment.
// We currently do this in Scene.MakeRootAgent() instead.
2010-03-05 23:18:47 +00:00
if ( AttachmentsModule ! = null )
2013-03-18 22:56:03 +00:00
AttachmentsModule . AttachObject ( sp , grp , 0 , false , false , true ) ;
2009-02-09 22:27:27 +00:00
}
else
{
2009-10-11 20:46:19 +00:00
RootPrim . RemFlag ( PrimFlags . TemporaryOnRez ) ;
RootPrim . AddFlag ( PrimFlags . TemporaryOnRez ) ;
}
}
else
{
AddRestoredSceneObject ( sceneObject , true , false ) ;
2009-02-09 22:27:27 +00:00
}
2009-10-11 20:46:19 +00:00
2009-02-09 22:27:27 +00:00
return true ;
}
2010-06-12 18:11:13 +00:00
2010-11-26 21:46:48 +00:00
private int GetStateSource ( SceneObjectGroup sog )
2010-06-12 18:11:13 +00:00
{
ScenePresence sp = GetScenePresence ( sog . OwnerID ) ;
if ( sp ! = null )
2011-04-30 00:09:48 +00:00
return sp . GetStateSource ( ) ;
2010-06-12 18:11:13 +00:00
2010-11-26 21:46:48 +00:00
return 2 ; // StateSource.PrimCrossing
2010-06-12 18:11:13 +00:00
}
2007-07-16 15:40:11 +00:00
# endregion
#region Add/Remove Avatar Methods
2011-12-08 18:34:23 +00:00
public override ISceneAgent AddNewClient ( IClientAPI client , PresenceType type )
2007-07-16 15:40:11 +00:00
{
2012-10-09 23:26:43 +00:00
ScenePresence sp ;
bool vialogin ;
2011-12-08 19:25:24 +00:00
// Validation occurs in LLUDPServer
2012-10-09 23:26:43 +00:00
/ /
// XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
// each other. In practice, this does not currently occur in the code.
2010-08-20 16:02:05 +00:00
AgentCircuitData aCircuit = m_authenticateHandler . GetAgentCircuitData ( client . CircuitCode ) ;
2012-10-09 23:26:43 +00:00
// We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection
// and a simultaneous one that removes it (as can happen if the client is closed at a particular point
// whilst connecting).
/ /
// It would be easier to lock across all NewUserConnection(), AddNewClient() and
// RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
// response in some module listening to AddNewClient()) from holding up unrelated agent calls.
/ /
// In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
// AddNewClient() operations (though not other ops).
// In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
lock ( aCircuit )
{
vialogin
= ( aCircuit . teleportFlags & ( uint ) Constants . TeleportFlags . ViaHGLogin ) ! = 0
| | ( aCircuit . teleportFlags & ( uint ) Constants . TeleportFlags . ViaLogin ) ! = 0 ;
// CheckHeartbeat();
sp = GetScenePresence ( client . AgentId ) ;
2011-01-27 04:46:31 +00:00
2012-10-09 23:26:43 +00:00
// XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
// could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
// other problems, and possible the code calling AddNewClient() should ensure that no client is already
// connected.
if ( sp = = null )
2009-02-11 21:07:41 +00:00
{
2012-10-09 23:26:43 +00:00
m_log . DebugFormat (
"[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}" ,
client . Name , client . AgentId , RegionInfo . RegionName , client . StartPos ) ;
m_clientManager . Add ( client ) ;
SubscribeToClientEvents ( client ) ;
sp = m_sceneGraph . CreateAndAddChildScenePresence ( client , aCircuit . Appearance , type ) ;
m_eventManager . TriggerOnNewPresence ( sp ) ;
sp . TeleportFlags = ( TPFlags ) aCircuit . teleportFlags ;
2009-08-16 23:17:19 +00:00
}
2012-10-09 23:26:43 +00:00
else
{
m_log . WarnFormat (
"[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence" ,
sp . IsChildAgent ? "child" : "root" , sp . Name , RegionInfo . RegionName ) ;
}
// We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
// client is for a root or child agent.
client . SceneAgent = sp ;
2011-06-07 19:10:57 +00:00
2013-05-29 22:08:54 +00:00
// This is currently also being done earlier in NewUserConnection for real users to see if this
// resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
// places. However, we still need to do it here for NPCs.
2012-10-09 23:26:43 +00:00
CacheUserName ( sp , aCircuit ) ;
EventManager . TriggerOnNewClient ( client ) ;
if ( vialogin )
EventManager . TriggerOnClientLogin ( client ) ;
}
2012-03-29 00:26:30 +00:00
2011-12-08 16:10:47 +00:00
m_LastLogin = Util . EnvironmentTickCount ( ) ;
2011-06-07 19:10:57 +00:00
2011-12-08 18:34:23 +00:00
return sp ;
2007-07-16 15:40:11 +00:00
}
2011-08-18 23:45:22 +00:00
/// <summary>
/// Cache the user name for later use.
/// </summary>
/// <param name="sp"></param>
/// <param name="aCircuit"></param>
private void CacheUserName ( ScenePresence sp , AgentCircuitData aCircuit )
2011-06-07 19:10:57 +00:00
{
2012-06-25 21:48:13 +00:00
if ( UserManagementModule ! = null )
2011-06-07 19:10:57 +00:00
{
string first = aCircuit . firstname , last = aCircuit . lastname ;
2011-06-28 23:28:22 +00:00
2013-05-29 22:08:54 +00:00
if ( sp ! = null & & sp . PresenceType = = PresenceType . Npc )
2011-08-18 23:45:22 +00:00
{
2012-06-25 21:48:13 +00:00
UserManagementModule . AddUser ( aCircuit . AgentID , first , last ) ;
2011-08-18 23:45:22 +00:00
}
else
2011-06-07 19:10:57 +00:00
{
2011-08-18 23:45:22 +00:00
string homeURL = string . Empty ;
if ( aCircuit . ServiceURLs . ContainsKey ( "HomeURI" ) )
homeURL = aCircuit . ServiceURLs [ "HomeURI" ] . ToString ( ) ;
if ( aCircuit . lastname . StartsWith ( "@" ) )
2011-06-07 19:10:57 +00:00
{
2011-08-18 23:45:22 +00:00
string [ ] parts = aCircuit . firstname . Split ( '.' ) ;
if ( parts . Length > = 2 )
{
first = parts [ 0 ] ;
last = parts [ 1 ] ;
}
2011-06-07 19:10:57 +00:00
}
2011-06-28 23:28:22 +00:00
2012-06-25 21:48:13 +00:00
UserManagementModule . AddUser ( aCircuit . AgentID , first , last , homeURL ) ;
2011-08-18 23:45:22 +00:00
}
2011-06-07 19:10:57 +00:00
}
}
2010-05-16 02:25:14 +00:00
private bool VerifyClient ( AgentCircuitData aCircuit , System . Net . IPEndPoint ep , out bool vialogin )
{
vialogin = false ;
// Do the verification here
2010-08-20 02:54:40 +00:00
if ( ( aCircuit . teleportFlags & ( uint ) Constants . TeleportFlags . ViaHGLogin ) ! = 0 )
2010-05-16 02:25:14 +00:00
{
2010-08-20 02:54:40 +00:00
m_log . DebugFormat ( "[SCENE]: Incoming client {0} {1} in region {2} via HG login" , aCircuit . firstname , aCircuit . lastname , RegionInfo . RegionName ) ;
2010-05-16 02:25:14 +00:00
vialogin = true ;
IUserAgentVerificationModule userVerification = RequestModuleInterface < IUserAgentVerificationModule > ( ) ;
if ( userVerification ! = null & & ep ! = null )
{
2010-08-20 02:54:40 +00:00
if ( ! userVerification . VerifyClient ( aCircuit , ep . Address . ToString ( ) ) )
2010-05-16 02:25:14 +00:00
{
// uh-oh, this is fishy
2010-08-13 22:15:11 +00:00
m_log . DebugFormat ( "[SCENE]: User Client Verification for {0} {1} in {2} returned false" , aCircuit . firstname , aCircuit . lastname , RegionInfo . RegionName ) ;
2010-05-16 02:25:14 +00:00
return false ;
}
else
2010-08-13 22:15:11 +00:00
m_log . DebugFormat ( "[SCENE]: User Client Verification for {0} {1} in {2} returned true" , aCircuit . firstname , aCircuit . lastname , RegionInfo . RegionName ) ;
2010-11-25 19:14:16 +00:00
2010-05-16 02:25:14 +00:00
}
}
2010-08-20 02:54:40 +00:00
else if ( ( aCircuit . teleportFlags & ( uint ) Constants . TeleportFlags . ViaLogin ) ! = 0 )
2010-08-20 16:02:05 +00:00
{
m_log . DebugFormat ( "[SCENE]: Incoming client {0} {1} in region {2} via regular login. Client IP verification not performed." ,
2010-08-20 02:54:40 +00:00
aCircuit . firstname , aCircuit . lastname , RegionInfo . RegionName ) ;
2010-08-20 16:02:05 +00:00
vialogin = true ;
}
2010-08-20 02:54:40 +00:00
2010-05-16 02:25:14 +00:00
return true ;
}
// Called by Caps, on the first HTTP contact from the client
public override bool CheckClient ( UUID agentID , System . Net . IPEndPoint ep )
{
AgentCircuitData aCircuit = m_authenticateHandler . GetAgentCircuitData ( agentID ) ;
if ( aCircuit ! = null )
{
bool vialogin = false ;
if ( ! VerifyClient ( aCircuit , ep , out vialogin ) )
{
// if it doesn't pass, we remove the agentcircuitdata altogether
// and the scene presence and the client, if they exist
try
{
2011-01-06 20:47:13 +00:00
// We need to wait for the client to make UDP contact first.
// It's the UDP contact that creates the scene presence
ScenePresence sp = WaitGetScenePresence ( agentID ) ;
2010-05-16 02:25:14 +00:00
if ( sp ! = null )
2011-01-06 20:47:13 +00:00
{
PresenceService . LogoutAgent ( sp . ControllingClient . SessionId ) ;
2010-05-16 02:25:14 +00:00
2011-01-06 20:47:13 +00:00
sp . ControllingClient . Close ( ) ;
}
else
{
m_log . WarnFormat ( "[SCENE]: Could not find scene presence for {0}" , agentID ) ;
}
2010-05-16 02:25:14 +00:00
// BANG! SLASH!
m_authenticateHandler . RemoveCircuit ( agentID ) ;
return false ;
}
catch ( Exception e )
{
2010-08-13 22:15:11 +00:00
m_log . DebugFormat ( "[SCENE]: Exception while closing aborted client: {0}" , e . StackTrace ) ;
2010-05-16 02:25:14 +00:00
}
}
else
return true ;
}
return false ;
}
2009-09-05 00:19:34 +00:00
2009-08-15 04:01:58 +00:00
/// <summary>
/// Register for events from the client
/// </summary>
/// <param name="client">The IClientAPI of the connected client</param>
2009-09-05 00:19:34 +00:00
public virtual void SubscribeToClientEvents ( IClientAPI client )
{
SubscribeToClientTerrainEvents ( client ) ;
SubscribeToClientPrimEvents ( client ) ;
SubscribeToClientPrimRezEvents ( client ) ;
SubscribeToClientInventoryEvents ( client ) ;
SubscribeToClientTeleportEvents ( client ) ;
SubscribeToClientScriptEvents ( client ) ;
SubscribeToClientParcelEvents ( client ) ;
SubscribeToClientGridEvents ( client ) ;
SubscribeToClientNetworkEvents ( client ) ;
}
public virtual void SubscribeToClientTerrainEvents ( IClientAPI client )
2007-07-16 15:40:11 +00:00
{
2007-07-17 17:47:23 +00:00
client . OnRegionHandShakeReply + = SendLayerData ;
2009-09-05 00:19:34 +00:00
}
public virtual void SubscribeToClientPrimEvents ( IClientAPI client )
2010-09-12 17:43:49 +00:00
{
2011-07-19 04:20:04 +00:00
client . OnUpdatePrimGroupPosition + = m_sceneGraph . UpdatePrimGroupPosition ;
2008-11-12 20:16:46 +00:00
client . OnUpdatePrimSinglePosition + = m_sceneGraph . UpdatePrimSinglePosition ;
2011-07-19 02:44:49 +00:00
client . OnUpdatePrimGroupRotation + = m_sceneGraph . UpdatePrimGroupRotation ;
client . OnUpdatePrimGroupMouseRotation + = m_sceneGraph . UpdatePrimGroupRotation ;
2008-11-12 20:16:46 +00:00
client . OnUpdatePrimSingleRotation + = m_sceneGraph . UpdatePrimSingleRotation ;
2009-07-17 14:58:54 +00:00
client . OnUpdatePrimSingleRotationPosition + = m_sceneGraph . UpdatePrimSingleRotationPosition ;
2011-07-19 02:44:49 +00:00
2008-11-12 20:16:46 +00:00
client . OnUpdatePrimScale + = m_sceneGraph . UpdatePrimScale ;
client . OnUpdatePrimGroupScale + = m_sceneGraph . UpdatePrimGroupScale ;
client . OnUpdateExtraParams + = m_sceneGraph . UpdateExtraParam ;
client . OnUpdatePrimShape + = m_sceneGraph . UpdatePrimShape ;
client . OnUpdatePrimTexture + = m_sceneGraph . UpdatePrimTexture ;
2009-08-16 06:06:06 +00:00
client . OnObjectRequest + = RequestPrim ;
2007-07-17 17:47:23 +00:00
client . OnObjectSelect + = SelectPrim ;
client . OnObjectDeselect + = DeselectPrim ;
2008-11-12 20:16:46 +00:00
client . OnGrabUpdate + = m_sceneGraph . MoveObject ;
2009-04-10 06:39:52 +00:00
client . OnSpinStart + = m_sceneGraph . SpinStart ;
client . OnSpinUpdate + = m_sceneGraph . SpinObject ;
2010-10-06 17:59:30 +00:00
client . OnDeRezObject + = DeRezObjects ;
2009-09-05 00:19:34 +00:00
2008-11-12 20:16:46 +00:00
client . OnObjectName + = m_sceneGraph . PrimName ;
client . OnObjectClickAction + = m_sceneGraph . PrimClickAction ;
client . OnObjectMaterial + = m_sceneGraph . PrimMaterial ;
2010-04-30 10:46:50 +00:00
client . OnLinkObjects + = LinkObjects ;
client . OnDelinkObjects + = DelinkObjects ;
2012-02-03 01:41:05 +00:00
client . OnObjectDuplicate + = DuplicateObject ;
2008-05-01 15:17:49 +00:00
client . OnObjectDuplicateOnRay + = doObjectDuplicateOnRay ;
2008-11-12 20:16:46 +00:00
client . OnUpdatePrimFlags + = m_sceneGraph . UpdatePrimFlags ;
2009-05-29 21:12:55 +00:00
client . OnRequestObjectPropertiesFamily + = m_sceneGraph . RequestObjectPropertiesFamily ;
2007-12-05 06:44:32 +00:00
client . OnObjectPermissions + = HandleObjectPermissionsUpdate ;
2009-09-05 00:19:34 +00:00
client . OnGrabObject + = ProcessObjectGrab ;
2010-01-29 23:12:08 +00:00
client . OnGrabUpdate + = ProcessObjectGrabUpdate ;
2009-09-05 00:19:34 +00:00
client . OnDeGrabObject + = ProcessObjectDeGrab ;
client . OnUndo + = m_sceneGraph . HandleUndo ;
2010-02-14 21:41:57 +00:00
client . OnRedo + = m_sceneGraph . HandleRedo ;
2009-09-05 00:19:34 +00:00
client . OnObjectDescription + = m_sceneGraph . PrimDescription ;
client . OnObjectIncludeInSearch + = m_sceneGraph . MakeObjectSearchable ;
client . OnObjectOwner + = ObjectOwner ;
2011-12-19 23:03:45 +00:00
client . OnObjectGroupRequest + = HandleObjectGroupUpdate ;
2009-09-05 00:19:34 +00:00
}
public virtual void SubscribeToClientPrimRezEvents ( IClientAPI client )
{
client . OnAddPrim + = AddNewPrim ;
client . OnRezObject + = RezObject ;
}
2009-08-12 20:11:15 +00:00
2009-09-05 00:19:34 +00:00
public virtual void SubscribeToClientInventoryEvents ( IClientAPI client )
{
2010-04-13 00:10:51 +00:00
client . OnLinkInventoryItem + = HandleLinkInventoryItem ;
2008-12-10 19:12:59 +00:00
client . OnCreateNewInventoryFolder + = HandleCreateInventoryFolder ;
client . OnUpdateInventoryFolder + = HandleUpdateInventoryFolder ;
2009-08-12 20:11:15 +00:00
client . OnMoveInventoryFolder + = HandleMoveInventoryFolder ; // 2; //!!
2008-12-10 19:12:59 +00:00
client . OnFetchInventoryDescendents + = HandleFetchInventoryDescendents ;
2009-08-12 20:11:15 +00:00
client . OnPurgeInventoryDescendents + = HandlePurgeInventoryDescendents ; // 2; //!!
2011-07-01 20:25:40 +00:00
client . OnFetchInventory + = m_asyncInventorySender . HandleFetchInventory ;
2007-12-03 20:06:01 +00:00
client . OnUpdateInventoryItem + = UpdateInventoryItemAsset ;
2007-11-18 13:50:46 +00:00
client . OnCopyInventoryItem + = CopyInventoryItem ;
2007-12-08 19:13:10 +00:00
client . OnMoveInventoryItem + = MoveInventoryItem ;
2008-02-18 03:25:14 +00:00
client . OnRemoveInventoryItem + = RemoveInventoryItem ;
client . OnRemoveInventoryFolder + = RemoveInventoryFolder ;
2007-08-21 21:03:18 +00:00
client . OnRezScript + = RezScript ;
2007-12-27 21:41:48 +00:00
client . OnRequestTaskInventory + = RequestTaskInventory ;
2007-08-22 18:36:47 +00:00
client . OnRemoveTaskItem + = RemoveTaskInventory ;
2007-12-22 02:52:35 +00:00
client . OnUpdateTaskInventory + = UpdateTaskInventory ;
2008-06-24 23:55:33 +00:00
client . OnMoveTaskItem + = ClientMoveTaskInventoryItem ;
2009-09-05 00:19:34 +00:00
}
2009-08-12 20:11:15 +00:00
2009-09-05 00:19:34 +00:00
public virtual void SubscribeToClientTeleportEvents ( IClientAPI client )
{
client . OnTeleportLocationRequest + = RequestTeleportLocation ;
}
public virtual void SubscribeToClientScriptEvents ( IClientAPI client )
{
2008-05-26 16:16:48 +00:00
client . OnScriptReset + = ProcessScriptReset ;
2008-06-28 16:08:12 +00:00
client . OnGetScriptRunning + = GetScriptRunning ;
client . OnSetScriptRunning + = SetScriptRunning ;
2009-09-05 00:19:34 +00:00
}
public virtual void SubscribeToClientParcelEvents ( IClientAPI client )
{
client . OnParcelReturnObjectsRequest + = LandChannel . ReturnObjectsInParcel ;
client . OnParcelSetOtherCleanTime + = LandChannel . SetParcelOtherCleanTime ;
client . OnParcelBuy + = ProcessParcelBuy ;
}
public virtual void SubscribeToClientGridEvents ( IClientAPI client )
{
2010-11-21 21:16:52 +00:00
//client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
2009-09-05 00:19:34 +00:00
client . OnMoneyTransferRequest + = ProcessMoneyTransferRequest ;
}
2010-07-30 20:58:24 +00:00
2009-09-05 00:19:34 +00:00
public virtual void SubscribeToClientNetworkEvents ( IClientAPI client )
{
2009-04-03 17:14:51 +00:00
client . OnNetworkStatsUpdate + = StatsReporter . AddPacketsStats ;
2009-10-13 19:50:59 +00:00
client . OnViewerEffect + = ProcessViewerEffect ;
2009-09-05 00:19:34 +00:00
}
/// <summary>
2010-07-30 20:41:44 +00:00
/// Unsubscribe the client from events.
2009-09-05 00:19:34 +00:00
/// </summary>
2010-07-30 20:58:24 +00:00
/// FIXME: Not called anywhere!
2010-07-30 20:41:44 +00:00
/// <param name="client">The IClientAPI of the client</param>
2009-09-05 00:19:34 +00:00
public virtual void UnSubscribeToClientEvents ( IClientAPI client )
{
UnSubscribeToClientTerrainEvents ( client ) ;
UnSubscribeToClientPrimEvents ( client ) ;
UnSubscribeToClientPrimRezEvents ( client ) ;
UnSubscribeToClientInventoryEvents ( client ) ;
UnSubscribeToClientTeleportEvents ( client ) ;
UnSubscribeToClientScriptEvents ( client ) ;
UnSubscribeToClientParcelEvents ( client ) ;
UnSubscribeToClientGridEvents ( client ) ;
UnSubscribeToClientNetworkEvents ( client ) ;
2007-07-16 15:40:11 +00:00
}
2008-05-16 13:33:57 +00:00
2009-09-05 00:19:34 +00:00
public virtual void UnSubscribeToClientTerrainEvents ( IClientAPI client )
{
client . OnRegionHandShakeReply - = SendLayerData ;
}
public virtual void UnSubscribeToClientPrimEvents ( IClientAPI client )
{
2011-07-19 04:20:04 +00:00
client . OnUpdatePrimGroupPosition - = m_sceneGraph . UpdatePrimGroupPosition ;
2009-09-05 00:19:34 +00:00
client . OnUpdatePrimSinglePosition - = m_sceneGraph . UpdatePrimSinglePosition ;
2011-07-19 02:44:49 +00:00
client . OnUpdatePrimGroupRotation - = m_sceneGraph . UpdatePrimGroupRotation ;
client . OnUpdatePrimGroupMouseRotation - = m_sceneGraph . UpdatePrimGroupRotation ;
2009-09-05 00:19:34 +00:00
client . OnUpdatePrimSingleRotation - = m_sceneGraph . UpdatePrimSingleRotation ;
client . OnUpdatePrimSingleRotationPosition - = m_sceneGraph . UpdatePrimSingleRotationPosition ;
2011-07-19 02:44:49 +00:00
2009-09-05 00:19:34 +00:00
client . OnUpdatePrimScale - = m_sceneGraph . UpdatePrimScale ;
client . OnUpdatePrimGroupScale - = m_sceneGraph . UpdatePrimGroupScale ;
client . OnUpdateExtraParams - = m_sceneGraph . UpdateExtraParam ;
client . OnUpdatePrimShape - = m_sceneGraph . UpdatePrimShape ;
client . OnUpdatePrimTexture - = m_sceneGraph . UpdatePrimTexture ;
client . OnObjectRequest - = RequestPrim ;
client . OnObjectSelect - = SelectPrim ;
client . OnObjectDeselect - = DeselectPrim ;
client . OnGrabUpdate - = m_sceneGraph . MoveObject ;
client . OnSpinStart - = m_sceneGraph . SpinStart ;
client . OnSpinUpdate - = m_sceneGraph . SpinObject ;
2010-10-06 17:59:30 +00:00
client . OnDeRezObject - = DeRezObjects ;
2009-09-05 00:19:34 +00:00
client . OnObjectName - = m_sceneGraph . PrimName ;
client . OnObjectClickAction - = m_sceneGraph . PrimClickAction ;
client . OnObjectMaterial - = m_sceneGraph . PrimMaterial ;
2010-04-30 10:46:50 +00:00
client . OnLinkObjects - = LinkObjects ;
client . OnDelinkObjects - = DelinkObjects ;
2012-02-03 01:41:05 +00:00
client . OnObjectDuplicate - = DuplicateObject ;
2009-09-05 00:19:34 +00:00
client . OnObjectDuplicateOnRay - = doObjectDuplicateOnRay ;
client . OnUpdatePrimFlags - = m_sceneGraph . UpdatePrimFlags ;
client . OnRequestObjectPropertiesFamily - = m_sceneGraph . RequestObjectPropertiesFamily ;
client . OnObjectPermissions - = HandleObjectPermissionsUpdate ;
client . OnGrabObject - = ProcessObjectGrab ;
client . OnDeGrabObject - = ProcessObjectDeGrab ;
client . OnUndo - = m_sceneGraph . HandleUndo ;
2010-02-14 21:41:57 +00:00
client . OnRedo - = m_sceneGraph . HandleRedo ;
2009-09-05 00:19:34 +00:00
client . OnObjectDescription - = m_sceneGraph . PrimDescription ;
client . OnObjectIncludeInSearch - = m_sceneGraph . MakeObjectSearchable ;
client . OnObjectOwner - = ObjectOwner ;
}
public virtual void UnSubscribeToClientPrimRezEvents ( IClientAPI client )
{
client . OnAddPrim - = AddNewPrim ;
client . OnRezObject - = RezObject ;
}
public virtual void UnSubscribeToClientInventoryEvents ( IClientAPI client )
{
client . OnCreateNewInventoryFolder - = HandleCreateInventoryFolder ;
client . OnUpdateInventoryFolder - = HandleUpdateInventoryFolder ;
client . OnMoveInventoryFolder - = HandleMoveInventoryFolder ; // 2; //!!
client . OnFetchInventoryDescendents - = HandleFetchInventoryDescendents ;
client . OnPurgeInventoryDescendents - = HandlePurgeInventoryDescendents ; // 2; //!!
2011-07-01 20:37:03 +00:00
client . OnFetchInventory - = m_asyncInventorySender . HandleFetchInventory ;
2009-09-05 00:19:34 +00:00
client . OnUpdateInventoryItem - = UpdateInventoryItemAsset ;
client . OnCopyInventoryItem - = CopyInventoryItem ;
client . OnMoveInventoryItem - = MoveInventoryItem ;
client . OnRemoveInventoryItem - = RemoveInventoryItem ;
client . OnRemoveInventoryFolder - = RemoveInventoryFolder ;
client . OnRezScript - = RezScript ;
client . OnRequestTaskInventory - = RequestTaskInventory ;
client . OnRemoveTaskItem - = RemoveTaskInventory ;
client . OnUpdateTaskInventory - = UpdateTaskInventory ;
client . OnMoveTaskItem - = ClientMoveTaskInventoryItem ;
}
public virtual void UnSubscribeToClientTeleportEvents ( IClientAPI client )
{
client . OnTeleportLocationRequest - = RequestTeleportLocation ;
2011-06-03 17:26:58 +00:00
//client.OnTeleportLandmarkRequest -= RequestTeleportLandmark;
2010-01-18 17:14:19 +00:00
//client.OnTeleportHomeRequest -= TeleportClientHome;
2009-09-05 00:19:34 +00:00
}
public virtual void UnSubscribeToClientScriptEvents ( IClientAPI client )
{
client . OnScriptReset - = ProcessScriptReset ;
client . OnGetScriptRunning - = GetScriptRunning ;
client . OnSetScriptRunning - = SetScriptRunning ;
}
public virtual void UnSubscribeToClientParcelEvents ( IClientAPI client )
{
client . OnParcelReturnObjectsRequest - = LandChannel . ReturnObjectsInParcel ;
client . OnParcelSetOtherCleanTime - = LandChannel . SetParcelOtherCleanTime ;
client . OnParcelBuy - = ProcessParcelBuy ;
}
public virtual void UnSubscribeToClientGridEvents ( IClientAPI client )
{
2010-11-21 21:16:52 +00:00
//client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
2009-09-05 00:19:34 +00:00
client . OnMoneyTransferRequest - = ProcessMoneyTransferRequest ;
}
public virtual void UnSubscribeToClientNetworkEvents ( IClientAPI client )
{
client . OnNetworkStatsUpdate - = StatsReporter . AddPacketsStats ;
2009-10-13 19:50:59 +00:00
client . OnViewerEffect - = ProcessViewerEffect ;
2009-09-05 00:19:34 +00:00
}
2008-10-04 18:46:34 +00:00
/// <summary>
/// Teleport an avatar to their home region
/// </summary>
2009-08-15 04:01:58 +00:00
/// <param name="agentId">The avatar's Unique ID</param>
/// <param name="client">The IClientAPI for the client</param>
2013-05-06 23:31:11 +00:00
public virtual bool TeleportClientHome ( UUID agentId , IClientAPI client )
2008-04-17 05:07:14 +00:00
{
2012-05-23 23:31:14 +00:00
if ( EntityTransferModule ! = null )
{
2013-05-06 23:31:11 +00:00
return EntityTransferModule . TeleportHome ( agentId , client ) ;
2012-05-23 23:31:14 +00:00
}
2010-01-18 17:14:19 +00:00
else
2008-04-17 05:07:14 +00:00
{
2010-01-18 17:14:19 +00:00
m_log . DebugFormat ( "[SCENE]: Unable to teleport user home: no AgentTransferModule is active" ) ;
client . SendTeleportFailed ( "Unable to perform teleports on this simulator." ) ;
2008-04-17 05:07:14 +00:00
}
2013-05-06 23:31:11 +00:00
return false ;
2008-05-01 18:04:42 +00:00
}
2008-05-16 01:22:11 +00:00
2012-02-03 01:41:05 +00:00
/// <summary>
/// Duplicates object specified by localID. This is the event handler for IClientAPI.
/// </summary>
/// <param name="originalPrim">ID of object to duplicate</param>
/// <param name="offset"></param>
/// <param name="flags"></param>
/// <param name="AgentID">Agent doing the duplication</param>
/// <param name="GroupID">Group of new object</param>
public void DuplicateObject ( uint originalPrim , Vector3 offset , uint flags , UUID AgentID , UUID GroupID )
{
SceneObjectGroup copy = SceneGraph . DuplicateObject ( originalPrim , offset , flags , AgentID , GroupID , Quaternion . Identity ) ;
if ( copy ! = null )
EventManager . TriggerObjectAddedToScene ( copy ) ;
}
2009-08-15 04:01:58 +00:00
/// <summary>
/// Duplicates object specified by localID at position raycasted against RayTargetObject using
/// RayEnd and RayStart to determine what the angle of the ray is
/// </summary>
/// <param name="localID">ID of object to duplicate</param>
/// <param name="dupeFlags"></param>
/// <param name="AgentID">Agent doing the duplication</param>
/// <param name="GroupID">Group of new object</param>
/// <param name="RayTargetObj">The target of the Ray</param>
/// <param name="RayEnd">The ending of the ray (farthest away point)</param>
/// <param name="RayStart">The Beginning of the ray (closest point)</param>
/// <param name="BypassRaycast">Bool to bypass raycasting</param>
/// <param name="RayEndIsIntersection">The End specified is the place to add the object</param>
/// <param name="CopyCenters">Position the object at the center of the face that it's colliding with</param>
/// <param name="CopyRotates">Rotate the object the same as the localID object</param>
2008-09-06 07:52:41 +00:00
public void doObjectDuplicateOnRay ( uint localID , uint dupeFlags , UUID AgentID , UUID GroupID ,
UUID RayTargetObj , Vector3 RayEnd , Vector3 RayStart ,
2008-06-13 00:21:53 +00:00
bool BypassRaycast , bool RayEndIsIntersection , bool CopyCenters , bool CopyRotates )
2008-05-16 01:22:11 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 pos ;
2008-05-02 18:36:41 +00:00
const bool frontFacesOnly = true ;
2008-06-10 00:18:00 +00:00
//m_log.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString());
2008-05-01 15:17:49 +00:00
SceneObjectPart target = GetSceneObjectPart ( localID ) ;
2008-05-02 02:31:22 +00:00
SceneObjectPart target2 = GetSceneObjectPart ( RayTargetObj ) ;
2008-05-01 15:17:49 +00:00
2008-05-02 02:31:22 +00:00
if ( target ! = null & & target2 ! = null )
2008-05-01 15:17:49 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 direction = Vector3 . Normalize ( RayEnd - RayStart ) ;
2008-05-01 15:17:49 +00:00
Vector3 AXOrigin = new Vector3 ( RayStart . X , RayStart . Y , RayStart . Z ) ;
2008-05-16 01:22:11 +00:00
Vector3 AXdirection = new Vector3 ( direction . X , direction . Y , direction . Z ) ;
2011-09-01 00:22:28 +00:00
pos = target2 . AbsolutePosition ;
//m_log.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());
// TODO: Raytrace better here
//EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
Ray NewRay = new Ray ( AXOrigin , AXdirection ) ;
// Ray Trace against target here
EntityIntersection ei = target2 . TestIntersectionOBB ( NewRay , Quaternion . Identity , frontFacesOnly , CopyCenters ) ;
// Un-comment out the following line to Get Raytrace results printed to the console.
//m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
float ScaleOffset = 0.5f ;
// If we hit something
if ( ei . HitTF )
{
Vector3 scale = target . Scale ;
Vector3 scaleComponent = new Vector3 ( ei . AAfaceNormal . X , ei . AAfaceNormal . Y , ei . AAfaceNormal . Z ) ;
if ( scaleComponent . X ! = 0 ) ScaleOffset = scale . X ;
if ( scaleComponent . Y ! = 0 ) ScaleOffset = scale . Y ;
if ( scaleComponent . Z ! = 0 ) ScaleOffset = scale . Z ;
ScaleOffset = Math . Abs ( ScaleOffset ) ;
Vector3 intersectionpoint = new Vector3 ( ei . ipoint . X , ei . ipoint . Y , ei . ipoint . Z ) ;
Vector3 normal = new Vector3 ( ei . normal . X , ei . normal . Y , ei . normal . Z ) ;
Vector3 offset = normal * ( ScaleOffset / 2f ) ;
pos = intersectionpoint + offset ;
// stick in offset format from the original prim
pos = pos - target . ParentGroup . AbsolutePosition ;
2012-02-03 01:41:05 +00:00
SceneObjectGroup copy ;
2011-09-01 00:22:28 +00:00
if ( CopyRotates )
2008-05-02 02:31:22 +00:00
{
2011-09-01 00:22:28 +00:00
Quaternion worldRot = target2 . GetWorldRotation ( ) ;
2008-05-16 01:22:11 +00:00
2011-09-01 00:22:28 +00:00
// SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
2012-02-03 01:41:05 +00:00
copy = m_sceneGraph . DuplicateObject ( localID , pos , target . GetEffectiveObjectFlags ( ) , AgentID , GroupID , worldRot ) ;
2011-09-01 00:22:28 +00:00
//obj.Rotation = worldRot;
//obj.UpdateGroupRotationR(worldRot);
}
else
{
2012-02-03 01:41:05 +00:00
copy = m_sceneGraph . DuplicateObject ( localID , pos , target . GetEffectiveObjectFlags ( ) , AgentID , GroupID , Quaternion . Identity ) ;
2008-05-01 15:17:49 +00:00
}
2012-02-03 01:41:05 +00:00
if ( copy ! = null )
EventManager . TriggerObjectAddedToScene ( copy ) ;
2008-05-01 15:17:49 +00:00
}
}
2008-05-01 18:04:42 +00:00
}
2008-05-16 13:33:57 +00:00
2008-06-19 17:03:59 +00:00
/// <summary>
/// Get the avatar apperance for the given client.
/// </summary>
/// <param name="client"></param>
/// <param name="appearance"></param>
2008-05-19 20:33:54 +00:00
public void GetAvatarAppearance ( IClientAPI client , out AvatarAppearance appearance )
2008-05-19 19:08:59 +00:00
{
2009-02-17 00:35:52 +00:00
AgentCircuitData aCircuit = m_authenticateHandler . GetAgentCircuitData ( client . CircuitCode ) ;
2009-02-22 12:39:46 +00:00
2009-02-23 10:36:16 +00:00
if ( aCircuit = = null )
2009-02-22 12:39:46 +00:00
{
m_log . DebugFormat ( "[APPEARANCE] Client did not supply a circuit. Non-Linden? Creating default appearance." ) ;
2011-08-01 23:13:04 +00:00
appearance = new AvatarAppearance ( ) ;
2009-02-22 12:39:46 +00:00
return ;
}
2009-02-17 00:35:52 +00:00
appearance = aCircuit . Appearance ;
if ( appearance = = null )
2008-06-19 17:03:59 +00:00
{
2009-02-17 00:35:52 +00:00
m_log . DebugFormat ( "[APPEARANCE]: Appearance not found in {0}, returning default" , RegionInfo . RegionName ) ;
2011-08-01 23:13:04 +00:00
appearance = new AvatarAppearance ( ) ;
2008-08-18 00:39:10 +00:00
}
2008-05-19 19:08:59 +00:00
}
2007-12-01 14:20:37 +00:00
2011-08-09 23:59:31 +00:00
public override void RemoveClient ( UUID agentID , bool closeChildAgents )
2007-07-16 15:40:11 +00:00
{
2012-03-23 01:03:10 +00:00
// CheckHeartbeat();
2012-02-01 10:05:04 +00:00
bool isChildAgent = false ;
2012-10-09 23:26:43 +00:00
AgentCircuitData acd ;
2012-06-08 00:24:44 +00:00
2012-10-09 23:26:43 +00:00
lock ( m_removeClientLock )
2012-06-08 00:24:44 +00:00
{
2012-10-09 23:26:43 +00:00
acd = m_authenticateHandler . GetAgentCircuitData ( agentID ) ;
2012-06-08 00:24:44 +00:00
2012-10-09 23:26:43 +00:00
if ( acd = = null )
2012-06-07 23:18:25 +00:00
{
2012-10-09 23:26:43 +00:00
m_log . ErrorFormat ( "[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient" , agentID ) ;
return ;
2012-06-07 23:18:25 +00:00
}
2012-10-09 23:26:43 +00:00
else
2008-12-15 20:45:40 +00:00
{
2012-10-29 23:22:40 +00:00
// We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
2012-10-09 23:26:43 +00:00
// simultaneously.
2012-10-29 23:22:40 +00:00
// We also need to remove by agent ID since NPCs will have no circuit code.
m_authenticateHandler . RemoveCircuit ( agentID ) ;
2008-12-15 20:45:40 +00:00
}
2012-10-09 23:26:43 +00:00
}
2008-12-14 02:17:12 +00:00
2012-10-09 23:26:43 +00:00
lock ( acd )
{
ScenePresence avatar = GetScenePresence ( agentID ) ;
if ( avatar = = null )
2009-05-29 21:12:55 +00:00
{
2012-10-09 23:26:43 +00:00
m_log . WarnFormat (
"[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene." , agentID ) ;
return ;
2007-12-12 18:03:37 +00:00
}
2012-10-09 23:26:43 +00:00
try
2011-12-07 18:43:48 +00:00
{
2012-10-09 23:26:43 +00:00
isChildAgent = avatar . IsChildAgent ;
m_log . DebugFormat (
"[SCENE]: Removing {0} agent {1} {2} from {3}" ,
( isChildAgent ? "child" : "root" ) , avatar . Name , agentID , RegionInfo . RegionName ) ;
// Don't do this to root agents, it's not nice for the viewer
if ( closeChildAgents & & isChildAgent )
{
// Tell a single agent to disconnect from the region.
IEventQueue eq = RequestModuleInterface < IEventQueue > ( ) ;
if ( eq ! = null )
{
eq . DisableSimulator ( RegionInfo . RegionHandle , avatar . UUID ) ;
}
else
{
avatar . ControllingClient . SendShutdownConnectionNotice ( ) ;
}
}
// Only applies to root agents.
if ( avatar . ParentID ! = 0 )
2012-02-01 09:36:14 +00:00
{
2012-10-09 23:26:43 +00:00
avatar . StandUp ( ) ;
2012-06-07 22:35:21 +00:00
}
2012-10-09 23:26:43 +00:00
m_sceneGraph . removeUserCount ( ! isChildAgent ) ;
// TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
// unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
if ( closeChildAgents & & CapsModule ! = null )
CapsModule . RemoveCaps ( agentID ) ;
if ( closeChildAgents & & ! isChildAgent )
{
List < ulong > regions = avatar . KnownRegionHandles ;
regions . Remove ( RegionInfo . RegionHandle ) ;
2013-05-16 15:37:21 +00:00
2013-05-16 16:12:02 +00:00
// This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
2013-07-14 14:28:40 +00:00
m_sceneGridService . SendCloseChildAgentConnections ( agentID , acd . SessionID . ToString ( ) , regions ) ;
2012-10-09 23:26:43 +00:00
}
m_eventManager . TriggerClientClosed ( agentID , this ) ;
m_eventManager . TriggerOnRemovePresence ( agentID ) ;
if ( ! isChildAgent )
{
if ( AttachmentsModule ! = null )
2012-06-08 00:24:44 +00:00
{
2012-10-09 23:26:43 +00:00
AttachmentsModule . DeRezAttachments ( avatar ) ;
}
2012-06-08 00:24:44 +00:00
2012-10-09 23:26:43 +00:00
ForEachClient (
delegate ( IClientAPI client )
{
//We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
2013-05-09 17:12:17 +00:00
try { client . SendKillObject ( new List < uint > { avatar . LocalId } ) ; }
2012-10-09 23:26:43 +00:00
catch ( NullReferenceException ) { }
} ) ;
}
2012-07-17 23:14:02 +00:00
2012-10-09 23:26:43 +00:00
// It's possible for child agents to have transactions if changes are being made cross-border.
if ( AgentTransactionsModule ! = null )
AgentTransactionsModule . RemoveAgentAssetTransactions ( agentID ) ;
2012-07-17 23:14:02 +00:00
}
catch ( Exception e )
{
m_log . Error (
2012-10-09 23:26:43 +00:00
string . Format ( "[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception " , avatar . Name , Name ) , e ) ;
}
finally
{
try
{
// Always clean these structures up so that any failure above doesn't cause them to remain in the
// scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
// the same cleanup exception continually.
m_sceneGraph . RemoveScenePresence ( agentID ) ;
m_clientManager . Remove ( agentID ) ;
avatar . Close ( ) ;
}
catch ( Exception e )
{
m_log . Error (
string . Format ( "[SCENE]: Exception in final clean up of {0} in {1}. Exception " , avatar . Name , Name ) , e ) ;
}
2012-07-17 23:14:02 +00:00
}
2012-06-08 00:24:44 +00:00
}
//m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
//m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
2007-07-16 15:40:11 +00:00
}
2008-03-31 18:41:24 +00:00
2009-08-15 01:37:25 +00:00
/// <summary>
/// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry.
///
/// </summary>
/// <param name="avatarID"></param>
/// <param name="regionslst"></param>
2008-09-06 07:52:41 +00:00
public void HandleRemoveKnownRegionsFromAvatar ( UUID avatarID , List < ulong > regionslst )
2008-02-20 01:17:21 +00:00
{
ScenePresence av = GetScenePresence ( avatarID ) ;
if ( av ! = null )
{
lock ( av )
{
for ( int i = 0 ; i < regionslst . Count ; i + + )
{
2011-10-07 05:47:33 +00:00
av . RemoveNeighbourRegion ( regionslst [ i ] ) ;
2008-02-20 01:17:21 +00:00
}
}
}
}
2007-12-27 21:41:48 +00:00
2007-07-17 17:47:23 +00:00
# endregion
2007-07-16 15:40:11 +00:00
2007-11-03 19:14:22 +00:00
#region Entities
2007-12-27 21:41:48 +00:00
2011-11-06 20:38:07 +00:00
public void SendKillObject ( List < uint > localIDs )
2007-08-21 18:11:45 +00:00
{
2011-11-06 20:38:07 +00:00
List < uint > deleteIDs = new List < uint > ( ) ;
2011-11-06 16:43:39 +00:00
2011-11-06 20:38:07 +00:00
foreach ( uint localID in localIDs )
2008-09-03 19:28:46 +00:00
{
2011-11-06 20:38:07 +00:00
SceneObjectPart part = GetSceneObjectPart ( localID ) ;
if ( part ! = null ) // It is a prim
2008-09-03 19:28:46 +00:00
{
2011-11-06 20:38:07 +00:00
if ( part . ParentGroup ! = null & & ! part . ParentGroup . IsDeleted ) // Valid
{
if ( part . ParentGroup . RootPart ! = part ) // Child part
continue ;
}
2008-09-03 19:28:46 +00:00
}
2011-11-06 20:38:07 +00:00
deleteIDs . Add ( localID ) ;
2008-09-03 19:28:46 +00:00
}
2013-05-09 17:12:17 +00:00
ForEachClient ( c = > c . SendKillObject ( deleteIDs ) ) ;
2007-08-21 18:11:45 +00:00
}
2007-11-03 19:14:22 +00:00
# endregion
2007-07-16 15:40:11 +00:00
2007-11-03 19:14:22 +00:00
#region RegionComms
2007-07-16 15:40:11 +00:00
/// <summary>
2008-09-07 03:22:33 +00:00
/// Do the work necessary to initiate a new user connection for a particular scene.
2007-07-16 15:40:11 +00:00
/// </summary>
2009-08-15 01:37:25 +00:00
/// <param name="agent">CircuitData of the agent who is connecting</param>
2012-10-09 21:19:47 +00:00
/// <param name="teleportFlags"></param>
2009-08-15 01:37:25 +00:00
/// <param name="reason">Outputs the reason for the false response on this string</param>
/// <returns>True if the region accepts this agent. False if it does not. False will
/// also return a reason.</returns>
2009-12-29 18:35:06 +00:00
public bool NewUserConnection ( AgentCircuitData agent , uint teleportFlags , out string reason )
2010-10-27 04:19:33 +00:00
{
return NewUserConnection ( agent , teleportFlags , out reason , true ) ;
}
/// <summary>
/// Do the work necessary to initiate a new user connection for a particular scene.
2012-10-09 21:19:47 +00:00
/// </summary>
/// <remarks>
/// The return bool should allow for connections to be refused, but as not all calling paths
/// take proper notice of it yet, we still allowed banned users in.
///
/// At the moment this method consists of setting up the caps infrastructure
2010-10-27 04:19:33 +00:00
/// The return bool should allow for connections to be refused, but as not all calling paths
/// take proper notice of it let, we allowed banned users in still.
2012-10-09 21:19:47 +00:00
///
/// This method is called by the login service (in the case of login) or another simulator (in the case of region
/// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection
/// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
/// the LLUDP stack).
/// </remarks>
2010-10-27 04:19:33 +00:00
/// <param name="agent">CircuitData of the agent who is connecting</param>
/// <param name="reason">Outputs the reason for the false response on this string</param>
/// <param name="requirePresenceLookup">True for normal presence. False for NPC
/// or other applications where a full grid/Hypergrid presence may not be required.</param>
/// <returns>True if the region accepts this agent. False if it does not. False will
/// also return a reason.</returns>
public bool NewUserConnection ( AgentCircuitData agent , uint teleportFlags , out string reason , bool requirePresenceLookup )
2007-07-16 15:40:11 +00:00
{
2012-02-19 17:09:57 +00:00
bool vialogin = ( ( teleportFlags & ( uint ) TPFlags . ViaLogin ) ! = 0 | |
2012-05-13 21:11:44 +00:00
( teleportFlags & ( uint ) TPFlags . ViaHGLogin ) ! = 0 ) ;
2012-02-19 17:09:57 +00:00
bool viahome = ( ( teleportFlags & ( uint ) TPFlags . ViaHome ) ! = 0 ) ;
bool godlike = ( ( teleportFlags & ( uint ) TPFlags . Godlike ) ! = 0 ) ;
2012-02-18 05:32:09 +00:00
2010-06-12 18:11:13 +00:00
reason = String . Empty ;
2009-12-29 18:35:06 +00:00
//Teleport flags:
/ /
// TeleportFlags.ViaGodlikeLure - Border Crossing
// TeleportFlags.ViaLogin - Login
// TeleportFlags.TeleportFlags.ViaLure - Teleport request sent by another user
// TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport
2009-05-06 20:02:49 +00:00
// Don't disable this log message - it's too helpful
2011-02-25 02:15:06 +00:00
m_log . DebugFormat (
2012-02-19 17:09:57 +00:00
"[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})" ,
2012-05-13 21:11:44 +00:00
RegionInfo . RegionName ,
( agent . child ? "child" : "root" ) ,
agent . firstname ,
agent . lastname ,
agent . AgentID ,
agent . circuitcode ,
agent . IPAddress ,
agent . Viewer ,
( ( TPFlags ) teleportFlags ) . ToString ( ) ,
agent . startpos
) ;
2008-12-14 02:17:12 +00:00
2012-07-18 23:09:22 +00:00
if ( ! LoginsEnabled )
2010-06-11 01:26:04 +00:00
{
2010-06-12 18:11:13 +00:00
reason = "Logins Disabled" ;
2009-05-06 20:02:49 +00:00
return false ;
2010-06-11 01:26:04 +00:00
}
2009-05-05 16:17:52 +00:00
2012-07-02 17:12:10 +00:00
//Check if the viewer is banned or in the viewer access list
//We check if the substring is listed for higher flexebility
bool ViewerDenied = true ;
//Check if the specific viewer is listed in the allowed viewer list
if ( m_AllowedViewers . Count > 0 )
{
foreach ( string viewer in m_AllowedViewers )
{
if ( viewer = = agent . Viewer . Substring ( 0 , viewer . Length ) . Trim ( ) . ToLower ( ) )
{
ViewerDenied = false ;
break ;
}
}
}
else
{
ViewerDenied = false ;
}
//Check if the viewer is in the banned list
2012-07-03 22:26:02 +00:00
if ( m_BannedViewers . Count > 0 )
2012-07-02 17:12:10 +00:00
{
2012-07-03 22:26:02 +00:00
foreach ( string viewer in m_BannedViewers )
2012-07-02 17:12:10 +00:00
{
if ( viewer = = agent . Viewer . Substring ( 0 , viewer . Length ) . Trim ( ) . ToLower ( ) )
{
ViewerDenied = true ;
break ;
}
}
}
if ( ViewerDenied )
{
m_log . DebugFormat (
"[SCENE]: Access denied for {0} {1} using {2}" ,
agent . firstname , agent . lastname , agent . Viewer ) ;
reason = "Access denied, your viewer is banned by the region owner" ;
return false ;
2010-06-11 01:26:04 +00:00
}
2009-05-05 16:17:52 +00:00
2012-10-09 23:26:43 +00:00
ILandObject land ;
2010-03-08 07:19:45 +00:00
2012-10-09 23:26:43 +00:00
lock ( agent )
2010-03-08 07:19:45 +00:00
{
2012-10-09 23:26:43 +00:00
ScenePresence sp = GetScenePresence ( agent . AgentID ) ;
if ( sp ! = null & & ! sp . IsChildAgent )
2010-03-08 07:19:45 +00:00
{
2012-10-09 23:26:43 +00:00
// We have a zombie from a crashed session.
// Or the same user is trying to be root twice here, won't work.
// Kill it.
m_log . WarnFormat (
"[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence." ,
sp . Name , sp . UUID , RegionInfo . RegionName ) ;
2013-07-09 21:12:52 +00:00
if ( sp . ControllingClient ! = null )
sp . ControllingClient . Close ( true ) ;
2012-10-09 23:26:43 +00:00
sp = null ;
2010-03-08 07:19:45 +00:00
}
2013-05-06 16:17:54 +00:00
// Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
// We need the circuit data here for some of the subsequent checks. (groups, for example)
// If the checks fail, we remove the circuit.
agent . teleportFlags = teleportFlags ;
m_authenticateHandler . AddNewCircuit ( agent . circuitcode , agent ) ;
2012-10-09 23:26:43 +00:00
land = LandChannel . GetLandObject ( agent . startpos . X , agent . startpos . Y ) ;
2013-05-06 16:17:54 +00:00
// On login test land permisions
2012-10-09 23:26:43 +00:00
if ( vialogin )
2010-06-12 18:11:13 +00:00
{
2013-04-28 23:55:34 +00:00
if ( land ! = null & & ! TestLandRestrictions ( agent . AgentID , out reason , ref agent . startpos . X , ref agent . startpos . Y ) )
2010-10-27 04:19:33 +00:00
{
2013-05-06 16:17:54 +00:00
m_authenticateHandler . RemoveCircuit ( agent . circuitcode ) ;
2010-06-12 18:11:13 +00:00
return false ;
2010-10-27 04:19:33 +00:00
}
2010-06-12 18:11:13 +00:00
}
2012-10-09 23:26:43 +00:00
if ( sp = = null ) // We don't have an [child] agent here already
2011-02-18 23:50:54 +00:00
{
2012-10-09 23:26:43 +00:00
if ( requirePresenceLookup )
{
try
{
if ( ! VerifyUserPresence ( agent , out reason ) )
2013-05-06 16:17:54 +00:00
{
m_authenticateHandler . RemoveCircuit ( agent . circuitcode ) ;
2012-10-09 23:26:43 +00:00
return false ;
2013-05-06 16:17:54 +00:00
}
2012-10-09 23:26:43 +00:00
}
catch ( Exception e )
{
m_log . ErrorFormat (
"[SCENE]: Exception verifying presence {0}{1}" , e . Message , e . StackTrace ) ;
2011-01-27 04:46:31 +00:00
2013-05-06 16:17:54 +00:00
m_authenticateHandler . RemoveCircuit ( agent . circuitcode ) ;
2012-10-09 23:26:43 +00:00
return false ;
}
}
try
{
if ( ! AuthorizeUser ( agent , out reason ) )
2013-05-06 16:17:54 +00:00
{
m_authenticateHandler . RemoveCircuit ( agent . circuitcode ) ;
2012-10-09 23:26:43 +00:00
return false ;
2013-05-06 16:17:54 +00:00
}
2012-10-09 23:26:43 +00:00
}
catch ( Exception e )
{
m_log . ErrorFormat (
"[SCENE]: Exception authorizing user {0}{1}" , e . Message , e . StackTrace ) ;
2009-05-29 21:12:55 +00:00
2013-05-06 16:17:54 +00:00
m_authenticateHandler . RemoveCircuit ( agent . circuitcode ) ;
2012-10-09 23:26:43 +00:00
return false ;
}
m_log . InfoFormat (
"[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})" ,
RegionInfo . RegionName , ( agent . child ? "child" : "root" ) , agent . firstname , agent . lastname ,
agent . AgentID , agent . circuitcode ) ;
2011-02-18 23:50:54 +00:00
if ( CapsModule ! = null )
2012-10-09 23:26:43 +00:00
{
2011-05-02 01:22:53 +00:00
CapsModule . SetAgentCapsSeeds ( agent ) ;
2012-10-09 23:26:43 +00:00
CapsModule . CreateCaps ( agent . AgentID ) ;
}
}
else
{
// Let the SP know how we got here. This has a lot of interesting
// uses down the line.
sp . TeleportFlags = ( TPFlags ) teleportFlags ;
if ( sp . IsChildAgent )
{
m_log . DebugFormat (
"[SCENE]: Adjusting known seeds for existing agent {0} in {1}" ,
agent . AgentID , RegionInfo . RegionName ) ;
sp . AdjustKnownSeeds ( ) ;
if ( CapsModule ! = null )
CapsModule . SetAgentCapsSeeds ( agent ) ;
}
2010-05-16 16:01:27 +00:00
}
2009-05-29 21:12:55 +00:00
2013-05-29 22:08:54 +00:00
// Try caching an incoming user name much earlier on to see if this helps with an issue
// where HG users are occasionally seen by others as "Unknown User" because their UUIDName
// request for the HG avatar appears to trigger before the user name is cached.
CacheUserName ( null , agent ) ;
}
2010-06-12 18:11:13 +00:00
2012-05-13 21:11:44 +00:00
if ( vialogin )
2009-05-06 20:02:49 +00:00
{
2011-09-02 22:19:27 +00:00
// CleanDroppedAttachments();
2010-11-08 02:37:28 +00:00
2010-06-12 18:11:13 +00:00
if ( TestBorderCross ( agent . startpos , Cardinals . E ) )
2009-09-06 20:15:06 +00:00
{
Border crossedBorder = GetCrossedBorder ( agent . startpos , Cardinals . E ) ;
agent . startpos . X = crossedBorder . BorderLine . Z - 1 ;
}
2009-08-08 04:10:19 +00:00
2009-09-06 20:15:06 +00:00
if ( TestBorderCross ( agent . startpos , Cardinals . N ) )
{
Border crossedBorder = GetCrossedBorder ( agent . startpos , Cardinals . N ) ;
agent . startpos . Y = crossedBorder . BorderLine . Z - 1 ;
}
2009-08-08 04:10:19 +00:00
2009-11-23 01:21:33 +00:00
//Mitigate http://opensimulator.org/mantis/view.php?id=3522
// Check if start position is outside of region
// If it is, check the Z start position also.. if not, leave it alone.
if ( BordersLocked )
{
lock ( EastBorders )
{
if ( agent . startpos . X > EastBorders [ 0 ] . BorderLine . Z )
{
m_log . Warn ( "FIX AGENT POSITION" ) ;
agent . startpos . X = EastBorders [ 0 ] . BorderLine . Z * 0.5f ;
if ( agent . startpos . Z > 720 )
agent . startpos . Z = 720 ;
}
}
lock ( NorthBorders )
{
if ( agent . startpos . Y > NorthBorders [ 0 ] . BorderLine . Z )
{
m_log . Warn ( "FIX Agent POSITION" ) ;
agent . startpos . Y = NorthBorders [ 0 ] . BorderLine . Z * 0.5f ;
if ( agent . startpos . Z > 720 )
agent . startpos . Z = 720 ;
}
}
2012-05-13 21:11:44 +00:00
} else
2009-11-23 01:21:33 +00:00
{
if ( agent . startpos . X > EastBorders [ 0 ] . BorderLine . Z )
{
m_log . Warn ( "FIX AGENT POSITION" ) ;
agent . startpos . X = EastBorders [ 0 ] . BorderLine . Z * 0.5f ;
if ( agent . startpos . Z > 720 )
agent . startpos . Z = 720 ;
}
if ( agent . startpos . Y > NorthBorders [ 0 ] . BorderLine . Z )
{
m_log . Warn ( "FIX Agent POSITION" ) ;
agent . startpos . Y = NorthBorders [ 0 ] . BorderLine . Z * 0.5f ;
if ( agent . startpos . Z > 720 )
agent . startpos . Z = 720 ;
}
}
2012-02-17 13:03:53 +00:00
2012-02-18 05:45:43 +00:00
// Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
if ( RegionInfo . RegionSettings . TelehubObject ! = UUID . Zero & &
RegionInfo . EstateSettings . AllowDirectTeleport = = false & &
! viahome & & ! godlike )
2012-02-17 13:03:53 +00:00
{
SceneObjectGroup telehub = GetSceneObjectGroup ( RegionInfo . RegionSettings . TelehubObject ) ;
// Can have multiple SpawnPoints
List < SpawnPoint > spawnpoints = RegionInfo . RegionSettings . SpawnPoints ( ) ;
2012-05-13 21:11:44 +00:00
if ( spawnpoints . Count > 1 )
2012-02-17 13:03:53 +00:00
{
2012-05-13 21:11:44 +00:00
// We have multiple SpawnPoints, Route the agent to a random or sequential one
if ( SpawnPointRouting = = "random" )
agent . startpos = spawnpoints [ Util . RandomClass . Next ( spawnpoints . Count ) - 1 ] . GetLocation (
telehub . AbsolutePosition ,
telehub . GroupRotation
) ;
else
agent . startpos = spawnpoints [ SpawnPoint ( ) ] . GetLocation (
telehub . AbsolutePosition ,
telehub . GroupRotation
) ;
2012-02-17 13:03:53 +00:00
}
else
{
// We have a single SpawnPoint and will route the agent to it
agent . startpos = spawnpoints [ 0 ] . GetLocation ( telehub . AbsolutePosition , telehub . GroupRotation ) ;
}
return true ;
}
2009-05-06 20:02:49 +00:00
// Honor parcel landing type and position.
if ( land ! = null )
2008-11-12 19:12:33 +00:00
{
2009-10-02 09:10:52 +00:00
if ( land . LandData . LandingType = = ( byte ) 1 & & land . LandData . UserLocation ! = Vector3 . Zero )
2008-04-05 09:47:05 +00:00
{
2009-10-02 09:10:52 +00:00
agent . startpos = land . LandData . UserLocation ;
2008-04-05 09:47:05 +00:00
}
2007-07-16 15:40:11 +00:00
}
2009-05-06 20:02:49 +00:00
}
2009-05-29 21:12:55 +00:00
2009-05-06 20:02:49 +00:00
return true ;
2009-04-14 19:35:35 +00:00
}
2009-03-03 15:41:21 +00:00
2013-04-28 23:55:34 +00:00
public bool TestLandRestrictions ( UUID agentID , out string reason , ref float posX , ref float posY )
2010-03-08 07:19:45 +00:00
{
2013-04-28 23:55:34 +00:00
if ( posX < 0 )
posX = 0 ;
else if ( posX > = 256 )
posX = 255.999f ;
if ( posY < 0 )
posY = 0 ;
else if ( posY > = 256 )
posY = 255.999f ;
reason = String . Empty ;
if ( Permissions . IsGod ( agentID ) )
return true ;
ILandObject land = LandChannel . GetLandObject ( posX , posY ) ;
if ( land = = null )
return false ;
bool banned = land . IsBannedFromLand ( agentID ) ;
bool restricted = land . IsRestrictedFromLand ( agentID ) ;
2010-03-08 07:19:45 +00:00
if ( banned | | restricted )
{
2013-04-28 23:55:34 +00:00
ILandObject nearestParcel = GetNearestAllowedParcel ( agentID , posX , posY ) ;
2010-03-08 07:19:45 +00:00
if ( nearestParcel ! = null )
{
//Move agent to nearest allowed
Vector3 newPosition = GetParcelCenterAtGround ( nearestParcel ) ;
2013-04-28 23:55:34 +00:00
posX = newPosition . X ;
posY = newPosition . Y ;
2010-03-08 07:19:45 +00:00
}
else
{
if ( banned )
{
reason = "Cannot regioncross into banned parcel." ;
}
else
{
reason = String . Format ( "Denied access to private region {0}: You are not on the access list for that region." ,
RegionInfo . RegionName ) ;
}
return false ;
}
}
reason = "" ;
return true ;
}
2009-08-15 01:37:25 +00:00
/// <summary>
2010-01-17 05:42:44 +00:00
/// Verifies that the user has a presence on the Grid
2009-08-15 01:37:25 +00:00
/// </summary>
/// <param name="agent">Circuit Data of the Agent we're verifying</param>
/// <param name="reason">Outputs the reason for the false response on this string</param>
/// <returns>True if the user has a session on the grid. False if it does not. False will
/// also return a reason.</returns>
2010-01-17 05:42:44 +00:00
public virtual bool VerifyUserPresence ( AgentCircuitData agent , out string reason )
2009-04-14 19:35:35 +00:00
{
2009-05-06 20:02:49 +00:00
reason = String . Empty ;
2010-01-17 05:42:44 +00:00
IPresenceService presence = RequestModuleInterface < IPresenceService > ( ) ;
if ( presence = = null )
2010-01-02 00:54:24 +00:00
{
2010-08-20 16:02:05 +00:00
reason = String . Format ( "Failed to verify user presence in the grid for {0} {1} in region {2}. Presence service does not exist." , agent . firstname , agent . lastname , RegionInfo . RegionName ) ;
2010-01-02 00:54:24 +00:00
return false ;
}
2010-01-17 05:42:44 +00:00
OpenSim . Services . Interfaces . PresenceInfo pinfo = presence . GetAgent ( agent . SessionID ) ;
2010-01-02 00:54:24 +00:00
2010-05-08 04:29:56 +00:00
if ( pinfo = = null )
2010-01-17 05:42:44 +00:00
{
2010-08-20 16:02:05 +00:00
reason = String . Format ( "Failed to verify user presence in the grid for {0} {1}, access denied to region {2}." , agent . firstname , agent . lastname , RegionInfo . RegionName ) ;
2010-01-17 05:42:44 +00:00
return false ;
}
2009-05-06 20:02:49 +00:00
2010-01-17 05:42:44 +00:00
return true ;
2008-08-25 07:35:17 +00:00
}
2009-08-15 01:37:25 +00:00
/// <summary>
/// Verify if the user can connect to this region. Checks the banlist and ensures that the region is set for public access
/// </summary>
/// <param name="agent">The circuit data for the agent</param>
/// <param name="reason">outputs the reason to this string</param>
/// <returns>True if the region accepts this agent. False if it does not. False will
/// also return a reason.</returns>
2009-05-06 20:02:49 +00:00
protected virtual bool AuthorizeUser ( AgentCircuitData agent , out string reason )
{
reason = String . Empty ;
2009-05-11 07:46:12 +00:00
if ( ! m_strictAccessControl ) return true ;
if ( Permissions . IsGod ( agent . AgentID ) ) return true ;
2009-09-11 02:56:08 +00:00
if ( AuthorizationService ! = null )
2009-09-09 18:42:53 +00:00
{
2011-07-23 02:46:55 +00:00
if ( ! AuthorizationService . IsAuthorizedForRegion (
agent . AgentID . ToString ( ) , agent . firstname , agent . lastname , RegionInfo . RegionID . ToString ( ) , out reason ) )
2009-09-13 04:56:09 +00:00
{
2012-03-17 17:00:11 +00:00
m_log . WarnFormat ( "[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because {4}" ,
agent . AgentID , agent . firstname , agent . lastname , RegionInfo . RegionName , reason ) ;
2011-07-23 02:46:55 +00:00
2009-09-30 16:00:09 +00:00
return false ;
2009-09-13 04:56:09 +00:00
}
2009-09-09 18:42:53 +00:00
}
2009-05-11 07:46:12 +00:00
2012-06-28 23:03:22 +00:00
if ( RegionInfo . EstateSettings ! = null )
2009-05-06 20:02:49 +00:00
{
2012-06-28 23:03:22 +00:00
if ( RegionInfo . EstateSettings . IsBanned ( agent . AgentID ) )
2010-06-11 01:26:04 +00:00
{
m_log . WarnFormat ( "[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist" ,
agent . AgentID , agent . firstname , agent . lastname , RegionInfo . RegionName ) ;
reason = String . Format ( "Denied access to region {0}: You have been banned from that region." ,
RegionInfo . RegionName ) ;
return false ;
}
2009-05-06 20:02:49 +00:00
}
2010-06-11 01:26:04 +00:00
else
2011-12-09 23:21:54 +00:00
{
2010-06-11 01:26:04 +00:00
m_log . ErrorFormat ( "[CONNECTION BEGIN]: Estate Settings is null!" ) ;
2011-12-09 23:21:54 +00:00
}
2009-05-06 20:02:49 +00:00
2013-07-24 18:23:19 +00:00
// We only test the things below when we want to cut off
// child agents from being present in the scene for which their root
// agent isn't allowed. Otherwise, we allow child agents. The test for
// the root is done elsewhere (QueryAccess)
if ( ! SeeIntoRegion )
2010-01-09 15:58:18 +00:00
{
2013-07-24 18:23:19 +00:00
List < UUID > agentGroups = new List < UUID > ( ) ;
2010-01-09 15:58:18 +00:00
2013-07-24 18:23:19 +00:00
if ( m_groupsModule ! = null )
2011-12-09 23:21:54 +00:00
{
2013-07-24 18:23:19 +00:00
GroupMembershipData [ ] GroupMembership = m_groupsModule . GetMembershipData ( agent . AgentID ) ;
if ( GroupMembership ! = null )
{
for ( int i = 0 ; i < GroupMembership . Length ; i + + )
agentGroups . Add ( GroupMembership [ i ] . GroupID ) ;
}
else
{
m_log . ErrorFormat ( "[CONNECTION BEGIN]: GroupMembership is null!" ) ;
}
2011-12-09 23:21:54 +00:00
}
2010-01-09 15:58:18 +00:00
2013-07-24 18:23:19 +00:00
bool groupAccess = false ;
UUID [ ] estateGroups = RegionInfo . EstateSettings . EstateGroups ;
2010-01-09 15:58:18 +00:00
2013-07-24 18:23:19 +00:00
if ( estateGroups ! = null )
2010-01-09 15:58:18 +00:00
{
2013-07-24 18:23:19 +00:00
foreach ( UUID group in estateGroups )
2010-06-11 01:26:04 +00:00
{
2013-07-24 18:23:19 +00:00
if ( agentGroups . Contains ( group ) )
{
groupAccess = true ;
break ;
}
2010-06-11 01:26:04 +00:00
}
2010-01-09 15:58:18 +00:00
}
2013-07-24 18:23:19 +00:00
else
{
m_log . ErrorFormat ( "[CONNECTION BEGIN]: EstateGroups is null!" ) ;
}
2010-01-09 15:58:18 +00:00
2013-07-24 18:23:19 +00:00
if ( ! RegionInfo . EstateSettings . PublicAccess & &
! RegionInfo . EstateSettings . HasAccess ( agent . AgentID ) & &
! groupAccess )
{
m_log . WarnFormat ( "[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate" ,
agent . AgentID , agent . firstname , agent . lastname , RegionInfo . RegionName ) ;
reason = String . Format ( "Denied access to private region {0}: You are not on the access list for that region." ,
RegionInfo . RegionName ) ;
return false ;
}
2009-05-06 20:02:49 +00:00
}
2009-05-11 07:46:12 +00:00
// TODO: estate/region settings are not properly hooked up
// to ILandObject.isRestrictedFromLand()
// if (null != LandChannel)
// {
// // region seems to have local Id of 1
// ILandObject land = LandChannel.GetLandObject(1);
// if (null != land)
// {
// if (land.isBannedFromLand(agent.AgentID))
// {
// m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
// agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
2009-05-29 21:12:55 +00:00
// reason = String.Format("Denied access to private region {0}: You are banned from that region.",
2009-05-11 07:46:12 +00:00
// RegionInfo.RegionName);
// return false;
// }
// if (land.isRestrictedFromLand(agent.AgentID))
// {
// m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
// agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
2009-05-29 21:12:55 +00:00
// reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
2009-05-11 07:46:12 +00:00
// RegionInfo.RegionName);
// return false;
// }
// }
// }
2009-05-06 20:02:49 +00:00
return true ;
}
2009-08-15 01:37:25 +00:00
/// <summary>
/// Update an AgentCircuitData object with new information
/// </summary>
/// <param name="data">Information to update the AgentCircuitData with</param>
2008-08-25 07:35:17 +00:00
public void UpdateCircuitData ( AgentCircuitData data )
{
m_authenticateHandler . UpdateAgentData ( data ) ;
}
2009-08-15 01:37:25 +00:00
/// <summary>
/// Change the Circuit Code for the user's Circuit Data
/// </summary>
/// <param name="oldcc">The old Circuit Code. Must match a previous circuit code</param>
/// <param name="newcc">The new Circuit Code. Must not be an already existing circuit code</param>
/// <returns>True if we successfully changed it. False if we did not</returns>
2008-08-25 07:35:17 +00:00
public bool ChangeCircuitCode ( uint oldcc , uint newcc )
{
return m_authenticateHandler . TryChangeCiruitCode ( oldcc , newcc ) ;
2008-05-16 01:22:11 +00:00
}
2008-03-20 20:04:45 +00:00
2012-04-26 15:20:53 +00:00
// /// <summary>
// /// The Grid has requested that we log-off a user. Log them off.
// /// </summary>
// /// <param name="AvatarID">Unique ID of the avatar to log-off</param>
// /// <param name="RegionSecret">SecureSessionID of the user, or the RegionSecret text when logging on to the grid</param>
// /// <param name="message">message to display to the user. Reason for being logged off</param>
// public void HandleLogOffUserFromGrid(UUID AvatarID, UUID RegionSecret, string message)
// {
// ScenePresence loggingOffUser = GetScenePresence(AvatarID);
// if (loggingOffUser != null)
// {
// UUID localRegionSecret = UUID.Zero;
2012-06-28 23:03:22 +00:00
// bool parsedsecret = UUID.TryParse(RegionInfo.regionSecret, out localRegionSecret);
2012-04-26 15:20:53 +00:00
/ /
// // Region Secret is used here in case a new sessionid overwrites an old one on the user server.
// // Will update the user server in a few revisions to use it.
/ /
// if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId || (parsedsecret && RegionSecret == localRegionSecret))
// {
// m_sceneGridService.SendCloseChildAgentConnections(loggingOffUser.UUID, loggingOffUser.KnownRegionHandles);
// loggingOffUser.ControllingClient.Kick(message);
// // Give them a second to receive the message!
// Thread.Sleep(1000);
// loggingOffUser.ControllingClient.Close();
// }
// else
// {
// m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate");
// }
// }
// else
// {
// m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString());
// }
// }
2008-08-28 14:41:54 +00:00
2013-03-28 22:55:13 +00:00
// /// <summary>
// /// Triggered when an agent crosses into this sim. Also happens on initial login.
// /// </summary>
// /// <param name="agentID"></param>
// /// <param name="position"></param>
// /// <param name="isFlying"></param>
// public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
// {
// ScenePresence presence = GetScenePresence(agentID);
// if (presence != null)
// {
// try
// {
// presence.MakeRootAgent(position, isFlying);
// }
// catch (Exception e)
// {
// m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace);
// }
// }
// else
// {
// m_log.ErrorFormat(
// "[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
// agentID, RegionInfo.RegionName);
// }
// }
2007-07-16 15:40:11 +00:00
2009-08-15 01:37:25 +00:00
/// <summary>
/// We've got an update about an agent that sees into this region,
/// send it to ScenePresence for processing It's the full data.
/// </summary>
2009-10-01 00:38:36 +00:00
/// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
2009-08-15 01:37:25 +00:00
/// Appearance, animations, position, etc.</param>
/// <returns>true if we handled it.</returns>
2008-12-29 22:22:05 +00:00
public virtual bool IncomingChildAgentDataUpdate ( AgentData cAgentData )
2007-12-10 00:46:56 +00:00
{
2010-01-12 17:22:58 +00:00
m_log . DebugFormat (
"[SCENE]: Incoming child agent update for {0} in {1}" , cAgentData . AgentID , RegionInfo . RegionName ) ;
2009-02-04 00:01:36 +00:00
2012-05-17 22:33:26 +00:00
// TODO: This check should probably be in QueryAccess().
2010-11-10 15:22:55 +00:00
ILandObject nearestParcel = GetNearestAllowedParcel ( cAgentData . AgentID , Constants . RegionSize / 2 , Constants . RegionSize / 2 ) ;
if ( nearestParcel = = null )
{
2012-04-26 23:58:54 +00:00
m_log . DebugFormat (
"[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel" ,
cAgentData . AgentID , RegionInfo . RegionName ) ;
2010-11-10 15:22:55 +00:00
return false ;
}
2012-10-16 00:20:41 +00:00
// We have to wait until the viewer contacts this region
// after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
// a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
2009-02-04 16:31:48 +00:00
ScenePresence childAgentUpdate = WaitGetScenePresence ( cAgentData . AgentID ) ;
2010-12-06 03:43:24 +00:00
2009-01-03 02:29:49 +00:00
if ( childAgentUpdate ! = null )
{
2013-07-14 17:26:05 +00:00
if ( cAgentData . SessionID ! = childAgentUpdate . ControllingClient . SessionId )
2013-07-14 16:21:28 +00:00
{
2013-07-14 17:26:05 +00:00
m_log . WarnFormat ( "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update)." , childAgentUpdate . UUID , cAgentData . SessionID ) ;
2013-07-14 16:21:28 +00:00
Console . WriteLine ( String . Format ( "[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}" ,
childAgentUpdate . UUID , childAgentUpdate . ControllingClient . SessionId , cAgentData . SessionID ) ) ;
}
2013-07-14 17:26:05 +00:00
childAgentUpdate . ChildAgentDataUpdate ( cAgentData ) ;
return true ;
2009-01-03 02:29:49 +00:00
}
return false ;
}
2009-08-15 01:37:25 +00:00
/// <summary>
/// We've got an update about an agent that sees into this region,
/// send it to ScenePresence for processing It's only positional data
/// </summary>
/// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
/// <returns>true if we handled it.</returns>
2009-01-03 02:29:49 +00:00
public virtual bool IncomingChildAgentDataUpdate ( AgentPosition cAgentData )
{
2010-12-06 03:43:24 +00:00
//m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
2008-12-29 22:22:05 +00:00
ScenePresence childAgentUpdate = GetScenePresence ( cAgentData . AgentID ) ;
2008-01-22 08:52:51 +00:00
if ( childAgentUpdate ! = null )
2007-12-10 00:46:56 +00:00
{
2013-07-14 16:21:28 +00:00
if ( childAgentUpdate . ControllingClient . SessionId = = cAgentData . SessionID )
2007-12-10 00:46:56 +00:00
{
2013-07-14 16:21:28 +00:00
// I can't imagine *yet* why we would get an update if the agent is a root agent..
// however to avoid a race condition crossing borders..
if ( childAgentUpdate . IsChildAgent )
{
uint rRegionX = ( uint ) ( cAgentData . RegionHandle > > 40 ) ;
uint rRegionY = ( ( ( uint ) ( cAgentData . RegionHandle ) ) > > 8 ) ;
uint tRegionX = RegionInfo . RegionLocX ;
uint tRegionY = RegionInfo . RegionLocY ;
//Send Data to ScenePresence
childAgentUpdate . ChildAgentDataUpdate ( cAgentData , tRegionX , tRegionY , rRegionX , rRegionY ) ;
// Not Implemented:
//TODO: Do we need to pass the message on to one of our neighbors?
}
2007-12-10 00:46:56 +00:00
}
2013-07-14 16:21:28 +00:00
else
m_log . WarnFormat ( "[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}" , childAgentUpdate . UUID , cAgentData . SessionID ) ;
2008-01-22 08:52:51 +00:00
return true ;
2007-12-10 00:46:56 +00:00
}
2009-02-04 00:01:36 +00:00
2008-01-22 08:52:51 +00:00
return false ;
2007-12-10 00:46:56 +00:00
}
2007-12-27 21:41:48 +00:00
2012-05-17 22:33:26 +00:00
/// <summary>
/// Poll until the requested ScenePresence appears or we timeout.
/// </summary>
/// <returns>The scene presence is found, else null.</returns>
/// <param name='agentID'></param>
2009-02-04 16:31:48 +00:00
protected virtual ScenePresence WaitGetScenePresence ( UUID agentID )
{
int ntimes = 10 ;
2012-05-17 22:33:26 +00:00
ScenePresence sp = null ;
while ( ( sp = GetScenePresence ( agentID ) ) = = null & & ( ntimes - - > 0 ) )
2009-02-04 16:31:48 +00:00
Thread . Sleep ( 1000 ) ;
2012-05-17 22:33:26 +00:00
if ( sp = = null )
m_log . WarnFormat (
"[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout" ,
agentID , RegionInfo . RegionName ) ;
// else
// m_log.DebugFormat(
// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
return sp ;
2009-02-04 16:31:48 +00:00
}
2009-03-23 02:37:19 +00:00
public virtual bool IncomingRetrieveRootAgent ( UUID id , out IAgentData agent )
{
agent = null ;
ScenePresence sp = GetScenePresence ( id ) ;
if ( ( sp ! = null ) & & ( ! sp . IsChildAgent ) )
{
sp . IsChildAgent = true ;
return sp . CopyAgent ( out agent ) ;
}
return false ;
}
2013-07-14 04:28:46 +00:00
/// <summary>
/// Authenticated close (via network)
/// </summary>
/// <param name="agentID"></param>
/// <param name="force"></param>
/// <param name="auth_token"></param>
/// <returns></returns>
public bool IncomingCloseAgent ( UUID agentID , bool force , string auth_token )
{
//m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
// Check that the auth_token is valid
AgentCircuitData acd = AuthenticateHandler . GetAgentCircuitData ( agentID ) ;
2013-07-14 14:28:40 +00:00
if ( acd ! = null & & acd . SessionID . ToString ( ) = = auth_token )
2013-07-14 04:28:46 +00:00
return IncomingCloseAgent ( agentID , force ) ;
else
m_log . ErrorFormat ( "[SCENE]: Request to close agent {0} with invalid authorization token {1}" , agentID , auth_token ) ;
return false ;
}
2009-03-23 02:37:19 +00:00
2007-12-06 04:01:56 +00:00
/// <summary>
2007-12-10 21:12:38 +00:00
/// Tell a single agent to disconnect from the region.
2007-12-06 04:01:56 +00:00
/// </summary>
/// <param name="agentID"></param>
2012-08-20 19:24:54 +00:00
/// <param name="force">
/// Force the agent to close even if it might be in the middle of some other operation. You do not want to
/// force unless you are absolutely sure that the agent is dead and a normal close is not working.
/// </param>
public bool IncomingCloseAgent ( UUID agentID , bool force )
2007-11-05 13:58:44 +00:00
{
2009-01-16 21:56:13 +00:00
//m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
2008-11-12 20:16:46 +00:00
ScenePresence presence = m_sceneGraph . GetScenePresence ( agentID ) ;
2008-11-12 19:12:33 +00:00
if ( presence ! = null )
2013-07-14 05:32:52 +00:00
{
2012-08-20 19:24:54 +00:00
presence . ControllingClient . Close ( force ) ;
2013-07-14 05:32:52 +00:00
return true ;
}
2009-02-04 00:01:36 +00:00
2013-07-14 04:28:46 +00:00
// Agent not here
2009-01-01 19:42:24 +00:00
return false ;
2007-11-05 13:58:44 +00:00
}
2008-08-16 19:34:12 +00:00
/// <summary>
2011-07-28 23:00:35 +00:00
/// Tries to teleport agent to another region.
2008-08-16 19:34:12 +00:00
/// </summary>
2011-07-28 23:00:35 +00:00
/// <remarks>
/// The region name must exactly match that given.
/// </remarks>
2008-08-16 19:34:12 +00:00
/// <param name="remoteClient"></param>
/// <param name="regionName"></param>
/// <param name="position"></param>
/// <param name="lookAt"></param>
2008-10-04 18:46:34 +00:00
/// <param name="teleportFlags"></param>
2008-09-06 07:52:41 +00:00
public void RequestTeleportLocation ( IClientAPI remoteClient , string regionName , Vector3 position ,
2008-10-04 18:46:34 +00:00
Vector3 lookat , uint teleportFlags )
2008-08-16 19:34:12 +00:00
{
2011-07-28 23:00:35 +00:00
GridRegion region = GridService . GetRegionByName ( RegionInfo . ScopeID , regionName ) ;
if ( region = = null )
2008-08-16 19:34:12 +00:00
{
// can't find the region: Tell viewer and abort
remoteClient . SendTeleportFailed ( "The region '" + regionName + "' could not be found." ) ;
return ;
}
2009-02-04 00:01:36 +00:00
2011-07-28 23:00:35 +00:00
RequestTeleportLocation ( remoteClient , region . RegionHandle , position , lookat , teleportFlags ) ;
2008-08-16 19:34:12 +00:00
}
2007-07-16 15:40:11 +00:00
/// <summary>
2007-12-10 21:12:38 +00:00
/// Tries to teleport agent to other region.
2007-07-16 15:40:11 +00:00
/// </summary>
/// <param name="remoteClient"></param>
2007-12-06 04:01:56 +00:00
/// <param name="regionHandle"></param>
2007-07-16 15:40:11 +00:00
/// <param name="position"></param>
/// <param name="lookAt"></param>
2008-10-04 18:46:34 +00:00
/// <param name="teleportFlags"></param>
2008-09-06 07:52:41 +00:00
public void RequestTeleportLocation ( IClientAPI remoteClient , ulong regionHandle , Vector3 position ,
2008-10-04 18:46:34 +00:00
Vector3 lookAt , uint teleportFlags )
2007-07-16 15:40:11 +00:00
{
2010-03-19 12:51:16 +00:00
ScenePresence sp = GetScenePresence ( remoteClient . AgentId ) ;
if ( sp ! = null )
2009-01-14 04:18:28 +00:00
{
2012-06-28 23:03:22 +00:00
uint regionX = RegionInfo . RegionLocX ;
uint regionY = RegionInfo . RegionLocY ;
2009-08-28 23:42:28 +00:00
Utils . LongToUInts ( regionHandle , out regionX , out regionY ) ;
2012-06-28 23:03:22 +00:00
int shiftx = ( int ) regionX - ( int ) RegionInfo . RegionLocX * ( int ) Constants . RegionSize ;
int shifty = ( int ) regionY - ( int ) RegionInfo . RegionLocY * ( int ) Constants . RegionSize ;
2009-08-28 23:42:28 +00:00
position . X + = shiftx ;
position . Y + = shifty ;
bool result = false ;
if ( TestBorderCross ( position , Cardinals . N ) )
result = true ;
if ( TestBorderCross ( position , Cardinals . S ) )
result = true ;
if ( TestBorderCross ( position , Cardinals . E ) )
result = true ;
if ( TestBorderCross ( position , Cardinals . W ) )
result = true ;
// bordercross if position is outside of region
if ( ! result )
2010-06-05 16:39:09 +00:00
{
2012-06-28 23:03:22 +00:00
regionHandle = RegionInfo . RegionHandle ;
2010-06-05 16:39:09 +00:00
}
2009-08-30 06:49:50 +00:00
else
{
// not in this region, undo the shift!
position . X - = shiftx ;
position . Y - = shifty ;
}
2009-08-28 23:42:28 +00:00
2012-05-23 23:31:14 +00:00
if ( EntityTransferModule ! = null )
{
EntityTransferModule . Teleport ( sp , regionHandle , position , lookAt , teleportFlags ) ;
}
2009-05-21 10:41:16 +00:00
else
{
2010-01-15 23:11:58 +00:00
m_log . DebugFormat ( "[SCENE]: Unable to perform teleports: no AgentTransferModule is active" ) ;
sp . ControllingClient . SendTeleportFailed ( "Unable to perform teleports on this simulator." ) ;
2009-05-21 10:41:16 +00:00
}
2007-07-16 15:40:11 +00:00
}
}
2011-01-28 00:37:37 +00:00
public bool CrossAgentToNewRegion ( ScenePresence agent , bool isFlying )
2009-02-12 23:23:44 +00:00
{
2012-05-23 23:31:14 +00:00
if ( EntityTransferModule ! = null )
{
return EntityTransferModule . Cross ( agent , isFlying ) ;
}
2010-01-15 23:11:58 +00:00
else
{
m_log . DebugFormat ( "[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule" ) ;
}
2011-01-28 00:37:37 +00:00
return false ;
2009-02-12 23:23:44 +00:00
}
2009-01-03 02:29:49 +00:00
public void SendOutChildAgentUpdates ( AgentPosition cadu , ScenePresence presence )
2008-01-22 08:52:51 +00:00
{
m_sceneGridService . SendChildAgentDataUpdate ( cadu , presence ) ;
}
2007-07-17 17:47:23 +00:00
# endregion
2007-07-19 10:44:19 +00:00
2009-02-05 18:36:53 +00:00
#region Other Methods
2009-05-29 21:12:55 +00:00
2010-09-12 06:41:48 +00:00
protected override IConfigSource GetConfig ( )
{
return m_config ;
}
2007-11-03 19:14:22 +00:00
# endregion
2008-09-06 07:52:41 +00:00
public void HandleObjectPermissionsUpdate ( IClientAPI controller , UUID agentID , UUID sessionID , byte field , uint localId , uint mask , byte set )
2007-12-05 06:44:32 +00:00
{
// Check for spoofing.. since this is permissions we're talking about here!
2007-12-06 04:01:56 +00:00
if ( ( controller . SessionId = = sessionID ) & & ( controller . AgentId = = agentID ) )
2007-12-05 06:44:32 +00:00
{
2008-02-10 14:27:21 +00:00
// Tell the object to do permission update
2008-03-28 14:59:52 +00:00
if ( localId ! = 0 )
{
SceneObjectGroup chObjectGroup = GetGroupByPrim ( localId ) ;
if ( chObjectGroup ! = null )
{
chObjectGroup . UpdatePermissions ( agentID , field , localId , mask , set ) ;
}
}
2007-12-05 06:44:32 +00:00
}
}
2007-12-06 04:01:56 +00:00
/// <summary>
2007-12-10 21:12:38 +00:00
/// Causes all clients to get a full object update on all of the objects in the scene.
2007-12-06 04:01:56 +00:00
/// </summary>
2007-09-17 07:31:15 +00:00
public void ForceClientUpdate ( )
2007-09-06 14:15:16 +00:00
{
2010-09-10 19:04:12 +00:00
EntityBase [ ] entityList = GetEntities ( ) ;
foreach ( EntityBase ent in entityList )
2007-09-06 14:15:16 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
( ( SceneObjectGroup ) ent ) . ScheduleGroupForFullUpdate ( ) ;
2007-09-06 14:15:16 +00:00
}
}
}
2007-09-19 00:30:55 +00:00
2007-12-06 04:01:56 +00:00
/// <summary>
2007-12-10 21:12:38 +00:00
/// This is currently only used for scale (to scale to MegaPrim size)
/// There is a console command that calls this in OpenSimMain
2007-12-06 04:01:56 +00:00
/// </summary>
/// <param name="cmdparams"></param>
public void HandleEditCommand ( string [ ] cmdparams )
2007-09-08 11:08:38 +00:00
{
2011-12-09 23:21:54 +00:00
m_log . DebugFormat ( "Searching for Primitive: '{0}'" , cmdparams [ 2 ] ) ;
2007-12-17 16:41:28 +00:00
2010-09-10 19:04:12 +00:00
EntityBase [ ] entityList = GetEntities ( ) ;
foreach ( EntityBase ent in entityList )
2007-09-08 11:08:38 +00:00
{
if ( ent is SceneObjectGroup )
{
2012-03-31 00:52:06 +00:00
SceneObjectPart part = ( ( SceneObjectGroup ) ent ) . GetPart ( ( ( SceneObjectGroup ) ent ) . UUID ) ;
2007-09-19 00:30:55 +00:00
if ( part ! = null )
{
2009-02-07 12:25:39 +00:00
if ( part . Name = = cmdparams [ 2 ] )
2007-09-19 00:30:55 +00:00
{
part . Resize (
2009-02-07 12:25:39 +00:00
new Vector3 ( Convert . ToSingle ( cmdparams [ 3 ] ) , Convert . ToSingle ( cmdparams [ 4 ] ) ,
Convert . ToSingle ( cmdparams [ 5 ] ) ) ) ;
2007-09-19 00:30:55 +00:00
2011-12-09 23:21:54 +00:00
m_log . DebugFormat ( "Edited scale of Primitive: {0}" , part . Name ) ;
2007-09-19 00:30:55 +00:00
}
}
2007-09-08 11:08:38 +00:00
}
}
}
2007-11-03 19:14:22 +00:00
#region Script Handling Methods
2007-12-06 04:01:56 +00:00
/// <summary>
2007-12-10 21:12:38 +00:00
/// Console command handler to send script command to script engine.
2007-12-06 04:01:56 +00:00
/// </summary>
/// <param name="args"></param>
2007-11-03 19:14:22 +00:00
public void SendCommandToPlugins ( string [ ] args )
2007-09-04 17:53:21 +00:00
{
2007-11-03 19:14:22 +00:00
m_eventManager . TriggerOnPluginConsole ( args ) ;
2007-09-04 17:53:21 +00:00
}
2007-12-27 21:41:48 +00:00
Again, great thanks to Alondria for:
Adding:: llSetParcelMusicUrl(), llGetRootPosition(), llGetRootRotation(),
llGetGeometricCenter(), llSetLocalRot(), llListReplaceList(),
llGetObjectPrimCount(),llGetParcelDetails(), llGetParcelMaxPrims(),
llWater(), llGetLocalRot(), and llGetAccel()
2007-12-24 21:16:32 +00:00
public LandData GetLandData ( float x , float y )
{
2009-10-02 09:10:52 +00:00
return LandChannel . GetLandObject ( x , y ) . LandData ;
Again, great thanks to Alondria for:
Adding:: llSetParcelMusicUrl(), llGetRootPosition(), llGetRootRotation(),
llGetGeometricCenter(), llSetLocalRot(), llListReplaceList(),
llGetObjectPrimCount(),llGetParcelDetails(), llGetParcelMaxPrims(),
llWater(), llGetLocalRot(), and llGetAccel()
2007-12-24 21:16:32 +00:00
}
2012-09-06 10:45:52 +00:00
/// <summary>
/// Get LandData by position.
/// </summary>
/// <param name="pos"></param>
/// <returns></returns>
public LandData GetLandData ( Vector3 pos )
{
return GetLandData ( pos . X , pos . Y ) ;
}
2008-08-16 19:20:14 +00:00
public LandData GetLandData ( uint x , uint y )
{
2009-03-05 20:32:35 +00:00
m_log . DebugFormat ( "[SCENE]: returning land for {0},{1}" , x , y ) ;
2009-10-02 09:10:52 +00:00
return LandChannel . GetLandObject ( ( int ) x , ( int ) y ) . LandData ;
2008-08-16 19:20:14 +00:00
}
2007-11-03 19:14:22 +00:00
# endregion
2007-08-13 19:39:51 +00:00
#region Script Engine
2007-09-19 00:30:55 +00:00
2008-09-25 17:26:32 +00:00
private bool ScriptDanger ( SceneObjectPart part , Vector3 pos )
2008-04-22 09:28:58 +00:00
{
2008-05-06 04:56:48 +00:00
ILandObject parcel = LandChannel . GetLandObject ( pos . X , pos . Y ) ;
2008-04-22 09:28:58 +00:00
if ( part ! = null )
{
if ( parcel ! = null )
{
2009-10-02 09:10:52 +00:00
if ( ( parcel . LandData . Flags & ( uint ) ParcelFlags . AllowOtherScripts ) ! = 0 )
2008-04-22 09:28:58 +00:00
{
return true ;
}
2009-10-02 09:10:52 +00:00
else if ( ( parcel . LandData . Flags & ( uint ) ParcelFlags . AllowGroupScripts ) ! = 0 )
2008-04-22 09:28:58 +00:00
{
2009-10-02 09:10:52 +00:00
if ( part . OwnerID = = parcel . LandData . OwnerID
| | ( parcel . LandData . IsGroupOwned & & part . GroupID = = parcel . LandData . GroupID )
2009-03-30 18:20:41 +00:00
| | Permissions . IsGod ( part . OwnerID ) )
2008-04-22 09:28:58 +00:00
{
return true ;
}
else
{
return false ;
}
2008-05-16 01:22:11 +00:00
}
2008-04-22 09:28:58 +00:00
else
{
2009-10-02 09:10:52 +00:00
if ( part . OwnerID = = parcel . LandData . OwnerID )
2008-04-22 09:28:58 +00:00
{
return true ;
}
else
{
return false ;
}
}
}
else
{
2008-05-01 18:04:42 +00:00
2008-04-22 09:28:58 +00:00
if ( pos . X > 0f & & pos . X < Constants . RegionSize & & pos . Y > 0f & & pos . Y < Constants . RegionSize )
{
2008-05-16 01:22:11 +00:00
// The only time parcel != null when an object is inside a region is when
2008-04-22 09:28:58 +00:00
// there is nothing behind the landchannel. IE, no land plugin loaded.
return true ;
}
else
{
// The object is outside of this region. Stop piping events to it.
return false ;
}
}
2008-04-22 10:11:29 +00:00
}
else
{
return false ;
}
}
2008-06-18 03:50:39 +00:00
2008-09-25 17:26:32 +00:00
public bool ScriptDanger ( uint localID , Vector3 pos )
2008-04-22 10:11:29 +00:00
{
SceneObjectPart part = GetSceneObjectPart ( localID ) ;
if ( part ! = null )
{
2008-09-25 17:26:32 +00:00
return ScriptDanger ( part , pos ) ;
2008-04-22 10:11:29 +00:00
}
else
{
return false ;
}
}
2008-09-25 17:26:32 +00:00
public bool PipeEventsForScript ( uint localID )
2008-04-22 10:11:29 +00:00
{
SceneObjectPart part = GetSceneObjectPart ( localID ) ;
2012-03-02 22:52:26 +00:00
2008-04-22 10:11:29 +00:00
if ( part ! = null )
{
2008-08-13 14:19:59 +00:00
SceneObjectPart parent = part . ParentGroup . RootPart ;
2012-03-02 22:43:24 +00:00
return ScriptDanger ( parent , parent . GetWorldPosition ( ) ) ;
2008-04-22 09:28:58 +00:00
}
else
{
return false ;
}
}
2007-08-13 19:39:51 +00:00
# endregion
2007-08-13 20:24:37 +00:00
2008-11-12 20:16:46 +00:00
#region SceneGraph wrapper methods
2007-11-03 19:14:22 +00:00
2007-12-06 04:01:56 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-12-06 04:01:56 +00:00
/// </summary>
/// <param name="localID"></param>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public UUID ConvertLocalIDToFullID ( uint localID )
2007-08-13 20:24:37 +00:00
{
2008-11-12 20:16:46 +00:00
return m_sceneGraph . ConvertLocalIDToFullID ( localID ) ;
2007-08-14 17:29:15 +00:00
}
2007-12-27 21:41:48 +00:00
2007-12-12 06:58:55 +00:00
public void SwapRootAgentCount ( bool rootChildChildRootTF )
{
2008-11-12 20:16:46 +00:00
m_sceneGraph . SwapRootChildAgent ( rootChildChildRootTF ) ;
2007-12-12 06:58:55 +00:00
}
2007-12-14 00:49:40 +00:00
public void AddPhysicalPrim ( int num )
{
2008-11-12 20:16:46 +00:00
m_sceneGraph . AddPhysicalPrim ( num ) ;
2007-12-14 00:49:40 +00:00
}
public void RemovePhysicalPrim ( int num )
{
2008-11-12 20:16:46 +00:00
m_sceneGraph . RemovePhysicalPrim ( num ) ;
2007-12-14 00:49:40 +00:00
}
2010-03-19 12:51:16 +00:00
public int GetRootAgentCount ( )
2007-11-03 19:14:22 +00:00
{
2010-03-19 12:51:16 +00:00
return m_sceneGraph . GetRootAgentCount ( ) ;
2007-11-03 19:14:22 +00:00
}
2010-03-19 12:51:16 +00:00
public int GetChildAgentCount ( )
2007-11-03 19:14:22 +00:00
{
2010-03-19 12:51:16 +00:00
return m_sceneGraph . GetChildAgentCount ( ) ;
2007-11-03 19:14:22 +00:00
}
/// <summary>
2010-03-19 12:51:16 +00:00
/// Request a scene presence by UUID. Fast, indexed lookup.
2007-11-03 19:14:22 +00:00
/// </summary>
2010-03-19 12:51:16 +00:00
/// <param name="agentID"></param>
/// <returns>null if the presence was not found</returns>
public ScenePresence GetScenePresence ( UUID agentID )
2007-11-03 19:14:22 +00:00
{
2010-03-19 12:51:16 +00:00
return m_sceneGraph . GetScenePresence ( agentID ) ;
2007-11-03 19:14:22 +00:00
}
2010-03-17 13:40:00 +00:00
/// <summary>
2010-03-19 12:51:16 +00:00
/// Request the scene presence by name.
2010-03-17 13:40:00 +00:00
/// </summary>
/// <param name="firstName"></param>
/// <param name="lastName"></param>
2010-03-19 12:51:16 +00:00
/// <returns>null if the presence was not found</returns>
2010-03-17 13:40:00 +00:00
public ScenePresence GetScenePresence ( string firstName , string lastName )
{
return m_sceneGraph . GetScenePresence ( firstName , lastName ) ;
}
/// <summary>
2010-03-19 12:51:16 +00:00
/// Request the scene presence by localID.
2010-03-17 13:40:00 +00:00
/// </summary>
/// <param name="localID"></param>
2010-03-19 12:51:16 +00:00
/// <returns>null if the presence was not found</returns>
2010-03-17 13:40:00 +00:00
public ScenePresence GetScenePresence ( uint localID )
{
return m_sceneGraph . GetScenePresence ( localID ) ;
}
2012-07-19 20:54:50 +00:00
/// <summary>
/// Gets all the scene presences in this scene.
/// </summary>
/// <remarks>
/// This method will return both root and child scene presences.
2012-07-19 21:32:27 +00:00
///
2012-07-19 20:54:50 +00:00
/// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not
/// involving creating a new List object.
/// </remarks>
/// <returns>
/// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene.
/// </returns>
public List < ScenePresence > GetScenePresences ( )
{
return new List < ScenePresence > ( m_sceneGraph . GetScenePresences ( ) ) ;
}
2011-10-27 07:42:21 +00:00
/// <summary>
2011-11-04 00:06:08 +00:00
/// Performs action on all avatars in the scene (root scene presences)
/// Avatars may be an NPC or a 'real' client.
2011-10-27 07:42:21 +00:00
/// </summary>
/// <param name="action"></param>
2011-11-04 00:53:51 +00:00
public void ForEachRootScenePresence ( Action < ScenePresence > action )
2011-10-27 07:42:21 +00:00
{
2012-02-22 00:55:16 +00:00
m_sceneGraph . ForEachAvatar ( action ) ;
2011-10-27 07:42:21 +00:00
}
2007-11-03 19:14:22 +00:00
/// <summary>
2011-11-04 00:06:08 +00:00
/// Performs action on all scene presences (root and child)
2007-11-03 19:14:22 +00:00
/// </summary>
/// <param name="action"></param>
public void ForEachScenePresence ( Action < ScenePresence > action )
{
2012-02-22 00:55:16 +00:00
m_sceneGraph . ForEachScenePresence ( action ) ;
2007-09-04 13:43:56 +00:00
}
2008-05-16 01:22:11 +00:00
2012-07-06 22:07:50 +00:00
/// <summary>
/// Get all the scene object groups.
/// </summary>
/// <returns>
/// The scene object groups. If the scene is empty then an empty list is returned.
/// </returns>
public List < SceneObjectGroup > GetSceneObjectGroups ( )
{
return m_sceneGraph . GetSceneObjectGroups ( ) ;
}
2011-05-20 22:34:34 +00:00
/// <summary>
/// Get a group via its UUID
/// </summary>
/// <param name="fullID"></param>
2012-10-24 03:10:22 +00:00
/// <returns>null if no group with that id exists</returns>
2011-05-20 22:34:34 +00:00
public SceneObjectGroup GetSceneObjectGroup ( UUID fullID )
{
return m_sceneGraph . GetSceneObjectGroup ( fullID ) ;
}
2012-10-24 03:10:22 +00:00
/// <summary>
/// Get a group via its local ID
/// </summary>
/// <remarks>This will only return a group if the local ID matches a root part</remarks>
/// <param name="localID"></param>
/// <returns>null if no group with that id exists</returns>
public SceneObjectGroup GetSceneObjectGroup ( uint localID )
{
return m_sceneGraph . GetSceneObjectGroup ( localID ) ;
}
2008-10-05 14:15:39 +00:00
/// <summary>
2011-05-20 22:41:14 +00:00
/// Get a group by name from the 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 no group with that name exists</returns>
public SceneObjectGroup GetSceneObjectGroup ( string name )
{
return m_sceneGraph . GetSceneObjectGroup ( name ) ;
}
2012-09-06 09:40:26 +00:00
/// <summary>
/// Attempt to get the SOG via its UUID
/// </summary>
/// <param name="fullID"></param>
/// <param name="sog"></param>
/// <returns></returns>
public bool TryGetSceneObjectGroup ( UUID fullID , out SceneObjectGroup sog )
{
sog = GetSceneObjectGroup ( fullID ) ;
return sog ! = null ;
}
2011-05-20 22:41:14 +00:00
/// <summary>
/// Get a prim by name from the scene (will return the first
2008-10-01 06:39:36 +00:00
/// found, if there are more than one prim with the same name)
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public SceneObjectPart GetSceneObjectPart ( string name )
{
2008-11-12 20:16:46 +00:00
return m_sceneGraph . GetSceneObjectPart ( name ) ;
2008-10-01 06:39:36 +00:00
}
2007-12-06 04:01:56 +00:00
/// <summary>
2008-11-10 18:10:00 +00:00
/// Get a prim via its local id
2007-12-06 04:01:56 +00:00
/// </summary>
/// <param name="localID"></param>
/// <returns></returns>
2007-11-03 19:14:22 +00:00
public SceneObjectPart GetSceneObjectPart ( uint localID )
2007-09-20 07:49:11 +00:00
{
2008-11-12 20:16:46 +00:00
return m_sceneGraph . GetSceneObjectPart ( localID ) ;
2007-11-03 19:14:22 +00:00
}
2007-09-20 07:49:11 +00:00
2007-12-06 04:01:56 +00:00
/// <summary>
2008-11-10 18:10:00 +00:00
/// Get a prim via its UUID
2007-12-06 04:01:56 +00:00
/// </summary>
/// <param name="fullID"></param>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public SceneObjectPart GetSceneObjectPart ( UUID fullID )
2007-11-03 19:14:22 +00:00
{
2008-11-12 20:16:46 +00:00
return m_sceneGraph . GetSceneObjectPart ( fullID ) ;
2007-09-20 07:49:11 +00:00
}
2007-09-24 04:49:05 +00:00
2012-09-06 09:40:37 +00:00
/// <summary>
/// Attempt to get a prim via its UUID
/// </summary>
/// <param name="fullID"></param>
/// <param name="sop"></param>
/// <returns></returns>
public bool TryGetSceneObjectPart ( UUID fullID , out SceneObjectPart sop )
{
sop = GetSceneObjectPart ( fullID ) ;
return sop ! = null ;
}
2009-11-14 06:13:40 +00:00
/// <summary>
/// Get a scene object group that contains the prim with the given local id
/// </summary>
/// <param name="localID"></param>
2011-12-17 02:23:24 +00:00
/// <returns>null if no scene object group containing that prim is found</returns>
2009-11-14 06:13:40 +00:00
public SceneObjectGroup GetGroupByPrim ( uint localID )
{
return m_sceneGraph . GetGroupByPrim ( localID ) ;
2012-02-02 00:27:20 +00:00
}
/// <summary>
/// Get a scene object group that contains the prim with the given uuid
/// </summary>
/// <param name="fullID"></param>
/// <returns>null if no scene object group containing that prim is found</returns>
public SceneObjectGroup GetGroupByPrim ( UUID fullID )
{
return m_sceneGraph . GetGroupByPrim ( fullID ) ;
2009-11-14 06:13:40 +00:00
}
2011-12-07 17:31:57 +00:00
public override bool TryGetScenePresence ( UUID agentID , out ScenePresence sp )
2007-09-24 04:49:05 +00:00
{
2011-12-07 17:31:57 +00:00
return m_sceneGraph . TryGetScenePresence ( agentID , out sp ) ;
2007-11-03 19:14:22 +00:00
}
2007-09-24 04:49:05 +00:00
2009-02-06 16:55:34 +00:00
public bool TryGetAvatarByName ( string avatarName , out ScenePresence avatar )
2007-11-03 19:14:22 +00:00
{
2008-11-12 20:16:46 +00:00
return m_sceneGraph . TryGetAvatarByName ( avatarName , out avatar ) ;
2007-09-24 04:49:05 +00:00
}
2007-10-29 11:54:31 +00:00
2011-11-04 00:06:08 +00:00
/// <summary>
/// Perform an action on all clients with an avatar in this scene (root only)
/// </summary>
/// <param name="action"></param>
public void ForEachRootClient ( Action < IClientAPI > action )
{
2011-11-04 00:53:51 +00:00
ForEachRootScenePresence ( delegate ( ScenePresence presence )
2011-11-04 00:06:08 +00:00
{
action ( presence . ControllingClient ) ;
} ) ;
}
/// <summary>
/// Perform an action on all clients connected to the region (root and child)
/// </summary>
/// <param name="action"></param>
2008-12-18 13:16:41 +00:00
public void ForEachClient ( Action < IClientAPI > action )
2007-10-29 11:54:31 +00:00
{
2009-10-27 17:07:35 +00:00
m_clientManager . ForEachSync ( action ) ;
2009-10-26 23:48:43 +00:00
}
public bool TryGetClient ( UUID avatarID , out IClientAPI client )
{
return m_clientManager . TryGetValue ( avatarID , out client ) ;
}
public bool TryGetClient ( System . Net . IPEndPoint remoteEndPoint , out IClientAPI client )
{
return m_clientManager . TryGetValue ( remoteEndPoint , out client ) ;
2007-10-29 11:54:31 +00:00
}
2007-11-03 19:14:22 +00:00
2009-09-29 14:54:56 +00:00
public void ForEachSOG ( Action < SceneObjectGroup > action )
{
m_sceneGraph . ForEachSOG ( action ) ;
}
2008-05-24 21:57:00 +00:00
/// <summary>
/// Returns a list of the entities in the scene. This is a new list so operations perform on the list itself
/// will not affect the original list of objects in the scene.
/// </summary>
/// <returns></returns>
2010-09-10 19:04:12 +00:00
public EntityBase [ ] GetEntities ( )
2007-12-17 16:41:28 +00:00
{
2008-11-12 20:16:46 +00:00
return m_sceneGraph . GetEntities ( ) ;
2007-12-17 16:41:28 +00:00
}
2007-11-03 19:14:22 +00:00
# endregion
2008-02-14 11:15:41 +00:00
2008-07-21 15:13:34 +00:00
2012-10-26 00:15:16 +00:00
// Commented pending deletion since this method no longer appears to do anything at all
// public bool NeedSceneCacheClear(UUID agentID)
// {
// IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
// if (inv == null)
// return true;
/ /
// return inv.NeedSceneCacheClear(agentID, this);
// }
2008-08-24 00:51:21 +00:00
2008-10-03 15:32:44 +00:00
public void CleanTempObjects ( )
{
2010-09-10 19:04:12 +00:00
EntityBase [ ] entities = GetEntities ( ) ;
foreach ( EntityBase obj in entities )
2008-10-03 15:32:44 +00:00
{
if ( obj is SceneObjectGroup )
{
SceneObjectGroup grp = ( SceneObjectGroup ) obj ;
2008-11-17 15:40:27 +00:00
if ( ! grp . IsDeleted )
2008-10-03 15:32:44 +00:00
{
if ( ( grp . RootPart . Flags & PrimFlags . TemporaryOnRez ) ! = 0 )
{
if ( grp . RootPart . Expires < = DateTime . Now )
2008-11-07 05:48:44 +00:00
DeleteSceneObject ( grp , false ) ;
2008-10-03 15:32:44 +00:00
}
}
}
}
2010-12-15 02:44:26 +00:00
2008-10-03 15:32:44 +00:00
}
2008-10-03 16:18:38 +00:00
public void DeleteFromStorage ( UUID uuid )
{
2012-06-28 23:03:22 +00:00
SimulationDataService . RemoveObject ( uuid , RegionInfo . RegionID ) ;
2008-10-03 16:18:38 +00:00
}
2008-10-10 01:10:33 +00:00
public int GetHealth ( )
{
2009-04-15 20:16:18 +00:00
// Returns:
// 1 = sim is up and accepting http requests. The heartbeat has
// stopped and the sim is probably locked up, but a remote
// admin restart may succeed
/ /
// 2 = Sim is up and the heartbeat is running. The sim is likely
// usable for people within and logins _may_ work
/ /
// 3 = We have seen a new user enter within the past 4 minutes
// which can be seen as positive confirmation of sim health
/ /
2009-12-01 15:48:11 +00:00
int health = 1 ; // Start at 1, means we're up
2012-03-23 00:54:37 +00:00
if ( ( Util . EnvironmentTickCountSubtract ( m_lastFrameTick ) ) < 1000 )
health + = 1 ;
2009-04-15 20:16:18 +00:00
else
return health ;
2008-10-10 01:10:33 +00:00
// A login in the last 4 mins? We can't be doing too badly
2009-12-01 15:48:11 +00:00
/ /
2009-11-29 10:06:25 +00:00
if ( ( Util . EnvironmentTickCountSubtract ( m_LastLogin ) ) < 240000 )
2008-10-10 01:10:33 +00:00
health + + ;
2009-04-15 20:16:18 +00:00
else
return health ;
2008-10-10 01:10:33 +00:00
2012-03-23 01:03:10 +00:00
// CheckHeartbeat();
2009-09-06 14:55:14 +00:00
2009-04-15 20:16:18 +00:00
return health ;
2008-10-10 01:10:33 +00:00
}
2008-12-26 12:58:02 +00:00
// This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
// update non-physical objects like the joint proxy objects that represent the position
// of the joints in the scene.
2008-12-30 01:08:07 +00:00
// This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene
2008-12-26 12:58:02 +00:00
// WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
2009-02-04 00:01:36 +00:00
// from within the OdePhysicsScene.
2008-12-26 12:58:02 +00:00
protected internal void jointMoved ( PhysicsJoint joint )
{
2008-12-30 01:08:07 +00:00
// m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked
2008-12-26 12:58:02 +00:00
SceneObjectPart jointProxyObject = GetSceneObjectPart ( joint . ObjectNameInScene ) ;
if ( jointProxyObject = = null )
{
jointErrorMessage ( joint , "WARNING, joint proxy not found, name " + joint . ObjectNameInScene ) ;
return ;
}
// now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine
SceneObjectPart trackedBody = GetSceneObjectPart ( joint . TrackedBodyName ) ; // FIXME: causes a sequential lookup
if ( trackedBody = = null ) return ; // the actor may have been deleted but the joint still lingers around a few frames waiting for deletion. during this time, trackedBody is NULL to prevent further motion of the joint proxy.
jointProxyObject . Velocity = trackedBody . Velocity ;
2009-11-02 19:28:35 +00:00
jointProxyObject . AngularVelocity = trackedBody . AngularVelocity ;
2008-12-26 12:58:02 +00:00
switch ( joint . Type )
{
case PhysicsJointType . Ball :
{
2009-10-26 06:16:12 +00:00
Vector3 jointAnchor = PhysicsScene . GetJointAnchor ( joint ) ;
2008-12-26 12:58:02 +00:00
Vector3 proxyPos = new Vector3 ( jointAnchor . X , jointAnchor . Y , jointAnchor . Z ) ;
jointProxyObject . ParentGroup . UpdateGroupPosition ( proxyPos ) ; // schedules the entire group for a terse update
}
break ;
case PhysicsJointType . Hinge :
{
2009-10-26 06:16:12 +00:00
Vector3 jointAnchor = PhysicsScene . GetJointAnchor ( joint ) ;
2008-12-26 12:58:02 +00:00
// Normally, we would just ask the physics scene to return the axis for the joint.
// Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should
// never occur. Therefore we cannot rely on ODE to always return a correct joint axis.
// Therefore the following call does not always work:
//PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint);
// instead we compute the joint orientation by saving the original joint orientation
// relative to one of the jointed bodies, and applying this transformation
// to the current position of the jointed bodies (the tracked body) to compute the
// current joint orientation.
if ( joint . TrackedBodyName = = null )
{
jointErrorMessage ( joint , "joint.TrackedBodyName is null, joint " + joint . ObjectNameInScene ) ;
}
Vector3 proxyPos = new Vector3 ( jointAnchor . X , jointAnchor . Y , jointAnchor . Z ) ;
Quaternion q = trackedBody . RotationOffset * joint . LocalRotation ;
jointProxyObject . ParentGroup . UpdateGroupPosition ( proxyPos ) ; // schedules the entire group for a terse update
2009-09-30 16:51:02 +00:00
jointProxyObject . ParentGroup . UpdateGroupRotationR ( q ) ; // schedules the entire group for a terse update
2008-12-26 12:58:02 +00:00
}
break ;
}
}
// This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
// update non-physical objects like the joint proxy objects that represent the position
// of the joints in the scene.
2008-12-30 01:08:07 +00:00
// This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene
2008-12-26 12:58:02 +00:00
// WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
// from within the OdePhysicsScene.
protected internal void jointDeactivated ( PhysicsJoint joint )
{
//m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene);
SceneObjectPart jointProxyObject = GetSceneObjectPart ( joint . ObjectNameInScene ) ;
if ( jointProxyObject = = null )
{
jointErrorMessage ( joint , "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint . ObjectNameInScene ) ;
return ;
}
// turn the proxy non-physical, which also stops its client-side interpolation
2010-08-13 19:23:53 +00:00
bool wasUsingPhysics = ( ( jointProxyObject . Flags & PrimFlags . Physics ) ! = 0 ) ;
2008-12-26 12:58:02 +00:00
if ( wasUsingPhysics )
{
jointProxyObject . UpdatePrimFlags ( false , false , true , false ) ; // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
}
}
// This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
// alert the user of errors by using the debug channel in the same way that scripts alert
// the user of compile errors.
2008-12-30 01:08:07 +00:00
// This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene
2008-12-26 12:58:02 +00:00
// WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
// from within the OdePhysicsScene.
public void jointErrorMessage ( PhysicsJoint joint , string message )
{
if ( joint ! = null )
{
2009-02-04 00:01:36 +00:00
if ( joint . ErrorMessageCount > PhysicsJoint . maxErrorMessages )
2008-12-26 12:58:02 +00:00
return ;
SceneObjectPart jointProxyObject = GetSceneObjectPart ( joint . ObjectNameInScene ) ;
if ( jointProxyObject ! = null )
{
2009-02-13 20:12:11 +00:00
SimChat ( Utils . StringToBytes ( "[NINJA]: " + message ) ,
2008-12-26 12:58:02 +00:00
ChatTypeEnum . DebugChannel ,
2147483647 ,
jointProxyObject . AbsolutePosition ,
jointProxyObject . Name ,
jointProxyObject . UUID ,
false ) ;
joint . ErrorMessageCount + + ;
if ( joint . ErrorMessageCount > PhysicsJoint . maxErrorMessages )
{
2009-02-13 20:12:11 +00:00
SimChat ( Utils . StringToBytes ( "[NINJA]: Too many messages for this joint, suppressing further messages." ) ,
2008-12-26 12:58:02 +00:00
ChatTypeEnum . DebugChannel ,
2147483647 ,
jointProxyObject . AbsolutePosition ,
jointProxyObject . Name ,
jointProxyObject . UUID ,
false ) ;
}
}
else
{
// couldn't find the joint proxy object; the error message is silently suppressed
}
}
}
2009-02-07 12:25:39 +00:00
public Scene ConsoleScene ( )
{
if ( MainConsole . Instance = = null )
return null ;
if ( MainConsole . Instance . ConsoleScene is Scene )
return ( Scene ) MainConsole . Instance . ConsoleScene ;
return null ;
}
2009-07-08 08:38:23 +00:00
public float GetGroundHeight ( float x , float y )
{
if ( x < 0 )
x = 0 ;
if ( x > = Heightmap . Width )
x = Heightmap . Width - 1 ;
if ( y < 0 )
y = 0 ;
if ( y > = Heightmap . Height )
y = Heightmap . Height - 1 ;
Vector3 p0 = new Vector3 ( x , y , ( float ) Heightmap [ ( int ) x , ( int ) y ] ) ;
Vector3 p1 = new Vector3 ( p0 ) ;
Vector3 p2 = new Vector3 ( p0 ) ;
p1 . X + = 1.0f ;
if ( p1 . X < Heightmap . Width )
p1 . Z = ( float ) Heightmap [ ( int ) p1 . X , ( int ) p1 . Y ] ;
p2 . Y + = 1.0f ;
if ( p2 . Y < Heightmap . Height )
p2 . Z = ( float ) Heightmap [ ( int ) p2 . X , ( int ) p2 . Y ] ;
Vector3 v0 = new Vector3 ( p1 . X - p0 . X , p1 . Y - p0 . Y , p1 . Z - p0 . Z ) ;
Vector3 v1 = new Vector3 ( p2 . X - p0 . X , p2 . Y - p0 . Y , p2 . Z - p0 . Z ) ;
v0 . Normalize ( ) ;
v1 . Normalize ( ) ;
Vector3 vsn = new Vector3 ( ) ;
vsn . X = ( v0 . Y * v1 . Z ) - ( v0 . Z * v1 . Y ) ;
vsn . Y = ( v0 . Z * v1 . X ) - ( v0 . X * v1 . Z ) ;
vsn . Z = ( v0 . X * v1 . Y ) - ( v0 . Y * v1 . X ) ;
vsn . Normalize ( ) ;
float xdiff = x - ( float ) ( ( int ) x ) ;
float ydiff = y - ( float ) ( ( int ) y ) ;
return ( ( ( vsn . X * xdiff ) + ( vsn . Y * ydiff ) ) / ( - 1 * vsn . Z ) ) + p0 . Z ;
}
2009-09-06 14:55:14 +00:00
2012-03-23 01:03:10 +00:00
// private void CheckHeartbeat()
// {
// if (m_firstHeartbeat)
// return;
/ /
// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000)
// StartTimer();
// }
2009-12-31 17:25:16 +00:00
public override ISceneObject DeserializeObject ( string representation )
{
return SceneObjectSerializer . FromXml2Format ( representation ) ;
}
public override bool AllowScriptCrossings
{
get { return m_allowScriptCrossings ; }
}
2010-03-08 07:19:45 +00:00
2013-04-24 23:24:48 +00:00
public Vector3 GetNearestAllowedPosition ( ScenePresence avatar )
2010-03-08 07:19:45 +00:00
{
2013-04-24 23:24:48 +00:00
return GetNearestAllowedPosition ( avatar , null ) ;
}
public Vector3 GetNearestAllowedPosition ( ScenePresence avatar , ILandObject excludeParcel )
{
ILandObject nearestParcel = GetNearestAllowedParcel ( avatar . UUID , avatar . AbsolutePosition . X , avatar . AbsolutePosition . Y , excludeParcel ) ;
2010-03-08 07:19:45 +00:00
if ( nearestParcel ! = null )
{
Vector3 dir = Vector3 . Normalize ( Vector3 . Multiply ( avatar . Velocity , - 1 ) ) ;
//Try to get a location that feels like where they came from
Vector3 ? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint ( avatar . AbsolutePosition , dir , nearestParcel ) ;
if ( nearestPoint ! = null )
{
2013-04-24 23:24:48 +00:00
Debug . WriteLine ( "Found a sane previous position based on velocity, sending them to: " + nearestPoint . ToString ( ) ) ;
2010-03-08 07:19:45 +00:00
return nearestPoint . Value ;
}
//Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel
Vector3 directionToParcelCenter = Vector3 . Subtract ( GetParcelCenterAtGround ( nearestParcel ) , avatar . AbsolutePosition ) ;
dir = Vector3 . Normalize ( directionToParcelCenter ) ;
nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint ( avatar . AbsolutePosition , dir , nearestParcel ) ;
if ( nearestPoint ! = null )
{
2013-04-24 23:24:48 +00:00
Debug . WriteLine ( "They had a zero velocity, sending them to: " + nearestPoint . ToString ( ) ) ;
2010-03-08 07:19:45 +00:00
return nearestPoint . Value ;
}
2013-04-24 23:24:48 +00:00
ILandObject dest = LandChannel . GetLandObject ( avatar . lastKnownAllowedPosition . X , avatar . lastKnownAllowedPosition . Y ) ;
if ( dest ! = excludeParcel )
{
// Ultimate backup if we have no idea where they are and
// the last allowed position was in another parcel
Debug . WriteLine ( "Have no idea where they are, sending them to: " + avatar . lastKnownAllowedPosition . ToString ( ) ) ;
return avatar . lastKnownAllowedPosition ;
}
2012-02-23 22:56:42 +00:00
2013-04-24 23:24:48 +00:00
// else fall through to region edge
2010-03-08 07:19:45 +00:00
}
//Go to the edge, this happens in teleporting to a region with no available parcels
Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition ( avatar ) ;
2011-11-24 22:45:29 +00:00
2010-03-08 07:19:45 +00:00
//Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
2013-04-24 23:24:48 +00:00
2010-03-08 07:19:45 +00:00
return nearestRegionEdgePoint ;
}
private Vector3 GetParcelCenterAtGround ( ILandObject parcel )
{
Vector2 center = GetParcelCenter ( parcel ) ;
return GetPositionAtGround ( center . X , center . Y ) ;
}
private Vector3 ? GetNearestPointInParcelAlongDirectionFromPoint ( Vector3 pos , Vector3 direction , ILandObject parcel )
{
Vector3 unitDirection = Vector3 . Normalize ( direction ) ;
//Making distance to search go through some sane limit of distance
for ( float distance = 0 ; distance < Constants . RegionSize * 2 ; distance + = . 5f )
{
Vector3 testPos = Vector3 . Add ( pos , Vector3 . Multiply ( unitDirection , distance ) ) ;
if ( parcel . ContainsPoint ( ( int ) testPos . X , ( int ) testPos . Y ) )
{
return testPos ;
}
}
return null ;
}
public ILandObject GetNearestAllowedParcel ( UUID avatarId , float x , float y )
2013-04-24 23:24:48 +00:00
{
return GetNearestAllowedParcel ( avatarId , x , y , null ) ;
}
public ILandObject GetNearestAllowedParcel ( UUID avatarId , float x , float y , ILandObject excludeParcel )
2010-03-08 07:19:45 +00:00
{
List < ILandObject > all = AllParcels ( ) ;
float minParcelDistance = float . MaxValue ;
ILandObject nearestParcel = null ;
foreach ( var parcel in all )
{
2013-04-24 23:24:48 +00:00
if ( ! parcel . IsEitherBannedOrRestricted ( avatarId ) & & parcel ! = excludeParcel )
2010-03-08 07:19:45 +00:00
{
float parcelDistance = GetParcelDistancefromPoint ( parcel , x , y ) ;
if ( parcelDistance < minParcelDistance )
{
minParcelDistance = parcelDistance ;
nearestParcel = parcel ;
}
}
}
return nearestParcel ;
}
private List < ILandObject > AllParcels ( )
{
return LandChannel . AllParcels ( ) ;
}
private float GetParcelDistancefromPoint ( ILandObject parcel , float x , float y )
{
return Vector2 . Distance ( new Vector2 ( x , y ) , GetParcelCenter ( parcel ) ) ;
}
//calculate the average center point of a parcel
private Vector2 GetParcelCenter ( ILandObject parcel )
{
int count = 0 ;
int avgx = 0 ;
int avgy = 0 ;
for ( int x = 0 ; x < Constants . RegionSize ; x + + )
{
for ( int y = 0 ; y < Constants . RegionSize ; y + + )
{
//Just keep a running average as we check if all the points are inside or not
if ( parcel . ContainsPoint ( x , y ) )
{
if ( count = = 0 )
{
avgx = x ;
avgy = y ;
}
else
{
avgx = ( avgx * count + x ) / ( count + 1 ) ;
avgy = ( avgy * count + y ) / ( count + 1 ) ;
}
count + = 1 ;
}
}
}
return new Vector2 ( avgx , avgy ) ;
}
private Vector3 GetNearestRegionEdgePosition ( ScenePresence avatar )
{
float xdistance = avatar . AbsolutePosition . X < Constants . RegionSize / 2 ? avatar . AbsolutePosition . X : Constants . RegionSize - avatar . AbsolutePosition . X ;
float ydistance = avatar . AbsolutePosition . Y < Constants . RegionSize / 2 ? avatar . AbsolutePosition . Y : Constants . RegionSize - avatar . AbsolutePosition . Y ;
//find out what vertical edge to go to
if ( xdistance < ydistance )
{
if ( avatar . AbsolutePosition . X < Constants . RegionSize / 2 )
{
return GetPositionAtAvatarHeightOrGroundHeight ( avatar , 0.0f , avatar . AbsolutePosition . Y ) ;
}
else
{
return GetPositionAtAvatarHeightOrGroundHeight ( avatar , Constants . RegionSize , avatar . AbsolutePosition . Y ) ;
}
}
//find out what horizontal edge to go to
else
{
if ( avatar . AbsolutePosition . Y < Constants . RegionSize / 2 )
{
return GetPositionAtAvatarHeightOrGroundHeight ( avatar , avatar . AbsolutePosition . X , 0.0f ) ;
}
else
{
return GetPositionAtAvatarHeightOrGroundHeight ( avatar , avatar . AbsolutePosition . X , Constants . RegionSize ) ;
}
}
}
private Vector3 GetPositionAtAvatarHeightOrGroundHeight ( ScenePresence avatar , float x , float y )
{
Vector3 ground = GetPositionAtGround ( x , y ) ;
2010-03-10 04:15:36 +00:00
if ( avatar . AbsolutePosition . Z > ground . Z )
2010-03-08 07:19:45 +00:00
{
ground . Z = avatar . AbsolutePosition . Z ;
}
return ground ;
}
private Vector3 GetPositionAtGround ( float x , float y )
{
return new Vector3 ( x , y , GetGroundHeight ( x , y ) ) ;
}
2010-05-04 16:10:13 +00:00
public List < UUID > GetEstateRegions ( int estateID )
{
2010-09-12 21:20:26 +00:00
IEstateDataService estateDataService = EstateDataService ;
if ( estateDataService = = null )
return new List < UUID > ( 0 ) ;
2010-05-04 16:10:13 +00:00
2010-09-12 21:20:26 +00:00
return estateDataService . GetRegions ( estateID ) ;
2010-05-04 16:10:13 +00:00
}
public void ReloadEstateData ( )
{
2010-09-12 21:20:26 +00:00
IEstateDataService estateDataService = EstateDataService ;
if ( estateDataService ! = null )
{
2012-06-28 23:03:22 +00:00
RegionInfo . EstateSettings = estateDataService . LoadEstateSettings ( RegionInfo . RegionID , false ) ;
2010-09-12 21:20:26 +00:00
TriggerEstateSunUpdate ( ) ;
}
2010-05-04 16:10:13 +00:00
}
public void TriggerEstateSunUpdate ( )
{
2012-12-25 08:47:45 +00:00
EventManager . TriggerEstateToolsSunUpdate ( RegionInfo . RegionHandle ) ;
2010-05-04 16:10:13 +00:00
}
2010-05-04 16:31:52 +00:00
private void HandleReloadEstate ( string module , string [ ] cmd )
{
if ( MainConsole . Instance . ConsoleScene = = null | |
( MainConsole . Instance . ConsoleScene is Scene & &
( Scene ) MainConsole . Instance . ConsoleScene = = this ) )
{
ReloadEstateData ( ) ;
}
}
2010-05-31 23:25:24 +00:00
2011-04-13 20:17:43 +00:00
/// <summary>
/// Get the volume of space that will encompass all the given objects.
/// </summary>
/// <param name="objects"></param>
/// <param name="minX"></param>
/// <param name="maxX"></param>
/// <param name="minY"></param>
/// <param name="maxY"></param>
/// <param name="minZ"></param>
/// <param name="maxZ"></param>
/// <returns></returns>
public static Vector3 [ ] GetCombinedBoundingBox (
List < SceneObjectGroup > objects ,
out float minX , out float maxX , out float minY , out float maxY , out float minZ , out float maxZ )
2010-05-31 23:25:24 +00:00
{
2013-04-06 01:34:51 +00:00
minX = float . MaxValue ;
maxX = float . MinValue ;
minY = float . MaxValue ;
maxY = float . MinValue ;
minZ = float . MaxValue ;
maxZ = float . MinValue ;
2010-05-31 23:25:24 +00:00
List < Vector3 > offsets = new List < Vector3 > ( ) ;
foreach ( SceneObjectGroup g in objects )
{
float ominX , ominY , ominZ , omaxX , omaxY , omaxZ ;
2010-10-06 23:13:17 +00:00
Vector3 vec = g . AbsolutePosition ;
2010-05-31 23:25:24 +00:00
g . GetAxisAlignedBoundingBoxRaw ( out ominX , out omaxX , out ominY , out omaxY , out ominZ , out omaxZ ) ;
2011-04-13 21:29:12 +00:00
// m_log.DebugFormat(
// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}",
// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ));
2010-05-31 23:25:24 +00:00
2010-10-06 23:13:17 +00:00
ominX + = vec . X ;
omaxX + = vec . X ;
ominY + = vec . Y ;
omaxY + = vec . Y ;
ominZ + = vec . Z ;
omaxZ + = vec . Z ;
2010-05-31 23:25:24 +00:00
if ( minX > ominX )
minX = ominX ;
if ( minY > ominY )
minY = ominY ;
if ( minZ > ominZ )
minZ = ominZ ;
if ( maxX < omaxX )
maxX = omaxX ;
if ( maxY < omaxY )
maxY = omaxY ;
if ( maxZ < omaxZ )
maxZ = omaxZ ;
}
foreach ( SceneObjectGroup g in objects )
{
Vector3 vec = g . AbsolutePosition ;
vec . X - = minX ;
vec . Y - = minY ;
vec . Z - = minZ ;
offsets . Add ( vec ) ;
}
return offsets . ToArray ( ) ;
}
2010-08-20 07:36:23 +00:00
2011-11-19 00:07:34 +00:00
/// <summary>
/// Regenerate the maptile for this scene.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
2011-12-31 05:32:28 +00:00
private void RegenerateMaptile ( )
2010-08-20 07:36:23 +00:00
{
IWorldMapModule mapModule = RequestModuleInterface < IWorldMapModule > ( ) ;
if ( mapModule ! = null )
mapModule . GenerateMaptile ( ) ;
}
2010-08-24 16:20:24 +00:00
2011-12-31 05:32:28 +00:00
private void RegenerateMaptileAndReregister ( object sender , ElapsedEventArgs e )
{
RegenerateMaptile ( ) ;
// We need to propagate the new image UUID to the grid service
// so that all simulators can retrieve it
string error = GridService . RegisterRegion ( RegionInfo . ScopeID , new GridRegion ( RegionInfo ) ) ;
if ( error ! = string . Empty )
throw new Exception ( error ) ;
}
2012-05-23 23:31:14 +00:00
/// <summary>
/// This method is called across the simulation connector to
/// determine if a given agent is allowed in this region
/// AS A ROOT AGENT
/// </summary>
/// <remarks>
/// Returning false here will prevent them
/// from logging into the region, teleporting into the region
/// or corssing the broder walking, but will NOT prevent
/// child agent creation, thereby emulating the SL behavior.
/// </remarks>
/// <param name='agentID'></param>
/// <param name='position'></param>
/// <param name='reason'></param>
/// <returns></returns>
2011-02-16 08:06:11 +00:00
public bool QueryAccess ( UUID agentID , Vector3 position , out string reason )
2010-12-09 01:55:32 +00:00
{
2013-04-28 23:55:34 +00:00
reason = "You are banned from the region" ;
2012-05-23 23:31:14 +00:00
if ( EntityTransferModule . IsInTransit ( agentID ) )
{
2012-05-25 01:02:53 +00:00
reason = "Agent is still in transit from this region" ;
2012-05-23 23:31:14 +00:00
2012-05-25 01:02:53 +00:00
m_log . WarnFormat (
"[SCENE]: Denying agent {0} entry into {1} since region still has them registered as in transit" ,
2012-05-23 23:31:14 +00:00
agentID , RegionInfo . RegionName ) ;
return false ;
}
2013-04-28 23:55:34 +00:00
if ( Permissions . IsGod ( agentID ) )
{
reason = String . Empty ;
return true ;
}
2012-05-17 22:33:26 +00:00
// FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
// However, the long term fix is to make sure root agent count is always accurate.
m_sceneGraph . RecalculateStats ( ) ;
int num = m_sceneGraph . GetRootAgentCount ( ) ;
2011-04-21 22:03:38 +00:00
if ( num > = RegionInfo . RegionSettings . AgentLimit )
{
if ( ! Permissions . IsAdministrator ( agentID ) )
{
reason = "The region is full" ;
2012-05-17 22:33:26 +00:00
m_log . DebugFormat (
"[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}" ,
agentID , RegionInfo . RegionName , RegionInfo . RegionSettings . AgentLimit ) ;
2011-04-21 22:03:38 +00:00
return false ;
}
}
2013-04-28 23:55:34 +00:00
ScenePresence presence = GetScenePresence ( agentID ) ;
IClientAPI client = null ;
AgentCircuitData aCircuit = null ;
if ( presence ! = null )
{
client = presence . ControllingClient ;
if ( client ! = null )
aCircuit = client . RequestClientInfo ( ) ;
}
// We may be called before there is a presence or a client.
// Fake AgentCircuitData to keep IAuthorizationModule smiling
if ( client = = null )
{
aCircuit = new AgentCircuitData ( ) ;
aCircuit . AgentID = agentID ;
aCircuit . firstname = String . Empty ;
aCircuit . lastname = String . Empty ;
}
try
{
if ( ! AuthorizeUser ( aCircuit , out reason ) )
{
// m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
return false ;
}
}
catch ( Exception e )
{
m_log . DebugFormat ( "[SCENE]: Exception authorizing agent: {0} " + e . StackTrace , e . Message ) ;
return false ;
}
2012-01-26 10:21:45 +00:00
if ( position = = Vector3 . Zero ) // Teleport
{
if ( ! RegionInfo . EstateSettings . AllowDirectTeleport )
{
SceneObjectGroup telehub ;
if ( RegionInfo . RegionSettings . TelehubObject ! = UUID . Zero & & ( telehub = GetSceneObjectGroup ( RegionInfo . RegionSettings . TelehubObject ) ) ! = null )
{
List < SpawnPoint > spawnPoints = RegionInfo . RegionSettings . SpawnPoints ( ) ;
bool banned = true ;
foreach ( SpawnPoint sp in spawnPoints )
{
Vector3 spawnPoint = sp . GetLocation ( telehub . AbsolutePosition , telehub . GroupRotation ) ;
ILandObject land = LandChannel . GetLandObject ( spawnPoint . X , spawnPoint . Y ) ;
if ( land = = null )
continue ;
if ( land . IsEitherBannedOrRestricted ( agentID ) )
continue ;
banned = false ;
break ;
}
if ( banned )
{
2013-02-10 18:01:33 +00:00
if ( Permissions . IsAdministrator ( agentID ) = = false | | Permissions . IsGridGod ( agentID ) = = false )
{
reason = "No suitable landing point found" ;
return false ;
}
reason = "Administrative access only" ;
return true ;
2012-01-26 10:21:45 +00:00
}
}
}
2013-04-28 23:55:34 +00:00
float posX = 128.0f ;
float posY = 128.0f ;
if ( ! TestLandRestrictions ( agentID , out reason , ref posX , ref posY ) )
{
// m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
return false ;
}
}
else // Walking
{
ILandObject land = LandChannel . GetLandObject ( position . X , position . Y ) ;
if ( land = = null )
return false ;
bool banned = land . IsBannedFromLand ( agentID ) ;
bool restricted = land . IsRestrictedFromLand ( agentID ) ;
if ( banned | | restricted )
return false ;
2012-01-26 10:21:45 +00:00
}
2011-02-16 08:06:11 +00:00
reason = String . Empty ;
2010-12-09 01:55:32 +00:00
return true ;
}
2011-09-21 22:56:11 +00:00
/// <summary>
/// This method deals with movement when an avatar is automatically moving (but this is distinct from the
/// autopilot that moves an avatar to a sit target!.
/// </summary>
/// <remarks>
/// This is not intended as a permament location for this method.
/// </remarks>
/// <param name="presence"></param>
private void HandleOnSignificantClientMovement ( ScenePresence presence )
{
if ( presence . MovingToTarget )
{
double distanceToTarget = Util . GetDistanceTo ( presence . AbsolutePosition , presence . MoveToPositionTarget ) ;
// m_log.DebugFormat(
// "[SCENE]: Abs pos of {0} is {1}, target {2}, distance {3}",
// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget);
// Check the error term of the current position in relation to the target position
if ( distanceToTarget < = ScenePresence . SIGNIFICANT_MOVEMENT )
{
// We are close enough to the target
// m_log.DebugFormat("[SCENEE]: Stopping autopilot of {0}", presence.Name);
presence . Velocity = Vector3 . Zero ;
presence . AbsolutePosition = presence . MoveToPositionTarget ;
presence . ResetMoveToTarget ( ) ;
2011-12-12 10:43:38 +00:00
if ( presence . Flying )
2011-09-21 22:56:11 +00:00
{
// A horrible hack to stop the avatar dead in its tracks rather than having them overshoot
// the target if flying.
// We really need to be more subtle (slow the avatar as it approaches the target) or at
// least be able to set collision status once, rather than 5 times to give it enough
// weighting so that that PhysicsActor thinks it really is colliding.
for ( int i = 0 ; i < 5 ; i + + )
2011-12-12 10:43:38 +00:00
presence . IsColliding = true ;
2011-09-21 22:56:11 +00:00
2011-09-21 23:16:05 +00:00
if ( presence . LandAtTarget )
2011-12-12 10:43:38 +00:00
presence . Flying = false ;
2011-09-21 22:56:11 +00:00
2011-09-21 23:16:05 +00:00
// Vector3 targetPos = presence.MoveToPositionTarget;
2011-09-21 22:56:11 +00:00
// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y];
// if (targetPos.Z - terrainHeight < 0.2)
// {
2011-12-12 10:43:38 +00:00
// presence.Flying = false;
2011-09-21 22:56:11 +00:00
// }
}
// m_log.DebugFormat(
// "[SCENE]: AgentControlFlags {0}, MovementFlag {1} for {2}",
// presence.AgentControlFlags, presence.MovementFlag, presence.Name);
}
else
{
// m_log.DebugFormat(
// "[SCENE]: Updating npc {0} at {1} for next movement to {2}",
// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget);
Vector3 agent_control_v3 = new Vector3 ( ) ;
2012-02-23 22:56:42 +00:00
presence . HandleMoveToTargetUpdate ( 1 , ref agent_control_v3 ) ;
2011-09-21 22:56:11 +00:00
presence . AddNewMovement ( agent_control_v3 ) ;
}
}
}
2012-05-13 21:11:44 +00:00
// manage and select spawn points in sequence
public int SpawnPoint ( )
{
int spawnpoints = RegionInfo . RegionSettings . SpawnPoints ( ) . Count ;
if ( spawnpoints = = 0 )
return 0 ;
m_SpawnPoint + + ;
if ( m_SpawnPoint > spawnpoints )
m_SpawnPoint = 1 ;
return m_SpawnPoint - 1 ;
}
2012-08-01 21:36:24 +00:00
2012-12-04 22:33:25 +00:00
/// <summary>
/// Wrappers to get physics modules retrieve assets.
/// </summary>
/// <remarks>
/// Has to be done this way
/// because we can't assign the asset service to physics directly - at the
/// time physics are instantiated it's not registered but it will be by
/// the time the first prim exists.
/// </remarks>
/// <param name="assetID"></param>
/// <param name="callback"></param>
2012-08-01 21:36:24 +00:00
public void PhysicsRequestAsset ( UUID assetID , AssetReceivedDelegate callback )
{
AssetService . Get ( assetID . ToString ( ) , callback , PhysicsAssetReceived ) ;
}
private void PhysicsAssetReceived ( string id , Object sender , AssetBase asset )
{
AssetReceivedDelegate callback = ( AssetReceivedDelegate ) sender ;
callback ( asset ) ;
}
2012-08-15 16:22:16 +00:00
public string GetExtraSetting ( string name )
{
2012-09-17 12:03:34 +00:00
if ( m_extraSettings = = null )
return String . Empty ;
2012-08-15 16:22:16 +00:00
string val ;
if ( ! m_extraSettings . TryGetValue ( name , out val ) )
return String . Empty ;
return val ;
}
public void StoreExtraSetting ( string name , string val )
{
2012-10-01 23:51:38 +00:00
if ( m_extraSettings = = null )
return ;
2012-08-15 16:22:16 +00:00
string oldVal ;
if ( m_extraSettings . TryGetValue ( name , out oldVal ) )
{
if ( oldVal = = val )
return ;
}
m_extraSettings [ name ] = val ;
m_SimulationDataService . SaveExtra ( RegionInfo . RegionID , name , val ) ;
m_eventManager . TriggerExtraSettingChanged ( this , name , val ) ;
}
public void RemoveExtraSetting ( string name )
{
2012-10-01 23:51:38 +00:00
if ( m_extraSettings = = null )
return ;
2012-08-15 16:22:16 +00:00
if ( ! m_extraSettings . ContainsKey ( name ) )
return ;
m_extraSettings . Remove ( name ) ;
m_SimulationDataService . RemoveExtra ( RegionInfo . RegionID , name ) ;
m_eventManager . TriggerExtraSettingChanged ( this , name , String . Empty ) ;
}
2007-07-16 15:40:11 +00:00
}
2010-08-20 07:36:23 +00:00
}