From 541a7660e06206c9a9eb2426dee0449afb554921 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Tue, 23 Nov 2010 16:08:10 -0800 Subject: Refactor appearance and avatar data sending code. Paritioning the routines into "one-to-many" and "many-to-one" makes it possible to call the right function on presence creation (both child and root) and when a child agent is promoted to root. This brings the total number of appearance sends down to one or two on login. Cleaned up the avatar update calls in the groups code. Cleaned up some commented and debugging code, and a few formating fixes. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 30 +-- .../EntityTransfer/EntityTransferModule.cs | 4 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 231 +++++++++++---------- .../Avatar/XmlRpcGroups/GroupsModule.cs | 9 +- 4 files changed, 132 insertions(+), 142 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 0df4585..ab1c206 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory }); } - // m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); + m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); } // Process the visual params, this may change height as well @@ -196,12 +196,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory sp.SetHeight(sp.Appearance.AvatarHeight); } } - - // Send the appearance back to the avatar, not clear that this is needed - sp.ControllingClient.SendAvatarDataImmediate(sp); - // AvatarAppearance avp = sp.Appearance; - // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); - } @@ -274,21 +268,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Send the appearance to everyone in the scene sp.SendAppearanceToAllOtherAgents(); - // sp.ControllingClient.SendAvatarDataImmediate(sp); - - // Send the appearance back to the avatar - // AvatarAppearance avp = sp.Appearance; - // sp.ControllingClient.SendAppearance(avp.Owner, avp.VisualParams, avp.Texture.GetBytes()); - -/* -// this needs to be fixed, the flag should be on scene presence not the region module - // Start the animations if necessary - if (!m_startAnimationSet) - { - sp.Animator.UpdateMovementAnimations(); - m_startAnimationSet = true; - } -*/ } private void HandleAppearanceSave(UUID agentid) @@ -374,6 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); + // operate on a copy of the appearance so we don't have to lock anything AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) @@ -388,9 +368,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory SetAppearanceAssets(sp.UUID, ref avatAppearance); // could get fancier with the locks here, but in the spirit of "last write wins" - // this should work correctly + // this should work correctly, also, we don't need to send the appearance here + // since the "iswearing" will trigger a new set of visual param and baked texture changes + // when those complete, the new appearance will be sent sp.Appearance = avatAppearance; - m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); + QueueAppearanceSave(client.AgentId); } private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index f02a922..b57dc88 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -903,8 +903,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } agent.MakeChildAgent(); + // now we have a child agent in this region. Request all interesting data about other (root) agents - agent.SendInitialFullUpdateToAllClients(); + agent.SendOtherAgentsAvatarDataToMe(); + agent.SendOtherAgentsAppearanceToMe(); CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index db69093..4a48ac3 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -703,7 +703,9 @@ namespace OpenSim.Region.Framework.Scenes // Note: This won't send data *to* other clients in that region (children don't send) // MIC: This gets called again in CompleteMovement - SendInitialFullUpdateToAllClients(); + // SendInitialFullUpdateToAllClients(); + SendOtherAgentsAvatarDataToMe(); + SendOtherAgentsAppearanceToMe(); RegisterToEvents(); SetDirectionVectors(); @@ -1613,7 +1615,7 @@ namespace OpenSim.Region.Framework.Scenes { AbsolutePosition = part.AbsolutePosition; Velocity = Vector3.Zero; - SendFullUpdateToAllClients(); + SendAvatarDataToAllAgents(); //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); } @@ -1688,7 +1690,7 @@ namespace OpenSim.Region.Framework.Scenes m_parentPosition = Vector3.Zero; m_parentID = 0; - SendFullUpdateToAllClients(); + SendAvatarDataToAllAgents(); m_requestedSitTargetID = 0; if (m_physicsActor != null && m_appearance != null) { @@ -2154,7 +2156,7 @@ namespace OpenSim.Region.Framework.Scenes RemoveFromPhysicalScene(); Animator.TrySetMovementAnimation(sitAnimation); - SendFullUpdateToAllClients(); + SendAvatarDataToAllAgents(); // This may seem stupid, but Our Full updates don't send avatar rotation :P // So we're also sending a terse update (which has avatar rotation) // [Update] We do now. @@ -2379,165 +2381,169 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) + /// Do everything required once a client completes its movement into a region and becomes + /// a root agent. /// - /// - public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar) + private void SendInitialData() { - // 2 stage check is needed. - if (remoteAvatar == null) - return; - - IClientAPI cl = remoteAvatar.ControllingClient; - if (cl == null) - return; + // Moved this into CompleteMovement to ensure that m_appearance is initialized before + // the inventory arrives + // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - if (m_appearance.Texture == null) - return; + // This agent just became root. We are going to tell everyone about it. The process of + // getting other avatars information was initiated in the constructor... don't do it + // again here... + SendAvatarDataToAllAgents(); -// MT: This is needed for sit. It's legal to send it to oneself, and the name -// of the method is a misnomer -// -// if (LocalId == remoteAvatar.LocalId) -// { -// m_log.WarnFormat("[SCENEPRESENCE]: An agent is attempting to send avatar data to itself; {0}", UUID); -// return; -// } + // We have an appearance but we may not have the baked textures. Check the asset cache + // to see if all the baked textures are already here. + if (m_scene.AvatarFactory != null) + { + if (m_scene.AvatarFactory.ValidateBakedTextureCache(m_controllingClient)) + { +// m_log.WarnFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); + SendAppearanceToAgent(this); - if (IsChildAgent) + // If the avatars baked textures are all in the cache, then we have a + // complete appearance... send it out, if not, then we'll send it when + // the avatar finishes updating its appearance + SendAppearanceToAllOtherAgents(); + } + } + else { - m_log.WarnFormat("[SCENEPRESENCE]: A child agent is attempting to send out avatar data; {0}", UUID); - return; + m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name); } - - remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); - m_scene.StatsReporter.AddAgentUpdates(1); } /// - /// Tell *ALL* agents about this agent + /// Send this agent's avatar data to all other root and child agents in the scene + /// This agent must be root. This avatar will receive its own update. /// - public void SendInitialFullUpdateToAllClients() + public void SendAvatarDataToAllAgents() { - m_perfMonMS = Util.EnvironmentTickCount(); - int avUpdates = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + // only send update from root agents to other clients; children are only "listening posts" + if (IsChildAgent) { - ++avUpdates; - - // Don't update ourselves - if (avatar.LocalId == LocalId) - return; - - // If this is a root agent, then get info about the avatar - if (!IsChildAgent) - { - SendFullUpdateToOtherClient(avatar); - } + m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); + return; + } + + m_perfMonMS = Util.EnvironmentTickCount(); - // If the other avatar is a root - if (!avatar.IsChildAgent) - { - avatar.SendFullUpdateToOtherClient(this); - avatar.SendAppearanceToOtherAgent(this); - avatar.Animator.SendAnimPackToClient(ControllingClient); - } - }); + int count = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + SendAvatarDataToAgent(scenePresence); + count++; + }); - m_scene.StatsReporter.AddAgentUpdates(avUpdates); + m_scene.StatsReporter.AddAgentUpdates(count); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - //Animator.SendAnimPack(); } - public void SendFullUpdateToAllClients() + /// + /// Send avatar data for all other root agents to this agent, this agent + /// can be either a child or root + /// + public void SendOtherAgentsAvatarDataToMe() { m_perfMonMS = Util.EnvironmentTickCount(); - // only send update from root agents to other clients; children are only "listening posts" - if (IsChildAgent) - { - m_log.Warn("[SCENEPRESENCE] attempt to send update from a childagent"); - return; - } - int count = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence sp) - { - if (sp.IsChildAgent) - return; - SendFullUpdateToOtherClient(sp); - ++count; - }); + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + // only send information about root agents + if (scenePresence.IsChildAgent) + return; + + // only send information about other root agents + if (scenePresence.UUID == UUID) + return; + + scenePresence.SendAvatarDataToAgent(this); + count++; + }); + m_scene.StatsReporter.AddAgentUpdates(count); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - Animator.SendAnimPack(); } /// - /// Do everything required once a client completes its movement into a region + /// Send avatar data to an agent. /// - public void SendInitialData() + /// + private void SendAvatarDataToAgent(ScenePresence avatar) { - // Moved this into CompleteMovement to ensure that m_appearance is initialized before - // the inventory arrives - // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); +// m_log.WarnFormat("[SP] Send avatar data from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); - m_controllingClient.SendAvatarDataImmediate(this); - if (m_scene.AvatarFactory != null) - { - if (m_scene.AvatarFactory.ValidateBakedTextureCache(m_controllingClient)) - { -// m_log.WarnFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); - m_controllingClient.SendAppearance( - m_appearance.Owner,m_appearance.VisualParams,m_appearance.Texture.GetBytes()); - } - } - else + avatar.ControllingClient.SendAvatarDataImmediate(this); + Animator.SendAnimPackToClient(avatar.ControllingClient); + } + + /// + /// Send this agent's appearance to all other root and child agents in the scene + /// This agent must be root. + /// + public void SendAppearanceToAllOtherAgents() + { + // only send update from root agents to other clients; children are only "listening posts" + if (IsChildAgent) { - m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name); + m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); + return; } + + m_perfMonMS = Util.EnvironmentTickCount(); + + int count = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + if (scenePresence.UUID == UUID) + return; - SendInitialFullUpdateToAllClients(); + SendAppearanceToAgent(scenePresence); + count++; + }); + + m_scene.StatsReporter.AddAgentUpdates(count); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); } /// - /// + /// Send appearance from all other root agents to this agent. this agent + /// can be either root or child /// - public void SendAppearanceToAllOtherAgents() + public void SendOtherAgentsAppearanceToMe() { -// DEBUG ON -// m_log.WarnFormat("[SCENEPRESENCE]: Send appearance from {0} to all other agents", m_uuid); -// DEBUG OFF m_perfMonMS = Util.EnvironmentTickCount(); + int count = 0; m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) { - if (scenePresence.UUID != UUID) - { - SendAppearanceToOtherAgent(scenePresence); - } + // only send information about root agents + if (scenePresence.IsChildAgent) + return; + + // only send information about other root agents + if (scenePresence.UUID == UUID) + return; + + scenePresence.SendAppearanceToAgent(this); + count++; }); + m_scene.StatsReporter.AddAgentUpdates(count); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); } /// - /// Send appearance data to an agent that isn't this one. + /// Send appearance data to an agent. /// /// - public void SendAppearanceToOtherAgent(ScenePresence avatar) + private void SendAppearanceToAgent(ScenePresence avatar) { - if (LocalId == avatar.LocalId) - { - m_log.WarnFormat("[SCENE PRESENCE]: An agent is attempting to send appearance data to itself; {0}", UUID); - return; - } - -// DEBUG ON // m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); -// DEBUG OFF avatar.ControllingClient.SendAppearance( m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); @@ -3050,9 +3056,6 @@ namespace OpenSim.Region.Framework.Scenes public void CopyFrom(AgentData cAgent) { -// DEBUG ON - m_log.ErrorFormat("[SCENEPRESENCE] CALLING COPYFROM"); -// DEBUG OFF m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 0c8113e..ccf5289 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1173,10 +1173,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups presence = scene.GetScenePresence(AgentID); if (presence != null) { - presence.Grouptitle = Title; + if (presence.Grouptitle != Title) + { + presence.Grouptitle = Title; - // FixMe: Ter suggests a "Schedule" method that I can't find. - presence.SendFullUpdateToAllClients(); + if (! presence.IsChildAgent) + presence.SendAvatarDataToAllAgents(); + } } } } -- cgit v1.1