From 05a2feba5d780c57c252891a20071800fd9f2e3e Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 4 Aug 2014 19:57:47 +0100 Subject: [PATCH] start sending terrain in scenePresence after well defined avatar. Minor change on significante AgentUpdate check. --- .../ClientStack/Linden/UDP/LLClientView.cs | 28 +- .../ClientStack/Linden/UDP/LLUDPServer.cs | 34 +- OpenSim/Region/Framework/Scenes/Scene.cs | 4 +- OpenSim/Region/Framework/Scenes/SceneBase.cs | 1160 ++++++++--------- .../Region/Framework/Scenes/ScenePresence.cs | 19 +- 5 files changed, 629 insertions(+), 616 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 34a2797add..7d61577a7a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -577,7 +577,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Fire the callback for this connection closing if (OnConnectionClosed != null) + { OnConnectionClosed(this); + } + // Flush all of the packets out of the UDP server for this client if (m_udpServer != null) @@ -5518,8 +5521,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); -// AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, false); - AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, true); + AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, false); AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest); AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance); @@ -5732,10 +5734,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar // Threshold for body rotation to be a significant agent update - private const float QDELTA = 0.000001f; + // private const float QDELTA = 0.000001f; + // QDELTA is now relative to abs of cos of angle between orientations + + private const float QDELTABODY = 1 - 0.0001f; + private const float QDELTAHEAD = 1 - 0.0001f; + // Threshold for camera rotation to be a significant agent update private const float VDELTA = 0.01f; - + /// /// This checks the update significance against the last update made. /// @@ -5755,13 +5762,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); + // float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); + // now using abs of cos + float qdelta1 = (float)Math.Abs(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation)); + float qdelta2 = (float)Math.Abs(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation)); bool movementSignificant = - (qdelta1 > QDELTA) // significant if body rotation above threshold - // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack +// (qdelta1 > QDELTA) // significant if body rotation above threshold + (qdelta1 < QDELTABODY) // higher angle lower cos +// Ignoring head rotation altogether, because it's not being used for anything interesting up the stack // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold + || (qdelta2 < QDELTAHEAD) // using cos above || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed @@ -6476,7 +6488,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Action handlerRegionHandShakeReply = OnRegionHandShakeReply; if (handlerRegionHandShakeReply != null) { - Thread.Sleep(500); +// Thread.Sleep(500); handlerRegionHandShakeReply(this); } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index b7c8594a6a..a3fdae1580 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1750,25 +1750,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP endPoint, sessionInfo); - // Send ack straight away to let the viewer know that the connection is active. - // The client will be null if it already exists (e.g. if on a region crossing the client sends a use - // circuit code to the existing child agent. This is not particularly obvious. - SendAckImmediate(endPoint, uccp.Header.Sequence); - - // We only want to send initial data to new clients, not ones which are being converted from child to root. - if (client != null) - { - AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); - bool tp = (aCircuit.teleportFlags > 0); - // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from - if (!tp) - client.SceneAgent.SendInitialDataToMe(); - } - // Now we know we can handle more data - Thread.Sleep(200); +// Thread.Sleep(200); - // Obtain the queue and remove it from the cache + // Obtain the pending queue and remove it from the cache Queue queue = null; lock (m_pendingCache) @@ -1790,6 +1775,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP PacketReceived(buf); } queue = null; + + // Send ack straight away to let the viewer know that the connection is active. + // The client will be null if it already exists (e.g. if on a region crossing the client sends a use + // circuit code to the existing child agent. This is not particularly obvious. + SendAckImmediate(endPoint, uccp.Header.Sequence); + + // We only want to send initial data to new clients, not ones which are being converted from child to root. + if (client != null) + { + AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); + bool tp = (aCircuit.teleportFlags > 0); + // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from + if (!tp) + client.SceneAgent.SendInitialDataToMe(); + } } else { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0266faf821..ec54e1571a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3179,7 +3179,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientTerrainEvents(IClientAPI client) { - client.OnRegionHandShakeReply += SendLayerData; +// client.OnRegionHandShakeReply += SendLayerData; } public virtual void SubscribeToClientPrimEvents(IClientAPI client) @@ -3307,7 +3307,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) { - client.OnRegionHandShakeReply -= SendLayerData; +// client.OnRegionHandShakeReply -= SendLayerData; } public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 08e26c541f..6adccca62f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -1,581 +1,581 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the 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.Reflection; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Console; - -using OpenSim.Region.Framework.Interfaces; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; - -namespace OpenSim.Region.Framework.Scenes -{ - public abstract class SceneBase : IScene - { +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the 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.Reflection; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +using OpenSim.Region.Framework.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.Framework.Scenes +{ + public abstract class SceneBase : IScene + { protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected static readonly string LogHeader = "[SCENE]"; - - #region Events - - public event restart OnRestart; - - #endregion - - #region Fields - - public string Name { get { return RegionInfo.RegionName; } } - - public IConfigSource Config - { - get { return GetConfig(); } - } - - protected virtual IConfigSource GetConfig() - { - return null; - } - - /// - /// All the region modules attached to this scene. - /// - public Dictionary RegionModules - { - get { return m_regionModules; } - } - private Dictionary m_regionModules = new Dictionary(); - - /// - /// The module interfaces available from this scene. - /// - protected Dictionary> ModuleInterfaces = new Dictionary>(); - - protected Dictionary ModuleAPIMethods = new Dictionary(); - - /// - /// The module commanders available from this scene - /// - protected Dictionary m_moduleCommanders = new Dictionary(); - - /// - /// Registered classes that are capable of creating entities. - /// - protected Dictionary m_entityCreators = new Dictionary(); - - /// - /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is - /// dispensed. - /// - protected uint m_lastAllocatedLocalId = 720000; - - private readonly Mutex _primAllocateMutex = new Mutex(false); - - protected readonly ClientManager m_clientManager = new ClientManager(); - - public bool LoginsEnabled - { - get - { - return m_loginsEnabled; - } - - set - { - if (m_loginsEnabled != value) - { - m_loginsEnabled = value; - EventManager.TriggerRegionLoginsStatusChange(this); - } - } - } - private bool m_loginsEnabled; - - public bool Ready - { - get - { - return m_ready; - } - - set - { - if (m_ready != value) - { - m_ready = value; - EventManager.TriggerRegionReadyStatusChange(this); - } - } - } - private bool m_ready; - - public float TimeDilation - { - get { return 1.0f; } - } - - protected ulong m_regionHandle; - protected string m_regionName; - - public ITerrainChannel Heightmap; - - /// - /// Allows retrieval of land information for this scene. - /// - public ILandChannel LandChannel; - - /// - /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules - /// to subscribe to scene events. - /// - public EventManager EventManager - { - get { return m_eventManager; } - } - protected EventManager m_eventManager; - - protected ScenePermissions m_permissions; - public ScenePermissions Permissions - { - get { return m_permissions; } - } - - protected string m_datastore; - - /* Used by the loadbalancer plugin on GForge */ - protected RegionStatus m_regStatus; - public RegionStatus RegionStatus - { - get { return m_regStatus; } - set { m_regStatus = value; } - } - - #endregion - - public SceneBase(RegionInfo regInfo) - { - RegionInfo = regInfo; - } - - #region Update Methods - - /// - /// Called to update the scene loop by a number of frames and until shutdown. - /// - /// - /// Number of frames to update. Exits on shutdown even if there are frames remaining. - /// If -1 then updates until shutdown. - /// - public abstract void Update(int frames); - - #endregion - - #region Terrain Methods - - /// - /// Loads the World heightmap - /// - public abstract void LoadWorldMap(); - - /// - /// Send the region heightmap to the client - /// - /// Client to send to - public virtual void SendLayerData(IClientAPI RemoteClient) - { - RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); - } - - #endregion - - #region Add/Remove Agent/Avatar - - public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type); - - public abstract bool CloseAgent(UUID agentID, bool force); - - public bool TryGetScenePresence(UUID agentID, out object scenePresence) - { - scenePresence = null; - ScenePresence sp = null; - if (TryGetScenePresence(agentID, out sp)) - { - scenePresence = sp; - return true; - } - - return false; - } - - /// - /// Try to get a scene presence from the scene - /// - /// - /// null if there is no scene presence with the given agent id - /// true if there was a scene presence with the given id, false otherwise. - public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); - - #endregion - - /// - /// - /// - /// - public virtual RegionInfo RegionInfo { get; private set; } - - #region admin stuff - - public abstract void OtherRegionUp(GridRegion otherRegion); - - public virtual string GetSimulatorVersion() - { - return "OpenSimulator Server"; - } - - #endregion - - #region Shutdown - - /// - /// Tidy before shutdown - /// - public virtual void Close() - { - try - { - EventManager.TriggerShutdown(); - } - catch (Exception e) - { - m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); - } - } - - #endregion - - /// - /// Returns a new unallocated local ID - /// - /// A brand new local ID - public uint AllocateLocalId() - { - uint myID; - - _primAllocateMutex.WaitOne(); - myID = ++m_lastAllocatedLocalId; - _primAllocateMutex.ReleaseMutex(); - - return myID; - } - - #region Module Methods - - /// - /// Add a region-module to this scene. TODO: This will replace AddModule in the future. - /// - /// - /// - public void AddRegionModule(string name, IRegionModuleBase module) - { - if (!RegionModules.ContainsKey(name)) - { - RegionModules.Add(name, module); - } - } - - public void RemoveRegionModule(string name) - { - RegionModules.Remove(name); - } - - /// - /// Register a module commander. - /// - /// - public void RegisterModuleCommander(ICommander commander) - { - lock (m_moduleCommanders) - { - m_moduleCommanders.Add(commander.Name, commander); - } - } - - /// - /// Unregister a module commander and all its commands - /// - /// - public void UnregisterModuleCommander(string name) - { - lock (m_moduleCommanders) - { - ICommander commander; - if (m_moduleCommanders.TryGetValue(name, out commander)) - m_moduleCommanders.Remove(name); - } - } - - /// - /// Get a module commander - /// - /// - /// The module commander, null if no module commander with that name was found - public ICommander GetCommander(string name) - { - lock (m_moduleCommanders) - { - if (m_moduleCommanders.ContainsKey(name)) - return m_moduleCommanders[name]; - } - - return null; - } - - public Dictionary GetCommanders() - { - return m_moduleCommanders; - } - - /// - /// Register an interface to a region module. This allows module methods to be called directly as - /// well as via events. If there is already a module registered for this interface, it is not replaced - /// (is this the best behaviour?) - /// - /// - public void RegisterModuleInterface(M mod) - { -// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); - - List l = null; - if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) - { - l = new List(); - ModuleInterfaces.Add(typeof(M), l); - } - - if (l.Count > 0) - return; - - l.Add(mod); - - if (mod is IEntityCreator) - { - IEntityCreator entityCreator = (IEntityCreator)mod; - foreach (PCode pcode in entityCreator.CreationCapabilities) - { - m_entityCreators[pcode] = entityCreator; - } - } - } - - public void UnregisterModuleInterface(M mod) - { - List l; - if (ModuleInterfaces.TryGetValue(typeof(M), out l)) - { - if (l.Remove(mod)) - { - if (mod is IEntityCreator) - { - IEntityCreator entityCreator = (IEntityCreator)mod; - foreach (PCode pcode in entityCreator.CreationCapabilities) - { - m_entityCreators[pcode] = null; - } - } - } - } - } - - public void StackModuleInterface(M mod) - { - List l; - if (ModuleInterfaces.ContainsKey(typeof(M))) - l = ModuleInterfaces[typeof(M)]; - else - l = new List(); - - if (l.Contains(mod)) - return; - - l.Add(mod); - - if (mod is IEntityCreator) - { - IEntityCreator entityCreator = (IEntityCreator)mod; - foreach (PCode pcode in entityCreator.CreationCapabilities) - { - m_entityCreators[pcode] = entityCreator; - } - } - - ModuleInterfaces[typeof(M)] = l; - } - - /// - /// For the given interface, retrieve the region module which implements it. - /// - /// null if there is no registered module implementing that interface - public T RequestModuleInterface() - { - if (ModuleInterfaces.ContainsKey(typeof(T)) && - (ModuleInterfaces[typeof(T)].Count > 0)) - return (T)ModuleInterfaces[typeof(T)][0]; - else - return default(T); - } - - /// - /// For the given interface, retrieve an array of region modules that implement it. - /// - /// an empty array if there are no registered modules implementing that interface - public T[] RequestModuleInterfaces() - { - if (ModuleInterfaces.ContainsKey(typeof(T))) - { - List ret = new List(); - - foreach (Object o in ModuleInterfaces[typeof(T)]) - ret.Add((T)o); - return ret.ToArray(); - } - else - { - return new T[] {}; - } - } - - #endregion - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// - /// - /// - /// - public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) - { - AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); - } - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// The use of IRegionModuleBase is a cheap trick to get a different method signature, - /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. - /// - /// - /// Category of the command. This is the section under which it will appear when the user asks for help - /// - /// - /// - /// - /// - public void AddCommand( - string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) - { - AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); - } - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// - /// - /// - /// - /// - public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) - { - string moduleName = ""; - - if (module != null) - moduleName = module.Name; - - AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); - } - - /// - /// Call this from a region module to add a command to the OpenSim console. - /// - /// - /// Category of the command. This is the section under which it will appear when the user asks for help - /// - /// - /// - /// - /// - /// - /// - public void AddCommand( - string category, IRegionModuleBase module, string command, - string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) - { - if (MainConsole.Instance == null) - return; - - bool shared = false; - - if (module != null) - shared = module is ISharedRegionModule; - - MainConsole.Instance.Commands.AddCommand( - category, shared, command, shorthelp, longhelp, descriptivehelp, callback); - } - - public virtual ISceneObject DeserializeObject(string representation) - { - return null; - } - - public virtual bool AllowScriptCrossings - { - get { return false; } - } - - public virtual void Start() - { - } - - public void Restart() - { - // This has to be here to fire the event - restart handlerPhysicsCrash = OnRestart; - if (handlerPhysicsCrash != null) - handlerPhysicsCrash(RegionInfo); - } - - public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); - } -} + protected static readonly string LogHeader = "[SCENE]"; + + #region Events + + public event restart OnRestart; + + #endregion + + #region Fields + + public string Name { get { return RegionInfo.RegionName; } } + + public IConfigSource Config + { + get { return GetConfig(); } + } + + protected virtual IConfigSource GetConfig() + { + return null; + } + + /// + /// All the region modules attached to this scene. + /// + public Dictionary RegionModules + { + get { return m_regionModules; } + } + private Dictionary m_regionModules = new Dictionary(); + + /// + /// The module interfaces available from this scene. + /// + protected Dictionary> ModuleInterfaces = new Dictionary>(); + + protected Dictionary ModuleAPIMethods = new Dictionary(); + + /// + /// The module commanders available from this scene + /// + protected Dictionary m_moduleCommanders = new Dictionary(); + + /// + /// Registered classes that are capable of creating entities. + /// + protected Dictionary m_entityCreators = new Dictionary(); + + /// + /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is + /// dispensed. + /// + protected uint m_lastAllocatedLocalId = 720000; + + private readonly Mutex _primAllocateMutex = new Mutex(false); + + protected readonly ClientManager m_clientManager = new ClientManager(); + + public bool LoginsEnabled + { + get + { + return m_loginsEnabled; + } + + set + { + if (m_loginsEnabled != value) + { + m_loginsEnabled = value; + EventManager.TriggerRegionLoginsStatusChange(this); + } + } + } + private bool m_loginsEnabled; + + public bool Ready + { + get + { + return m_ready; + } + + set + { + if (m_ready != value) + { + m_ready = value; + EventManager.TriggerRegionReadyStatusChange(this); + } + } + } + private bool m_ready; + + public float TimeDilation + { + get { return 1.0f; } + } + + protected ulong m_regionHandle; + protected string m_regionName; + + public ITerrainChannel Heightmap; + + /// + /// Allows retrieval of land information for this scene. + /// + public ILandChannel LandChannel; + + /// + /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules + /// to subscribe to scene events. + /// + public EventManager EventManager + { + get { return m_eventManager; } + } + protected EventManager m_eventManager; + + protected ScenePermissions m_permissions; + public ScenePermissions Permissions + { + get { return m_permissions; } + } + + protected string m_datastore; + + /* Used by the loadbalancer plugin on GForge */ + protected RegionStatus m_regStatus; + public RegionStatus RegionStatus + { + get { return m_regStatus; } + set { m_regStatus = value; } + } + + #endregion + + public SceneBase(RegionInfo regInfo) + { + RegionInfo = regInfo; + } + + #region Update Methods + + /// + /// Called to update the scene loop by a number of frames and until shutdown. + /// + /// + /// Number of frames to update. Exits on shutdown even if there are frames remaining. + /// If -1 then updates until shutdown. + /// + public abstract void Update(int frames); + + #endregion + + #region Terrain Methods + + /// + /// Loads the World heightmap + /// + public abstract void LoadWorldMap(); + + /// + /// Send the region heightmap to the client + /// + /// Client to send to + public virtual void SendLayerData(IClientAPI RemoteClient) + { + RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); + } + + #endregion + + #region Add/Remove Agent/Avatar + + public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type); + + public abstract bool CloseAgent(UUID agentID, bool force); + + public bool TryGetScenePresence(UUID agentID, out object scenePresence) + { + scenePresence = null; + ScenePresence sp = null; + if (TryGetScenePresence(agentID, out sp)) + { + scenePresence = sp; + return true; + } + + return false; + } + + /// + /// Try to get a scene presence from the scene + /// + /// + /// null if there is no scene presence with the given agent id + /// true if there was a scene presence with the given id, false otherwise. + public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); + + #endregion + + /// + /// + /// + /// + public virtual RegionInfo RegionInfo { get; private set; } + + #region admin stuff + + public abstract void OtherRegionUp(GridRegion otherRegion); + + public virtual string GetSimulatorVersion() + { + return "OpenSimulator Server"; + } + + #endregion + + #region Shutdown + + /// + /// Tidy before shutdown + /// + public virtual void Close() + { + try + { + EventManager.TriggerShutdown(); + } + catch (Exception e) + { + m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); + } + } + + #endregion + + /// + /// Returns a new unallocated local ID + /// + /// A brand new local ID + public uint AllocateLocalId() + { + uint myID; + + _primAllocateMutex.WaitOne(); + myID = ++m_lastAllocatedLocalId; + _primAllocateMutex.ReleaseMutex(); + + return myID; + } + + #region Module Methods + + /// + /// Add a region-module to this scene. TODO: This will replace AddModule in the future. + /// + /// + /// + public void AddRegionModule(string name, IRegionModuleBase module) + { + if (!RegionModules.ContainsKey(name)) + { + RegionModules.Add(name, module); + } + } + + public void RemoveRegionModule(string name) + { + RegionModules.Remove(name); + } + + /// + /// Register a module commander. + /// + /// + public void RegisterModuleCommander(ICommander commander) + { + lock (m_moduleCommanders) + { + m_moduleCommanders.Add(commander.Name, commander); + } + } + + /// + /// Unregister a module commander and all its commands + /// + /// + public void UnregisterModuleCommander(string name) + { + lock (m_moduleCommanders) + { + ICommander commander; + if (m_moduleCommanders.TryGetValue(name, out commander)) + m_moduleCommanders.Remove(name); + } + } + + /// + /// Get a module commander + /// + /// + /// The module commander, null if no module commander with that name was found + public ICommander GetCommander(string name) + { + lock (m_moduleCommanders) + { + if (m_moduleCommanders.ContainsKey(name)) + return m_moduleCommanders[name]; + } + + return null; + } + + public Dictionary GetCommanders() + { + return m_moduleCommanders; + } + + /// + /// Register an interface to a region module. This allows module methods to be called directly as + /// well as via events. If there is already a module registered for this interface, it is not replaced + /// (is this the best behaviour?) + /// + /// + public void RegisterModuleInterface(M mod) + { +// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); + + List l = null; + if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) + { + l = new List(); + ModuleInterfaces.Add(typeof(M), l); + } + + if (l.Count > 0) + return; + + l.Add(mod); + + if (mod is IEntityCreator) + { + IEntityCreator entityCreator = (IEntityCreator)mod; + foreach (PCode pcode in entityCreator.CreationCapabilities) + { + m_entityCreators[pcode] = entityCreator; + } + } + } + + public void UnregisterModuleInterface(M mod) + { + List l; + if (ModuleInterfaces.TryGetValue(typeof(M), out l)) + { + if (l.Remove(mod)) + { + if (mod is IEntityCreator) + { + IEntityCreator entityCreator = (IEntityCreator)mod; + foreach (PCode pcode in entityCreator.CreationCapabilities) + { + m_entityCreators[pcode] = null; + } + } + } + } + } + + public void StackModuleInterface(M mod) + { + List l; + if (ModuleInterfaces.ContainsKey(typeof(M))) + l = ModuleInterfaces[typeof(M)]; + else + l = new List(); + + if (l.Contains(mod)) + return; + + l.Add(mod); + + if (mod is IEntityCreator) + { + IEntityCreator entityCreator = (IEntityCreator)mod; + foreach (PCode pcode in entityCreator.CreationCapabilities) + { + m_entityCreators[pcode] = entityCreator; + } + } + + ModuleInterfaces[typeof(M)] = l; + } + + /// + /// For the given interface, retrieve the region module which implements it. + /// + /// null if there is no registered module implementing that interface + public T RequestModuleInterface() + { + if (ModuleInterfaces.ContainsKey(typeof(T)) && + (ModuleInterfaces[typeof(T)].Count > 0)) + return (T)ModuleInterfaces[typeof(T)][0]; + else + return default(T); + } + + /// + /// For the given interface, retrieve an array of region modules that implement it. + /// + /// an empty array if there are no registered modules implementing that interface + public T[] RequestModuleInterfaces() + { + if (ModuleInterfaces.ContainsKey(typeof(T))) + { + List ret = new List(); + + foreach (Object o in ModuleInterfaces[typeof(T)]) + ret.Add((T)o); + return ret.ToArray(); + } + else + { + return new T[] {}; + } + } + + #endregion + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// + /// + /// + /// + public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) + { + AddCommand(module, command, shorthelp, longhelp, string.Empty, callback); + } + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// The use of IRegionModuleBase is a cheap trick to get a different method signature, + /// though all new modules should be using interfaces descended from IRegionModuleBase anyway. + /// + /// + /// Category of the command. This is the section under which it will appear when the user asks for help + /// + /// + /// + /// + /// + public void AddCommand( + string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback) + { + AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback); + } + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// + /// + /// + /// + /// + public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) + { + string moduleName = ""; + + if (module != null) + moduleName = module.Name; + + AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback); + } + + /// + /// Call this from a region module to add a command to the OpenSim console. + /// + /// + /// Category of the command. This is the section under which it will appear when the user asks for help + /// + /// + /// + /// + /// + /// + /// + public void AddCommand( + string category, IRegionModuleBase module, string command, + string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) + { + if (MainConsole.Instance == null) + return; + + bool shared = false; + + if (module != null) + shared = module is ISharedRegionModule; + + MainConsole.Instance.Commands.AddCommand( + category, shared, command, shorthelp, longhelp, descriptivehelp, callback); + } + + public virtual ISceneObject DeserializeObject(string representation) + { + return null; + } + + public virtual bool AllowScriptCrossings + { + get { return false; } + } + + public virtual void Start() + { + } + + public void Restart() + { + // This has to be here to fire the event + restart handlerPhysicsCrash = OnRestart; + if (handlerPhysicsCrash != null) + handlerPhysicsCrash(RegionInfo); + } + + public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); + } +} diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 24a92eb468..8088dd374c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3473,6 +3473,7 @@ namespace OpenSim.Region.Framework.Scenes landch.sendClientInitialLandInfo(ControllingClient); } } + m_scene.SendLayerData(ControllingClient); SendOtherAgentsAvatarDataToMe(); SendOtherAgentsAppearanceToMe(); @@ -5426,7 +5427,7 @@ namespace OpenSim.Region.Framework.Scenes { if (p.IsChildAgent) continue; - m_log.Debug("[AVATAR]: viewMe: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: viewMe: " + Lastname + " " + p.Lastname); ControllingClient.SendAvatarDataImmediate(p); p.SendAppearanceToAgent(this); p.SendAttachmentsToClient(ControllingClient); @@ -5454,7 +5455,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in killsToSendme) { - m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); try { ControllingClient.SendKillObject(new List { p.LocalId }); } catch (NullReferenceException) { } } @@ -5499,7 +5500,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in killsToSendto) { - m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); try { p.ControllingClient.SendKillObject(new List { LocalId }); } catch (NullReferenceException) { } } @@ -5509,7 +5510,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in killsToSendme) { - m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); try { ControllingClient.SendKillObject(new List { p.LocalId }); } catch (NullReferenceException) { } } @@ -5519,7 +5520,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in viewsToSendto) { - m_log.Debug("[AVATAR]: viewTo: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: viewTo: " + Lastname + " " + p.Lastname); p.ControllingClient.SendAvatarDataImmediate(this); SendAppearanceToAgent(p); SendAttachmentsToClient(p.ControllingClient); @@ -5532,9 +5533,9 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in viewsToSendme) { - m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname); if (p.IsChildAgent) continue; +// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname); ControllingClient.SendAvatarDataImmediate(p); p.SendAppearanceToAgent(this); p.SendAttachmentsToClient(ControllingClient); @@ -5603,7 +5604,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in killsToSendme) { - m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); try { ControllingClient.SendKillObject(new List { p.LocalId }); } catch (NullReferenceException) { } } @@ -5752,7 +5753,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in killsToSendto) { - m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); try { p.ControllingClient.SendKillObject(new List { LocalId }); } catch (NullReferenceException) { } } @@ -5762,7 +5763,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (ScenePresence p in killsToSendme) { - m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); +// m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); try {ControllingClient.SendKillObject(new List { p.LocalId }); } catch (NullReferenceException) { } }