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.
viewer-2-initial-appearance
Mic Bowman 2010-11-23 16:08:10 -08:00 committed by Justin Clark-Casey (justincc)
parent 7c02d5cec5
commit 541a7660e0
6 changed files with 161 additions and 182 deletions

View File

@ -302,31 +302,26 @@ namespace OpenSim.Framework
if (args["start_pos"] != null) if (args["start_pos"] != null)
Vector3.TryParse(args["start_pos"].AsString(), out startpos); Vector3.TryParse(args["start_pos"].AsString(), out startpos);
// DEBUG ON m_log.InfoFormat("[AGENTCIRCUITDATA] agentid={0}, child={1}, startpos={2}",AgentID,child,startpos.ToString());
m_log.WarnFormat("[AGENTCIRCUITDATA] agentid={0}, child={1}, startpos={2}",AgentID,child,startpos.ToString());
// DEBUG OFF
try { try {
// Unpack various appearance elements // Unpack various appearance elements
Appearance = new AvatarAppearance(AgentID); Appearance = new AvatarAppearance(AgentID);
// Eventually this code should be deprecated, use full appearance // Eventually this code should be deprecated, use full appearance
// packing in packed_appearance // packing in packed_appearance
if (args["appearance_serial"] != null) if (args["appearance_serial"] != null)
Appearance.Serial = args["appearance_serial"].AsInteger(); Appearance.Serial = args["appearance_serial"].AsInteger();
if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map))
{ {
Appearance.Unpack((OSDMap)args["packed_appearance"]); Appearance.Unpack((OSDMap)args["packed_appearance"]);
// DEBUG ON m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance");
m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance"); }
// DEBUG OFF else
m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance");
} }
// DEBUG ON catch (Exception e)
else
m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance");
// DEBUG OFF
} catch (Exception e)
{ {
m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message); m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message);
} }

View File

@ -331,9 +331,7 @@ namespace OpenSim.Framework
public virtual OSDMap Pack() public virtual OSDMap Pack()
{ {
// DEBUG ON m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Pack data");
// DEBUG OFF
OSDMap args = new OSDMap(); OSDMap args = new OSDMap();
args["message_type"] = OSD.FromString("AgentData"); args["message_type"] = OSD.FromString("AgentData");
@ -454,9 +452,7 @@ namespace OpenSim.Framework
/// <param name="hash"></param> /// <param name="hash"></param>
public virtual void Unpack(OSDMap args) public virtual void Unpack(OSDMap args)
{ {
// DEBUG ON m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data");
m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Unpack data");
// DEBUG OFF
if (args.ContainsKey("region_id")) if (args.ContainsKey("region_id"))
UUID.TryParse(args["region_id"].AsString(), out RegionID); 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) if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map)
Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]);
// DEBUG ON
else else
m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance"); m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance");
// DEBUG OFF
if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array)
{ {

View File

@ -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 // 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); 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 // Send the appearance to everyone in the scene
sp.SendAppearanceToAllOtherAgents(); 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) 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); // 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); AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false);
foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
@ -388,9 +368,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
SetAppearanceAssets(sp.UUID, ref avatAppearance); SetAppearanceAssets(sp.UUID, ref avatAppearance);
// could get fancier with the locks here, but in the spirit of "last write wins" // 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; sp.Appearance = avatAppearance;
m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); QueueAppearanceSave(client.AgentId);
} }
private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance)

View File

@ -903,8 +903,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
agent.MakeChildAgent(); agent.MakeChildAgent();
// now we have a child agent in this region. Request all interesting data about other (root) agents // 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); CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);

View File

