diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 5b2484d760..4abb6e2d75 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3703,209 +3703,166 @@ namespace OpenSim.Region.ClientStack.LindenUDP int updatesThisCall = 0; -// -// DEBUGGING CODE... REMOVE -// LogQueueProcessEvent(this.m_agentId,m_entityUpdates,m_maxUpdates); -// // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race // condition where a kill can be processed before an out-of-date update for the same object. float avgTimeDilation = 1.0f; - lock (m_killRecord) + EntityUpdate update; + Int32 timeinqueue; // this is just debugging code & can be dropped later + + while (updatesThisCall < m_maxUpdates) { - EntityUpdate update; - Int32 timeinqueue; // this is just debugging code & can be dropped later - - while (updatesThisCall < m_maxUpdates) + lock (m_entityUpdates.SyncRoot) + if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) + break; + avgTimeDilation += update.TimeDilation; + avgTimeDilation *= 0.5f; + + if (update.Entity is SceneObjectPart) { - lock (m_entityUpdates.SyncRoot) - if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) - break; - avgTimeDilation += update.TimeDilation; - avgTimeDilation *= 0.5f; + SceneObjectPart part = (SceneObjectPart)update.Entity; - if (update.Entity is SceneObjectPart) + // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client + // will never receive an update after a prim kill. Even then, keeping the kill record may be a good + // safety measure. + // + // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update + // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs + // updates and kills on different threads with different scheduling strategies, hence this protection. + // + // This doesn't appear to apply to child prims - a client will happily ignore these updates + // after the root prim has been deleted. + lock (m_killRecord) { - SceneObjectPart part = (SceneObjectPart)update.Entity; + if (m_killRecord.Contains(part.LocalId)) + continue; + if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId)) + continue; + } - // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client - // will never receive an update after a prim kill. Even then, keeping the kill record may be a good - // safety measure. - // - // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update - // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs - // updates and kills on different threads with different scheduling strategies, hence this protection. - // - // This doesn't appear to apply to child prims - a client will happily ignore these updates - // after the root prim has been deleted. - lock (m_killRecord) - { - if (m_killRecord.Contains(part.LocalId)) - continue; - if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId)) - continue; - } + if (part.ParentGroup.IsDeleted) + continue; - if (part.ParentGroup.IsDeleted) + if (part.ParentGroup.IsAttachment) + { // Someone else's HUD, why are we getting these? + if (part.ParentGroup.OwnerID != AgentId && + part.ParentGroup.RootPart.Shape.State >= 30) + continue; + ScenePresence sp; + // Owner is not in the sim, don't update it to + // anyone + if (!m_scene.TryGetScenePresence(part.OwnerID, out sp)) continue; - if (part.ParentGroup.IsAttachment) - { // Someone else's HUD, why are we getting these? - if (part.ParentGroup.OwnerID != AgentId && - part.ParentGroup.RootPart.Shape.State >= 30) - continue; - ScenePresence sp; - // Owner is not in the sim, don't update it to - // anyone - if (!m_scene.TryGetScenePresence(part.OwnerID, out sp)) - continue; - - List atts = sp.Attachments; - bool found = false; - foreach (SceneObjectGroup att in atts) - { - if (att == part.ParentGroup) - { - found = true; - break; - } - } - - // It's an attachment of a valid avatar, but - // doesn't seem to be attached, skip - if (!found) - continue; - } - - if (part.ParentGroup.IsAttachment && m_disableFacelights) + List atts = sp.Attachments; + bool found = false; + foreach (SceneObjectGroup att in atts) { - if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && - part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand) + if (att == part.ParentGroup) { - part.Shape.LightEntry = false; + found = true; + break; } } + + // It's an attachment of a valid avatar, but + // doesn't seem to be attached, skip + if (!found) + continue; } - ++updatesThisCall; + if (part.ParentGroup.IsAttachment && m_disableFacelights) + { + if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && + part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand) + { + part.Shape.LightEntry = false; + } + } + } - #region UpdateFlags to packet type conversion + ++updatesThisCall; - PrimUpdateFlags updateFlags = update.Flags; + #region UpdateFlags to packet type conversion - bool canUseCompressed = true; - bool canUseImproved = true; + PrimUpdateFlags updateFlags = update.Flags; - // Compressed object updates only make sense for LL primitives - if (!(update.Entity is SceneObjectPart)) + bool canUseCompressed = true; + bool canUseImproved = true; + + // Compressed object updates only make sense for LL primitives + if (!(update.Entity is SceneObjectPart)) + { + canUseCompressed = false; + } + + if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) + { + canUseCompressed = false; + canUseImproved = false; + } + else + { + if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || + updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || + updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || + updateFlags.HasFlag(PrimUpdateFlags.Joint)) { canUseCompressed = false; } - if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) + if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || + updateFlags.HasFlag(PrimUpdateFlags.ParentID) || + updateFlags.HasFlag(PrimUpdateFlags.Scale) || + updateFlags.HasFlag(PrimUpdateFlags.PrimData) || + updateFlags.HasFlag(PrimUpdateFlags.Text) || + updateFlags.HasFlag(PrimUpdateFlags.NameValue) || + updateFlags.HasFlag(PrimUpdateFlags.ExtraData) || + updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) || + updateFlags.HasFlag(PrimUpdateFlags.Sound) || + updateFlags.HasFlag(PrimUpdateFlags.Particles) || + updateFlags.HasFlag(PrimUpdateFlags.Material) || + updateFlags.HasFlag(PrimUpdateFlags.ClickAction) || + updateFlags.HasFlag(PrimUpdateFlags.MediaURL) || + updateFlags.HasFlag(PrimUpdateFlags.Joint)) { - canUseCompressed = false; canUseImproved = false; } - else - { - if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || - updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || - updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || - updateFlags.HasFlag(PrimUpdateFlags.Joint)) - { - if (update.Entity is ScenePresence) - { - objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); - } - else - { - objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); - } - } - - if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || - updateFlags.HasFlag(PrimUpdateFlags.ParentID) || - updateFlags.HasFlag(PrimUpdateFlags.Scale) || - updateFlags.HasFlag(PrimUpdateFlags.PrimData) || - updateFlags.HasFlag(PrimUpdateFlags.Text) || - updateFlags.HasFlag(PrimUpdateFlags.NameValue) || - updateFlags.HasFlag(PrimUpdateFlags.ExtraData) || - updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) || - updateFlags.HasFlag(PrimUpdateFlags.Sound) || - updateFlags.HasFlag(PrimUpdateFlags.Particles) || - updateFlags.HasFlag(PrimUpdateFlags.Material) || - updateFlags.HasFlag(PrimUpdateFlags.ClickAction) || - updateFlags.HasFlag(PrimUpdateFlags.MediaURL) || - updateFlags.HasFlag(PrimUpdateFlags.Joint)) - { - canUseImproved = false; - } - } - - #endregion UpdateFlags to packet type conversion - - #region Block Construction - - // TODO: Remove this once we can build compressed updates - canUseCompressed = false; - - if (!canUseImproved && !canUseCompressed) - { - if (update.Entity is ScenePresence) - { - objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); - } - else - { - // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment) - // { - // SceneObjectPart sop = (SceneObjectPart)update.Entity; - // string text = sop.Text; - // if (text.IndexOf("\n") >= 0) - // text = text.Remove(text.IndexOf("\n")); - // - // if (m_attachmentsSent.Contains(sop.ParentID)) - // { - //// m_log.DebugFormat( - //// "[CLIENT]: Sending full info about attached prim {0} text {1}", - //// sop.LocalId, text); - // - // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId)); - // - // m_attachmentsSent.Add(sop.LocalId); - // } - // else - // { - // m_log.DebugFormat( - // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet", - // sop.LocalId, text, sop.ParentID); - // - // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId); - // } - // } - // else - // { - objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); - // } - } - } - else if (!canUseImproved) - { - compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); - } - else - { - if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) - // Self updates go into a special list - terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); - else - // Everything else goes here - terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); - } - - #endregion Block Construction } + + #endregion UpdateFlags to packet type conversion + + #region Block Construction + + // TODO: Remove this once we can build compressed updates + canUseCompressed = false; + + if (!canUseImproved && !canUseCompressed) + { + if (update.Entity is ScenePresence) + { + objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); + } + else + { + objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); + } + } + else if (!canUseImproved) + { + compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); + } + else + { + if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) + // Self updates go into a special list + terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + else + // Everything else goes here + terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + } + + #endregion Block Construction } #region Packet Sending