From a4304fb9e6ec94b9a2aa70db85a68b9b102d4c33 Mon Sep 17 00:00:00 2001
From: Justin Clarke Casey
Date: Thu, 13 Mar 2008 00:22:38 +0000
Subject: * Fix Mantis 761 (linking and delinking prims rapidly caused prims to
'disappear') * Root cause was that if two updates occurred in the same second
of time, the second one was never sent * Linking/delinking appears to be okay
now
---
OpenSim/Region/Environment/Scenes/InnerScene.cs | 6 +++++
OpenSim/Region/Environment/Scenes/Scene.cs | 2 +-
.../Region/Environment/Scenes/SceneObjectGroup.cs | 14 +++++++---
.../Region/Environment/Scenes/SceneObjectPart.cs | 22 ++++++++++++----
OpenSim/Region/Environment/Scenes/ScenePresence.cs | 30 ++++++++++++++--------
5 files changed, 55 insertions(+), 19 deletions(-)
diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs
index e195c92..0272a7e 100644
--- a/OpenSim/Region/Environment/Scenes/InnerScene.cs
+++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs
@@ -206,6 +206,12 @@ namespace OpenSim.Region.Environment.Scenes
}
}
+ ///
+ /// Add an entity to the list of prims to process on the next update
+ ///
+ ///
+ /// A
+ ///
internal void AddToUpdateList(EntityBase obj)
{
lock (m_updateList)
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index 1a73e78..7ea528c 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -614,7 +614,7 @@ namespace OpenSim.Region.Environment.Scenes
}
///
- ///
+ /// Start the timer which triggers regular scene updates
///
public void StartTimer()
{
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index 1a32460..50dc2ae 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -247,9 +247,11 @@ namespace OpenSim.Region.Environment.Scenes
public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part)
{
m_scene = scene;
+
part.SetParent(this);
part.ParentID = 0;
part.LinkNum = 0;
+
m_parts.Add(part.UUID, part);
SetPartAsRoot(part);
@@ -691,7 +693,7 @@ namespace OpenSim.Region.Environment.Scenes
#region Scheduling
///
- ///
+ /// Examine this object's parts to see if they've changed sufficiently to warrant an update
///
public override void Update()
{
@@ -703,6 +705,7 @@ namespace OpenSim.Region.Environment.Scenes
}
lastPhysGroupPos = AbsolutePosition;
}
+
if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
|| (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
|| (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1)
@@ -714,6 +717,7 @@ namespace OpenSim.Region.Environment.Scenes
}
lastPhysGroupRot = GroupRotation;
}
+
foreach (SceneObjectPart part in m_parts.Values)
{
part.SendScheduledUpdates();
@@ -737,7 +741,7 @@ namespace OpenSim.Region.Environment.Scenes
}
///
- ///
+ /// Schedule a full update for every part in this object
///
public void ScheduleGroupForFullUpdate()
{
@@ -910,6 +914,7 @@ namespace OpenSim.Region.Environment.Scenes
linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
linkPart.ParentID = m_rootPart.LocalId;
+
linkPart.LinkNum = m_parts.Count;
m_parts.Add(linkPart.UUID, linkPart);
@@ -1015,7 +1020,7 @@ namespace OpenSim.Region.Environment.Scenes
//m_rootPart.DoPhysicsPropertyUpdate(m_rootPart.PhysActor.IsPhysical, true);
//}
- SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
+ SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
m_scene.AddEntity(objectGroup);
@@ -1715,6 +1720,9 @@ namespace OpenSim.Region.Environment.Scenes
m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId);
}
+ ///
+ /// Completely delete this group and tell all the scene presences about that deletion.
+ ///
public void DeleteGroup()
{
DetachFromBackup(this);
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index f20a638..b708d04 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -132,7 +132,12 @@ namespace OpenSim.Region.Environment.Scenes
[XmlIgnore] public uint TimeStampLastActivity = 0; // Will be used for AutoReturn
///
- /// Only used internally to schedule client updates
+ /// Only used internally to schedule client updates.
+ /// 0 - no update is scheduled
+ /// 1 - terse update scheduled
+ /// 2 - full update scheduled
+ ///
+ /// TODO - This should be an enumeration
///
private byte m_updateFlag;
@@ -1090,7 +1095,7 @@ namespace OpenSim.Region.Environment.Scenes
#region Update Scheduling
///
- ///
+ /// Clear all pending updates
///
private void ClearUpdateSchedule()
{
@@ -1098,7 +1103,7 @@ namespace OpenSim.Region.Environment.Scenes
}
///
- ///
+ /// Schedules this prim for a full update
///
public void ScheduleFullUpdate()
{
@@ -1107,6 +1112,7 @@ namespace OpenSim.Region.Environment.Scenes
m_parentGroup.HasGroupChanged = true;
m_parentGroup.QueueForUpdateCheck();
}
+
TimeStampFull = (uint) Util.UnixTimeSinceEpoch();
m_updateFlag = 2;
}
@@ -1156,7 +1162,7 @@ namespace OpenSim.Region.Environment.Scenes
}
///
- ///
+ /// Tell all the prims which have had updates scheduled
///
public void SendScheduledUpdates()
{
@@ -1688,7 +1694,10 @@ namespace OpenSim.Region.Environment.Scenes
}
#region Client Update Methods
-
+
+ ///
+ /// Tell all scene presences that they should send updates for this part to their clients
+ ///
public void AddFullUpdateToAllAvatars()
{
List avatars = m_parentGroup.GetScenePresences();
@@ -1697,6 +1706,7 @@ namespace OpenSim.Region.Environment.Scenes
avatars[i].QueuePartForUpdate(this);
}
}
+
public void SendFullUpdateToAllClientsExcept(LLUUID agentID)
{
List avatars = m_parentGroup.GetScenePresences();
@@ -1710,6 +1720,8 @@ namespace OpenSim.Region.Environment.Scenes
}
}
}
+
+
public void AddFullUpdateToAvatar(ScenePresence presence)
{
presence.QueuePartForUpdate(this);
diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
index fc13ebb..2f35fe3 100644
--- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
@@ -418,6 +418,10 @@ namespace OpenSim.Region.Environment.Scenes
#endregion
+ ///
+ /// Add the part to the queue of parts for which we need to send an update to the client
+ ///
+ ///
public void QueuePartForUpdate(SceneObjectPart part)
{
//if (InterestList.Contains(part.ParentGroup))
@@ -434,6 +438,11 @@ namespace OpenSim.Region.Environment.Scenes
return m_scene.PermissionsMngr.GenerateClientFlags(m_uuid, ObjectID);
}
+ ///
+ /// Send updates to the client about prims which have been placed on the update queue. We don't
+ /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
+ /// timestamp has already been sent.
+ ///
public void SendPrimUpdates()
{
// if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode)
@@ -446,13 +455,12 @@ namespace OpenSim.Region.Environment.Scenes
if (!m_gotAllObjectsInScene)
{
if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor)
- {
-
+ {
m_scene.SendAllSceneObjectsToClient(this);
- m_gotAllObjectsInScene = true;
-
+ m_gotAllObjectsInScene = true;
}
}
+
if (m_partsUpdateQueue.Count > 0)
{
bool runUpdate = true;
@@ -465,16 +473,18 @@ namespace OpenSim.Region.Environment.Scenes
ScenePartUpdate update = m_updateTimes[part.UUID];
// Two updates can occur with the same timestamp (especially
- // since our timestamp resolution is to the nearest second). The first
- // could have been sent in the last update - we still need to send the
- // second here.
-
- if (update.LastFullUpdateTime < part.TimeStampFull)
+ // since our timestamp resolution is to the nearest second). Therefore, we still need
+ // to send an update even if the last full update time is identical to the part's
+ // update timestamp.
+ //
+ // If we don't do this, various events (such as linking and delinking in the same
+ // second), will stop working properly!
+ if (update.LastFullUpdateTime <= part.TimeStampFull)
{
//need to do a full update
part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID));
- // We'll update to the part's timestamp rather than the current to
+ // We'll update to the part's timestamp rather than the current time to
// avoid the race condition whereby the next tick occurs while we are
// doing this update. If this happened, then subsequent updates which occurred
// on the same tick or the next tick of the last update would be ignored.
--
cgit v1.1