From 355cde464a7ada3c6ab8fce7eb4118ad5cec0351 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 8 Dec 2011 16:10:47 +0000 Subject: Simplify Scene.AddNewClient() If sp becomes null right after we've checked or created it, then behaviour down the line is going to be wrong anyway. So instead retain the check/create ScenePresence reference and use this. --- OpenSim/Region/Framework/Scenes/Scene.cs | 45 ++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 87af206..21c4a87 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2487,7 +2487,7 @@ namespace OpenSim.Region.Framework.Scenes #region Add/Remove Avatar Methods /// - /// Add a new client and create a child agent for it. + /// Add a new client and create a child scene presence for it. /// /// /// The type of agent to add. @@ -2504,42 +2504,53 @@ namespace OpenSim.Region.Framework.Scenes CheckHeartbeat(); - if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here + ScenePresence sp = GetScenePresence(client.AgentId); + + // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this + // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause + // other problems, and possible the code calling AddNewClient() should ensure that no client is already + // connected. + if (sp == null) { - m_log.Debug("[SCENE]: Adding new agent " + client.Name + " to scene " + RegionInfo.RegionName); + m_log.Debug("[SCENE]: Adding new child scene presence " + client.Name + " to scene " + RegionInfo.RegionName); m_clientManager.Add(client); SubscribeToClientEvents(client); - ScenePresence sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); m_eventManager.TriggerOnNewPresence(sp); sp.TeleportFlags = (TeleportFlags)aCircuit.teleportFlags; - // HERE!!! Do the initial attachments right here - // first agent upon login is a root agent by design. - // All other AddNewClient calls find aCircuit.child to be true + // The first agent upon login is a root agent by design. + // For this agent we will have to rez the attachments. + // All other AddNewClient calls find aCircuit.child to be true. if (aCircuit.child == false) { + // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to + // start the scripts again (since this is done in RezAttachments()). + // XXX: This is convoluted. sp.IsChildAgent = false; if (AttachmentsModule != null) Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); } } - - ScenePresence createdSp = GetScenePresence(client.AgentId); - if (createdSp != null) + else { - m_LastLogin = Util.EnvironmentTickCount(); + m_log.WarnFormat( + "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", + sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); + } - // Cache the user's name - CacheUserName(createdSp, aCircuit); + m_LastLogin = Util.EnvironmentTickCount(); - EventManager.TriggerOnNewClient(client); - if (vialogin) - EventManager.TriggerOnClientLogin(client); - } + // Cache the user's name + CacheUserName(sp, aCircuit); + + EventManager.TriggerOnNewClient(client); + if (vialogin) + EventManager.TriggerOnClientLogin(client); // Send all scene object to the new client Util.FireAndForget(delegate -- cgit v1.1 From f61e54892f2284b6f89bacf3069467c05b2eea11 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 8 Dec 2011 18:34:23 +0000 Subject: On a new client circuit, send the initial reply ack to let the client know it's live before sending other data. This means that avatar/appearance data of other avatars and scene objects for a client will be sent after the ack rather than possibly before. This may stop some avatars appearing grey on login. This introduces a new OpenSim.Framework.ISceneAgent to accompany the existing OpenSim.Framework.ISceneObject and ISceneEntity This allows IClientAPI to handle this as it can't reference OpenSim.Region.Framework.Interfaces --- OpenSim/Region/Framework/Scenes/Scene.cs | 15 ++------- OpenSim/Region/Framework/Scenes/SceneBase.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 39 +++++++++++++++--------- 3 files changed, 29 insertions(+), 27 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 21c4a87..d47536a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2491,13 +2491,13 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// The type of agent to add. - public override void AddNewClient(IClientAPI client, PresenceType type) + public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) { AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); bool vialogin = false; if (aCircuit == null) // no good, didn't pass NewUserConnection successfully - return; + return null; vialogin = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; @@ -2552,16 +2552,7 @@ namespace OpenSim.Region.Framework.Scenes if (vialogin) EventManager.TriggerOnClientLogin(client); - // Send all scene object to the new client - Util.FireAndForget(delegate - { - EntityBase[] entities = Entities.GetEntities(); - foreach(EntityBase e in entities) - { - if (e != null && e is SceneObjectGroup) - ((SceneObjectGroup)e).SendFullUpdateToClient(client); - } - }); + return sp; } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index a633c72..da15491 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -175,7 +175,7 @@ namespace OpenSim.Region.Framework.Scenes #region Add/Remove Agent/Avatar - public abstract void AddNewClient(IClientAPI client, PresenceType type); + public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); public abstract void RemoveClient(UUID agentID, bool closeChildAgents); public bool TryGetScenePresence(UUID agentID, out object scenePresence) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5b9438b..8e55996 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -782,15 +782,6 @@ namespace OpenSim.Region.Framework.Scenes AdjustKnownSeeds(); - // 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) - -// MIC: This gets called again in CompleteMovement - // SendInitialFullUpdateToAllClients(); - SendOtherAgentsAvatarDataToMe(); - SendOtherAgentsAppearanceToMe(); - RegisterToEvents(); SetDirectionVectors(); @@ -1191,9 +1182,9 @@ namespace OpenSim.Region.Framework.Scenes { // DateTime startTime = DateTime.Now; - m_log.DebugFormat( - "[SCENE PRESENCE]: Completing movement of {0} into region {1}", - client.Name, Scene.RegionInfo.RegionName); +// m_log.DebugFormat( +// "[SCENE PRESENCE]: Completing movement of {0} into region {1}", +// client.Name, Scene.RegionInfo.RegionName); Vector3 look = Velocity; if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) @@ -1225,7 +1216,7 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); - SendInitialData(); + ValidateAndSendAppearanceAndAgentData(); // Create child agents in neighbouring regions if (openChildAgents && !IsChildAgent) @@ -2512,11 +2503,31 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); } + public void SendInitialDataToMe() + { + // 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) + SendOtherAgentsAvatarDataToMe(); + SendOtherAgentsAppearanceToMe(); + + // Send all scene object to the new client + Util.FireAndForget(delegate + { + EntityBase[] entities = Scene.Entities.GetEntities(); + foreach(EntityBase e in entities) + { + if (e != null && e is SceneObjectGroup) + ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); + } + }); + } + /// /// Do everything required once a client completes its movement into a region and becomes /// a root agent. /// - private void SendInitialData() + private void ValidateAndSendAppearanceAndAgentData() { //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); // Moved this into CompleteMovement to ensure that Appearance is initialized before -- cgit v1.1 From 54360dd20ef4034e33bfeadcb067d8ff6cbf7e70 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 8 Dec 2011 18:39:56 +0000 Subject: When a client connects to a scene, send other avatar appearance data asynchronously to reduce hold up in the IN UDP packet processing loop. This is already being done for the initial object data send. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 8e55996..a70c276 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2505,15 +2505,15 @@ namespace OpenSim.Region.Framework.Scenes public void SendInitialDataToMe() { - // 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) - SendOtherAgentsAvatarDataToMe(); - SendOtherAgentsAppearanceToMe(); - // Send all scene object to the new client Util.FireAndForget(delegate { + // 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) + SendOtherAgentsAvatarDataToMe(); + SendOtherAgentsAppearanceToMe(); + EntityBase[] entities = Scene.Entities.GetEntities(); foreach(EntityBase e in entities) { -- cgit v1.1