aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-07-09 21:24:32 +0100
committerJustin Clark-Casey (justincc)2012-07-09 21:24:32 +0100
commit2eaa6d5ace738cf1848f82ce7a0b435928b6846f (patch)
tree091add9a2885fbb702cf908e1b2f70f5d1730131 /OpenSim/Region
parentMore keys for automated ini processing (diff)
downloadopensim-SC-2eaa6d5ace738cf1848f82ce7a0b435928b6846f.zip
opensim-SC-2eaa6d5ace738cf1848f82ce7a0b435928b6846f.tar.gz
opensim-SC-2eaa6d5ace738cf1848f82ce7a0b435928b6846f.tar.bz2
opensim-SC-2eaa6d5ace738cf1848f82ce7a0b435928b6846f.tar.xz
Do not allow a script to attach a prim if its being sat upon.
This prevents a stack overflow where a get position on the avatar will refer to the attachment which will in turn refer back to the avatar. This required recording of all sitting avatars on a prim which is done separately from recording the sit target avatar. Recording HashSet is null if there are no sitting avatars in order to save memory.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs32
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs98
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs18
5 files changed, 162 insertions, 9 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 9eb0e38..eccf7a6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -251,6 +251,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
251// m_log.DebugFormat( 251// m_log.DebugFormat(
252// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", 252// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
253// group.Name, group.LocalId, sp.Name, attachmentPt, silent); 253// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
254
255 if (group.GetSittingAvatarsCount() != 0)
256 {
257// m_log.WarnFormat(
258// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
259// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
260
261 return false;
262 }
254 263
255 if (sp.GetAttachments(attachmentPt).Contains(group)) 264 if (sp.GetAttachments(attachmentPt).Contains(group))
256 { 265 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 5dcbd28..3e06900 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -118,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
118 118
119 Scene scene = CreateDefaultTestScene(); 119 Scene scene = CreateDefaultTestScene();
120 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 120 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
121 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); 121 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
122 122
123 string attName = "att"; 123 string attName = "att";
124 124
@@ -154,6 +154,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
154// TestHelpers.DisableLogging(); 154// TestHelpers.DisableLogging();
155 } 155 }
156 156
157 /// <summary>
158 /// Test that we do not attempt to attach an in-world object that someone else is sitting on.
159 /// </summary>
160 [Test]
161 public void TestAddSatOnAttachmentFromGround()
162 {
163 TestHelpers.InMethod();
164// TestHelpers.EnableLogging();
165
166 Scene scene = CreateDefaultTestScene();
167 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
168 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
169
170 string attName = "att";
171
172 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
173
174 UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(scene, 0x2);
175 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, ua2);
176
177 // Put avatar within 10m of the prim so that sit doesn't fail.
178 sp2.AbsolutePosition = new Vector3(0, 0, 0);
179 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
180
181 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false);
182
183 Assert.That(sp.HasAttachments(), Is.False);
184 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
185 }
186
157 [Test] 187 [Test]
158 public void TestAddAttachmentFromInventory() 188 public void TestAddAttachmentFromInventory()
159 { 189 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 4e0e183..fc04761 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -3401,6 +3401,20 @@ namespace OpenSim.Region.Framework.Scenes
3401 return count; 3401 return count;
3402 } 3402 }
3403 3403
3404 /// <summary>
3405 /// Gets the number of sitting avatars.
3406 /// </summary>
3407 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
3408 /// <returns></returns>
3409 public int GetSittingAvatarsCount()
3410 {
3411 int count = 0;
3412
3413 Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => count += p.GetSittingAvatarsCount());
3414
3415 return count;
3416 }
3417
3404 public override string ToString() 3418 public override string ToString()
3405 { 3419 {
3406 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition); 3420 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 3d81358..6518b84 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -374,7 +374,6 @@ namespace OpenSim.Region.Framework.Scenes
374 private uint _category; 374 private uint _category;
375 private Int32 _creationDate; 375 private Int32 _creationDate;
376 private uint _parentID = 0; 376 private uint _parentID = 0;
377 private UUID m_sitTargetAvatar = UUID.Zero;
378 private uint _baseMask = (uint)PermissionMask.All; 377 private uint _baseMask = (uint)PermissionMask.All;
379 private uint _ownerMask = (uint)PermissionMask.All; 378 private uint _ownerMask = (uint)PermissionMask.All;
380 private uint _groupMask = (uint)PermissionMask.None; 379 private uint _groupMask = (uint)PermissionMask.None;
@@ -1233,13 +1232,20 @@ namespace OpenSim.Region.Framework.Scenes
1233 } 1232 }
1234 1233
1235 /// <summary> 1234 /// <summary>
1236 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1235 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
1237 /// </summary> 1236 /// </summary>
1238 public UUID SitTargetAvatar 1237 public UUID SitTargetAvatar { get; set; }
1239 { 1238
1240 get { return m_sitTargetAvatar; } 1239 /// <summary>
1241 set { m_sitTargetAvatar = value; } 1240 /// IDs of all avatars start on this object part.
1242 } 1241 /// </summary>
1242 /// <remarks>
1243 /// We need to track this so that we can stop sat upon prims from being attached.
1244 /// </remarks>
1245 /// <value>
1246 /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene.
1247 /// </value>
1248 private HashSet<UUID> m_sittingAvatars;
1243 1249
1244 public virtual UUID RegionID 1250 public virtual UUID RegionID
1245 { 1251 {
@@ -4493,5 +4499,83 @@ namespace OpenSim.Region.Framework.Scenes
4493 Color color = Color; 4499 Color color = Color;
4494 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4500 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4495 } 4501 }
4502
4503 /// <summary>
4504 /// Record an avatar sitting on this part.
4505 /// </summary>
4506 /// <remarks>This is called for all the sitting avatars whether there is a sit target set or not.</remarks>
4507 /// <returns>
4508 /// true if the avatar was not already recorded, false otherwise.
4509 /// </returns>
4510 /// <param name='avatarId'></param>
4511 protected internal bool AddSittingAvatar(UUID avatarId)
4512 {
4513 HashSet<UUID> sittingAvatars = m_sittingAvatars;
4514
4515 if (sittingAvatars == null)
4516 sittingAvatars = new HashSet<UUID>();
4517
4518 lock (sittingAvatars)
4519 {
4520 m_sittingAvatars = sittingAvatars;
4521 return m_sittingAvatars.Add(avatarId);
4522 }
4523 }
4524
4525 /// <summary>
4526 /// Remove an avatar recorded as sitting on this part.
4527 /// </summary>
4528 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
4529 /// <returns>
4530 /// true if the avatar was present and removed, false if it was not present.
4531 /// </returns>
4532 /// <param name='avatarId'></param>
4533 protected internal bool RemoveSittingAvatar(UUID avatarId)
4534 {
4535 HashSet<UUID> sittingAvatars = m_sittingAvatars;
4536
4537 // This can occur under a race condition where another thread
4538 if (sittingAvatars == null)
4539 return false;
4540
4541 lock (sittingAvatars)
4542 {
4543 if (sittingAvatars.Remove(avatarId))
4544 {
4545 if (sittingAvatars.Count == 0)
4546 m_sittingAvatars = null;
4547
4548 return true;
4549 }
4550 }
4551
4552 return false;
4553 }
4554
4555 /// <summary>
4556 /// Get a copy of the list of sitting avatars.
4557 /// </summary>
4558 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
4559 /// <returns></returns>
4560 public HashSet<UUID> GetSittingAvatars()
4561 {
4562 return new HashSet<UUID>(m_sittingAvatars);
4563 }
4564
4565 /// <summary>
4566 /// Gets the number of sitting avatars.
4567 /// </summary>
4568 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
4569 /// <returns></returns>
4570 public int GetSittingAvatarsCount()
4571 {
4572 HashSet<UUID> sittingAvatars = m_sittingAvatars;
4573
4574 if (sittingAvatars == null)
4575 return 0;
4576
4577 lock (sittingAvatars)
4578 return sittingAvatars.Count;
4579 }
4496 } 4580 }
4497} 4581}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index c7a670f..c6a2a03 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -578,6 +578,12 @@ namespace OpenSim.Region.Framework.Scenes
578 public uint ParentID { get; set; } 578 public uint ParentID { get; set; }
579 579
580 /// <summary> 580 /// <summary>
581 /// Are we sitting on an object?
582 /// </summary>
583 /// <remarks>A more readable way of testing presence sit status than ParentID == 0</remarks>
584 public bool IsSatOnObject { get { return ParentID != 0; } }
585
586 /// <summary>
581 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 587 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
582 /// </summary> 588 /// </summary>
583 /// <remarks> 589 /// <remarks>
@@ -1808,6 +1814,8 @@ namespace OpenSim.Region.Framework.Scenes
1808 SendAvatarDataToAllAgents(); 1814 SendAvatarDataToAllAgents();
1809 m_requestedSitTargetID = 0; 1815 m_requestedSitTargetID = 0;
1810 1816
1817 part.RemoveSittingAvatar(UUID);
1818
1811 if (part != null) 1819 if (part != null)
1812 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1820 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1813 } 1821 }
@@ -1887,7 +1895,7 @@ namespace OpenSim.Region.Framework.Scenes
1887 ) 1895 )
1888 )); 1896 ));
1889 1897
1890// m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied); 1898 m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied);
1891 1899
1892 if (PhysicsActor != null) 1900 if (PhysicsActor != null)
1893 m_sitAvatarHeight = PhysicsActor.Size.Z; 1901 m_sitAvatarHeight = PhysicsActor.Size.Z;
@@ -1920,6 +1928,12 @@ namespace OpenSim.Region.Framework.Scenes
1920 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1928 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1921 canSit = true; 1929 canSit = true;
1922 } 1930 }
1931// else
1932// {
1933// m_log.DebugFormat(
1934// "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m",
1935// Name, part.Name, part.LocalId);
1936// }
1923 } 1937 }
1924 1938
1925 if (canSit) 1939 if (canSit)
@@ -1930,6 +1944,8 @@ namespace OpenSim.Region.Framework.Scenes
1930 RemoveFromPhysicalScene(); 1944 RemoveFromPhysicalScene();
1931 } 1945 }
1932 1946
1947 part.AddSittingAvatar(UUID);
1948
1933 cameraAtOffset = part.GetCameraAtOffset(); 1949 cameraAtOffset = part.GetCameraAtOffset();
1934 cameraEyeOffset = part.GetCameraEyeOffset(); 1950 cameraEyeOffset = part.GetCameraEyeOffset();
1935 forceMouselook = part.GetForceMouselook(); 1951 forceMouselook = part.GetForceMouselook();