/OpenSim/Region/Framework/Scenes/Scene.cs
C# | 4980 lines | 3384 code | 694 blank | 902 comment | 506 complexity | cb7c8e4c8650ce7af238a32b7e33a597 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyrightD
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Text;
- using System.Threading;
- using System.Timers;
- using System.Xml;
- using Nini.Config;
- using OpenMetaverse;
- using OpenMetaverse.Packets;
- using OpenMetaverse.Imaging;
- using OpenSim.Framework;
- using OpenSim.Services.Interfaces;
- using OpenSim.Framework.Communications;
- using OpenSim.Framework.Communications.Cache;
- using OpenSim.Framework.Communications.Clients;
- using OpenSim.Framework.Console;
- using OpenSim.Region.Framework.Interfaces;
- using OpenSim.Region.Framework.Scenes.Scripting;
- using OpenSim.Region.Framework.Scenes.Serialization;
- using OpenSim.Region.Physics.Manager;
- using Timer=System.Timers.Timer;
- using TPFlags = OpenSim.Framework.Constants.TeleportFlags;
- using GridRegion = OpenSim.Services.Interfaces.GridRegion;
- namespace OpenSim.Region.Framework.Scenes
- {
- public delegate bool FilterAvatarList(ScenePresence avatar);
- public partial class Scene : SceneBase
- {
- public enum UpdatePrioritizationSchemes {
- Time = 0,
- Distance = 1,
- SimpleAngularDistance = 2,
- FrontBack = 3,
- }
- public delegate void SynchronizeSceneHandler(Scene scene);
- public SynchronizeSceneHandler SynchronizeScene = null;
- /* Used by the loadbalancer plugin on GForge */
- protected int m_splitRegionID = 0;
- public int SplitRegionID
- {
- get { return m_splitRegionID; }
- set { m_splitRegionID = value; }
- }
- private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
- private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
- #region Fields
- protected Timer m_restartWaitTimer = new Timer();
- public SimStatsReporter StatsReporter;
- protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
- protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
- private volatile int m_bordersLocked = 0;
- public bool BordersLocked
- {
- get { return m_bordersLocked == 1; }
- set
- {
- if (value == true)
- m_bordersLocked = 1;
- else
- m_bordersLocked = 0;
- }
- }
- 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>();
- /// <value>
- /// The scene graph for this scene
- /// </value>
- /// TODO: Possibly stop other classes being able to manipulate this directly.
- private SceneGraph m_sceneGraph;
- /// <summary>
- /// Are we applying physics to any of the prims in this scene?
- /// </summary>
- public bool m_physicalPrim;
- public float m_maxNonphys = 256;
- public float m_maxPhys = 10;
- public bool m_clampPrimSize;
- public bool m_trustBinaries;
- public bool m_allowScriptCrossings;
- public bool m_useFlySlow;
- public bool m_usePreJump;
- public bool m_seeIntoRegionFromNeighbor;
- // 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;
- public int MaxUndoCount = 5;
- private int m_RestartTimerCounter;
- private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
- private int m_incrementsof15seconds;
- private volatile bool m_backingup;
- private bool m_useAsyncWhenPossible;
- private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
- private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>();
- protected string m_simulatorVersion = "OpenSimulator Server";
- protected ModuleLoader m_moduleLoader;
- protected StorageManager m_storageManager;
- protected AgentCircuitManager m_authenticateHandler;
- public CommunicationsManager CommsManager;
- protected SceneCommunicationService m_sceneGridService;
- public bool LoginsDisabled = true;
- public new float TimeDilation
- {
- get { return m_sceneGraph.PhysicsScene.TimeDilation; }
- }
- public SceneCommunicationService SceneGridService
- {
- get { return m_sceneGridService; }
- }
- public IXfer XferManager;
- protected IAssetService m_AssetService;
- protected IAuthorizationService m_AuthorizationService;
- private Object m_heartbeatLock = new Object();
- public IAssetService AssetService
- {
- get
- {
- if (m_AssetService == null)
- {
- m_AssetService = RequestModuleInterface<IAssetService>();
- if (m_AssetService == null)
- {
- throw new Exception("No IAssetService available.");
- }
- }
- return m_AssetService;
- }
- }
-
- public IAuthorizationService AuthorizationService
- {
- get
- {
- if (m_AuthorizationService == null)
- {
- m_AuthorizationService = RequestModuleInterface<IAuthorizationService>();
- 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");
- }
- }
- return m_AuthorizationService;
- }
- }
- protected IInventoryService m_InventoryService;
- public IInventoryService InventoryService
- {
- get
- {
- if (m_InventoryService == null)
- {
- m_InventoryService = RequestModuleInterface<IInventoryService>();
- if (m_InventoryService == null)
- {
- 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.");
- }
- }
- return m_InventoryService;
- }
- }
- protected IGridService m_GridService;
- 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;
- }
- }
- protected IXMLRPC m_xmlrpcModule;
- protected IWorldComm m_worldCommModule;
- protected IAvatarFactory m_AvatarFactory;
- public IAvatarFactory AvatarFactory
- {
- get { return m_AvatarFactory; }
- }
- protected IConfigSource m_config;
- protected IRegionSerialiserModule m_serialiser;
- protected IInterregionCommsOut m_interregionCommsOut;
- protected IInterregionCommsIn m_interregionCommsIn;
- protected IDialogModule m_dialogModule;
- protected ITeleportModule m_teleportModule;
- protected ICapabilitiesModule m_capsModule;
- public ICapabilitiesModule CapsModule
- {
- get { return m_capsModule; }
- }
- protected override IConfigSource GetConfig()
- {
- return m_config;
- }
- // Central Update Loop
- protected int m_fps = 10;
- protected uint m_frame;
- protected float m_timespan = 0.089f;
- protected DateTime m_lastupdate = DateTime.UtcNow;
- private int m_update_physics = 1;
- private int m_update_entitymovement = 1;
- private int m_update_objects = 1; // Update objects which have scheduled themselves for updates
- 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;
- private int m_update_land = 1;
- 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;
- private int lastCompletedFrame;
- 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; } }
- public int MonitorLastFrameTick { get { return lastCompletedFrame; } }
- private bool m_physics_enabled = true;
- private bool m_scripts_enabled = true;
- private string m_defaultScriptEngine;
- private int m_LastLogin;
- private Thread HeartbeatThread;
- private volatile bool shuttingdown;
- private int m_lastUpdate;
- private bool m_firstHeartbeat = true;
- private UpdatePrioritizationSchemes m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
- private bool m_reprioritization_enabled = true;
- private double m_reprioritization_interval = 5000.0;
- private double m_root_reprioritization_distance = 10.0;
- private double m_child_reprioritization_distance = 20.0;
- private object m_deleting_scene_object = new object();
- // 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;
- #endregion
- #region Properties
- public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return this.m_update_prioritization_scheme; } }
- public bool IsReprioritizationEnabled { get { return m_reprioritization_enabled; } }
- public double ReprioritizationInterval { get { return m_reprioritization_interval; } }
- public double RootReprioritizationDistance { get { return m_root_reprioritization_distance; } }
- public double ChildReprioritizationDistance { get { return m_child_reprioritization_distance; } }
- public AgentCircuitManager AuthenticateHandler
- {
- get { return m_authenticateHandler; }
- }
- public SceneGraph SceneContents
- {
- get { return m_sceneGraph; }
- }
- // an instance to the physics plugin's Scene object.
- public PhysicsScene PhysicsScene
- {
- get { return m_sceneGraph.PhysicsScene; }
- 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;
- }
- }
- }
- // This gets locked so things stay thread safe.
- public object SyncRoot
- {
- get { return m_sceneGraph.m_syncRoot; }
- }
- /// <summary>
- /// This is for llGetRegionFPS
- /// </summary>
- public float SimulatorFPS
- {
- get { return StatsReporter.getLastReportedSimFPS(); }
- }
-
- public float[] SimulatorStats
- {
- get { return StatsReporter.getLastReportedSimStats(); }
- }
- public string DefaultScriptEngine
- {
- get { return m_defaultScriptEngine; }
- }
- public EntityManager Entities
- {
- get { return m_sceneGraph.Entities; }
- }
- public Dictionary<UUID, ScenePresence> m_restorePresences
- {
- get { return m_sceneGraph.RestorePresences; }
- set { m_sceneGraph.RestorePresences = value; }
- }
- public int objectCapacity = 45000;
- #endregion
- #region BinaryStats
- public class StatLogger
- {
- public DateTime StartTime;
- public string Path;
- public System.IO.BinaryWriter Log;
- }
- static StatLogger m_statLog = null;
- static TimeSpan m_statLogPeriod = TimeSpan.FromSeconds(300);
- static string m_statsDir = String.Empty;
- static Object m_statLockObject = new Object();
- private void LogSimStats(SimStats stats)
- {
- SimStatsPacket pack = new SimStatsPacket();
- pack.Region = new SimStatsPacket.RegionBlock();
- pack.Region.RegionX = stats.RegionX;
- pack.Region.RegionY = stats.RegionY;
- pack.Region.RegionFlags = stats.RegionFlags;
- pack.Region.ObjectCapacity = stats.ObjectCapacity;
- //pack.Region = //stats.RegionBlock;
- pack.Stat = stats.StatsBlock;
- pack.Header.Reliable = false;
- // note that we are inside the reporter lock when called
- DateTime now = DateTime.Now;
- // hide some time information into the packet
- pack.Header.Sequence = (uint)now.Ticks;
- lock (m_statLockObject) // m_statLog is shared so make sure there is only executer here
- {
- try
- {
- if (m_statLog == null || now > m_statLog.StartTime + m_statLogPeriod)
- {
- // First log file or time has expired, start writing to a new log file
- if (m_statLog != null && m_statLog.Log != null)
- {
- m_statLog.Log.Close();
- }
- m_statLog = new StatLogger();
- m_statLog.StartTime = now;
- m_statLog.Path = (m_statsDir.Length > 0 ? m_statsDir + System.IO.Path.DirectorySeparatorChar.ToString() : "")
- + String.Format("stats-{0}.log", now.ToString("yyyyMMddHHmmss"));
- m_statLog.Log = new BinaryWriter(File.Open(m_statLog.Path, FileMode.Append, FileAccess.Write));
- }
- // Write the serialized data to disk
- if (m_statLog != null && m_statLog.Log != null)
- m_statLog.Log.Write(pack.ToBytes());
- }
- catch (Exception ex)
- {
- m_log.Error("statistics gathering failed: " + ex.Message, ex);
- if (m_statLog != null && m_statLog.Log != null)
- {
- m_statLog.Log.Close();
- }
- m_statLog = null;
- }
- }
- return;
- }
- #endregion
- #region Constructors
- public Scene(RegionInfo regInfo, AgentCircuitManager authen,
- CommunicationsManager commsMan, SceneCommunicationService sceneGridService,
- StorageManager storeManager,
- ModuleLoader moduleLoader, bool dumpAssetsToFile, bool physicalPrim,
- bool SeeIntoRegionFromNeighbor, IConfigSource config, string simulatorVersion)
- {
- m_config = config;
- Random random = new Random();
-
- BordersLocked = true;
- Border northBorder = new Border();
- northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<---
- northBorder.CrossDirection = Cardinals.N;
- NorthBorders.Add(northBorder);
- Border southBorder = new Border();
- southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
- southBorder.CrossDirection = Cardinals.S;
- SouthBorders.Add(southBorder);
- Border eastBorder = new Border();
- eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<---
- eastBorder.CrossDirection = Cardinals.E;
- EastBorders.Add(eastBorder);
- Border westBorder = new Border();
- westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
- westBorder.CrossDirection = Cardinals.W;
- WestBorders.Add(westBorder);
- BordersLocked = false;
- m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue/2))+(uint)(uint.MaxValue/4);
- m_moduleLoader = moduleLoader;
- m_authenticateHandler = authen;
- CommsManager = commsMan;
- m_sceneGridService = sceneGridService;
- m_storageManager = storeManager;
- m_regInfo = regInfo;
- m_regionHandle = m_regInfo.RegionHandle;
- m_regionName = m_regInfo.RegionName;
- m_datastore = m_regInfo.DataStore;
- m_lastUpdate = Util.EnvironmentTickCount();
- m_physicalPrim = physicalPrim;
- m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
- m_eventManager = new EventManager();
- m_permissions = new ScenePermissions(this);
- m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
- m_asyncSceneObjectDeleter.Enabled = true;
- // Load region settings
- m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
- if (m_storageManager.EstateDataStore != null)
- {
- m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID);
- }
- //Bind Storage Manager functions to some land manager functions for this scene
- EventManager.OnLandObjectAdded +=
- new EventManager.LandObjectAdded(m_storageManager.DataStore.StoreLandObject);
- EventManager.OnLandObjectRemoved +=
- new EventManager.LandObjectRemoved(m_storageManager.DataStore.RemoveLandObject);
- m_sceneGraph = new SceneGraph(this, m_regInfo);
- // If the scene graph has an Unrecoverable error, restart this sim.
- // 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
- m_sceneGraph.UnRecoverableError += RestartNow;
- RegisterDefaultSceneEvents();
- DumpAssetsToFile = dumpAssetsToFile;
- m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts;
- m_physics_enabled = !RegionInfo.RegionSettings.DisablePhysics;
- StatsReporter = new SimStatsReporter(this);
- StatsReporter.OnSendStatsResult += SendSimStatsPackets;
- StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
- StatsReporter.SetObjectCapacity(objectCapacity);
- // Old
- /*
- m_simulatorVersion = simulatorVersion
- + " (OS " + Util.GetOperatingSystemInformation() + ")"
- + " ChilTasks:" + m_seeIntoRegionFromNeighbor.ToString()
- + " PhysPrim:" + m_physicalPrim.ToString();
- */
- m_simulatorVersion = simulatorVersion + " (" + Util.GetRuntimeInformation() + ")";
- try
- {
- // Region config overrides global config
- //
- IConfig startupConfig = m_config.Configs["Startup"];
- // Should we try to run loops synchronously or asynchronously?
- m_useAsyncWhenPossible = startupConfig.GetBoolean("use_async_when_possible", false);
- //Animation states
- m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
- // TODO: Change default to true once the feature is supported
- m_usePreJump = startupConfig.GetBoolean("enableprejump", false);
- m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
- if (RegionInfo.NonphysPrimMax > 0)
- {
- m_maxNonphys = RegionInfo.NonphysPrimMax;
- }
- m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
- if (RegionInfo.PhysPrimMax > 0)
- {
- m_maxPhys = RegionInfo.PhysPrimMax;
- }
- // Here, if clamping is requested in either global or
- // local config, it will be used
- //
- m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
- if (RegionInfo.ClampPrimSize)
- {
- m_clampPrimSize = true;
- }
- m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
- m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
- m_dontPersistBefore =
- startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
- m_dontPersistBefore *= 10000000;
- m_persistAfter =
- startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
- m_persistAfter *= 10000000;
- m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
- IConfig packetConfig = m_config.Configs["PacketPool"];
- if (packetConfig != null)
- {
- PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
- PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
- }
- m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
- IConfig interest_management_config = m_config.Configs["InterestManagement"];
- if (interest_management_config != null)
- {
- string update_prioritization_scheme = interest_management_config.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower();
- switch (update_prioritization_scheme)
- {
- case "time":
- m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
- break;
- case "distance":
- m_update_prioritization_scheme = UpdatePrioritizationSchemes.Distance;
- break;
- case "simpleangulardistance":
- m_update_prioritization_scheme = UpdatePrioritizationSchemes.SimpleAngularDistance;
- break;
- case "frontback":
- m_update_prioritization_scheme = UpdatePrioritizationSchemes.FrontBack;
- break;
- default:
- m_log.Warn("[SCENE]: UpdatePrioritizationScheme was not recognized, setting to default settomg of Time");
- m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
- break;
- }
- m_reprioritization_enabled = interest_management_config.GetBoolean("ReprioritizationEnabled", true);
- m_reprioritization_interval = interest_management_config.GetDouble("ReprioritizationInterval", 5000.0);
- m_root_reprioritization_distance = interest_management_config.GetDouble("RootReprioritizationDistance", 10.0);
- m_child_reprioritization_distance = interest_management_config.GetDouble("ChildReprioritizationDistance", 20.0);
- }
- m_log.Info("[SCENE]: Using the " + m_update_prioritization_scheme + " prioritization scheme");
- #region BinaryStats
- try
- {
- IConfig statConfig = m_config.Configs["Statistics.Binary"];
- if (statConfig.Contains("enabled") && statConfig.GetBoolean("enabled"))
- {
- if (statConfig.Contains("collect_region_stats"))
- {
- if (statConfig.GetBoolean("collect_region_stats"))
- {
- // if enabled, add us to the event. If not enabled, I won't get called
- StatsReporter.OnSendStatsResult += LogSimStats;
- }
- }
- if (statConfig.Contains("region_stats_period_seconds"))
- {
- m_statLogPeriod = TimeSpan.FromSeconds(statConfig.GetInt("region_stats_period_seconds"));
- }
- if (statConfig.Contains("stats_dir"))
- {
- m_statsDir = statConfig.GetString("stats_dir");
- }
- }
- }
- catch
- {
- // if it doesn't work, we don't collect anything
- }
- #endregion BinaryStats
- }
- catch
- {
- m_log.Warn("[SCENE]: Failed to load StartupConfig");
- }
- }
- /// <summary>
- /// Mock constructor for scene group persistency unit tests.
- /// SceneObjectGroup RegionId property is delegated to Scene.
- /// </summary>
- /// <param name="regInfo"></param>
- public Scene(RegionInfo regInfo)
- {
- BordersLocked = true;
- Border northBorder = new Border();
- northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<---
- northBorder.CrossDirection = Cardinals.N;
- NorthBorders.Add(northBorder);
- Border southBorder = new Border();
- southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
- southBorder.CrossDirection = Cardinals.S;
- SouthBorders.Add(southBorder);
- Border eastBorder = new Border();
- eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<---
- eastBorder.CrossDirection = Cardinals.E;
- EastBorders.Add(eastBorder);
- Border westBorder = new Border();
- westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
- westBorder.CrossDirection = Cardinals.W;
- WestBorders.Add(westBorder);
- BordersLocked = false;
- m_regInfo = regInfo;
- m_eventManager = new EventManager();
- m_lastUpdate = Util.EnvironmentTickCount();
- }
- #endregion
- #region Startup / Close Methods
- public bool ShuttingDown
- {
- get { return shuttingdown; }
- }
- /// <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; }
- }
- protected virtual void RegisterDefaultSceneEvents()
- {
- IDialogModule dm = RequestModuleInterface<IDialogModule>();
- if (dm != null)
- m_eventManager.OnPermissionError += dm.SendAlertToUser;
- }
- public override string GetSimulatorVersion()
- {
- return m_simulatorVersion;
- }
- /// <summary>
- /// Another region is up.
- ///
- /// 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.
- /// </summary>
- /// <param name="otherRegion">RegionInfo handle for the new region.</param>
- /// <returns>True after all operations complete, throws exceptions otherwise.</returns>
- public override void OtherRegionUp(GridRegion otherRegion)
- {
- uint xcell = (uint)((int)otherRegion.RegionLocX / (int)Constants.RegionSize);
- uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize);
- m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
- RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
- if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
- {
- // If these are cast to INT because long + negative values + abs returns invalid data
- int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX);
- int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY);
- if (resultX <= 1 && resultY <= 1)
- {
- // Let the grid service module know, so this can be cached
- m_eventManager.TriggerOnRegionUp(otherRegion);
- RegionInfo regInfo = new RegionInfo(xcell, ycell, otherRegion.InternalEndPoint, otherRegion.ExternalHostName);
- regInfo.RegionID = otherRegion.RegionID;
- regInfo.RegionName = otherRegion.RegionName;
- regInfo.ScopeID = otherRegion.ScopeID;
- regInfo.ExternalHostName = otherRegion.ExternalHostName;
- try
- {
- ForEachScenePresence(delegate(ScenePresence agent)
- {
- // If agent is a root agent.
- if (!agent.IsChildAgent)
- {
- //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);
- InformClientOfNeighbor(agent, regInfo);
- }
- }
- );
- }
- catch (NullReferenceException)
- {
- // This means that we're not booted up completely yet.
- // This shouldn't happen too often anymore.
- m_log.Error("[SCENE]: Couldn't inform client of regionup because we got a null reference exception");
- }
- }
- else
- {
- m_log.Info("[INTERGRID]: Got notice about far away Region: " + otherRegion.RegionName.ToString() +
- " at (" + otherRegion.RegionLocX.ToString() + ", " +
- otherRegion.RegionLocY.ToString() + ")");
- }
- }
- }
- public void AddNeighborRegion(RegionInfo region)
- {
- lock (m_neighbours)
- {
- if (!CheckNeighborRegion(region))
- {
- m_neighbours.Add(region);
- }
- }
- }
- 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;
- }
- // Alias IncomingHelloNeighbour OtherRegionUp, for now
- public GridRegion IncomingHelloNeighbour(RegionInfo neighbour)
- {
- OtherRegionUp(new GridRegion(neighbour));
- return new GridRegion(RegionInfo);
- }
- /// <summary>
- /// Given float seconds, this will restart the region.
- /// </summary>
- /// <param name="seconds">float indicating duration before restart.</param>
- public virtual void Restart(float seconds)
- {
- // notifications are done in 15 second increments
- // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
- // It's a 'Cancel restart' request.
- // RestartNow() does immediate restarting.
- if (seconds < 15)
- {
- m_restartTimer.Stop();
- m_dialogModule.SendGeneralAlert("Restart Aborted");
- }
- else
- {
- // Now we figure out what to set the timer to that does the notifications and calls, RestartNow()
- m_restartTimer.Interval = 15000;
- m_incrementsof15seconds = (int)seconds / 15;
- m_RestartTimerCounter = 0;
- m_restartTimer.AutoReset = true;
- m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
- m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
- m_restartTimer.Start();
- m_dialogModule.SendNotificationToUsersInRegion(
- UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
- }
- }
- // The Restart timer has occured.
- // We have to figure out if this is a notification or if the number of seconds specified in Restart
- // have elapsed.
- // If they have elapsed, call RestartNow()
- public void RestartTimer_Elapsed(object sender, ElapsedEventArgs e)
- {
- m_RestartTimerCounter++;
- if (m_RestartTimerCounter <= m_incrementsof15seconds)
- {
- if (m_RestartTimerCounter == 4 || m_RestartTimerCounter == 6 || m_RestartTimerCounter == 7)
- m_dialogModule.SendNotificationToUsersInRegion(
- UUID.Random(),
- String.Empty,
- RegionInfo.RegionName + ": Restarting in " + ((8 - m_RestartTimerCounter) * 15) + " seconds");
- }
- else
- {
- m_restartTimer.Stop();
- m_restartTimer.AutoReset = false;
- RestartNow();
- }
- }
- // This causes the region to restart immediatley.
- public void RestartNow()
- {
- IConfig startupConfig = m_config.Configs["Startup"];
- if (startupConfig != null)
- {
- if (startupConfig.GetBoolean("InworldRestartShutsDown", false))
- {
- MainConsole.Instance.RunCommand("shutdown");
- return;
- }
- }
- if (PhysicsScene != null)
- {
- PhysicsScene.Dispose();
- }
- m_log.Error("[REGION]: Closing");
- Close();
- m_log.Error("[REGION]: Firing Region Restart Message");
- base.Restart(0);
- }
- // This is a helper function that notifies root agents in this region that a new sim near them has come up
- // This is in the form of a timer because when an instance of OpenSim.exe is started,
- // 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.
- public void RestartNotifyWaitElapsed(object sender, ElapsedEventArgs e)
- {
- m_restartWaitTimer.Stop();
- lock (m_regionRestartNotifyList)
- {
- foreach (RegionInfo region in m_regionRestartNotifyList)
- {
- try
- {
- ForEachScenePresence(delegate(ScenePresence agent)
- {
- // If agent is a root agent.
- if (!agent.IsChildAgent)
- {
- //agent.ControllingClient.new
- //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo());
- InformClientOfNeighbor(agent, region);
- }
- }
- );
- }
- catch (NullReferenceException)
- {
- // This means that we're not booted up completely yet.
- // This shouldn't happen too often anymore.
- }
- }
- // Reset list to nothing.
- m_regionRestartNotifyList.Clear();
- }
- }
- public void SetSceneCoreDebug(bool ScriptEngine, bool CollisionEvents, bool PhysicsEngine)
- {
- if (m_scripts_enabled != !ScriptEngine)
- {
- // Tedd! Here's the method to disable the scripting engine!
- if (ScriptEngine)
- {
- m_log.Info("Stopping all Scripts in Scene");
- foreach (EntityBase ent in Entities)
- {
- if (ent is SceneObjectGroup)
- {
- ((SceneObjectGroup) ent).RemoveScriptInstances(false);
- }
- }
- }
- else
- {
- m_log.Info("Starting all Scripts in Scene");
- lock (Entities)
- {
- foreach (EntityBase ent in Entities)
- {
- if (ent is SceneObjectGroup)
- {
- ((SceneObjectGroup)ent).CreateScriptInstances(0, false, DefaultScriptEngine, 0);
- }
- }
- }
- }
- m_scripts_enabled = !ScriptEngine;
- m_log.Info("[TOTEDD]: Here is the method to trigger disabling of the scripting engine");
- }
- if (m_physics_enabled != !PhysicsEngine)
- {
- m_physics_enabled = !PhysicsEngine;
- }
- }
- public int GetInaccurateNeighborCount()
- {
- return m_neighbours.Count;
- }
- // This is the method that shuts down the scene.
- public override void Close()
- {
- m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
- m_restartTimer.Stop();
- m_restartTimer.Close();
- // Kick all ROOT agents with the message, 'The simulator is going down'
- ForEachScenePresence(delegate(ScenePresence avatar)
- {
- if (avatar.KnownChildRegionHandles.Contains(RegionInfo.RegionHandle))
- avatar.KnownChildRegionHandles.Remove(RegionInfo.RegionHandle);
- if (!avatar.IsChildAgent)
- avatar.ControllingClient.Kick("The simulator is going down.");
- avatar.ControllingClient.SendShutdownConnectionNotice();
- });
- // Wait here, or the kick messages won't actually get to the agents before the scene terminates.
- Thread.Sleep(500);
- // Stop all client threads.
- ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); });
- // Stop updating the scene objects and agents.
- //m_heartbeatTimer.Close();
- shuttingdown = true;
- m_log.Debug("[SCENE]: Persisting changed objects");
- List<EntityBase> entities = GetEntities();
- foreach (EntityBase entity in entities)
- {
- if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged)
- {
- ((SceneObjectGroup)entity).ProcessBackup(m_storageManager.DataStore, false);
- }
- }
- m_sceneGraph.Close();
- // De-register with region communications (events cleanup)
- UnRegisterRegionWithComms();
- // call the base class Close method.
- base.Close();
- }
- /// <summary>
- /// Start the timer which triggers regular scene updates
- /// </summary>
- public void StartTimer()
- {
- //m_log.Debug("[SCENE]: Starting timer");
- //m_heartbeatTimer.Enabled = true;
- //m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
- //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
- if (HeartbeatThread != null)
- {
- HeartbeatThread.Abort();
- HeartbeatThread = null;
- }
- m_lastUpdate = Util.EnvironmentTickCount();
- HeartbeatThread = Watchdog.StartThread(Heartbeat, "Heartbeat for region " + RegionInfo.RegionName, ThreadPriority.Normal, false);
- }
- /// <summary>
- /// Sets up references to modules required by the scene
- /// </summary>
- public void SetModuleInterfaces()
- {
- m_xmlrpcModule = RequestModuleInterface<IXMLRPC>();
- m_worldCommModule = RequestModuleInterface<IWorldComm>();
- XferManager = RequestModuleInterface<IXfer>();
- m_AvatarFactory = RequestModuleInterface<IAvatarFactory>();
- m_serialiser = RequestModuleInterface<IRegionSerialiserModule>();
- m_interregionCommsOut = RequestModuleInterface<IInterregionCommsOut>();
- m_interregionCommsIn = RequestModuleInterface<IInterregionCommsIn>();
- m_dialogModule = RequestModuleInterface<IDialogModule>();
- m_capsModule = RequestModuleInterface<ICapabilitiesModule>();
- m_teleportModule = RequestModuleInterface<ITeleportModule>();
- }
- #endregion
- #region Update Methods
- /// <summary>
- /// Performs per-frame updates regularly
- /// </summary>
- private void Heartbeat()
- {
- if (!Monitor.TryEnter(m_heartbeatLock))
- {
- Watchdog.RemoveThread();
- return;
- }
- try
- {
- Update();
- m_lastUpdate = Util.EnvironmentTickCount();
- m_firstHeartbeat = false;
- }
- catch (ThreadAbortException)
- {
- }
- finally
- {
- Monitor.Pulse(m_heartbeatLock);
- Monitor.Exit(m_heartbeatLock);
- }
- Watchdog.RemoveThread();
- }
- /// <summary>
- /// Performs per-frame updates on the scene, this should be the central scene loop
- /// </summary>
- public override void Update()
- {
- float physicsFPS;
- int maintc;
- while (!shuttingdown)
- {
- TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate;
- physicsFPS = 0f;
- maintc = Util.EnvironmentTickCount();
- int tmpFrameMS = maintc;
- tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
- // Increment the frame counter
- ++m_frame;
- try
- {
- // 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 (m_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 (m_frame % m_update_presences == 0)
- m_sceneGraph.UpdatePresences();
- int tmpPhysicsMS2 = Util.EnvironmentTickCount();
- if ((m_frame % m_update_physics == 0) && m_physics_enabled)
- m_sceneGraph.UpdatePreparePhysics();
- physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
- if (m_frame % m_update_entitymovement == 0)
- m_sceneGraph.UpdateScenePresenceMovement();
- int tmpPhysicsMS = Util.EnvironmentTickCount();
- if (m_frame % m_update_physics == 0)
- …
Large files files are truncated, but you can click here to view the full file