@ -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) // Note: This won't send data *to* other clients in that region (children don't send)
// MIC: This gets called again in CompleteMovement // MIC: This gets called again in CompleteMovement
SendInitialFullUpdateToAllClients(); // SendInitialFullUpdateToAllClients();
SendOtherAgentsAvatarDataToMe();
SendOtherAgentsAppearanceToMe();
RegisterToEvents(); RegisterToEvents();
SetDirectionVectors(); SetDirectionVectors();
@ -1613,7 +1615,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
AbsolutePosition = part.AbsolutePosition; AbsolutePosition = part.AbsolutePosition;
Velocity = Vector3.Zero; Velocity = Vector3.Zero;
SendFullUpdateToAllClients(); SendAvatarDataToAllAgents();
//HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID);
} }
@ -1688,7 +1690,7 @@ namespace OpenSim.Region.Framework.Scenes
m_parentPosition = Vector3.Zero; m_parentPosition = Vector3.Zero;
m_parentID = 0; m_parentID = 0;
SendFullUpdateToAllClients(); SendAvatarDataToAllAgents();
m_requestedSitTargetID = 0; m_requestedSitTargetID = 0;
if (m_physicsActor != null && m_appearance != null) if (m_physicsActor != null && m_appearance != null)
{ {
@ -2154,7 +2156,7 @@ namespace OpenSim.Region.Framework.Scenes
RemoveFromPhysicalScene(); RemoveFromPhysicalScene();
Animator.TrySetMovementAnimation(sitAnimation); Animator.TrySetMovementAnimation(sitAnimation);
SendFullUpdateToAllClients(); SendAvatarDataToAllAgents();
// This may seem stupid, but Our Full updates don't send avatar rotation :P // 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) // So we're also sending a terse update (which has avatar rotation)
// [Update] We do now. // [Update] We do now.
@ -2379,165 +2381,169 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
/// <param name="remoteAvatar"></param> private void SendInitialData()
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);
}
/// <summary>
/// Tell *ALL* agents about this agent
/// </summary>
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();
}
/// <summary>
/// Do everything required once a client completes its movement into a region
/// </summary>
public void SendInitialData()
{ {
// Moved this into CompleteMovement to ensure that m_appearance is initialized before // Moved this into CompleteMovement to ensure that m_appearance is initialized before
// the inventory arrives // the inventory arrives
// m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); // 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 != null)
{ {
if (m_scene.AvatarFactory.ValidateBakedTextureCache(m_controllingClient)) if (m_scene.AvatarFactory.ValidateBakedTextureCache(m_controllingClient))
{ {
// m_log.WarnFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); // m_log.WarnFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name);
m_controllingClient.SendAppearance( SendAppearanceToAgent(this);
m_appearance.Owner,m_appearance.VisualParams,m_appearance.Texture.GetBytes());
// 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 else
{ {
m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name); m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name);
} }
SendInitialFullUpdateToAllClients();
} }
/// <summary> /// <summary>
/// /// 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.
/// </summary> /// </summary>
public void SendAppearanceToAllOtherAgents() public void SendAvatarDataToAllAgents()
{ {
// DEBUG ON // only send update from root agents to other clients; children are only "listening posts"
// m_log.WarnFormat("[SCENEPRESENCE]: Send appearance from {0} to all other agents", m_uuid); if (IsChildAgent)
// DEBUG OFF {
m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent");
return;
}
m_perfMonMS = Util.EnvironmentTickCount(); m_perfMonMS = Util.EnvironmentTickCount();
int count = 0;
m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
{ {
if (scenePresence.UUID != UUID) SendAvatarDataToAgent(scenePresence);
{ count++;
SendAppearanceToOtherAgent(scenePresence);
}
}); });
m_scene.StatsReporter.AddAgentUpdates(count);
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
} }
/// <summary> /// <summary>
/// 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
/// </summary>
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));
}
/// <summary>
/// Send avatar data to an agent.
/// </summary> /// </summary>
/// <param name="avatar"></param> /// <param name="avatar"></param>
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);
}
/// <summary>
/// Send this agent's appearance to all other root and child agents in the scene
/// This agent must be root.
/// </summary>
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; 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));
}
/// <summary>
/// Send appearance from all other root agents to this agent. this agent
/// can be either root or child
/// </summary>
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));
}
/// <summary>
/// Send appearance data to an agent.
/// </summary>
/// <param name="avatar"></param>
private void SendAppearanceToAgent(ScenePresence avatar)
{
// m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); // m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId);
// DEBUG OFF
avatar.ControllingClient.SendAppearance( avatar.ControllingClient.SendAppearance(
m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
@ -3050,9 +3056,6 @@ namespace OpenSim.Region.Framework.Scenes
public void CopyFrom(AgentData cAgent) public void CopyFrom(AgentData cAgent)
{ {
// DEBUG ON
m_log.ErrorFormat("[SCENEPRESENCE] CALLING COPYFROM");
// DEBUG OFF
m_originRegionID = cAgent.RegionID; m_originRegionID = cAgent.RegionID;
m_callbackURI = cAgent.CallbackURI; m_callbackURI = cAgent.CallbackURI;

View File

@ -1173,10 +1173,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
presence = scene.GetScenePresence(AgentID); presence = scene.GetScenePresence(AgentID);
if (presence != null) if (presence != null)
{ {
presence.Grouptitle = Title; if (presence.Grouptitle != Title)
{
presence.Grouptitle = Title;
// FixMe: Ter suggests a "Schedule" method that I can't find. if (! presence.IsChildAgent)
presence.SendFullUpdateToAllClients(); presence.SendAvatarDataToAllAgents();
}
} }
} }
} }