From e3262ef5ace4be920edfa0dd4e4f23fc20b07b70 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 14 Dec 2010 17:50:37 -0800 Subject: Commented out the UpdateLand call from the Update thread loop, because this may be causing the #LoginLag. Attachments taint the prim count. Twice. Each. --- OpenSim/Region/Framework/Scenes/Scene.cs | 12 ++++++------ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index de75375..73a0803 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1302,12 +1302,12 @@ namespace OpenSim.Region.Framework.Scenes terrainMS = Util.EnvironmentTickCountSubtract(terMS); } - if (m_frame % m_update_land == 0) - { - int ldMS = Util.EnvironmentTickCount(); - UpdateLand(); - landMS = Util.EnvironmentTickCountSubtract(ldMS); - } + //if (m_frame % m_update_land == 0) + //{ + // int ldMS = Util.EnvironmentTickCount(); + // UpdateLand(); + // landMS = Util.EnvironmentTickCountSubtract(ldMS); + //} frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 62d7011..432ce46 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2314,6 +2314,7 @@ namespace OpenSim.Region.Framework.Scenes // followed suggestion from mic bowman. reversed the two lines below. if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something CheckForBorderCrossing(); + CheckForSignificantMovement(); // sends update to the modules. } } -- cgit v1.1 From 74c68474e01eedc6cc4c9ef26386939c1d693172 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 14 Dec 2010 18:44:26 -0800 Subject: Another attempt at moving heavy computation away from the Update loop. #LoginLag --- OpenSim/Region/Framework/Scenes/Scene.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 73a0803..52e2e5d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -176,6 +176,8 @@ namespace OpenSim.Region.Framework.Scenes private object m_deleting_scene_object = new object(); private object m_cleaningAttachments = new object(); + private bool m_cleaningTemps = false; + private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; private bool m_reprioritizationEnabled = true; private double m_reprioritizationInterval = 5000.0; @@ -1272,10 +1274,11 @@ namespace OpenSim.Region.Framework.Scenes physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); // Delete temp-on-rez stuff - if (m_frame % m_update_backup == 0) + if (m_frame % m_update_backup == 0 && !m_cleaningTemps) { int tmpTempOnRezMS = Util.EnvironmentTickCount(); - CleanTempObjects(); + m_cleaningTemps = true; + Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); } @@ -4391,6 +4394,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + } public void DeleteFromStorage(UUID uuid) -- cgit v1.1 From ed26376ec5377050dd2cf0b17f41009834638875 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 14 Dec 2010 20:15:26 -0800 Subject: Yet more things out of the main Update thread loop and into threadlets. This time, SendPrimsUpdate. Plus a few more tweaks on triggering actions from the Update loop. #LoginLag. --- OpenSim/Region/Framework/Scenes/Scene.cs | 15 +++++++-------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 ++++- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 52e2e5d..50efe65 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -150,7 +150,7 @@ namespace OpenSim.Region.Framework.Scenes private int m_update_backup = 200; private int m_update_terrain = 50; private int m_update_land = 1; - private int m_update_coarse_locations = 50; + private int m_update_coarse_locations = 80; private int frameMS; private int physicsMS2; @@ -1274,7 +1274,7 @@ namespace OpenSim.Region.Framework.Scenes physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); // Delete temp-on-rez stuff - if (m_frame % m_update_backup == 0 && !m_cleaningTemps) + if (m_frame % 1000 == 0 && !m_cleaningTemps) { int tmpTempOnRezMS = Util.EnvironmentTickCount(); m_cleaningTemps = true; @@ -1400,13 +1400,12 @@ namespace OpenSim.Region.Framework.Scenes private void CheckAtTargets() { + Dictionary.ValueCollection objs; lock (m_groupsWithTargets) - { - foreach (SceneObjectGroup entry in m_groupsWithTargets.Values) - { - entry.checkAtTargets(); - } - } + objs = m_groupsWithTargets.Values; + + foreach (SceneObjectGroup entry in objs) + entry.checkAtTargets(); } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 432ce46..9d72bf6 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2279,6 +2279,8 @@ namespace OpenSim.Region.Framework.Scenes #region Overridden Methods + private bool sendingPrims = false; + public override void Update() { const float ROTATION_TOLERANCE = 0.01f; @@ -2286,7 +2288,8 @@ namespace OpenSim.Region.Framework.Scenes const float POSITION_TOLERANCE = 0.05f; //const int TIME_MS_TOLERANCE = 3000; - SendPrimUpdates(); + if (!sendingPrims) + Util.FireAndForget(delegate { sendingPrims = true; SendPrimUpdates(); sendingPrims = false; }); if (m_isChildAgent == false) { -- cgit v1.1 From 0745d65344a030f598c4b6e522c78fd0e49850d4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 15 Dec 2010 23:11:42 +0000 Subject: Put in locks on m_killRecord to replace changed locks on m_entityUpdates.SyncRoot These locks are necessary to avoid a delete/update race condition for scene objects. However, since we're now locking on m_killRecord this shouldn't cause delays to m_entityUpdates reprioritization --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 393 +++++++++++---------- 1 file changed, 200 insertions(+), 193 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2a59a0c..3b7328d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -327,7 +327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an /// ownerless phantom. /// - /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock + /// All manipulation of this set has to occur under a lock /// /// protected HashSet m_killRecord; @@ -1521,7 +1521,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_scene.GetScenePresence(localID) == null) { - lock (m_entityUpdates.SyncRoot) + // 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. + lock (m_killRecord) { m_killRecord.Add(localID); @@ -3558,221 +3560,226 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; int updatesThisCall = 0; - EntityUpdate update; - while (updatesThisCall < maxUpdates) - { - lock (m_entityUpdates.SyncRoot) - if (!m_entityUpdates.TryDequeue(out update)) - break; - - if (update.Entity is SceneObjectPart) - { - SceneObjectPart part = (SceneObjectPart)update.Entity; - - // 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. - if (m_killRecord.Contains(part.LocalId)) - { - // m_log.WarnFormat( - // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", - // part.LocalId, Name); - continue; - } - - if (part.ParentGroup.IsAttachment && m_disableFacelights) + // 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. + lock (m_killRecord) + { + EntityUpdate update; + while (updatesThisCall < maxUpdates) + { + lock (m_entityUpdates.SyncRoot) + if (!m_entityUpdates.TryDequeue(out update)) + break; + + if (update.Entity is SceneObjectPart) { - if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && - part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand) + SceneObjectPart part = (SceneObjectPart)update.Entity; + + // 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. + if (m_killRecord.Contains(part.LocalId)) { - part.Shape.LightEntry = false; + // m_log.WarnFormat( + // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", + // part.LocalId, Name); + continue; + } + + 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; + } } } - } - - ++updatesThisCall; - - #region UpdateFlags to packet type conversion - - PrimUpdateFlags updateFlags = update.Flags; - - 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)) + + ++updatesThisCall; + + #region UpdateFlags to packet type conversion + + PrimUpdateFlags updateFlags = update.Flags; + + 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.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)) + + if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) { + canUseCompressed = false; 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 - } - - #region Packet Sending + if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || + updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || + updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || + updateFlags.HasFlag(PrimUpdateFlags.Joint)) + { + canUseCompressed = false; + } - const float TIME_DILATION = 1.0f; - ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - - if (terseAgentUpdateBlocks.IsValueCreated) - { - List blocks = terseAgentUpdateBlocks.Value; - - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; - packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; - - for (int i = 0; i < blocks.Count; i++) - packet.ObjectData[i] = blocks[i]; - - OutPacket(packet, ThrottleOutPacketType.Unknown, true); - } - - if (objectUpdateBlocks.IsValueCreated) - { - List blocks = objectUpdateBlocks.Value; + 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; + } + } - ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; - packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; + #endregion UpdateFlags to packet type conversion - for (int i = 0; i < blocks.Count; i++) - packet.ObjectData[i] = blocks[i]; + #region Block Construction - OutPacket(packet, ThrottleOutPacketType.Task, true); - } + // TODO: Remove this once we can build compressed updates + canUseCompressed = false; - if (compressedUpdateBlocks.IsValueCreated) - { - List blocks = compressedUpdateBlocks.Value; + 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))); + } - ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; - packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count]; + #endregion Block Construction + } - for (int i = 0; i < blocks.Count; i++) - packet.ObjectData[i] = blocks[i]; + #region Packet Sending + + const float TIME_DILATION = 1.0f; + ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - OutPacket(packet, ThrottleOutPacketType.Task, true); - } + if (terseAgentUpdateBlocks.IsValueCreated) + { + List blocks = terseAgentUpdateBlocks.Value; - if (terseUpdateBlocks.IsValueCreated) - { - List blocks = terseUpdateBlocks.Value; + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); - packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; - packet.RegionData.TimeDilation = timeDilation; - packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; - for (int i = 0; i < blocks.Count; i++) - packet.ObjectData[i] = blocks[i]; + OutPacket(packet, ThrottleOutPacketType.Unknown, true); + } - OutPacket(packet, ThrottleOutPacketType.Task, true); + if (objectUpdateBlocks.IsValueCreated) + { + List blocks = objectUpdateBlocks.Value; + + ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; + + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + + OutPacket(packet, ThrottleOutPacketType.Task, true); + } + + if (compressedUpdateBlocks.IsValueCreated) + { + List blocks = compressedUpdateBlocks.Value; + + ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count]; + + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + + OutPacket(packet, ThrottleOutPacketType.Task, true); + } + + if (terseUpdateBlocks.IsValueCreated) + { + List blocks = terseUpdateBlocks.Value; + + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; + + for (int i = 0; i < blocks.Count; i++) + packet.ObjectData[i] = blocks[i]; + + OutPacket(packet, ThrottleOutPacketType.Task, true); + } } #endregion Packet Sending -- cgit v1.1