diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index cc9fcea2e7..1600bdc00d 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -302,31 +302,26 @@ namespace OpenSim.Framework if (args["start_pos"] != null) Vector3.TryParse(args["start_pos"].AsString(), out startpos); -// DEBUG ON - m_log.WarnFormat("[AGENTCIRCUITDATA] agentid={0}, child={1}, startpos={2}",AgentID,child,startpos.ToString()); -// DEBUG OFF + m_log.InfoFormat("[AGENTCIRCUITDATA] agentid={0}, child={1}, startpos={2}",AgentID,child,startpos.ToString()); try { - // Unpack various appearance elements - Appearance = new AvatarAppearance(AgentID); + // Unpack various appearance elements + Appearance = new AvatarAppearance(AgentID); - // Eventually this code should be deprecated, use full appearance - // packing in packed_appearance - if (args["appearance_serial"] != null) - Appearance.Serial = args["appearance_serial"].AsInteger(); + // Eventually this code should be deprecated, use full appearance + // packing in packed_appearance + if (args["appearance_serial"] != null) + Appearance.Serial = args["appearance_serial"].AsInteger(); - if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) - { - Appearance.Unpack((OSDMap)args["packed_appearance"]); -// DEBUG ON - m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance"); -// DEBUG OFF + if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) + { + Appearance.Unpack((OSDMap)args["packed_appearance"]); + m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance"); + } + else + m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance"); } -// DEBUG ON - else - m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance"); -// DEBUG OFF - } catch (Exception e) + catch (Exception e) { m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message); } diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index a2273385e0..ce0b2fb784 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -331,9 +331,7 @@ namespace OpenSim.Framework public virtual OSDMap Pack() { -// DEBUG ON - m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Pack data"); -// DEBUG OFF + m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data"); OSDMap args = new OSDMap(); args["message_type"] = OSD.FromString("AgentData"); @@ -454,9 +452,7 @@ namespace OpenSim.Framework /// public virtual void Unpack(OSDMap args) { -// DEBUG ON - m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Unpack data"); -// DEBUG OFF + m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data"); if (args.ContainsKey("region_id")) UUID.TryParse(args["region_id"].AsString(), out RegionID); @@ -613,10 +609,8 @@ namespace OpenSim.Framework if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map) Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); -// DEBUG ON else m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance"); -// DEBUG OFF if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) { diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 0df4585eec..ab1c206f9a 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 81d6f70f36..aa7a1cd109 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -925,8 +925,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/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f3964c2276..bcb715ba28 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -398,7 +398,7 @@ namespace OpenSim.Region.Framework.Scenes Vector3 offset = p.GetWorldPosition() - av.ParentPosition; av.AbsolutePosition += offset; av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index bdd42fc35e..8cc2be1b8a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -803,7 +803,7 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 offset = (m_offsetPosition - oldpos); av.OffsetPosition += offset; - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c35df089e4..98a3b29c62 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -767,7 +767,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(); @@ -1757,7 +1759,7 @@ namespace OpenSim.Region.Framework.Scenes { AbsolutePosition = part.AbsolutePosition; Velocity = Vector3.Zero; - SendFullUpdateToAllClients(); + SendAvatarDataToAllAgents(); HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ?? } @@ -1867,7 +1869,7 @@ namespace OpenSim.Region.Framework.Scenes m_parentID = 0; m_linkedPrim = UUID.Zero; m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - SendFullUpdateToAllClients(); + SendAvatarDataToAllAgents(); m_requestedSitTargetID = 0; if (m_physicsActor != null && m_appearance != null) { @@ -2462,8 +2464,8 @@ namespace OpenSim.Region.Framework.Scenes Velocity = Vector3.Zero; RemoveFromPhysicalScene(); Animator.TrySetMovementAnimation(sitAnimation); - SendFullUpdateToAllClients(); - SendTerseUpdateToAllClients(); + SendAvatarDataToAllAgents(); + //SendTerseUpdateToAllClients(); } public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal) @@ -2742,165 +2744,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) - { - // 2 stage check is needed. - if (remoteAvatar == null) - return; - - IClientAPI cl = remoteAvatar.ControllingClient; - if (cl == null) - return; - - if (m_appearance.Texture == null) - return; - -// 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; -// } - - if (IsChildAgent) - { - m_log.WarnFormat("[SCENEPRESENCE]: A child agent is attempting to send out avatar data; {0}", UUID); - return; - } - - remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); - m_scene.StatsReporter.AddAgentUpdates(1); - } - - /// - /// Tell *ALL* agents about this agent - /// - public void SendInitialFullUpdateToAllClients() - { - m_perfMonMS = Util.EnvironmentTickCount(); - int avUpdates = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - ++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); - } - - // If the other avatar is a root - if (!avatar.IsChildAgent) - { - avatar.SendFullUpdateToOtherClient(this); - avatar.SendAppearanceToOtherAgent(this); - avatar.Animator.SendAnimPackToClient(ControllingClient); - } - }); - - m_scene.StatsReporter.AddAgentUpdates(avUpdates); - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - //Animator.SendAnimPack(); - } - - public void SendFullUpdateToAllClients() - { - 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.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 - /// - public void SendInitialData() + private void SendInitialData() { // Moved this into CompleteMovement to ensure that m_appearance is initialized before // the inventory arrives // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - m_controllingClient.SendAvatarDataImmediate(this); + // 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(); + + // 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); - m_controllingClient.SendAppearance( - m_appearance.Owner,m_appearance.VisualParams,m_appearance.Texture.GetBytes()); + SendAppearanceToAgent(this); + + // 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]: AvatarFactory not set for {0}", Name); } - - SendInitialFullUpdateToAllClients(); } /// - /// + /// 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 SendAppearanceToAllOtherAgents() + public void SendAvatarDataToAllAgents() { -// DEBUG ON -// m_log.WarnFormat("[SCENEPRESENCE]: Send appearance from {0} to all other agents", m_uuid); -// DEBUG OFF + // only send update from root agents to other clients; children are only "listening posts" + if (IsChildAgent) + { + 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) - { - SendAppearanceToOtherAgent(scenePresence); - } + SendAvatarDataToAgent(scenePresence); + 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 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(); + + int count = 0; + 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)); + } + + /// + /// Send avatar data to an agent. /// /// - public void SendAppearanceToOtherAgent(ScenePresence avatar) + private void SendAvatarDataToAgent(ScenePresence avatar) { - if (LocalId == avatar.LocalId) +// m_log.WarnFormat("[SP] Send avatar data from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); + + 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("[SCENE PRESENCE]: An agent is attempting to send appearance data to itself; {0}", UUID); + m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); return; } + + m_perfMonMS = Util.EnvironmentTickCount(); -// DEBUG ON + int count = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + if (scenePresence.UUID == UUID) + return; + + 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 SendOtherAgentsAppearanceToMe() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + int count = 0; + 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.SendAppearanceToAgent(this); + count++; + }); + + m_scene.StatsReporter.AddAgentUpdates(count); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + /// + /// Send appearance data to an agent. + /// + /// + private void SendAppearanceToAgent(ScenePresence avatar) + { // 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()); @@ -3413,9 +3419,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 0c8113e604..ccf52892dc 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(); + } } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7e9224d8df..1dd4ca49a9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4007,6 +4007,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { linknum -= (m_host.ParentGroup.PrimCount) + 1; + if (linknum < 0) + return UUID.Zero.ToString(); + List avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET); if (avatars.Count > linknum) { @@ -6753,7 +6756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } if (buttons.Data[i].ToString().Length > 24) { - LSLError("button label cannot be longer than 24 characters"); + llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters"); return; } buts[i] = buttons.Data[i].ToString(); @@ -7316,7 +7319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector v; v = rules.GetVector3Item(idx++); av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); break; @@ -7326,7 +7329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Rotation r; r = rules.GetQuaternionItem(idx++); av.OffsetRotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); break; } }