From 5460f2e035f50aade96b3daa0cb284bcb6faeea7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 1 Dec 2011 23:24:15 +0000 Subject: [PATCH 01/26] refactor: Separate the upload baked texture handler out from BunchOfCaps --- .../Handlers/GetTexture/GetTextureHandler.cs | 4 +- .../UploadBakedTextureHandler.cs | 179 ++++++++++++++++++ .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 123 +----------- .../Linden/Caps/UploadBakedTextureModule.cs | 112 +++++++++++ 4 files changed, 293 insertions(+), 125 deletions(-) create mode 100644 OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs create mode 100644 OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index e1b4fe756b..245d9312d2 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs @@ -350,7 +350,5 @@ namespace OpenSim.Capabilities.Handlers } return null; } - - } -} +} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs new file mode 100644 index 0000000000..97b558cad7 --- /dev/null +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -0,0 +1,179 @@ +/* + * 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; +using System.Collections.Specialized; +using System.Drawing; +using System.Drawing.Imaging; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Imaging; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Capabilities.Handlers +{ + public class UploadBakedTextureHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Caps m_HostCapsObj; + private IAssetService m_assetService; + private bool m_persistBakedTextures; + + public UploadBakedTextureHandler(Caps caps, IAssetService assetService, bool persistBakedTextures) + { + m_HostCapsObj = caps; + m_assetService = assetService; + m_persistBakedTextures = persistBakedTextures; + } + + /// + /// Handle a request from the client for a Uri to upload a baked texture. + /// + /// + /// + /// + /// + /// + /// The upload response if the request is successful, null otherwise. + public string UploadBakedTexture( + string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + try + { +// m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + m_regionName); + + string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; + string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + + BakedTextureUploader uploader = + new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener); + uploader.OnUpLoad += BakedTextureUploaded; + + m_HostCapsObj.HttpListener.AddStreamHandler( + new BinaryStreamHandler("POST", capsBase + uploaderPath, + uploader.uploaderCaps)); + + string protocol = "http://"; + + if (m_HostCapsObj.SSLCaps) + protocol = "https://"; + + string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + + m_HostCapsObj.Port.ToString() + capsBase + uploaderPath; + + LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); + uploadResponse.uploader = uploaderURL; + uploadResponse.state = "upload"; + + return LLSDHelpers.SerialiseLLSDReply(uploadResponse); + } + catch (Exception e) + { + m_log.Error("[CAPS]: " + e.ToString()); + } + + return null; + } + + /// + /// Called when a baked texture has been successfully uploaded by a client. + /// + /// + /// + private void BakedTextureUploaded(UUID assetID, byte[] data) + { + // m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString()); + + AssetBase asset; + asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); + asset.Data = data; + asset.Temporary = true; + asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are + m_assetService.Store(asset); + } + } + + class BakedTextureUploader + { + public event Action OnUpLoad; + + private string uploaderPath = String.Empty; + private UUID newAssetID; + private IHttpServer httpListener; + + public BakedTextureUploader(string path, IHttpServer httpServer) + { + newAssetID = UUID.Random(); + uploaderPath = path; + httpListener = httpServer; + // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID); + } + + /// + /// Handle raw uploaded baked texture data. + /// + /// + /// + /// + /// + public string uploaderCaps(byte[] data, string path, string param) + { + Action handlerUpLoad = OnUpLoad; + if (handlerUpLoad != null) + { + Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); }); + } + + string res = String.Empty; + LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); + uploadComplete.new_asset = newAssetID.ToString(); + uploadComplete.new_inventory_item = UUID.Zero; + uploadComplete.state = "complete"; + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); + + httpListener.RemoveStreamHandler("POST", uploaderPath); + + // m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID); + + return res; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 07b4df3d3b..98dda36273 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -56,8 +56,6 @@ namespace OpenSim.Region.ClientStack.Linden string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, string assetType); - public delegate void UploadedBakedTexture(UUID assetID, byte[] data); - public delegate UUID UpdateItem(UUID itemID, byte[] data); public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); @@ -97,7 +95,6 @@ namespace OpenSim.Region.ClientStack.Linden private static readonly string m_notecardTaskUpdatePath = "0005/"; // private static readonly string m_fetchInventoryPath = "0006/"; // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. - private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule. // These are callbacks which will be setup by the scene so that we can update scene data when we @@ -164,8 +161,6 @@ namespace OpenSim.Region.ClientStack.Linden IRequestHandler req = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory); m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); - m_HostCapsObj.RegisterHandler("UploadBakedTexture", new RestStreamHandler("POST", capsBase + m_uploadBakedTexturePath, UploadBakedTexture)); - } catch (Exception e) { @@ -330,74 +325,6 @@ namespace OpenSim.Region.ClientStack.Linden } } - /// - /// Handle a request from the client for a Uri to upload a baked texture. - /// - /// - /// - /// - /// - /// - /// The upload response if the request is successful, null otherwise. - public string UploadBakedTexture(string request, string path, - string param, OSHttpRequest httpRequest, - OSHttpResponse httpResponse) - { - try - { -// m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + m_regionName); - - string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; - string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); - - BakedTextureUploader uploader = - new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener); - uploader.OnUpLoad += BakedTextureUploaded; - - m_HostCapsObj.HttpListener.AddStreamHandler( - new BinaryStreamHandler("POST", capsBase + uploaderPath, - uploader.uploaderCaps)); - - string protocol = "http://"; - - if (m_HostCapsObj.SSLCaps) - protocol = "https://"; - - string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + - m_HostCapsObj.Port.ToString() + capsBase + uploaderPath; - - LLSDAssetUploadResponse uploadResponse = - new LLSDAssetUploadResponse(); - uploadResponse.uploader = uploaderURL; - uploadResponse.state = "upload"; - - return LLSDHelpers.SerialiseLLSDReply(uploadResponse); - } - catch (Exception e) - { - m_log.Error("[CAPS]: " + e.ToString()); - } - - return null; - } - - /// - /// Called when a baked texture has been successfully uploaded by a client. - /// - /// - /// - public void BakedTextureUploaded(UUID assetID, byte[] data) - { - // m_log.WarnFormat("[CAPS]: Received baked texture {0}", assetID.ToString()); - - AssetBase asset; - asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); - asset.Data = data; - asset.Temporary = true; - asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are - m_assetService.Store(asset); - } - /// /// Called when new asset data for an agent inventory item update has been uploaded. /// @@ -1067,6 +994,7 @@ namespace OpenSim.Region.ClientStack.Linden // XXX Maybe this should be some meaningful error packet return null; } + ///Left this in and commented in case there are unforseen issues //private void SaveAssetToFile(string filename, byte[] data) //{ @@ -1090,53 +1018,4 @@ namespace OpenSim.Region.ClientStack.Linden fs.Close(); } } - - public class BakedTextureUploader - { - public event UploadedBakedTexture OnUpLoad; - private UploadedBakedTexture handlerUpLoad = null; - - private string uploaderPath = String.Empty; - private UUID newAssetID; - private IHttpServer httpListener; - - public BakedTextureUploader(string path, IHttpServer httpServer) - { - newAssetID = UUID.Random(); - uploaderPath = path; - httpListener = httpServer; - // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID); - } - - /// - /// Handle raw uploaded baked texture data. - /// - /// - /// - /// - /// - public string uploaderCaps(byte[] data, string path, string param) - { - handlerUpLoad = OnUpLoad; - if (handlerUpLoad != null) - { - Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); }); - } - - string res = String.Empty; - LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); - uploadComplete.new_asset = newAssetID.ToString(); - uploadComplete.new_inventory_item = UUID.Zero; - uploadComplete.state = "complete"; - - res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); - - httpListener.RemoveStreamHandler("POST", uploaderPath); - - // m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID); - - return res; - } - } - } \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs new file mode 100644 index 0000000000..e61815fd4a --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs @@ -0,0 +1,112 @@ +/* + * 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; +using System.Collections.Specialized; +using System.Drawing; +using System.Drawing.Imaging; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Imaging; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OpenSim.Capabilities.Handlers; + +namespace OpenSim.Region.ClientStack.Linden +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class UploadBakedTextureModule : INonSharedRegionModule + { +// private static readonly ILog m_log = +// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// For historical reasons this is fixed, but there + /// + private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule. + + private Scene m_scene; + private bool m_persistBakedTextures; + + public void Initialise(IConfigSource source) + { + IConfig sconfig = source.Configs["Startup"]; + if (sconfig != null) + m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); + } + + public void AddRegion(Scene s) + { + m_scene = s; + } + + public void RemoveRegion(Scene s) + { + } + + public void RegionLoaded(Scene s) + { + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "UploadBakedTextureModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void RegisterCaps(UUID agentID, Caps caps) + { + caps.RegisterHandler( + "UploadBakedTexture", + new RestStreamHandler( + "POST", + "/CAPS/" + m_uploadBakedTexturePath, + new UploadBakedTextureHandler( + caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture)); + } + } +} \ No newline at end of file From 1854c52ea3c60d0a47f9793a7f5ec405e15489ca Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 1 Dec 2011 23:38:25 +0000 Subject: [PATCH 02/26] Stop performing the asset save part of baked texture uploading on the UploadBakedTexture cap asynchronously. This prevents a possible race condition where the client would be told all baked textures had updated before they were in the asset service. The client would then trigger a set appearance which, after a delay, would send the avatar appearance out to other clients. The race condition seems unlikely because of this delay but it's still possible. Might help with grey avatar appearances. --- .../UploadBakedTextureHandler.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs index 97b558cad7..b89fd6ab02 100644 --- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -106,7 +106,7 @@ namespace OpenSim.Capabilities.Handlers } catch (Exception e) { - m_log.Error("[CAPS]: " + e.ToString()); + m_log.Error("[UPLOAD BAKED TEXTURE HANDLER]: " + e.ToString()); } return null; @@ -132,6 +132,8 @@ namespace OpenSim.Capabilities.Handlers class BakedTextureUploader { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public event Action OnUpLoad; private string uploaderPath = String.Empty; @@ -156,10 +158,12 @@ namespace OpenSim.Capabilities.Handlers public string uploaderCaps(byte[] data, string path, string param) { Action handlerUpLoad = OnUpLoad; + + // Don't do this asynchronously, otherwise it's possible for the client to send set appearance information + // on another thread which might send out avatar updates before the asset has been put into the asset + // service. if (handlerUpLoad != null) - { - Util.FireAndForget(delegate(object o) { handlerUpLoad(newAssetID, data); }); - } + handlerUpLoad(newAssetID, data); string res = String.Empty; LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); @@ -171,7 +175,7 @@ namespace OpenSim.Capabilities.Handlers httpListener.RemoveStreamHandler("POST", uploaderPath); - // m_log.InfoFormat("[CAPS] baked texture upload completed for {0}",newAssetID); +// m_log.DebugFormat("[BAKED TEXTURE UPLOADER]: baked texture upload completed for {0}", newAssetID); return res; } From 2a6597f61e6a21a6950a0b951e56a13c54e49e21 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 2 Dec 2011 22:14:47 +0000 Subject: [PATCH 03/26] Remove pointless Animator.TrySetMovementAnimation("STAND") in ScenePresnece constructor. Comment was right - it is indeed useless since SP always starts off as child and TrySetMovementAnimation screens out child SP --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c2d3501825..1c2025ce51 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -782,9 +782,6 @@ namespace OpenSim.Region.Framework.Scenes AdjustKnownSeeds(); - // TODO: I think, this won't send anything, as we are still a child here... - Animator.TrySetMovementAnimation("STAND"); - // we created a new ScenePresence (a new child agent) in a fresh region. // Request info about all the (root) agents in this region // Note: This won't send data *to* other clients in that region (children don't send) From 054ebe8878cbd1552fe96c0df631f50d5c2409d3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 2 Dec 2011 23:56:01 +0000 Subject: [PATCH 04/26] Stop some places where we're trying to reset animations in child agents where such requests are ignored. --- .../EntityTransfer/EntityTransferModule.cs | 210 +++++++++--------- .../Scenes/Animation/ScenePresenceAnimator.cs | 13 +- OpenSim/Region/Framework/Scenes/Scene.cs | 1 - .../Region/Framework/Scenes/ScenePresence.cs | 25 +-- 4 files changed, 133 insertions(+), 116 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index d01f89b550..99064c8a1f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -495,7 +495,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Well, this is it. The agent is over there. KillEntity(sp.Scene, sp.LocalId); - // Now let's make it officially a child agent sp.MakeChildAgent(); @@ -510,9 +509,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Scene.IncomingCloseAgent(sp.UUID); } else + { // now we have a child agent in this region. sp.Reset(); - + } // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! if (sp.Scene.NeedSceneCacheClear(sp.UUID)) @@ -946,111 +946,121 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) { - ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); - - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", agent.Firstname, agent.Lastname, neighbourx, neighboury, version); - - Scene m_scene = agent.Scene; - - if (neighbourRegion != null) + try { - if (!agent.ValidateAttachments()) - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.", - agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName); - - pos = pos + (agent.Velocity); - - SetInTransit(agent.UUID); - AgentData cAgent = new AgentData(); - agent.CopyTo(cAgent); - cAgent.Position = pos; - if (isFlying) - cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; - cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + - "agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; - - if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) + ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); + + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", agent.Firstname, agent.Lastname, neighbourx, neighboury, version); + + Scene m_scene = agent.Scene; + + if (neighbourRegion != null) { - // region doesn't take it - ReInstantiateScripts(agent); - ResetFromTransit(agent.UUID); - return agent; + if (!agent.ValidateAttachments()) + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.", + agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName); + + pos = pos + (agent.Velocity); + + SetInTransit(agent.UUID); + AgentData cAgent = new AgentData(); + agent.CopyTo(cAgent); + cAgent.Position = pos; + if (isFlying) + cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; + cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + + "agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; + + if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) + { + // region doesn't take it + ReInstantiateScripts(agent); + ResetFromTransit(agent.UUID); + return agent; + } + + // Next, let's close the child agent connections that are too far away. + agent.CloseChildAgents(neighbourx, neighboury); + + //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo(); + agent.ControllingClient.RequestClientInfo(); + + //m_log.Debug("BEFORE CROSS"); + //Scene.DumpChildrenSeeds(UUID); + //DumpKnownRegions(); + string agentcaps; + if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) + { + m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", + neighbourRegion.RegionHandle); + return agent; + } + string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); + + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); + + IEventQueue eq = agent.Scene.RequestModuleInterface(); + if (eq != null) + { + eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, + capsPath, agent.UUID, agent.ControllingClient.SessionId); + } + else + { + agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, + capsPath); + } + + if (!WaitForCallback(agent.UUID)) + { + m_log.Debug("[ENTITY TRANSFER MODULE]: Callback never came in crossing agent"); + ReInstantiateScripts(agent); + ResetFromTransit(agent.UUID); + + // Yikes! We should just have a ref to scene here. + //agent.Scene.InformClientOfNeighbours(agent); + EnableChildAgents(agent); + + return agent; + } + + agent.MakeChildAgent(); + + // now we have a child agent in this region. Request all interesting data about other (root) agents + agent.SendOtherAgentsAvatarDataToMe(); + agent.SendOtherAgentsAppearanceToMe(); + + // Backwards compatibility + if (version == "Unknown" || version == string.Empty) + { + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old neighbor, passing attachments one by one..."); + CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); + } + + AgentHasMovedAway(agent, false); + + // the user may change their profile information in other region, + // so the userinfo in UserProfileCache is not reliable any more, delete it + // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! + if (agent.Scene.NeedSceneCacheClear(agent.UUID)) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); + } } - - // Next, let's close the child agent connections that are too far away. - agent.CloseChildAgents(neighbourx, neighboury); - - //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo(); - agent.ControllingClient.RequestClientInfo(); - - //m_log.Debug("BEFORE CROSS"); + + //m_log.Debug("AFTER CROSS"); //Scene.DumpChildrenSeeds(UUID); //DumpKnownRegions(); - string agentcaps; - if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) - { - m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", - neighbourRegion.RegionHandle); - return agent; - } - string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); - - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); - - IEventQueue eq = agent.Scene.RequestModuleInterface(); - if (eq != null) - { - eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, - capsPath, agent.UUID, agent.ControllingClient.SessionId); - } - else - { - agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, - capsPath); - } - - if (!WaitForCallback(agent.UUID)) - { - m_log.Debug("[ENTITY TRANSFER MODULE]: Callback never came in crossing agent"); - ReInstantiateScripts(agent); - ResetFromTransit(agent.UUID); - - // Yikes! We should just have a ref to scene here. - //agent.Scene.InformClientOfNeighbours(agent); - EnableChildAgents(agent); - - return agent; - } - - agent.MakeChildAgent(); - - // now we have a child agent in this region. Request all interesting data about other (root) agents - agent.SendOtherAgentsAvatarDataToMe(); - agent.SendOtherAgentsAppearanceToMe(); - - // Backwards compatibility - if (version == "Unknown" || version == string.Empty) - { - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Old neighbor, passing attachments one by one..."); - CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); - } - - AgentHasMovedAway(agent, false); - - // the user may change their profile information in other region, - // so the userinfo in UserProfileCache is not reliable any more, delete it - // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! - if (agent.Scene.NeedSceneCacheClear(agent.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); - } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2}. Exception {3}{4}", + agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); } - //m_log.Debug("AFTER CROSS"); - //Scene.DumpChildrenSeeds(UUID); - //DumpKnownRegions(); return agent; } diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 4cf854edf8..6b1208cbb0 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -131,8 +131,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation public void ResetAnimations() { +// m_log.DebugFormat( +// "[SCENE PRESENCE ANIMATOR]: Resetting animations for {0} in {1}", +// m_scenePresence.Name, m_scenePresence.Scene.RegionInfo.RegionName); + m_animations.Clear(); - TrySetMovementAnimation("STAND"); } /// @@ -155,6 +158,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation SendAnimPack(); } } + // Don't leave this on since on teleports SP.HandleAgentUpdate() still hammers us for a while after it teleports +// else +// { +// m_log.WarnFormat( +// "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", +// anim, m_scenePresence.Name); +// throw new Exception(string.Format("aaargh on setting {0}", anim)); +// } } /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 9a71cd4879..3ac6327797 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3700,7 +3700,6 @@ namespace OpenSim.Region.Framework.Scenes return false; } - ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1c2025ce51..b93b67de45 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -995,13 +995,17 @@ namespace OpenSim.Region.Framework.Scenes /// /// This turns a root agent into a child agent + /// + /// /// when an agent departs this region for a neighbor, this gets called. /// /// It doesn't get called for a teleport. Reason being, an agent that /// teleports out may not end up anywhere near this region - /// + /// public void MakeChildAgent() { + m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); + // Reset these so that teleporting in and walking out isn't seen // as teleporting back TeleportFlags = TeleportFlags.Default; @@ -2295,11 +2299,6 @@ namespace OpenSim.Region.Framework.Scenes { m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); - - // TODO: This doesn't prevent the user from walking yet. - // Setting parent ID would fix this, if we knew what value - // to use. Or we could add a m_isSitting variable. - //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); SitGround = true; RemoveFromPhysicalScene(); } @@ -2908,9 +2907,12 @@ namespace OpenSim.Region.Framework.Scenes public void Reset() { +// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); + // Put the child agent back at the center AbsolutePosition = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); + Animator.ResetAnimations(); } @@ -3133,7 +3135,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public void CopyFrom(AgentData cAgent) + private void CopyFrom(AgentData cAgent) { m_originRegionID = cAgent.RegionID; @@ -3192,13 +3194,8 @@ namespace OpenSim.Region.Framework.Scenes } } catch { } - // Animations - try - { - Animator.ResetAnimations(); - Animator.Animations.FromArray(cAgent.Anims); - } - catch { } + + Animator.Animations.FromArray(cAgent.Anims); if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0) { From 96c191f4fdbd64009fc210b8c911c832723bb10e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 00:09:18 +0000 Subject: [PATCH 05/26] Stop SP.HandleAgentUpdate() and PhysicsCollisionUpdate() from being processed if we're dealing with a child ScenePresence. Neither of these can have any effect on child agents Now leaving warning about trying to set animation on a child agent active. Might temporarily pop up now and again. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 14 ++++++-------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 11 +++++++---- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 6b1208cbb0..a2805d20bc 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -158,14 +158,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation SendAnimPack(); } } - // Don't leave this on since on teleports SP.HandleAgentUpdate() still hammers us for a while after it teleports -// else -// { -// m_log.WarnFormat( -// "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", -// anim, m_scenePresence.Name); -// throw new Exception(string.Format("aaargh on setting {0}", anim)); -// } + else + { + m_log.WarnFormat( + "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", + anim, m_scenePresence.Name); + } } /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b93b67de45..c517978ded 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1293,11 +1293,11 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE PRESENCE]: In {0} received agent update from {1}", // Scene.RegionInfo.RegionName, remoteClient.Name); - //if (IsChildAgent) - //{ + if (IsChildAgent) + { // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); - // return; - //} + return; + } ++m_movementUpdateCount; if (m_movementUpdateCount < 1) @@ -3280,6 +3280,9 @@ namespace OpenSim.Region.Framework.Scenes // Event called by the physics plugin to tell the avatar about a collision. private void PhysicsCollisionUpdate(EventArgs e) { + if (IsChildAgent) + return; + //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( // as of this comment the interval is set in AddToPhysicalScene From 5ba8ca5662efb9c4f595e9a703535661d72e5b2f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 00:27:21 +0000 Subject: [PATCH 06/26] Rename ScenePresenceAnimator.GetMovementAnimation() -> DetermineMovementAnimation() for better code readability --- .../Scenes/Animation/ScenePresenceAnimator.cs | 11 ++++++++--- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index a2805d20bc..cac936ce63 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -59,6 +59,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation get { return m_movementAnimation; } } protected string m_movementAnimation = "CROUCH"; + private int m_animTickFall; public int m_animTickJump; // ScenePresence has to see this to control +Z force public bool m_jumping = false; @@ -146,6 +147,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation { if (!m_scenePresence.IsChildAgent) { +// m_log.DebugFormat( +// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}", +// anim, m_scenePresence.Name); + if (m_animations.TrySetDefaultAnimation( anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) { @@ -169,7 +174,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// /// This method determines the proper movement related animation /// - public string GetMovementAnimation() + public string DetermineMovementAnimation() { const float FALL_DELAY = 800f; const float PREJUMP_DELAY = 200f; @@ -283,7 +288,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation int jumptime; jumptime = Environment.TickCount - m_animTickJump; - if ((move.Z > 0f) && (!m_jumping)) { // Start jumping, prejump @@ -387,6 +391,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation #endregion Ground Movement m_falling = false; + return m_movementAnimation; } @@ -395,7 +400,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// public void UpdateMovementAnimations() { - m_movementAnimation = GetMovementAnimation(); + m_movementAnimation = DetermineMovementAnimation(); TrySetMovementAnimation(m_movementAnimation); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 6c54c9beb1..2812683f6d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5554,7 +5554,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api flags |= ScriptBaseClass.AGENT_TYPING; } - string agentMovementAnimation = agent.Animator.GetMovementAnimation(); + string agentMovementAnimation = agent.Animator.DetermineMovementAnimation(); if (agentMovementAnimation == "CROUCH") { From 8185ce8b4afab459655f5cd362b2c6bbb98c28c3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 00:30:13 +0000 Subject: [PATCH 07/26] Do a cagent.Anims != null check in SP.CopyFrom() --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c517978ded..7156137aad 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3195,7 +3195,9 @@ namespace OpenSim.Region.Framework.Scenes } catch { } - Animator.Animations.FromArray(cAgent.Anims); + // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? + if (cAgent.Anims != null) + Animator.Animations.FromArray(cAgent.Anims); if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0) { From 5bbfb082ddf963037bf291caa9327ef9c7eff3e9 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 00:33:24 +0000 Subject: [PATCH 08/26] Use agent.Animator.CurrentMovementAnimation in llGetAgentInfo() rather than asking for a new determination --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2812683f6d..6c418df6ad 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5554,7 +5554,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api flags |= ScriptBaseClass.AGENT_TYPING; } - string agentMovementAnimation = agent.Animator.DetermineMovementAnimation(); + string agentMovementAnimation = agent.Animator.CurrentMovementAnimation; if (agentMovementAnimation == "CROUCH") { From 0ca8491bbeab74e4cb50521d4857104c7e0a59b9 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 00:40:08 +0000 Subject: [PATCH 09/26] refactor: Use just ScenePresenceAnimator.CurrentMovementAnimation rather than duplicating it with m_movementAnimation --- .../Scenes/Animation/ScenePresenceAnimator.cs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index cac936ce63..2a6b8eaed2 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -54,11 +54,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// /// The current movement animation /// - public string CurrentMovementAnimation - { - get { return m_movementAnimation; } - } - protected string m_movementAnimation = "CROUCH"; + public string CurrentMovementAnimation { get; private set; } private int m_animTickFall; public int m_animTickJump; // ScenePresence has to see this to control +Z force @@ -80,6 +76,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation public ScenePresenceAnimator(ScenePresence sp) { m_scenePresence = sp; + CurrentMovementAnimation = "CROUCH"; } public void AddAnimation(UUID animID, UUID objectID) @@ -174,7 +171,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// /// This method determines the proper movement related animation /// - public string DetermineMovementAnimation() + private string DetermineMovementAnimation() { const float FALL_DELAY = 800f; const float PREJUMP_DELAY = 200f; @@ -277,7 +274,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation return "FALLDOWN"; } - return m_movementAnimation; + return CurrentMovementAnimation; } #endregion Falling/Floating/Landing @@ -331,7 +328,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation #region Ground Movement - if (m_movementAnimation == "FALLDOWN") + if (CurrentMovementAnimation == "FALLDOWN") { m_falling = false; m_animTickFall = Environment.TickCount; @@ -344,16 +341,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation else return "LAND"; } - else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP")) + else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) { int landElapsed = Environment.TickCount - m_animTickFall; int limit = 1000; - if(m_movementAnimation == "LAND") limit = 350; + if (CurrentMovementAnimation == "LAND") + limit = 350; // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client if ((m_animTickFall != 0) && (landElapsed <= limit)) { - return m_movementAnimation; + return CurrentMovementAnimation; } else { @@ -392,7 +390,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation m_falling = false; - return m_movementAnimation; + return CurrentMovementAnimation; } /// @@ -400,8 +398,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// public void UpdateMovementAnimations() { - m_movementAnimation = DetermineMovementAnimation(); - TrySetMovementAnimation(m_movementAnimation); + CurrentMovementAnimation = DetermineMovementAnimation(); + TrySetMovementAnimation(CurrentMovementAnimation); } public UUID[] GetAnimationArray() From f08aad8a403e18625c01c0b3b4b6d4248476a64b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 01:47:12 +0000 Subject: [PATCH 10/26] For now, disable mechanism to limit avatar animation updates since this causes avatars to never reach the correct animation after some actions. This reverts to situation where animation updates are made each frame on SP.PhysicsCollisionUpdate (though a packet is only sent if the anim actually changes). m_updateCount was not being update on various avatar state changes, causing the correct animations to never be sent. Always setting in HandleAgentUpdate() is not enough since the avatar is continually sending AgentUpdate packets. One would need to identify all the conditions under which animations need to play out and set m_updateCount appropriately in SP.HandleAgentUpdate() --- .../Scenes/Animation/ScenePresenceAnimator.cs | 5 ++ .../Region/Framework/Scenes/ScenePresence.cs | 46 +++++++++---------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 2a6b8eaed2..43cfd807b3 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -399,6 +399,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation public void UpdateMovementAnimations() { CurrentMovementAnimation = DetermineMovementAnimation(); + +// m_log.DebugFormat( +// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", +// CurrentMovementAnimation, m_scenePresence.Name); + TrySetMovementAnimation(CurrentMovementAnimation); } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 7156137aad..663c9aeaad 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -149,9 +149,9 @@ namespace OpenSim.Region.Framework.Scenes } private bool m_wasFlying; // add for fly velocity control - private int m_lastColCount = -1; //KF: Look for Collision chnages - private int m_updateCount = 0; //KF: Update Anims for a while - private static readonly int UPDATE_COUNT = 10; // how many frames to update for +// private int m_lastColCount = -1; //KF: Look for Collision chnages +// private int m_updateCount = 0; //KF: Update Anims for a while +// private static readonly int UPDATE_COUNT = 10; // how many frames to update for private TeleportFlags m_teleportFlags; public TeleportFlags TeleportFlags @@ -1366,14 +1366,14 @@ namespace OpenSim.Region.Framework.Scenes #endregion Inputs - // Make anims work for client side autopilot - if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0) - m_updateCount = UPDATE_COUNT; - - // Make turning in place work - if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 || - (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) - m_updateCount = UPDATE_COUNT; +// // Make anims work for client side autopilot +// if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0) +// m_updateCount = UPDATE_COUNT; +// +// // Make turning in place work +// if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0 || +// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) +// m_updateCount = UPDATE_COUNT; if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) { @@ -2297,7 +2297,7 @@ namespace OpenSim.Region.Framework.Scenes public void HandleAgentSitOnGround() { - m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. +// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); SitGround = true; RemoveFromPhysicalScene(); @@ -3290,11 +3290,11 @@ namespace OpenSim.Region.Framework.Scenes // as of this comment the interval is set in AddToPhysicalScene if (Animator != null) { - if (m_updateCount > 0) - { +// if (m_updateCount > 0) +// { Animator.UpdateMovementAnimations(); - m_updateCount--; - } +// m_updateCount--; +// } } CollisionEventUpdate collisionData = (CollisionEventUpdate)e; @@ -3302,13 +3302,13 @@ namespace OpenSim.Region.Framework.Scenes CollisionPlane = Vector4.UnitW; - // No collisions at all means we may be flying. Update always - // to make falling work - if (m_lastColCount != coldata.Count || coldata.Count == 0) - { - m_updateCount = UPDATE_COUNT; - m_lastColCount = coldata.Count; - } +// // No collisions at all means we may be flying. Update always +// // to make falling work +// if (m_lastColCount != coldata.Count || coldata.Count == 0) +// { +// m_updateCount = UPDATE_COUNT; +// m_lastColCount = coldata.Count; +// } if (coldata.Count != 0 && Animator != null) { From feef1dd73243cfdd5322632fb67e64cabc1ad4bc Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 02:05:11 +0000 Subject: [PATCH 11/26] Stop calling Animator.UpdateMovementAnimations() at the end of HandleAgentUpdate(). There's no point doing this if it's being called via PhysicsCollisionUpdate --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 663c9aeaad..8865b3d9a6 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1582,8 +1582,8 @@ namespace OpenSim.Region.Framework.Scenes // } // } - if (update_movementflag && ParentID == 0) - Animator.UpdateMovementAnimations(); +// if (update_movementflag && ParentID == 0) +// Animator.UpdateMovementAnimations(); } m_scene.EventManager.TriggerOnClientMovement(this); From a009871827c250cc677bd42aed2351a3c2cec021 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 02:39:21 +0000 Subject: [PATCH 12/26] Add basic TestFlyingAnimation() regression test --- .../Region/Framework/Scenes/ScenePresence.cs | 7 +- .../Tests/ScenePresenceAnimationTests.cs | 70 +++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 8865b3d9a6..05331066dc 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3279,8 +3279,11 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); } - // Event called by the physics plugin to tell the avatar about a collision. - private void PhysicsCollisionUpdate(EventArgs e) + /// + /// Event called by the physics plugin to tell the avatar about a collision. + /// + /// + public void PhysicsCollisionUpdate(EventArgs e) { if (IsChildAgent) return; diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs new file mode 100644 index 0000000000..4a0533c44a --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs @@ -0,0 +1,70 @@ +/* + * 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.Text; +using System.Threading; +using System.Timers; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.Framework.EntityTransfer; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Region.Physics.Manager; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + /// + /// Scene presence animation tests + /// + [TestFixture] + public class ScenePresenceAnimationTests + { + [Test] + public void TestFlyingAnimation() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + TestScene scene = SceneHelpers.SetupScene(); + ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); + sp.PhysicsActor.Flying = true; + sp.PhysicsCollisionUpdate(new CollisionEventUpdate()); + + Assert.That(sp.Animator.CurrentMovementAnimation, Is.EqualTo("HOVER")); + } + } +} \ No newline at end of file From b66fe3e9ffd968c2c8aaa0fba108e86b8c4f04d9 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 02:45:02 +0000 Subject: [PATCH 13/26] Add method doc to SP.PhysicsCollisionUpdate() to make it clear that it's called continuously even where there are no collisions --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 05331066dc..1fe8048a8f 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3282,6 +3282,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// Event called by the physics plugin to tell the avatar about a collision. /// + /// + /// This function is called continuously, even when there are no collisions which might be very inefficient. + /// However, we can't avoid this yet since some of this method might currently rely on being called every frame. + /// /// public void PhysicsCollisionUpdate(EventArgs e) { From e26ef8aeca6fbdf4b355e6fcdb66f09d79d05915 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 02:48:16 +0000 Subject: [PATCH 14/26] change misleading login = http://127.0.0.1:9000/ in GridInfoService in Robust.ini.example to 8002 --- bin/Robust.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index beef1c30fe..90f7b5c0ac 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -260,7 +260,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ; See http://opensimulator.org/wiki/GridInfo ; login uri: for grid this is the login server URI - login = http://127.0.0.1:9000/ + login = http://127.0.0.1:8002/ ; long grid name: the long name of your grid gridname = "the lost continent of hippo" From 585fc5e79d4b87a5375fa3c2986b5f91d0de1f4e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 02:51:17 +0000 Subject: [PATCH 15/26] Update SP.PhysicsCollisionUpdate() doc. It might be inefficient, but there are collisions every frame if the avatar is walking/standing on the ground or a prim surface --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1fe8048a8f..5b9438b9e6 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3283,8 +3283,11 @@ namespace OpenSim.Region.Framework.Scenes /// Event called by the physics plugin to tell the avatar about a collision. /// /// - /// This function is called continuously, even when there are no collisions which might be very inefficient. - /// However, we can't avoid this yet since some of this method might currently rely on being called every frame. + /// This function is called continuously, even when there are no collisions. If the avatar is walking on the + /// ground or a prim then there will be collision information between the avatar and the surface. + /// + /// FIXME: However, we can't safely avoid calling this yet where there are no collisions without analyzing whether + /// any part of this method is relying on an every-frame call. /// /// public void PhysicsCollisionUpdate(EventArgs e) From e75bcd4c59234382ac3efb743a228cd23d92ad45 Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 25 Nov 2011 15:21:42 +0100 Subject: [PATCH 16/26] Workaround for mesh to correct the number of faces in GetNumberOfSides(). Meshs are handeled as sculpts but can have up to 8 faces (SL restriction the collada format can handle even more). The patch enables all LSL function that adressing faces to behave correct. Like llGetNumberOfSides(); llSetLinkPrimitiveParamsFast(); llSetPrimitiveParams(); llSetColor(); Signed-off-by: marc --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 24322a174f..304a7a7b10 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3272,7 +3272,15 @@ namespace OpenSim.Region.Framework.Scenes if (hasHollow) ret += 1; break; case PrimType.SCULPT: - ret = 1; + // Special mesh handling + if (this.Shape.SculptType == 5) + { + ret = 7; // its a mesh then max 8 faces + } + else + { + ret = 1; // its a sculpt then max 1 faces + } break; } return ret; From aba42d85434b0e0f367a4f691a9fab9d68fab99a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 15:54:06 +0000 Subject: [PATCH 17/26] Correct SOP.GetNumberOfSides() to return 8 for meshes rather than 7 We are returning the actual number of 'sides', not the maximum index number. Also minor format corrections. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 304a7a7b10..dcbcfa312b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3273,16 +3273,13 @@ namespace OpenSim.Region.Framework.Scenes break; case PrimType.SCULPT: // Special mesh handling - if (this.Shape.SculptType == 5) - { - ret = 7; // its a mesh then max 8 faces - } + if (Shape.SculptType == (byte)SculptType.Mesh) + ret = 8; // if it's a mesh then max 8 faces else - { - ret = 1; // its a sculpt then max 1 faces - } + ret = 1; // if it's a sculpt then max 1 face break; } + return ret; } @@ -3295,6 +3292,7 @@ namespace OpenSim.Region.Framework.Scenes { if (Shape.SculptEntry) return PrimType.SCULPT; + if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) { if (Shape.PathCurve == (byte)Extrusion.Straight) From aac3f2d04ed5d828f48959f73fca893f884cec3b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 16:04:11 +0000 Subject: [PATCH 18/26] Add agent circuit number checks to TestCloseAgent() --- .../Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index f0bbf0bc2b..f6a3d1f148 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -103,11 +103,15 @@ namespace OpenSim.Region.Framework.Scenes.Tests ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null); + Assert.That(scene.AuthenticateHandler.AgentCircuits.Count, Is.EqualTo(1)); + Assert.That(scene.AuthenticateHandler.AgentCircuitsByUUID.Count, Is.EqualTo(1)); scene.IncomingCloseAgent(sp.UUID); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); + Assert.That(scene.AuthenticateHandler.AgentCircuits.Count, Is.EqualTo(0)); + Assert.That(scene.AuthenticateHandler.AgentCircuitsByUUID.Count, Is.EqualTo(0)); } /// From c934901a056f142c49e6b449971fcaf59ff19d82 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 16:11:47 +0000 Subject: [PATCH 19/26] Use GetAgentCircuits() to receive a copy of the AgentCircuitsByUUID dictionary rather than AgentCircuitManager.AgentCircuits directly in "show circuits" to avoid enumeration exceptions --- OpenSim/Framework/AgentCircuitManager.cs | 91 +++++++++++-------- OpenSim/Region/Application/OpenSim.cs | 2 +- .../Scenes/Tests/ScenePresenceAgentTests.cs | 6 +- 3 files changed, 57 insertions(+), 42 deletions(-) diff --git a/OpenSim/Framework/AgentCircuitManager.cs b/OpenSim/Framework/AgentCircuitManager.cs index 1ce8c34079..a59bcfa1c4 100644 --- a/OpenSim/Framework/AgentCircuitManager.cs +++ b/OpenSim/Framework/AgentCircuitManager.cs @@ -35,15 +35,22 @@ namespace OpenSim.Framework /// public class AgentCircuitManager { - public Dictionary AgentCircuits = new Dictionary(); - public Dictionary AgentCircuitsByUUID = new Dictionary(); + /// + /// Agent circuits indexed by circuit code. + /// + private Dictionary m_agentCircuits = new Dictionary(); + + /// + /// Agent circuits indexed by agent UUID. + /// + private Dictionary m_agentCircuitsByUUID = new Dictionary(); public virtual AuthenticateResponse AuthenticateSession(UUID sessionID, UUID agentID, uint circuitcode) { AgentCircuitData validcircuit = null; - if (AgentCircuits.ContainsKey(circuitcode)) + if (m_agentCircuits.ContainsKey(circuitcode)) { - validcircuit = AgentCircuits[circuitcode]; + validcircuit = m_agentCircuits[circuitcode]; } AuthenticateResponse user = new AuthenticateResponse(); if (validcircuit == null) @@ -82,71 +89,81 @@ namespace OpenSim.Framework /// public virtual void AddNewCircuit(uint circuitCode, AgentCircuitData agentData) { - lock (AgentCircuits) + lock (m_agentCircuits) { - if (AgentCircuits.ContainsKey(circuitCode)) + if (m_agentCircuits.ContainsKey(circuitCode)) { - AgentCircuits[circuitCode] = agentData; - AgentCircuitsByUUID[agentData.AgentID] = agentData; + m_agentCircuits[circuitCode] = agentData; + m_agentCircuitsByUUID[agentData.AgentID] = agentData; } else { - AgentCircuits.Add(circuitCode, agentData); - AgentCircuitsByUUID[agentData.AgentID] = agentData; + m_agentCircuits.Add(circuitCode, agentData); + m_agentCircuitsByUUID[agentData.AgentID] = agentData; } } } public virtual void RemoveCircuit(uint circuitCode) { - lock (AgentCircuits) + lock (m_agentCircuits) { - if (AgentCircuits.ContainsKey(circuitCode)) + if (m_agentCircuits.ContainsKey(circuitCode)) { - UUID agentID = AgentCircuits[circuitCode].AgentID; - AgentCircuits.Remove(circuitCode); - AgentCircuitsByUUID.Remove(agentID); + UUID agentID = m_agentCircuits[circuitCode].AgentID; + m_agentCircuits.Remove(circuitCode); + m_agentCircuitsByUUID.Remove(agentID); } } } public virtual void RemoveCircuit(UUID agentID) { - lock (AgentCircuits) + lock (m_agentCircuits) { - if (AgentCircuitsByUUID.ContainsKey(agentID)) + if (m_agentCircuitsByUUID.ContainsKey(agentID)) { - uint circuitCode = AgentCircuitsByUUID[agentID].circuitcode; - AgentCircuits.Remove(circuitCode); - AgentCircuitsByUUID.Remove(agentID); + uint circuitCode = m_agentCircuitsByUUID[agentID].circuitcode; + m_agentCircuits.Remove(circuitCode); + m_agentCircuitsByUUID.Remove(agentID); } } } public AgentCircuitData GetAgentCircuitData(uint circuitCode) { AgentCircuitData agentCircuit = null; - AgentCircuits.TryGetValue(circuitCode, out agentCircuit); + m_agentCircuits.TryGetValue(circuitCode, out agentCircuit); return agentCircuit; } public AgentCircuitData GetAgentCircuitData(UUID agentID) { AgentCircuitData agentCircuit = null; - AgentCircuitsByUUID.TryGetValue(agentID, out agentCircuit); + m_agentCircuitsByUUID.TryGetValue(agentID, out agentCircuit); return agentCircuit; } + /// + /// Get all current agent circuits indexed by agent UUID. + /// + /// + public Dictionary GetAgentCircuits() + { + lock (m_agentCircuitsByUUID) + return new Dictionary(m_agentCircuitsByUUID); + } + public void UpdateAgentData(AgentCircuitData agentData) { - if (AgentCircuits.ContainsKey((uint) agentData.circuitcode)) + if (m_agentCircuits.ContainsKey((uint) agentData.circuitcode)) { - AgentCircuits[(uint) agentData.circuitcode].firstname = agentData.firstname; - AgentCircuits[(uint) agentData.circuitcode].lastname = agentData.lastname; - AgentCircuits[(uint) agentData.circuitcode].startpos = agentData.startpos; + m_agentCircuits[(uint) agentData.circuitcode].firstname = agentData.firstname; + m_agentCircuits[(uint) agentData.circuitcode].lastname = agentData.lastname; + m_agentCircuits[(uint) agentData.circuitcode].startpos = agentData.startpos; // Updated for when we don't know them before calling Scene.NewUserConnection - AgentCircuits[(uint) agentData.circuitcode].SecureSessionID = agentData.SecureSessionID; - AgentCircuits[(uint) agentData.circuitcode].SessionID = agentData.SessionID; + m_agentCircuits[(uint) agentData.circuitcode].SecureSessionID = agentData.SecureSessionID; + m_agentCircuits[(uint) agentData.circuitcode].SessionID = agentData.SessionID; // m_log.Debug("update user start pos is " + agentData.startpos.X + " , " + agentData.startpos.Y + " , " + agentData.startpos.Z); } @@ -159,16 +176,16 @@ namespace OpenSim.Framework /// public bool TryChangeCiruitCode(uint circuitcode, uint newcircuitcode) { - lock (AgentCircuits) + lock (m_agentCircuits) { - if (AgentCircuits.ContainsKey((uint)circuitcode) && !AgentCircuits.ContainsKey((uint)newcircuitcode)) + if (m_agentCircuits.ContainsKey((uint)circuitcode) && !m_agentCircuits.ContainsKey((uint)newcircuitcode)) { - AgentCircuitData agentData = AgentCircuits[(uint)circuitcode]; + AgentCircuitData agentData = m_agentCircuits[(uint)circuitcode]; agentData.circuitcode = newcircuitcode; - AgentCircuits.Remove((uint)circuitcode); - AgentCircuits.Add(newcircuitcode, agentData); + m_agentCircuits.Remove((uint)circuitcode); + m_agentCircuits.Add(newcircuitcode, agentData); return true; } } @@ -178,17 +195,17 @@ namespace OpenSim.Framework public void UpdateAgentChildStatus(uint circuitcode, bool childstatus) { - if (AgentCircuits.ContainsKey(circuitcode)) + if (m_agentCircuits.ContainsKey(circuitcode)) { - AgentCircuits[circuitcode].child = childstatus; + m_agentCircuits[circuitcode].child = childstatus; } } public bool GetAgentChildStatus(uint circuitcode) { - if (AgentCircuits.ContainsKey(circuitcode)) + if (m_agentCircuits.ContainsKey(circuitcode)) { - return AgentCircuits[circuitcode].child; + return m_agentCircuits[circuitcode].child; } return false; } diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 4b38a2e2f7..8d98cc9b93 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -1039,7 +1039,7 @@ namespace OpenSim { //this.HttpServer. acd.AppendFormat("{0}:\n", scene.RegionInfo.RegionName); - foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.AgentCircuits.Values) + foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.GetAgentCircuits().Values) acd.AppendFormat("\t{0} {1} ({2})\n", aCircuit.firstname, aCircuit.lastname, (aCircuit.child ? "Child" : "Root")); } ); diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index f6a3d1f148..57d22bde68 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -103,15 +103,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null); - Assert.That(scene.AuthenticateHandler.AgentCircuits.Count, Is.EqualTo(1)); - Assert.That(scene.AuthenticateHandler.AgentCircuitsByUUID.Count, Is.EqualTo(1)); + Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); scene.IncomingCloseAgent(sp.UUID); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); - Assert.That(scene.AuthenticateHandler.AgentCircuits.Count, Is.EqualTo(0)); - Assert.That(scene.AuthenticateHandler.AgentCircuitsByUUID.Count, Is.EqualTo(0)); + Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(0)); } /// From ced820bd5e0fe9c20309fe1a3cb91f9ee316ec22 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 16:19:11 +0000 Subject: [PATCH 20/26] Improve locking in AgentCircuitManager --- OpenSim/Framework/AgentCircuitManager.cs | 66 +++++++++++++++--------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/OpenSim/Framework/AgentCircuitManager.cs b/OpenSim/Framework/AgentCircuitManager.cs index a59bcfa1c4..b6e48b4372 100644 --- a/OpenSim/Framework/AgentCircuitManager.cs +++ b/OpenSim/Framework/AgentCircuitManager.cs @@ -38,6 +38,9 @@ namespace OpenSim.Framework /// /// Agent circuits indexed by circuit code. /// + /// + /// We lock this for operations both on this dictionary and on m_agentCircuitsByUUID + /// private Dictionary m_agentCircuits = new Dictionary(); /// @@ -48,16 +51,20 @@ namespace OpenSim.Framework public virtual AuthenticateResponse AuthenticateSession(UUID sessionID, UUID agentID, uint circuitcode) { AgentCircuitData validcircuit = null; - if (m_agentCircuits.ContainsKey(circuitcode)) + + lock (m_agentCircuits) { - validcircuit = m_agentCircuits[circuitcode]; + if (m_agentCircuits.ContainsKey(circuitcode)) + validcircuit = m_agentCircuits[circuitcode]; } + AuthenticateResponse user = new AuthenticateResponse(); + if (validcircuit == null) { //don't have this circuit code in our list user.Authorised = false; - return (user); + return user; } if ((sessionID == validcircuit.SessionID) && (agentID == validcircuit.AgentID)) @@ -79,7 +86,7 @@ namespace OpenSim.Framework user.Authorised = false; } - return (user); + return user; } /// @@ -129,17 +136,24 @@ namespace OpenSim.Framework } } } + public AgentCircuitData GetAgentCircuitData(uint circuitCode) { AgentCircuitData agentCircuit = null; - m_agentCircuits.TryGetValue(circuitCode, out agentCircuit); + + lock (m_agentCircuits) + m_agentCircuits.TryGetValue(circuitCode, out agentCircuit); + return agentCircuit; } public AgentCircuitData GetAgentCircuitData(UUID agentID) { AgentCircuitData agentCircuit = null; - m_agentCircuitsByUUID.TryGetValue(agentID, out agentCircuit); + + lock (m_agentCircuits) + m_agentCircuitsByUUID.TryGetValue(agentID, out agentCircuit); + return agentCircuit; } @@ -149,23 +163,26 @@ namespace OpenSim.Framework /// public Dictionary GetAgentCircuits() { - lock (m_agentCircuitsByUUID) + lock (m_agentCircuits) return new Dictionary(m_agentCircuitsByUUID); } public void UpdateAgentData(AgentCircuitData agentData) { - if (m_agentCircuits.ContainsKey((uint) agentData.circuitcode)) + lock (m_agentCircuits) { - m_agentCircuits[(uint) agentData.circuitcode].firstname = agentData.firstname; - m_agentCircuits[(uint) agentData.circuitcode].lastname = agentData.lastname; - m_agentCircuits[(uint) agentData.circuitcode].startpos = agentData.startpos; + if (m_agentCircuits.ContainsKey((uint) agentData.circuitcode)) + { + m_agentCircuits[(uint) agentData.circuitcode].firstname = agentData.firstname; + m_agentCircuits[(uint) agentData.circuitcode].lastname = agentData.lastname; + m_agentCircuits[(uint) agentData.circuitcode].startpos = agentData.startpos; - // Updated for when we don't know them before calling Scene.NewUserConnection - m_agentCircuits[(uint) agentData.circuitcode].SecureSessionID = agentData.SecureSessionID; - m_agentCircuits[(uint) agentData.circuitcode].SessionID = agentData.SessionID; + // Updated for when we don't know them before calling Scene.NewUserConnection + m_agentCircuits[(uint) agentData.circuitcode].SecureSessionID = agentData.SecureSessionID; + m_agentCircuits[(uint) agentData.circuitcode].SessionID = agentData.SessionID; - // m_log.Debug("update user start pos is " + agentData.startpos.X + " , " + agentData.startpos.Y + " , " + agentData.startpos.Z); + // m_log.Debug("update user start pos is " + agentData.startpos.X + " , " + agentData.startpos.Y + " , " + agentData.startpos.Z); + } } } @@ -189,25 +206,24 @@ namespace OpenSim.Framework return true; } } - return false; + return false; } public void UpdateAgentChildStatus(uint circuitcode, bool childstatus) { - if (m_agentCircuits.ContainsKey(circuitcode)) - { - m_agentCircuits[circuitcode].child = childstatus; - } + lock (m_agentCircuits) + if (m_agentCircuits.ContainsKey(circuitcode)) + m_agentCircuits[circuitcode].child = childstatus; } public bool GetAgentChildStatus(uint circuitcode) { - if (m_agentCircuits.ContainsKey(circuitcode)) - { - return m_agentCircuits[circuitcode].child; - } + lock (m_agentCircuits) + if (m_agentCircuits.ContainsKey(circuitcode)) + return m_agentCircuits[circuitcode].child; + return false; } } -} +} \ No newline at end of file From 4919c6056022053f8632b030a06fd8f48ac02a8e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 18:59:54 +0000 Subject: [PATCH 21/26] Add beginning of ScenePresenceAgentTests.TestCreateChildScenePresence() This required an option to be added to NullRegionData via ConnectionString for it to act as a non-static instance, so that regression tests (which only load this class once) don't get hopeless confused and complex to compensate. Normal standalone operation unaffected. --- OpenSim/Data/Null/NullRegionData.cs | 40 +++++++++--- .../Tests/AgentCircuitManagerTests.cs | 2 - OpenSim/Framework/Tests/AnimationTests.cs | 2 - .../EntityTransfer/EntityTransferModule.cs | 1 - .../Grid/Tests/GridConnectorsTests.cs | 9 +-- .../Scenes/Tests/ScenePresenceAgentTests.cs | 63 ++++++++++++++----- OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 3 + prebuild.xml | 1 + 8 files changed, 89 insertions(+), 32 deletions(-) diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs index 9d09af7636..deb50cb4df 100644 --- a/OpenSim/Data/Null/NullRegionData.cs +++ b/OpenSim/Data/Null/NullRegionData.cs @@ -40,24 +40,40 @@ namespace OpenSim.Data.Null { private static NullRegionData Instance = null; + /// + /// Should we use the static instance for all invocations? + /// + private bool m_useStaticInstance = true; + // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); Dictionary m_regionData = new Dictionary(); public NullRegionData(string connectionString, string realm) { - if (Instance == null) +// m_log.DebugFormat( +// "[NULL REGION DATA]: Constructor got connectionString {0}, realm {1}", connectionString, realm); + + // The !static connection string is a hack so that regression tests can use this module without a high degree of fragility + // in having to deal with the static reference in the once-loaded NullRegionData class. + // + // In standalone operation, we have to use only one instance of this class since the login service and + // simulator have no other way of using a common data store. + if (connectionString == "!static") + m_useStaticInstance = false; + else if (Instance == null) Instance = this; - //Console.WriteLine("[XXX] NullRegionData constructor"); } private delegate bool Matcher(string value); public List Get(string regionName, UUID scopeID) { - if (Instance != this) + if (m_useStaticInstance && Instance != this) return Instance.Get(regionName, scopeID); +// m_log.DebugFormat("[NULL REGION DATA]: Getting region {0}, scope {1}", regionName, scopeID); + string cleanName = regionName.ToLower(); // Handle SQL wildcards @@ -82,6 +98,7 @@ namespace OpenSim.Data.Null cleanName = cleanName.Remove(cleanName.Length - 1); } } + Matcher queryMatch; if (wildcardPrefix && wildcardSuffix) queryMatch = delegate(string s) { return s.Contains(cleanName); }; @@ -110,7 +127,7 @@ namespace OpenSim.Data.Null public RegionData Get(int posX, int posY, UUID scopeID) { - if (Instance != this) + if (m_useStaticInstance && Instance != this) return Instance.Get(posX, posY, scopeID); List ret = new List(); @@ -129,7 +146,7 @@ namespace OpenSim.Data.Null public RegionData Get(UUID regionID, UUID scopeID) { - if (Instance != this) + if (m_useStaticInstance && Instance != this) return Instance.Get(regionID, scopeID); if (m_regionData.ContainsKey(regionID)) @@ -140,7 +157,7 @@ namespace OpenSim.Data.Null public List Get(int startX, int startY, int endX, int endY, UUID scopeID) { - if (Instance != this) + if (m_useStaticInstance && Instance != this) return Instance.Get(startX, startY, endX, endY, scopeID); List ret = new List(); @@ -156,9 +173,12 @@ namespace OpenSim.Data.Null public bool Store(RegionData data) { - if (Instance != this) + if (m_useStaticInstance && Instance != this) return Instance.Store(data); +// m_log.DebugFormat( +// "[NULL REGION DATA]: Storing region {0} {1}, scope {2}", data.RegionName, data.RegionID, data.ScopeID); + m_regionData[data.RegionID] = data; return true; @@ -166,7 +186,7 @@ namespace OpenSim.Data.Null public bool SetDataItem(UUID regionID, string item, string value) { - if (Instance != this) + if (m_useStaticInstance && Instance != this) return Instance.SetDataItem(regionID, item, value); if (!m_regionData.ContainsKey(regionID)) @@ -179,9 +199,11 @@ namespace OpenSim.Data.Null public bool Delete(UUID regionID) { - if (Instance != this) + if (m_useStaticInstance && Instance != this) return Instance.Delete(regionID); +// m_log.DebugFormat("[NULL REGION DATA]: Deleting region {0}", regionID); + if (!m_regionData.ContainsKey(regionID)) return false; diff --git a/OpenSim/Framework/Tests/AgentCircuitManagerTests.cs b/OpenSim/Framework/Tests/AgentCircuitManagerTests.cs index 9615f1b6ca..ae132c8c8b 100644 --- a/OpenSim/Framework/Tests/AgentCircuitManagerTests.cs +++ b/OpenSim/Framework/Tests/AgentCircuitManagerTests.cs @@ -194,8 +194,6 @@ namespace OpenSim.Framework.Tests resp = agentCircuitManager.AuthenticateSession(SessionId2, AgentId2, circuitcode2); Assert.That(!resp.Authorised); - } - } } diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs index aa4c6aa1a7..967a35562c 100644 --- a/OpenSim/Framework/Tests/AnimationTests.cs +++ b/OpenSim/Framework/Tests/AnimationTests.cs @@ -87,8 +87,6 @@ namespace OpenSim.Framework.Tests anim4.SequenceNum = anim2.SequenceNum; Assert.That(anim4.ObjectID == objUUID2 && anim4.AnimID == animUUID2 && anim4.SequenceNum == 1, "void constructor and manual field population failed to set the properties correctly."); - - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 99064c8a1f..2f947fd1ab 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -1341,7 +1341,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer string reason = String.Empty; - bool regionAccepted = m_scene.SimulationService.CreateAgent(reg, a, (uint)TeleportFlags.Default, out reason); if (regionAccepted && newAgent) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index cd7d6bc71c..b286d172e4 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -31,11 +31,10 @@ using System.IO; using System.Reflection; using System.Threading; using log4net.Config; +using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenSim.Framework; -using Nini.Config; - using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; using OpenSim.Region.Framework.Scenes; using GridRegion = OpenSim.Services.Interfaces.GridRegion; @@ -69,6 +68,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests [Test] public void TestRegisterRegion() { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + SetUp(); // Create 4 regions @@ -191,7 +193,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests results = m_LocalConnector.GetHyperlinks(UUID.Zero); Assert.IsNotNull(results, "Retrieved GetHyperlinks list is null"); Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected"); - } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 57d22bde68..f479e12c63 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -31,7 +31,7 @@ using System.Reflection; using System.Text; using System.Threading; using System.Timers; -using Timer=System.Timers.Timer; +using Timer = System.Timers.Timer; using Nini.Config; using NUnit.Framework; using OpenMetaverse; @@ -39,11 +39,13 @@ using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.ClientStack.Linden; using OpenSim.Region.CoreModules.Framework.EntityTransfer; using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.Framework.Scenes.Tests { @@ -112,14 +114,40 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(0)); } + [Test] + public void TestCreateChildScenePresence() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + LocalSimulationConnectorModule lsc = new LocalSimulationConnectorModule(); + + IConfigSource configSource = new IniConfigSource(); + IConfig config = configSource.AddConfig("Modules"); + config.Set("SimulationServices", "LocalSimulationConnectorModule"); + + TestScene scene = SceneHelpers.SetupScene(); + SceneHelpers.SetupSceneModules(scene, configSource, lsc); + + UUID agentId = TestHelpers.ParseTail(0x01); + AgentCircuitData acd = SceneHelpers.GenerateAgentData(agentId); + + GridRegion region = scene.GridService.GetRegionByName(UUID.Zero, scene.RegionInfo.RegionName); + string reason; + scene.SimulationService.CreateAgent(region, acd, (uint)TeleportFlags.ViaLogin, out reason); + + Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); + Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); + } + /// /// Test that if a root agent logs into a region, a child agent is also established in the neighbouring region /// /// - /// Please note that unlike the other tests here, this doesn't rely on structures + /// Please note that unlike the other tests here, this doesn't rely on anything set up in the instance fields. /// [Test] - public void TestChildAgentEstablished() + public void TestChildAgentEstablishedInNeighbour() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -127,18 +155,25 @@ namespace OpenSim.Region.Framework.Scenes.Tests UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001"); TestScene myScene1 = SceneHelpers.SetupScene("Neighbour y", UUID.Random(), 1000, 1000); -// TestScene myScene2 = SceneHelpers.SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000); - - IConfigSource configSource = new IniConfigSource(); - configSource.AddConfig("Modules").Set("EntityTransferModule", "BasicEntityTransferModule"); - EntityTransferModule etm = new EntityTransferModule(); - - SceneHelpers.SetupSceneModules(myScene1, configSource, etm); - - SceneHelpers.AddScenePresence(myScene1, agent1Id); -// ScenePresence childPresence = myScene2.GetScenePresence(agent1); + TestScene myScene2 = SceneHelpers.SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000); - // TODO: Need to do a fair amount of work to allow synchronous establishment of child agents + IConfigSource configSource = new IniConfigSource(); + IConfig config = configSource.AddConfig("Startup"); + config.Set("serverside_object_permissions", true); + config.Set("EventQueue", true); + + EntityTransferModule etm = new EntityTransferModule(); + + EventQueueGetModule eqgm1 = new EventQueueGetModule(); + SceneHelpers.SetupSceneModules(myScene1, configSource, etm, eqgm1); + + EventQueueGetModule eqgm2 = new EventQueueGetModule(); + SceneHelpers.SetupSceneModules(myScene2, configSource, etm, eqgm2); + +// SceneHelpers.AddScenePresence(myScene1, agent1Id); +// ScenePresence childPresence = myScene2.GetScenePresence(agent1); +// +// // TODO: Need to do a fair amount of work to allow synchronous establishment of child agents // Assert.That(childPresence, Is.Not.Null); // Assert.That(childPresence.IsChildAgent, Is.True); } diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index d358ae86f2..e4640be04b 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -49,6 +49,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common.Mock; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Tests.Common { @@ -139,6 +140,7 @@ namespace OpenSim.Tests.Common testScene.RegionInfo.EstateSettings = new EstateSettings(); testScene.LoginsDisabled = false; + testScene.RegisterRegionWithGrid(); return testScene; } @@ -222,6 +224,7 @@ namespace OpenSim.Tests.Common config.Configs["Modules"].Set("GridServices", "LocalGridServicesConnector"); config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll:NullRegionData"); config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); + config.Configs["GridService"].Set("ConnectionString", "!static"); LocalGridServicesConnector gridService = new LocalGridServicesConnector(); gridService.Initialise(config); diff --git a/prebuild.xml b/prebuild.xml index a7e3bde5b8..4e3617214d 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -3016,6 +3016,7 @@ + From 3852f05e6e03425e06eec1faa19929146901c92e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 19:10:32 +0000 Subject: [PATCH 22/26] Extend TestCreateChildScenePresence to make assertions both at CreateAgent stage and then at Scene.AddClient() --- .../Scenes/Tests/ScenePresenceAgentTests.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index f479e12c63..df2dacb306 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -131,13 +131,29 @@ namespace OpenSim.Region.Framework.Scenes.Tests UUID agentId = TestHelpers.ParseTail(0x01); AgentCircuitData acd = SceneHelpers.GenerateAgentData(agentId); + acd.child = true; GridRegion region = scene.GridService.GetRegionByName(UUID.Zero, scene.RegionInfo.RegionName); string reason; + // XXX: ViaLogin may not be correct here. scene.SimulationService.CreateAgent(region, acd, (uint)TeleportFlags.ViaLogin, out reason); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); + + // There's no scene presence yet since only an agent circuit has been established. + Assert.That(scene.GetScenePresence(agentId), Is.Null); + + TestClient client = new TestClient(acd, scene); + scene.AddNewClient(client, PresenceType.User); + + Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); + Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); + + ScenePresence sp = scene.GetScenePresence(agentId); + Assert.That(sp, Is.Not.Null); + Assert.That(sp.UUID, Is.EqualTo(agentId)); + Assert.That(sp.IsChildAgent, Is.True); } /// From a4d82895be6617ab409735c107903c6aaef2c234 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 19:14:37 +0000 Subject: [PATCH 23/26] Remove T012_TestAddNeighbourRegion() and T013_TestRemoveNeighbourRegion() since they don't do anything useful. --- .../Scenes/Tests/ScenePresenceAgentTests.cs | 75 ++----------------- 1 file changed, 5 insertions(+), 70 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index df2dacb306..946481c7ea 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -135,6 +135,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests GridRegion region = scene.GridService.GetRegionByName(UUID.Zero, scene.RegionInfo.RegionName); string reason; + + // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and + // establish a child scene presence. We pass in the circuit code that the client has to connect with *** // XXX: ViaLogin may not be correct here. scene.SimulationService.CreateAgent(region, acd, (uint)TeleportFlags.ViaLogin, out reason); @@ -144,6 +147,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests // There's no scene presence yet since only an agent circuit has been established. Assert.That(scene.GetScenePresence(agentId), Is.Null); + // *** This is the second stage, where the client established a child agent/scene presence using the + // circuit code given to the scene in stage 1 *** TestClient client = new TestClient(acd, scene); scene.AddNewClient(client, PresenceType.User); @@ -247,48 +252,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests // Assert.That(presence, Is.Null, "presence is not null"); // } - [Test] - public void T012_TestAddNeighbourRegion() - { - TestHelpers.InMethod(); - - string reason; - - if (acd1 == null) - fixNullPresence(); - - scene.NewUserConnection(acd1, 0, out reason); - if (testclient == null) - testclient = new TestClient(acd1, scene); - scene.AddNewClient(testclient, PresenceType.User); - - ScenePresence presence = scene.GetScenePresence(agent1); - presence.MakeRootAgent(new Vector3(90,90,90),false); - - string cap = presence.ControllingClient.RequestClientInfo().CapsPath; - - presence.AddNeighbourRegion(region2, cap); - presence.AddNeighbourRegion(region3, cap); - - Assert.That(presence.KnownRegionCount, Is.EqualTo(2)); - } - - [Test] - public void T013_TestRemoveNeighbourRegion() - { - TestHelpers.InMethod(); - - ScenePresence presence = scene.GetScenePresence(agent1); - presence.RemoveNeighbourRegion(region3); - - Assert.That(presence.KnownRegionCount,Is.EqualTo(1)); - /* - presence.MakeChildAgent; - presence.MakeRootAgent; - CompleteAvatarMovement - */ - } - // I'm commenting this test because it does not represent // crossings. The Thread.Sleep's in here are not meaningful mocks, // and they sometimes fail in panda. @@ -391,33 +354,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); } - - public void fixNullPresence() - { - string firstName = "testfirstname"; - - AgentCircuitData agent = new AgentCircuitData(); - agent.AgentID = agent1; - agent.firstname = firstName; - agent.lastname = "testlastname"; - agent.SessionID = UUID.Zero; - agent.SecureSessionID = UUID.Zero; - agent.circuitcode = 123; - agent.BaseFolder = UUID.Zero; - agent.InventoryFolder = UUID.Zero; - agent.startpos = Vector3.Zero; - agent.CapsPath = GetRandomCapsObjectPath(); - agent.Appearance = new AvatarAppearance(); - - acd1 = agent; - } - - public static string GetRandomCapsObjectPath() - { - UUID caps = UUID.Random(); - string capsPath = caps.ToString(); - capsPath = capsPath.Remove(capsPath.Length - 4, 4); - return capsPath; - } } } \ No newline at end of file From a82aea53f863566037fa4fe3d546f57a49a126fa Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 3 Dec 2011 19:32:59 +0000 Subject: [PATCH 24/26] Split up test SceneHelpers to provide an AddChildScenePresence() call --- .../Scenes/Tests/ScenePresenceAgentTests.cs | 1 + OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 35 +++++++++++++------ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 946481c7ea..d4c299f996 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -166,6 +166,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests /// /// /// Please note that unlike the other tests here, this doesn't rely on anything set up in the instance fields. + /// INCOMPLETE /// [Test] public void TestChildAgentEstablishedInNeighbour() diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index e4640be04b..a25eb66751 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -396,27 +396,42 @@ namespace OpenSim.Tests.Common /// public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData) { - string reason; - // We emulate the proper login sequence here by doing things in four stages - // Stage 0: log the presence + // Stage 0: login scene.PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID); - // Stage 1: simulate login by telling the scene to expect a new user connection - if (!scene.NewUserConnection(agentData, (uint)TeleportFlags.ViaLogin, out reason)) + // Stages 1 & 2 + ScenePresence sp = IntroduceClientToScene(scene, agentData, TeleportFlags.ViaLogin); + + // Stage 3: Complete the entrance into the region. This converts the child agent into a root agent. + sp.CompleteMovement(sp.ControllingClient, true); + + return sp; + } + + private static ScenePresence IntroduceClientToScene(Scene scene, AgentCircuitData agentData, TeleportFlags tf) + { + string reason; + + // Stage 1: tell the scene to expect a new user connection + if (!scene.NewUserConnection(agentData, (uint)tf, out reason)) Console.WriteLine("NewUserConnection failed: " + reason); // Stage 2: add the new client as a child agent to the scene TestClient client = new TestClient(agentData, scene); scene.AddNewClient(client, PresenceType.User); - // Stage 3: Complete the entrance into the region. This converts the child agent into a root agent. - ScenePresence scp = scene.GetScenePresence(agentData.AgentID); - scp.CompleteMovement(client, true); - //scp.MakeRootAgent(new Vector3(90, 90, 90), true); + return scene.GetScenePresence(agentData.AgentID); + } - return scp; + public static ScenePresence AddChildScenePresence(Scene scene, UUID agentId) + { + AgentCircuitData acd = GenerateAgentData(agentId); + acd.child = true; + + // XXX: ViaLogin may not be correct for child agents + return IntroduceClientToScene(scene, acd, TeleportFlags.ViaLogin); } /// From 080dfcc9c96c387599cf6734756a83e33a210553 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 4 Dec 2011 08:24:16 -0800 Subject: [PATCH 25/26] HG: Renamed one method --- OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs | 2 +- .../Services/Connectors/Hypergrid/UserAgentServiceConnector.cs | 2 +- OpenSim/Services/HypergridService/GatekeeperService.cs | 2 +- OpenSim/Services/HypergridService/UserAgentService.cs | 2 +- OpenSim/Services/Interfaces/IHypergridServices.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 72a4aeaa62..50010f2dfb 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -143,7 +143,7 @@ namespace OpenSim.Server.Handlers.Hypergrid UUID.TryParse(sessionID_str, out sessionID); string gridName = (string)requestData["externalName"]; - bool success = m_HomeUsersService.AgentIsComingHome(sessionID, gridName); + bool success = m_HomeUsersService.IsAgentComingHome(sessionID, gridName); Hashtable hash = new Hashtable(); hash["result"] = success.ToString(); diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 63aabad04f..7a4ec57997 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -358,7 +358,7 @@ namespace OpenSim.Services.Connectors.Hypergrid return null; } - public bool AgentIsComingHome(UUID sessionID, string thisGridExternalName) + public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName) { Hashtable hash = new Hashtable(); hash["sessionID"] = sessionID.ToString(); diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index e26383f0ff..5d99c79ac8 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -243,7 +243,7 @@ namespace OpenSim.Services.HypergridService // Make sure this is the user coming home, and not a foreign user with same UUID as a local user if (m_UserAgentService != null) { - if (!m_UserAgentService.AgentIsComingHome(aCircuit.SessionID, m_ExternalName)) + if (!m_UserAgentService.IsAgentComingHome(aCircuit.SessionID, m_ExternalName)) { // Can't do, sorry reason = "Unauthorized"; diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 1559cf3205..cdc560c4f5 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -281,7 +281,7 @@ namespace OpenSim.Services.HypergridService } // We need to prevent foreign users with the same UUID as a local user - public bool AgentIsComingHome(UUID sessionID, string thisGridExternalName) + public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName) { if (!m_TravelingAgents.ContainsKey(sessionID)) return false; diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 220caef007..e86ec519e5 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -65,7 +65,7 @@ namespace OpenSim.Services.Interfaces List StatusNotification(List friends, UUID userID, bool online); //List GetOnlineFriends(UUID userID, List friends); - bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); + bool IsAgentComingHome(UUID sessionID, string thisGridExternalName); bool VerifyAgent(UUID sessionID, string token); bool VerifyClient(UUID sessionID, string reportedIP); } From a2d98c72930594da2cd8056adf1e2be942051843 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 4 Dec 2011 10:10:09 -0800 Subject: [PATCH 26/26] HG: Added HEAD method to Helo service. This is the preferred method, but its wide use will have to wait a few releases. So the sims are still calling GET for now. --- .../Handlers/Hypergrid/HeloServerConnector.cs | 34 ++++++++++++++++++- .../Hypergrid/HeloServiceConnector.cs | 2 ++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs index 39baa324cb..4accea1ecd 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs @@ -45,9 +45,11 @@ namespace OpenSim.Server.Handlers.Hypergrid base(config, server, configName) { server.AddStreamHandler(new HeloServerGetHandler("opensim-robust")); + server.AddStreamHandler(new HeloServerHeadHandler("opensim-robust")); } } + [Obsolete] public class HeloServerGetHandler : BaseStreamHandler { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -68,7 +70,7 @@ namespace OpenSim.Server.Handlers.Hypergrid private byte[] OKResponse(OSHttpResponse httpResponse) { - m_log.Debug("[HELO]: hi, I was called"); + m_log.Debug("[HELO]: hi, GET was called"); httpResponse.AddHeader("X-Handlers-Provided", m_HandlersType); httpResponse.StatusCode = (int)HttpStatusCode.OK; httpResponse.StatusDescription = "OK"; @@ -76,4 +78,34 @@ namespace OpenSim.Server.Handlers.Hypergrid } } + + public class HeloServerHeadHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_HandlersType; + + public HeloServerHeadHandler(string handlersType) : + base("HEAD", "/helo") + { + m_HandlersType = handlersType; + } + + public override byte[] Handle(string path, Stream requestData, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return OKResponse(httpResponse); + } + + private byte[] OKResponse(OSHttpResponse httpResponse) + { + m_log.Debug("[HELO]: hi, HEAD was called"); + httpResponse.AddHeader("X-Handlers-Provided", m_HandlersType); + httpResponse.StatusCode = (int)HttpStatusCode.OK; + httpResponse.StatusDescription = "OK"; + return new byte[0]; + } + + } + } diff --git a/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs index 7b166c14e3..7cfd6e8df3 100644 --- a/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs @@ -54,6 +54,8 @@ namespace OpenSim.Services.Connectors public virtual string Helo() { HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI + "/helo"); + // Eventually we need to switch to HEAD + /* req.Method = "HEAD"; */ try {