diff options
Diffstat (limited to '')
29 files changed, 781 insertions, 280 deletions
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index c130038..ebfebc4 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs | |||
@@ -92,9 +92,14 @@ namespace OpenSim | |||
92 | m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); | 92 | m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); |
93 | } | 93 | } |
94 | 94 | ||
95 | m_log.DebugFormat( | 95 | m_log.InfoFormat( |
96 | "[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture); | 96 | "[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture); |
97 | 97 | ||
98 | string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU"); | ||
99 | |||
100 | m_log.InfoFormat( | ||
101 | "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset"); | ||
102 | |||
98 | // Increase the number of IOCP threads available. Mono defaults to a tragically low number | 103 | // Increase the number of IOCP threads available. Mono defaults to a tragically low number |
99 | int workerThreads, iocpThreads; | 104 | int workerThreads, iocpThreads; |
100 | System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); | 105 | System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); |
@@ -109,7 +114,6 @@ namespace OpenSim | |||
109 | 114 | ||
110 | // Check if the system is compatible with OpenSimulator. | 115 | // Check if the system is compatible with OpenSimulator. |
111 | // Ensures that the minimum system requirements are met | 116 | // Ensures that the minimum system requirements are met |
112 | m_log.Info("Performing compatibility checks... \n"); | ||
113 | string supported = String.Empty; | 117 | string supported = String.Empty; |
114 | if (Util.IsEnvironmentSupported(ref supported)) | 118 | if (Util.IsEnvironmentSupported(ref supported)) |
115 | { | 119 | { |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 1fa5ec0..2bb60d5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -257,16 +257,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
257 | 257 | ||
258 | lock (sp.AttachmentsSyncLock) | 258 | lock (sp.AttachmentsSyncLock) |
259 | { | 259 | { |
260 | foreach (SceneObjectGroup grp in sp.GetAttachments()) | 260 | foreach (SceneObjectGroup so in sp.GetAttachments()) |
261 | { | 261 | { |
262 | grp.Scene.DeleteSceneObject(grp, false); | 262 | // We can only remove the script instances from the script engine after we've retrieved their xml state |
263 | // when we update the attachment item. | ||
264 | m_scene.DeleteSceneObject(so, false, false); | ||
263 | 265 | ||
264 | if (saveChanged || saveAllScripted) | 266 | if (saveChanged || saveAllScripted) |
265 | { | 267 | { |
266 | grp.IsAttachment = false; | 268 | so.IsAttachment = false; |
267 | grp.AbsolutePosition = grp.RootPart.AttachedPos; | 269 | so.AbsolutePosition = so.RootPart.AttachedPos; |
268 | UpdateKnownItem(sp, grp, saveAllScripted); | 270 | UpdateKnownItem(sp, so, saveAllScripted); |
269 | } | 271 | } |
272 | |||
273 | so.RemoveScriptInstances(true); | ||
270 | } | 274 | } |
271 | 275 | ||
272 | sp.ClearAttachments(); | 276 | sp.ClearAttachments(); |
@@ -297,6 +301,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
297 | // m_log.DebugFormat( | 301 | // m_log.DebugFormat( |
298 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", | 302 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", |
299 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); | 303 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); |
304 | |||
305 | if (group.GetSittingAvatarsCount() != 0) | ||
306 | { | ||
307 | // m_log.WarnFormat( | ||
308 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", | ||
309 | // group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); | ||
310 | |||
311 | return false; | ||
312 | } | ||
300 | 313 | ||
301 | if (sp.GetAttachments(attachmentPt).Contains(group)) | 314 | if (sp.GetAttachments(attachmentPt).Contains(group)) |
302 | { | 315 | { |
@@ -357,30 +370,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
357 | group.AttachmentPoint = attachmentPt; | 370 | group.AttachmentPoint = attachmentPt; |
358 | group.AbsolutePosition = attachPos; | 371 | group.AbsolutePosition = attachPos; |
359 | 372 | ||
360 | // We also don't want to do any of the inventory operations for an NPC. | ||
361 | if (sp.PresenceType != PresenceType.Npc) | 373 | if (sp.PresenceType != PresenceType.Npc) |
362 | { | 374 | UpdateUserInventoryWithAttachment(sp, group, attachmentPt); |
363 | // Remove any previous attachments | ||
364 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
365 | |||
366 | // At the moment we can only deal with a single attachment | ||
367 | if (attachments.Count != 0) | ||
368 | { | ||
369 | if (attachments[0].FromItemID != UUID.Zero) | ||
370 | DetachSingleAttachmentToInvInternal(sp, attachments[0]); | ||
371 | else | ||
372 | m_log.WarnFormat( | ||
373 | "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", | ||
374 | attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); | ||
375 | } | ||
376 | |||
377 | // Add the new attachment to inventory if we don't already have it. | ||
378 | UUID newAttachmentItemID = group.FromItemID; | ||
379 | if (newAttachmentItemID == UUID.Zero) | ||
380 | newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; | ||
381 | |||
382 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); | ||
383 | } | ||
384 | 375 | ||
385 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); | 376 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); |
386 | } | 377 | } |
@@ -388,6 +379,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
388 | return true; | 379 | return true; |
389 | } | 380 | } |
390 | 381 | ||
382 | private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt) | ||
383 | { | ||
384 | // Remove any previous attachments | ||
385 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
386 | |||
387 | // At the moment we can only deal with a single attachment | ||
388 | if (attachments.Count != 0) | ||
389 | { | ||
390 | if (attachments[0].FromItemID != UUID.Zero) | ||
391 | DetachSingleAttachmentToInvInternal(sp, attachments[0]); | ||
392 | else | ||
393 | m_log.WarnFormat( | ||
394 | "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", | ||
395 | attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); | ||
396 | } | ||
397 | |||
398 | // Add the new attachment to inventory if we don't already have it. | ||
399 | UUID newAttachmentItemID = group.FromItemID; | ||
400 | if (newAttachmentItemID == UUID.Zero) | ||
401 | newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; | ||
402 | |||
403 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); | ||
404 | } | ||
405 | |||
391 | public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) | 406 | public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) |
392 | { | 407 | { |
393 | return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null); | 408 | return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null); |
@@ -721,79 +736,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
721 | // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", | 736 | // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", |
722 | // grp.Name, grp.LocalId, remoteClient.Name); | 737 | // grp.Name, grp.LocalId, remoteClient.Name); |
723 | 738 | ||
724 | // Vector3 inventoryStoredPosition = new Vector3 | 739 | InventoryItemBase newItem |
725 | // (((grp.AbsolutePosition.X > (int)Constants.RegionSize) | 740 | = m_invAccessModule.CopyToInventory( |
726 | // ? (float)Constants.RegionSize - 6 | 741 | DeRezAction.TakeCopy, |
727 | // : grp.AbsolutePosition.X) | 742 | m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID, |
728 | // , | 743 | new List<SceneObjectGroup> { grp }, |
729 | // (grp.AbsolutePosition.Y > (int)Constants.RegionSize) | 744 | sp.ControllingClient, true)[0]; |
730 | // ? (float)Constants.RegionSize - 6 | ||
731 | // : grp.AbsolutePosition.Y, | ||
732 | // grp.AbsolutePosition.Z); | ||
733 | // | ||
734 | // Vector3 originalPosition = grp.AbsolutePosition; | ||
735 | // | ||
736 | // grp.AbsolutePosition = inventoryStoredPosition; | ||
737 | |||
738 | // If we're being called from a script, then trying to serialize that same script's state will not complete | ||
739 | // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if | ||
740 | // the client/server crashes rather than logging out normally, the attachment's scripts will resume | ||
741 | // without state on relog. Arguably, this is what we want anyway. | ||
742 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false); | ||
743 | |||
744 | // grp.AbsolutePosition = originalPosition; | ||
745 | |||
746 | AssetBase asset = m_scene.CreateAsset( | ||
747 | grp.GetPartName(grp.LocalId), | ||
748 | grp.GetPartDescription(grp.LocalId), | ||
749 | (sbyte)AssetType.Object, | ||
750 | Utils.StringToBytes(sceneObjectXml), | ||
751 | sp.UUID); | ||
752 | |||
753 | m_scene.AssetService.Store(asset); | ||
754 | |||
755 | InventoryItemBase item = new InventoryItemBase(); | ||
756 | item.CreatorId = grp.RootPart.CreatorID.ToString(); | ||
757 | item.CreatorData = grp.RootPart.CreatorData; | ||
758 | item.Owner = sp.UUID; | ||
759 | item.ID = UUID.Random(); | ||
760 | item.AssetID = asset.FullID; | ||
761 | item.Description = asset.Description; | ||
762 | item.Name = asset.Name; | ||
763 | item.AssetType = asset.Type; | ||
764 | item.InvType = (int)InventoryType.Object; | ||
765 | |||
766 | InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | ||
767 | if (folder != null) | ||
768 | item.Folder = folder.ID; | ||
769 | else // oopsies | ||
770 | item.Folder = UUID.Zero; | ||
771 | |||
772 | // Nix the special bits we used to use for slam and the folded perms | ||
773 | uint allowablePermissionsMask = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move); | ||
774 | |||
775 | if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions()) | ||
776 | { | ||
777 | item.BasePermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask; | ||
778 | item.CurrentPermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask; | ||
779 | item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask; | ||
780 | item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask; | ||
781 | item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask; | ||
782 | } | ||
783 | else | ||
784 | { | ||
785 | item.BasePermissions = grp.RootPart.BaseMask & allowablePermissionsMask; | ||
786 | item.CurrentPermissions = grp.RootPart.OwnerMask & allowablePermissionsMask; | ||
787 | item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask; | ||
788 | item.EveryOnePermissions = grp.RootPart.EveryoneMask & allowablePermissionsMask; | ||
789 | item.GroupPermissions = grp.RootPart.GroupMask & allowablePermissionsMask; | ||
790 | } | ||
791 | item.CreationDate = Util.UnixTimeSinceEpoch(); | ||
792 | 745 | ||
793 | // sets itemID so client can show item as 'attached' in inventory | 746 | // sets itemID so client can show item as 'attached' in inventory |
794 | grp.FromItemID = item.ID; | 747 | grp.FromItemID = newItem.ID; |
795 | 748 | ||
796 | return item; | 749 | return newItem; |
797 | } | 750 | } |
798 | 751 | ||
799 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) | 752 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) |
@@ -802,7 +755,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
802 | 755 | ||
803 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); | 756 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); |
804 | sp.RemoveAttachment(so); | 757 | sp.RemoveAttachment(so); |
805 | m_scene.DeleteSceneObject(so, false); | 758 | |
759 | // We can only remove the script instances from the script engine after we've retrieved their xml state | ||
760 | // when we update the attachment item. | ||
761 | m_scene.DeleteSceneObject(so, false, false); | ||
806 | 762 | ||
807 | // Prepare sog for storage | 763 | // Prepare sog for storage |
808 | so.AttachedAvatar = UUID.Zero; | 764 | so.AttachedAvatar = UUID.Zero; |
@@ -811,6 +767,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
811 | so.AbsolutePosition = so.RootPart.AttachedPos; | 767 | so.AbsolutePosition = so.RootPart.AttachedPos; |
812 | 768 | ||
813 | UpdateKnownItem(sp, so, true); | 769 | UpdateKnownItem(sp, so, true); |
770 | so.RemoveScriptInstances(true); | ||
814 | } | 771 | } |
815 | 772 | ||
816 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( | 773 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( |
@@ -920,7 +877,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
920 | item = m_scene.InventoryService.GetItem(item); | 877 | item = m_scene.InventoryService.GetItem(item); |
921 | bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); | 878 | bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); |
922 | if (changed && m_scene.AvatarFactory != null) | 879 | if (changed && m_scene.AvatarFactory != null) |
880 | { | ||
881 | // m_log.DebugFormat( | ||
882 | // "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()", | ||
883 | // sp.Name, att.Name, AttachmentPt); | ||
884 | |||
923 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | 885 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); |
886 | } | ||
924 | } | 887 | } |
925 | 888 | ||
926 | #endregion | 889 | #endregion |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 2eb0ac5..8423d43 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 | ||
@@ -149,9 +149,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
149 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | 149 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); |
150 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); | 150 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); |
151 | 151 | ||
152 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
153 | |||
152 | // TestHelpers.DisableLogging(); | 154 | // TestHelpers.DisableLogging(); |
153 | } | 155 | } |
154 | 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, false); | ||
182 | |||
183 | Assert.That(sp.HasAttachments(), Is.False); | ||
184 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
185 | } | ||
186 | |||
155 | [Test] | 187 | [Test] |
156 | public void TestAddAttachmentFromInventory() | 188 | public void TestAddAttachmentFromInventory() |
157 | { | 189 | { |
@@ -181,6 +213,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
181 | // Check appearance status | 213 | // Check appearance status |
182 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | 214 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); |
183 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | 215 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); |
216 | |||
217 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
184 | } | 218 | } |
185 | 219 | ||
186 | [Test] | 220 | [Test] |
@@ -239,6 +273,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
239 | 273 | ||
240 | // Check item status | 274 | // Check item status |
241 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); | 275 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); |
276 | |||
277 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); | ||
242 | } | 278 | } |
243 | 279 | ||
244 | /// <summary> | 280 | /// <summary> |
@@ -300,6 +336,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
300 | Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID)); | 336 | Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID)); |
301 | Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID)); | 337 | Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID)); |
302 | Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | 338 | Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); |
339 | |||
340 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
303 | } | 341 | } |
304 | 342 | ||
305 | [Test] | 343 | [Test] |
@@ -399,6 +437,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
399 | Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name)); | 437 | Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name)); |
400 | Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest)); | 438 | Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest)); |
401 | 439 | ||
440 | Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
441 | |||
402 | // Check attachments have been removed from sceneA | 442 | // Check attachments have been removed from sceneA |
403 | ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID); | 443 | ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID); |
404 | 444 | ||
@@ -410,6 +450,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
410 | // This is the actual attachment, which should no longer exist | 450 | // This is the actual attachment, which should no longer exist |
411 | List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments(); | 451 | List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments(); |
412 | Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); | 452 | Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); |
453 | |||
454 | Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); | ||
413 | } | 455 | } |
414 | 456 | ||
415 | // I'm commenting this test because scene setup NEEDS InventoryService to | 457 | // I'm commenting this test because scene setup NEEDS InventoryService to |
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index dc6efed..424e0ab 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | |||
@@ -79,7 +79,6 @@ | |||
79 | <RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" /> | 79 | <RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" /> |
80 | <RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \ | 80 | <RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \ |
81 | <RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \ | 81 | <RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \ |
82 | <RegionModule id="Warp3DImageModule" type="OpenSim.Region.CoreModules.World.Warp3DMap.Warp3DImageModule" /> \ | ||
83 | 82 | ||
84 | </Extension> | 83 | </Extension> |
85 | 84 | ||
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 724bb4c..00be5df 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | |||
@@ -730,7 +730,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
730 | { | 730 | { |
731 | if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout)) | 731 | if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout)) |
732 | { | 732 | { |
733 | m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted region {0}", regionhandle); | 733 | m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle); |
734 | 734 | ||
735 | m_blacklistedregions.Remove(regionhandle); | 735 | m_blacklistedregions.Remove(regionhandle); |
736 | } | 736 | } |
@@ -781,7 +781,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
781 | { | 781 | { |
782 | if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) | 782 | if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) |
783 | { | 783 | { |
784 | m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted URL {0}", httpserver); | 784 | m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver); |
785 | 785 | ||
786 | m_blacklistedurls.Remove(httpserver); | 786 | m_blacklistedurls.Remove(httpserver); |
787 | } | 787 | } |
@@ -1343,7 +1343,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1343 | if (terrain == null) | 1343 | if (terrain == null) |
1344 | return; | 1344 | return; |
1345 | 1345 | ||
1346 | m_log.DebugFormat("[WORLDMAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName); | 1346 | m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName); |
1347 | 1347 | ||
1348 | byte[] data = terrain.WriteJpeg2000Image(); | 1348 | byte[] data = terrain.WriteJpeg2000Image(); |
1349 | if (data == null) | 1349 | if (data == null) |
@@ -1365,7 +1365,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1365 | asset.Flags = AssetFlags.Maptile; | 1365 | asset.Flags = AssetFlags.Maptile; |
1366 | 1366 | ||
1367 | // Store the new one | 1367 | // Store the new one |
1368 | m_log.DebugFormat("[WORLDMAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName); | 1368 | m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName); |
1369 | 1369 | ||
1370 | m_scene.AssetService.Store(asset); | 1370 | m_scene.AssetService.Store(asset); |
1371 | 1371 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 4f0e100..4274cbe 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs | |||
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
92 | void ResumeScripts(); | 92 | void ResumeScripts(); |
93 | 93 | ||
94 | /// <summary> | 94 | /// <summary> |
95 | /// Stop all the scripts in this entity. | 95 | /// Stop and remove all the scripts in this entity from the scene. |
96 | /// </summary> | 96 | /// </summary> |
97 | /// <param name="sceneObjectBeingDeleted"> | 97 | /// <param name="sceneObjectBeingDeleted"> |
98 | /// Should be true if these scripts are being removed because the scene | 98 | /// Should be true if these scripts are being removed because the scene |
@@ -101,6 +101,11 @@ namespace OpenSim.Region.Framework.Interfaces | |||
101 | void RemoveScriptInstances(bool sceneObjectBeingDeleted); | 101 | void RemoveScriptInstances(bool sceneObjectBeingDeleted); |
102 | 102 | ||
103 | /// <summary> | 103 | /// <summary> |
104 | /// Stop all the scripts in this entity. | ||
105 | /// </summary> | ||
106 | void StopScriptInstances(); | ||
107 | |||
108 | /// <summary> | ||
104 | /// Start a script which is in this entity's inventory. | 109 | /// Start a script which is in this entity's inventory. |
105 | /// </summary> | 110 | /// </summary> |
106 | /// <param name="item"></param> | 111 | /// <param name="item"></param> |
@@ -131,7 +136,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
131 | ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); | 136 | ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); |
132 | 137 | ||
133 | /// <summary> | 138 | /// <summary> |
134 | /// Stop a script which is in this prim's inventory. | 139 | /// Stop and remove a script which is in this prim's inventory from the scene. |
135 | /// </summary> | 140 | /// </summary> |
136 | /// <param name="itemId"></param> | 141 | /// <param name="itemId"></param> |
137 | /// <param name="sceneObjectBeingDeleted"> | 142 | /// <param name="sceneObjectBeingDeleted"> |
@@ -141,6 +146,12 @@ namespace OpenSim.Region.Framework.Interfaces | |||
141 | void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted); | 146 | void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted); |
142 | 147 | ||
143 | /// <summary> | 148 | /// <summary> |
149 | /// Stop a script which is in this prim's inventory. | ||
150 | /// </summary> | ||
151 | /// <param name="itemId"></param> | ||
152 | void StopScriptInstance(UUID itemId); | ||
153 | |||
154 | /// <summary> | ||
144 | /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative | 155 | /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative |
145 | /// name is chosen. | 156 | /// name is chosen. |
146 | /// </summary> | 157 | /// </summary> |
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs index 860483d..d582149 100644 --- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs +++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs | |||
@@ -184,6 +184,14 @@ namespace OpenSim.Region.Framework.Interfaces | |||
184 | bool Stand(UUID agentID, Scene scene); | 184 | bool Stand(UUID agentID, Scene scene); |
185 | 185 | ||
186 | /// <summary> | 186 | /// <summary> |
187 | /// Get the NPC to touch an object. | ||
188 | /// </summary> | ||
189 | /// <param name="agentID"></param> | ||
190 | /// <param name="partID"></param> | ||
191 | /// <returns>true if the touch is actually attempted, false if not</returns> | ||
192 | bool Touch(UUID agentID, UUID partID); | ||
193 | |||
194 | /// <summary> | ||
187 | /// Delete an NPC. | 195 | /// Delete an NPC. |
188 | /// </summary> | 196 | /// </summary> |
189 | /// <param name="agentID">The UUID of the NPC</param> | 197 | /// <param name="agentID">The UUID of the NPC</param> |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a63ed13..eae8b8e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -2281,13 +2281,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
2281 | /// <summary> | 2281 | /// <summary> |
2282 | /// Synchronously delete the given object from the scene. | 2282 | /// Synchronously delete the given object from the scene. |
2283 | /// </summary> | 2283 | /// </summary> |
2284 | /// <remarks> | ||
2285 | /// Scripts are also removed. | ||
2286 | /// </remarks> | ||
2284 | /// <param name="group">Object Id</param> | 2287 | /// <param name="group">Object Id</param> |
2285 | /// <param name="silent">Suppress broadcasting changes to other clients.</param> | 2288 | /// <param name="silent">Suppress broadcasting changes to other clients.</param> |
2286 | public void DeleteSceneObject(SceneObjectGroup group, bool silent) | 2289 | public void DeleteSceneObject(SceneObjectGroup group, bool silent) |
2290 | { | ||
2291 | DeleteSceneObject(group, silent, true); | ||
2292 | } | ||
2293 | |||
2294 | /// <summary> | ||
2295 | /// Synchronously delete the given object from the scene. | ||
2296 | /// </summary> | ||
2297 | /// <param name="group">Object Id</param> | ||
2298 | /// <param name="silent">Suppress broadcasting changes to other clients.</param> | ||
2299 | /// <param name="removeScripts">If true, then scripts are removed. If false, then they are only stopped.</para> | ||
2300 | public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts) | ||
2287 | { | 2301 | { |
2288 | // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); | 2302 | // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); |
2289 | 2303 | ||
2290 | group.RemoveScriptInstances(true); | 2304 | if (removeScripts) |
2305 | group.RemoveScriptInstances(true); | ||
2306 | else | ||
2307 | group.StopScriptInstances(); | ||
2291 | 2308 | ||
2292 | SceneObjectPart[] partList = group.Parts; | 2309 | SceneObjectPart[] partList = group.Parts; |
2293 | 2310 | ||
@@ -2595,7 +2612,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
2595 | } | 2612 | } |
2596 | catch (Exception e) | 2613 | catch (Exception e) |
2597 | { | 2614 | { |
2598 | m_log.WarnFormat("[SCENE]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); | 2615 | m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); |
2616 | return false; | ||
2617 | } | ||
2618 | |||
2619 | // If the user is banned, we won't let any of their objects | ||
2620 | // enter. Period. | ||
2621 | // | ||
2622 | if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID, 36)) | ||
2623 | { | ||
2624 | m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID); | ||
2599 | return false; | 2625 | return false; |
2600 | } | 2626 | } |
2601 | 2627 | ||
@@ -2606,14 +2632,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
2606 | 2632 | ||
2607 | if (!AddSceneObject(newObject)) | 2633 | if (!AddSceneObject(newObject)) |
2608 | { | 2634 | { |
2609 | m_log.DebugFormat("[SCENE]: Problem adding scene object {0} in {1} ", sog.UUID, RegionInfo.RegionName); | 2635 | m_log.DebugFormat( |
2636 | "[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName); | ||
2610 | return false; | 2637 | return false; |
2611 | } | 2638 | } |
2612 | 2639 | ||
2613 | // For attachments, we need to wait until the agent is root | ||
2614 | // before we restart the scripts, or else some functions won't work. | ||
2615 | if (!newObject.IsAttachment) | 2640 | if (!newObject.IsAttachment) |
2616 | { | 2641 | { |
2642 | // FIXME: It would be better to never add the scene object at all rather than add it and then delete | ||
2643 | // it | ||
2644 | if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition)) | ||
2645 | { | ||
2646 | // Deny non attachments based on parcel settings | ||
2647 | // | ||
2648 | m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings"); | ||
2649 | |||
2650 | DeleteSceneObject(newObject, false); | ||
2651 | |||
2652 | return false; | ||
2653 | } | ||
2654 | |||
2655 | // For attachments, we need to wait until the agent is root | ||
2656 | // before we restart the scripts, or else some functions won't work. | ||
2617 | newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); | 2657 | newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); |
2618 | newObject.ResumeScripts(); | 2658 | newObject.ResumeScripts(); |
2619 | } | 2659 | } |
@@ -2650,8 +2690,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2650 | return false; | 2690 | return false; |
2651 | } | 2691 | } |
2652 | 2692 | ||
2653 | sceneObject.SetScene(this); | ||
2654 | |||
2655 | // Force allocation of new LocalId | 2693 | // Force allocation of new LocalId |
2656 | // | 2694 | // |
2657 | SceneObjectPart[] parts = sceneObject.Parts; | 2695 | SceneObjectPart[] parts = sceneObject.Parts; |
@@ -2707,18 +2745,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2707 | return false; | 2745 | return false; |
2708 | } | 2746 | } |
2709 | AddRestoredSceneObject(sceneObject, true, false); | 2747 | AddRestoredSceneObject(sceneObject, true, false); |
2710 | |||
2711 | if (!Permissions.CanObjectEntry(sceneObject.UUID, | ||
2712 | true, sceneObject.AbsolutePosition)) | ||
2713 | { | ||
2714 | // Deny non attachments based on parcel settings | ||
2715 | // | ||
2716 | m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings"); | ||
2717 | |||
2718 | DeleteSceneObject(sceneObject, false); | ||
2719 | |||
2720 | return false; | ||
2721 | } | ||
2722 | } | 2748 | } |
2723 | 2749 | ||
2724 | return true; | 2750 | return true; |
@@ -4654,6 +4680,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
4654 | } | 4680 | } |
4655 | 4681 | ||
4656 | /// <summary> | 4682 | /// <summary> |
4683 | /// Get all the scene object groups. | ||
4684 | /// </summary> | ||
4685 | /// <returns> | ||
4686 | /// The scene object groups. If the scene is empty then an empty list is returned. | ||
4687 | /// </returns> | ||
4688 | public List<SceneObjectGroup> GetSceneObjectGroups() | ||
4689 | { | ||
4690 | return m_sceneGraph.GetSceneObjectGroups(); | ||
4691 | } | ||
4692 | |||
4693 | /// <summary> | ||
4657 | /// Get a group via its UUID | 4694 | /// Get a group via its UUID |
4658 | /// </summary> | 4695 | /// </summary> |
4659 | /// <param name="fullID"></param> | 4696 | /// <param name="fullID"></param> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 3390aba..b23d2e5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -401,9 +401,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
401 | 401 | ||
402 | if (Entities.ContainsKey(sceneObject.UUID)) | 402 | if (Entities.ContainsKey(sceneObject.UUID)) |
403 | { | 403 | { |
404 | // m_log.DebugFormat( | 404 | m_log.DebugFormat( |
405 | // "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", | 405 | "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", |
406 | // m_parentScene.RegionInfo.RegionName, sceneObject.UUID); | 406 | m_parentScene.RegionInfo.RegionName, sceneObject.UUID); |
407 | 407 | ||
408 | return false; | 408 | return false; |
409 | } | 409 | } |
@@ -1038,6 +1038,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | /// <summary> | 1040 | /// <summary> |
1041 | /// Get all the scene object groups. | ||
1042 | /// </summary> | ||
1043 | /// <returns> | ||
1044 | /// The scene object groups. If the scene is empty then an empty list is returned. | ||
1045 | /// </returns> | ||
1046 | protected internal List<SceneObjectGroup> GetSceneObjectGroups() | ||
1047 | { | ||
1048 | lock (SceneObjectGroupsByFullID) | ||
1049 | return new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); | ||
1050 | } | ||
1051 | |||
1052 | /// <summary> | ||
1041 | /// Get a group in the scene | 1053 | /// Get a group in the scene |
1042 | /// </summary> | 1054 | /// </summary> |
1043 | /// <param name="fullID">UUID of the group</param> | 1055 | /// <param name="fullID">UUID of the group</param> |
@@ -1180,11 +1192,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1180 | /// <param name="action"></param> | 1192 | /// <param name="action"></param> |
1181 | protected internal void ForEachSOG(Action<SceneObjectGroup> action) | 1193 | protected internal void ForEachSOG(Action<SceneObjectGroup> action) |
1182 | { | 1194 | { |
1183 | List<SceneObjectGroup> objlist; | 1195 | foreach (SceneObjectGroup obj in GetSceneObjectGroups()) |
1184 | lock (SceneObjectGroupsByFullID) | ||
1185 | objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); | ||
1186 | |||
1187 | foreach (SceneObjectGroup obj in objlist) | ||
1188 | { | 1196 | { |
1189 | try | 1197 | try |
1190 | { | 1198 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 1038111..26524fb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs | |||
@@ -79,7 +79,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
79 | } | 79 | } |
80 | 80 | ||
81 | /// <summary> | 81 | /// <summary> |
82 | /// Stop the scripts contained in all the prims in this group | 82 | /// Stop and remove the scripts contained in all the prims in this group |
83 | /// </summary> | 83 | /// </summary> |
84 | public void RemoveScriptInstances(bool sceneObjectBeingDeleted) | 84 | public void RemoveScriptInstances(bool sceneObjectBeingDeleted) |
85 | { | 85 | { |
@@ -89,6 +89,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
89 | } | 89 | } |
90 | 90 | ||
91 | /// <summary> | 91 | /// <summary> |
92 | /// Stop the scripts contained in all the prims in this group | ||
93 | /// </summary> | ||
94 | public void StopScriptInstances() | ||
95 | { | ||
96 | Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => p.Inventory.StopScriptInstances()); | ||
97 | } | ||
98 | |||
99 | /// <summary> | ||
92 | /// Add an inventory item from a user's inventory to a prim in this scene object. | 100 | /// Add an inventory item from a user's inventory to a prim in this scene object. |
93 | /// </summary> | 101 | /// </summary> |
94 | /// <param name="agentID">The agent adding the item.</param> | 102 | /// <param name="agentID">The agent adding the item.</param> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f68a5b3..cc7d0fb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -1674,16 +1674,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1674 | { | 1674 | { |
1675 | return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); | 1675 | return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); |
1676 | } | 1676 | } |
1677 | |||
1678 | /// <summary> | ||
1679 | /// Added as a way for the storage provider to reset the scene, | ||
1680 | /// most likely a better way to do this sort of thing but for now... | ||
1681 | /// </summary> | ||
1682 | /// <param name="scene"></param> | ||
1683 | public void SetScene(Scene scene) | ||
1684 | { | ||
1685 | m_scene = scene; | ||
1686 | } | ||
1687 | 1677 | ||
1688 | /// <summary> | 1678 | /// <summary> |
1689 | /// Set a part to act as the root part for this scene object | 1679 | /// Set a part to act as the root part for this scene object |
@@ -4324,6 +4314,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
4324 | return count; | 4314 | return count; |
4325 | } | 4315 | } |
4326 | 4316 | ||
4317 | /// <summary> | ||
4318 | /// Gets the number of sitting avatars. | ||
4319 | /// </summary> | ||
4320 | /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> | ||
4321 | /// <returns></returns> | ||
4322 | public int GetSittingAvatarsCount() | ||
4323 | { | ||
4324 | int count = 0; | ||
4325 | |||
4326 | Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => count += p.GetSittingAvatarsCount()); | ||
4327 | |||
4328 | return count; | ||
4329 | } | ||
4330 | |||
4327 | public override string ToString() | 4331 | public override string ToString() |
4328 | { | 4332 | { |
4329 | return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition); | 4333 | 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 7b1f5d2..1f1caca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -147,6 +147,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
147 | get { return ParentGroup.RootPart == this; } | 147 | get { return ParentGroup.RootPart == this; } |
148 | } | 148 | } |
149 | 149 | ||
150 | /// <summary> | ||
151 | /// Is an explicit sit target set for this part? | ||
152 | /// </summary> | ||
153 | public bool IsSitTargetSet | ||
154 | { | ||
155 | get | ||
156 | { | ||
157 | return | ||
158 | !(SitTargetPosition == Vector3.Zero | ||
159 | && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion | ||
160 | || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 1f && SitTargetOrientation.W == 0f // W-Z Mapping was invalid at one point | ||
161 | || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f && SitTargetOrientation.W == 0f)); // Invalid Quaternion | ||
162 | } | ||
163 | } | ||
164 | |||
150 | #region Fields | 165 | #region Fields |
151 | 166 | ||
152 | public bool AllowedDrop; | 167 | public bool AllowedDrop; |
@@ -426,7 +441,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
426 | private uint _category; | 441 | private uint _category; |
427 | private Int32 _creationDate; | 442 | private Int32 _creationDate; |
428 | private uint _parentID = 0; | 443 | private uint _parentID = 0; |
429 | private UUID m_sitTargetAvatar = UUID.Zero; | ||
430 | private uint _baseMask = (uint)PermissionMask.All; | 444 | private uint _baseMask = (uint)PermissionMask.All; |
431 | private uint _ownerMask = (uint)PermissionMask.All; | 445 | private uint _ownerMask = (uint)PermissionMask.All; |
432 | private uint _groupMask = (uint)PermissionMask.None; | 446 | private uint _groupMask = (uint)PermissionMask.None; |
@@ -1312,13 +1326,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1312 | } | 1326 | } |
1313 | 1327 | ||
1314 | /// <summary> | 1328 | /// <summary> |
1315 | /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero | 1329 | /// 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 |
1316 | /// </summary> | 1330 | /// </summary> |
1317 | public UUID SitTargetAvatar | 1331 | public UUID SitTargetAvatar { get; set; } |
1318 | { | 1332 | |
1319 | get { return m_sitTargetAvatar; } | 1333 | /// <summary> |
1320 | set { m_sitTargetAvatar = value; } | 1334 | /// IDs of all avatars start on this object part. |
1321 | } | 1335 | /// </summary> |
1336 | /// <remarks> | ||
1337 | /// We need to track this so that we can stop sat upon prims from being attached. | ||
1338 | /// </remarks> | ||
1339 | /// <value> | ||
1340 | /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene. | ||
1341 | /// </value> | ||
1342 | private HashSet<UUID> m_sittingAvatars; | ||
1322 | 1343 | ||
1323 | public virtual UUID RegionID | 1344 | public virtual UUID RegionID |
1324 | { | 1345 | { |
@@ -5128,5 +5149,99 @@ namespace OpenSim.Region.Framework.Scenes | |||
5128 | Inventory.UpdateInventoryItem(item, false, false); | 5149 | Inventory.UpdateInventoryItem(item, false, false); |
5129 | } | 5150 | } |
5130 | } | 5151 | } |
5152 | |||
5153 | /// <summary> | ||
5154 | /// Record an avatar sitting on this part. | ||
5155 | /// </summary> | ||
5156 | /// <remarks>This is called for all the sitting avatars whether there is a sit target set or not.</remarks> | ||
5157 | /// <returns> | ||
5158 | /// true if the avatar was not already recorded, false otherwise. | ||
5159 | /// </returns> | ||
5160 | /// <param name='avatarId'></param> | ||
5161 | protected internal bool AddSittingAvatar(UUID avatarId) | ||
5162 | { | ||
5163 | if (IsSitTargetSet && SitTargetAvatar == UUID.Zero) | ||
5164 | SitTargetAvatar = avatarId; | ||
5165 | |||
5166 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5167 | |||
5168 | if (sittingAvatars == null) | ||
5169 | sittingAvatars = new HashSet<UUID>(); | ||
5170 | |||
5171 | lock (sittingAvatars) | ||
5172 | { | ||
5173 | m_sittingAvatars = sittingAvatars; | ||
5174 | return m_sittingAvatars.Add(avatarId); | ||
5175 | } | ||
5176 | } | ||
5177 | |||
5178 | /// <summary> | ||
5179 | /// Remove an avatar recorded as sitting on this part. | ||
5180 | /// </summary> | ||
5181 | /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> | ||
5182 | /// <returns> | ||
5183 | /// true if the avatar was present and removed, false if it was not present. | ||
5184 | /// </returns> | ||
5185 | /// <param name='avatarId'></param> | ||
5186 | protected internal bool RemoveSittingAvatar(UUID avatarId) | ||
5187 | { | ||
5188 | if (SitTargetAvatar == avatarId) | ||
5189 | SitTargetAvatar = UUID.Zero; | ||
5190 | |||
5191 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5192 | |||
5193 | // This can occur under a race condition where another thread | ||
5194 | if (sittingAvatars == null) | ||
5195 | return false; | ||
5196 | |||
5197 | lock (sittingAvatars) | ||
5198 | { | ||
5199 | if (sittingAvatars.Remove(avatarId)) | ||
5200 | { | ||
5201 | if (sittingAvatars.Count == 0) | ||
5202 | m_sittingAvatars = null; | ||
5203 | |||
5204 | return true; | ||
5205 | } | ||
5206 | } | ||
5207 | |||
5208 | return false; | ||
5209 | } | ||
5210 | |||
5211 | /// <summary> | ||
5212 | /// Get a copy of the list of sitting avatars. | ||
5213 | /// </summary> | ||
5214 | /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> | ||
5215 | /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns> | ||
5216 | public HashSet<UUID> GetSittingAvatars() | ||
5217 | { | ||
5218 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5219 | |||
5220 | if (sittingAvatars == null) | ||
5221 | { | ||
5222 | return null; | ||
5223 | } | ||
5224 | else | ||
5225 | { | ||
5226 | lock (sittingAvatars) | ||
5227 | return new HashSet<UUID>(sittingAvatars); | ||
5228 | } | ||
5229 | } | ||
5230 | |||
5231 | /// <summary> | ||
5232 | /// Gets the number of sitting avatars. | ||
5233 | /// </summary> | ||
5234 | /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> | ||
5235 | /// <returns></returns> | ||
5236 | public int GetSittingAvatarsCount() | ||
5237 | { | ||
5238 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5239 | |||
5240 | if (sittingAvatars == null) | ||
5241 | return 0; | ||
5242 | |||
5243 | lock (sittingAvatars) | ||
5244 | return sittingAvatars.Count; | ||
5245 | } | ||
5131 | } | 5246 | } |
5132 | } | 5247 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 1dff088..e5e29d0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | |||
@@ -292,7 +292,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
292 | } | 292 | } |
293 | 293 | ||
294 | /// <summary> | 294 | /// <summary> |
295 | /// Stop all the scripts in this prim. | 295 | /// Stop and remove all the scripts in this prim. |
296 | /// </summary> | 296 | /// </summary> |
297 | /// <param name="sceneObjectBeingDeleted"> | 297 | /// <param name="sceneObjectBeingDeleted"> |
298 | /// Should be true if these scripts are being removed because the scene | 298 | /// Should be true if these scripts are being removed because the scene |
@@ -309,6 +309,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
309 | } | 309 | } |
310 | 310 | ||
311 | /// <summary> | 311 | /// <summary> |
312 | /// Stop all the scripts in this prim. | ||
313 | /// </summary> | ||
314 | public void StopScriptInstances() | ||
315 | { | ||
316 | GetInventoryItems(InventoryType.LSL).ForEach(i => StopScriptInstance(i)); | ||
317 | } | ||
318 | |||
319 | /// <summary> | ||
312 | /// Start a script which is in this prim's inventory. | 320 | /// Start a script which is in this prim's inventory. |
313 | /// </summary> | 321 | /// </summary> |
314 | /// <param name="item"></param> | 322 | /// <param name="item"></param> |
@@ -596,7 +604,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
596 | } | 604 | } |
597 | 605 | ||
598 | /// <summary> | 606 | /// <summary> |
599 | /// Stop a script which is in this prim's inventory. | 607 | /// Stop and remove a script which is in this prim's inventory. |
600 | /// </summary> | 608 | /// </summary> |
601 | /// <param name="itemId"></param> | 609 | /// <param name="itemId"></param> |
602 | /// <param name="sceneObjectBeingDeleted"> | 610 | /// <param name="sceneObjectBeingDeleted"> |
@@ -615,7 +623,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
615 | } | 623 | } |
616 | else | 624 | else |
617 | { | 625 | { |
618 | m_log.ErrorFormat( | 626 | m_log.WarnFormat( |
619 | "[PRIM INVENTORY]: " + | 627 | "[PRIM INVENTORY]: " + |
620 | "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", | 628 | "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", |
621 | itemId, m_part.Name, m_part.UUID, | 629 | itemId, m_part.Name, m_part.UUID, |
@@ -624,6 +632,51 @@ namespace OpenSim.Region.Framework.Scenes | |||
624 | } | 632 | } |
625 | 633 | ||
626 | /// <summary> | 634 | /// <summary> |
635 | /// Stop a script which is in this prim's inventory. | ||
636 | /// </summary> | ||
637 | /// <param name="itemId"></param> | ||
638 | /// <param name="sceneObjectBeingDeleted"> | ||
639 | /// Should be true if this script is being removed because the scene | ||
640 | /// object is being deleted. This will prevent spurious updates to the client. | ||
641 | /// </param> | ||
642 | public void StopScriptInstance(UUID itemId) | ||
643 | { | ||
644 | TaskInventoryItem scriptItem; | ||
645 | |||
646 | lock (m_items) | ||
647 | m_items.TryGetValue(itemId, out scriptItem); | ||
648 | |||
649 | if (scriptItem != null) | ||
650 | { | ||
651 | StopScriptInstance(scriptItem); | ||
652 | } | ||
653 | else | ||
654 | { | ||
655 | m_log.WarnFormat( | ||
656 | "[PRIM INVENTORY]: " + | ||
657 | "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", | ||
658 | itemId, m_part.Name, m_part.UUID, | ||
659 | m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | /// <summary> | ||
664 | /// Stop a script which is in this prim's inventory. | ||
665 | /// </summary> | ||
666 | /// <param name="itemId"></param> | ||
667 | /// <param name="sceneObjectBeingDeleted"> | ||
668 | /// Should be true if this script is being removed because the scene | ||
669 | /// object is being deleted. This will prevent spurious updates to the client. | ||
670 | /// </param> | ||
671 | public void StopScriptInstance(TaskInventoryItem item) | ||
672 | { | ||
673 | m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); | ||
674 | |||
675 | // At the moment, even stopped scripts are counted as active, which is probably wrong. | ||
676 | // m_part.ParentGroup.AddActiveScriptCount(-1); | ||
677 | } | ||
678 | |||
679 | /// <summary> | ||
627 | /// Check if the inventory holds an item with a given name. | 680 | /// Check if the inventory holds an item with a given name. |
628 | /// </summary> | 681 | /// </summary> |
629 | /// <param name="name"></param> | 682 | /// <param name="name"></param> |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f0ceff6..e27d309 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -594,6 +594,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
594 | private UUID m_parentUUID = UUID.Zero; | 594 | private UUID m_parentUUID = UUID.Zero; |
595 | 595 | ||
596 | /// <summary> | 596 | /// <summary> |
597 | /// Are we sitting on an object? | ||
598 | /// </summary> | ||
599 | /// <remarks>A more readable way of testing presence sit status than ParentID == 0</remarks> | ||
600 | public bool IsSatOnObject { get { return ParentID != 0; } } | ||
601 | |||
602 | /// <summary> | ||
597 | /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. | 603 | /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. |
598 | /// </summary> | 604 | /// </summary> |
599 | /// <remarks> | 605 | /// <remarks> |
@@ -1940,10 +1946,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1940 | } | 1946 | } |
1941 | } | 1947 | } |
1942 | 1948 | ||
1943 | // Reset sit target. | ||
1944 | if (part.SitTargetAvatar == UUID) | ||
1945 | part.SitTargetAvatar = UUID.Zero; | ||
1946 | |||
1947 | part.ParentGroup.DeleteAvatar(UUID); | 1949 | part.ParentGroup.DeleteAvatar(UUID); |
1948 | // ParentPosition = part.GetWorldPosition(); | 1950 | // ParentPosition = part.GetWorldPosition(); |
1949 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); | 1951 | ControllingClient.SendClearFollowCamProperties(part.ParentUUID); |
@@ -1961,6 +1963,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1961 | SendAvatarDataToAllAgents(); | 1963 | SendAvatarDataToAllAgents(); |
1962 | m_requestedSitTargetID = 0; | 1964 | m_requestedSitTargetID = 0; |
1963 | 1965 | ||
1966 | part.RemoveSittingAvatar(UUID); | ||
1967 | |||
1964 | if (part != null) | 1968 | if (part != null) |
1965 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); | 1969 | part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); |
1966 | } | 1970 | } |
@@ -1994,15 +1998,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1994 | //look for prims with explicit sit targets that are available | 1998 | //look for prims with explicit sit targets that are available |
1995 | foreach (SceneObjectPart part in partArray) | 1999 | foreach (SceneObjectPart part in partArray) |
1996 | { | 2000 | { |
1997 | // Is a sit target available? | 2001 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) |
1998 | Vector3 avSitOffset = part.SitTargetPosition; | ||
1999 | Quaternion avSitOrientation = part.SitTargetOrientation; | ||
2000 | UUID avOnTargetAlready = part.SitTargetAvatar; | ||
2001 | |||
2002 | bool SitTargetUnOccupied = avOnTargetAlready == UUID.Zero; | ||
2003 | bool SitTargetisSet = avSitOffset != Vector3.Zero || avSitOrientation != Quaternion.Identity; | ||
2004 | |||
2005 | if (SitTargetisSet && SitTargetUnOccupied) | ||
2006 | { | 2002 | { |
2007 | //switch the target to this prim | 2003 | //switch the target to this prim |
2008 | return part; | 2004 | return part; |
@@ -2013,10 +2009,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2013 | return targetPart; | 2009 | return targetPart; |
2014 | } | 2010 | } |
2015 | 2011 | ||
2016 | private void SendSitResponse(UUID targetID, Vector3 offset, Quaternion pSitOrientation) | 2012 | private void SendSitResponse(UUID targetID, Vector3 offset, Quaternion sitOrientation) |
2017 | { | 2013 | { |
2018 | Vector3 pos = new Vector3(); | ||
2019 | Quaternion sitOrientation = pSitOrientation; | ||
2020 | Vector3 cameraEyeOffset = Vector3.Zero; | 2014 | Vector3 cameraEyeOffset = Vector3.Zero; |
2021 | Vector3 cameraAtOffset = Vector3.Zero; | 2015 | Vector3 cameraAtOffset = Vector3.Zero; |
2022 | bool forceMouselook = false; | 2016 | bool forceMouselook = false; |
@@ -2028,42 +2022,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
2028 | // TODO: determine position to sit at based on scene geometry; don't trust offset from client | 2022 | // TODO: determine position to sit at based on scene geometry; don't trust offset from client |
2029 | // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it | 2023 | // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it |
2030 | 2024 | ||
2031 | // Is a sit target available? | ||
2032 | Vector3 avSitOffSet = part.SitTargetPosition; | ||
2033 | Quaternion avSitOrientation = part.SitTargetOrientation; | ||
2034 | UUID avOnTargetAlready = part.SitTargetAvatar; | ||
2035 | |||
2036 | bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); | ||
2037 | bool SitTargetisSet = | ||
2038 | (!(avSitOffSet == Vector3.Zero && | ||
2039 | ( | ||
2040 | avSitOrientation == Quaternion.Identity // Valid Zero Rotation quaternion | ||
2041 | || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point | ||
2042 | || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion | ||
2043 | ) | ||
2044 | )); | ||
2045 | |||
2046 | // m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied); | ||
2047 | |||
2048 | if (PhysicsActor != null) | 2025 | if (PhysicsActor != null) |
2049 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; | 2026 | m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; |
2050 | 2027 | ||
2051 | bool canSit = false; | 2028 | bool canSit = false; |
2052 | pos = part.AbsolutePosition + offset; | 2029 | Vector3 pos = part.AbsolutePosition + offset; |
2053 | 2030 | ||
2054 | if (SitTargetisSet) | 2031 | if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) |
2055 | { | 2032 | { |
2056 | if (SitTargetUnOccupied) | ||
2057 | { | ||
2058 | // m_log.DebugFormat( | 2033 | // m_log.DebugFormat( |
2059 | // "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied", | 2034 | // "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied", |
2060 | // Name, part.Name, part.LocalId); | 2035 | // Name, part.Name, part.LocalId); |
2061 | 2036 | ||
2062 | part.SitTargetAvatar = UUID; | 2037 | offset = part.SitTargetPosition; |
2063 | offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); | 2038 | sitOrientation = part.SitTargetOrientation; |
2064 | sitOrientation = avSitOrientation; | 2039 | canSit = true; |
2065 | canSit = true; | ||
2066 | } | ||
2067 | } | 2040 | } |
2068 | else | 2041 | else |
2069 | { | 2042 | { |
@@ -2076,6 +2049,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2076 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); | 2049 | AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); |
2077 | canSit = true; | 2050 | canSit = true; |
2078 | } | 2051 | } |
2052 | // else | ||
2053 | // { | ||
2054 | // m_log.DebugFormat( | ||
2055 | // "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m", | ||
2056 | // Name, part.Name, part.LocalId); | ||
2057 | // } | ||
2079 | } | 2058 | } |
2080 | 2059 | ||
2081 | if (canSit) | 2060 | if (canSit) |
@@ -2086,6 +2065,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2086 | RemoveFromPhysicalScene(); | 2065 | RemoveFromPhysicalScene(); |
2087 | } | 2066 | } |
2088 | 2067 | ||
2068 | part.AddSittingAvatar(UUID); | ||
2069 | |||
2089 | cameraAtOffset = part.GetCameraAtOffset(); | 2070 | cameraAtOffset = part.GetCameraAtOffset(); |
2090 | cameraEyeOffset = part.GetCameraEyeOffset(); | 2071 | cameraEyeOffset = part.GetCameraEyeOffset(); |
2091 | forceMouselook = part.GetForceMouselook(); | 2072 | forceMouselook = part.GetForceMouselook(); |
@@ -2362,6 +2343,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2362 | 2343 | ||
2363 | if (part != null) | 2344 | if (part != null) |
2364 | { | 2345 | { |
2346 | if (part.ParentGroup.IsAttachment) | ||
2347 | { | ||
2348 | m_log.WarnFormat( | ||
2349 | "[SCENE PRESENCE]: Avatar {0} tried to sit on part {1} from object {2} in {3} but this is an attachment for avatar id {4}", | ||
2350 | Name, part.Name, part.ParentGroup.Name, Scene.Name, part.ParentGroup.AttachedAvatar); | ||
2351 | |||
2352 | return; | ||
2353 | } | ||
2354 | |||
2365 | if (part.SitTargetAvatar == UUID) | 2355 | if (part.SitTargetAvatar == UUID) |
2366 | { | 2356 | { |
2367 | Vector3 sitTargetPos = part.SitTargetPosition; | 2357 | Vector3 sitTargetPos = part.SitTargetPosition; |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs index ed39be1..493ab70 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | ||
29 | using System.Reflection; | 30 | using System.Reflection; |
30 | using Nini.Config; | 31 | using Nini.Config; |
31 | using NUnit.Framework; | 32 | using NUnit.Framework; |
@@ -69,6 +70,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
69 | m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); | 70 | m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); |
70 | 71 | ||
71 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); | 72 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); |
73 | Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); | ||
74 | Assert.That(part.GetSittingAvatars(), Is.Null); | ||
72 | Assert.That(m_sp.ParentID, Is.EqualTo(0)); | 75 | Assert.That(m_sp.ParentID, Is.EqualTo(0)); |
73 | } | 76 | } |
74 | 77 | ||
@@ -86,7 +89,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
86 | 89 | ||
87 | m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); | 90 | m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); |
88 | 91 | ||
92 | Assert.That(m_sp.PhysicsActor, Is.Null); | ||
93 | |||
89 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); | 94 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); |
95 | Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); | ||
96 | HashSet<UUID> sittingAvatars = part.GetSittingAvatars(); | ||
97 | Assert.That(sittingAvatars.Count, Is.EqualTo(1)); | ||
98 | Assert.That(sittingAvatars.Contains(m_sp.UUID)); | ||
90 | Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); | 99 | Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); |
91 | } | 100 | } |
92 | 101 | ||
@@ -104,10 +113,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
104 | 113 | ||
105 | m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); | 114 | m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); |
106 | 115 | ||
107 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); | ||
108 | Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); | ||
109 | Assert.That(m_sp.PhysicsActor, Is.Null); | ||
110 | |||
111 | // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the | 116 | // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the |
112 | // default avatar. | 117 | // default avatar. |
113 | // Curiously, Vector3.ToString() will not display the last two places of the float. For example, | 118 | // Curiously, Vector3.ToString() will not display the last two places of the float. For example, |
@@ -119,6 +124,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
119 | m_sp.StandUp(); | 124 | m_sp.StandUp(); |
120 | 125 | ||
121 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); | 126 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); |
127 | Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); | ||
128 | Assert.That(part.GetSittingAvatars(), Is.Null); | ||
122 | Assert.That(m_sp.ParentID, Is.EqualTo(0)); | 129 | Assert.That(m_sp.ParentID, Is.EqualTo(0)); |
123 | Assert.That(m_sp.PhysicsActor, Is.Not.Null); | 130 | Assert.That(m_sp.PhysicsActor, Is.Not.Null); |
124 | } | 131 | } |
@@ -145,11 +152,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
145 | Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); | 152 | Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); |
146 | Assert.That(m_sp.PhysicsActor, Is.Null); | 153 | Assert.That(m_sp.PhysicsActor, Is.Null); |
147 | 154 | ||
155 | Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); | ||
156 | HashSet<UUID> sittingAvatars = part.GetSittingAvatars(); | ||
157 | Assert.That(sittingAvatars.Count, Is.EqualTo(1)); | ||
158 | Assert.That(sittingAvatars.Contains(m_sp.UUID)); | ||
159 | |||
148 | m_sp.StandUp(); | 160 | m_sp.StandUp(); |
149 | 161 | ||
150 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); | 162 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); |
151 | Assert.That(m_sp.ParentID, Is.EqualTo(0)); | 163 | Assert.That(m_sp.ParentID, Is.EqualTo(0)); |
152 | Assert.That(m_sp.PhysicsActor, Is.Not.Null); | 164 | Assert.That(m_sp.PhysicsActor, Is.Not.Null); |
165 | |||
166 | Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); | ||
167 | Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); | ||
168 | Assert.That(part.GetSittingAvatars(), Is.Null); | ||
153 | } | 169 | } |
154 | 170 | ||
155 | [Test] | 171 | [Test] |
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 0b9f875..600cafb 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs | |||
@@ -228,9 +228,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady | |||
228 | // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", | 228 | // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", |
229 | // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); | 229 | // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); |
230 | 230 | ||
231 | m_log.InfoFormat("[RegionReady]: Initialization complete - logins enabled for {0}", m_scene.RegionInfo.RegionName); | 231 | m_log.InfoFormat( |
232 | "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); | ||
232 | 233 | ||
233 | if ( m_uri != string.Empty ) | 234 | if (m_uri != string.Empty) |
234 | { | 235 | { |
235 | RRAlert("enabled"); | 236 | RRAlert("enabled"); |
236 | } | 237 | } |
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 4fcf40d..045661a 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs | |||
@@ -104,6 +104,45 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
104 | OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment"); | 104 | OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment"); |
105 | } | 105 | } |
106 | 106 | ||
107 | public bool Touch(UUID target) | ||
108 | { | ||
109 | SceneObjectPart part = m_scene.GetSceneObjectPart(target); | ||
110 | if (part == null) | ||
111 | return false; | ||
112 | bool objectTouchable = hasTouchEvents(part); // Only touch an object that is scripted to respond | ||
113 | if (!objectTouchable && !part.IsRoot) | ||
114 | objectTouchable = hasTouchEvents(part.ParentGroup.RootPart); | ||
115 | if (!objectTouchable) | ||
116 | return false; | ||
117 | // Set up the surface args as if the touch is from a client that does not support this | ||
118 | SurfaceTouchEventArgs surfaceArgs = new SurfaceTouchEventArgs(); | ||
119 | surfaceArgs.FaceIndex = -1; // TOUCH_INVALID_FACE | ||
120 | surfaceArgs.Binormal = Vector3.Zero; // TOUCH_INVALID_VECTOR | ||
121 | surfaceArgs.Normal = Vector3.Zero; // TOUCH_INVALID_VECTOR | ||
122 | surfaceArgs.STCoord = new Vector3(-1.0f, -1.0f, 0.0f); // TOUCH_INVALID_TEXCOORD | ||
123 | surfaceArgs.UVCoord = surfaceArgs.STCoord; // TOUCH_INVALID_TEXCOORD | ||
124 | List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>(); | ||
125 | touchArgs.Add(surfaceArgs); | ||
126 | Vector3 offset = part.OffsetPosition * -1.0f; | ||
127 | if (OnGrabObject == null) | ||
128 | return false; | ||
129 | OnGrabObject(part.LocalId, offset, this, touchArgs); | ||
130 | if (OnGrabUpdate != null) | ||
131 | OnGrabUpdate(part.UUID, offset, part.ParentGroup.RootPart.GroupPosition, this, touchArgs); | ||
132 | if (OnDeGrabObject != null) | ||
133 | OnDeGrabObject(part.LocalId, this, touchArgs); | ||
134 | return true; | ||
135 | } | ||
136 | |||
137 | private bool hasTouchEvents(SceneObjectPart part) | ||
138 | { | ||
139 | if ((part.ScriptEvents & scriptEvents.touch) != 0 || | ||
140 | (part.ScriptEvents & scriptEvents.touch_start) != 0 || | ||
141 | (part.ScriptEvents & scriptEvents.touch_end) != 0) | ||
142 | return true; | ||
143 | return false; | ||
144 | } | ||
145 | |||
107 | public void InstantMessage(UUID target, string message) | 146 | public void InstantMessage(UUID target, string message) |
108 | { | 147 | { |
109 | OnInstantMessage(this, new GridInstantMessage(m_scene, | 148 | OnInstantMessage(this, new GridInstantMessage(m_scene, |
@@ -153,6 +192,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
153 | 192 | ||
154 | private void SendOnChatFromClient(int channel, string message, ChatTypeEnum chatType) | 193 | private void SendOnChatFromClient(int channel, string message, ChatTypeEnum chatType) |
155 | { | 194 | { |
195 | if (channel == 0) | ||
196 | { | ||
197 | message = message.Trim(); | ||
198 | if (string.IsNullOrEmpty(message)) | ||
199 | { | ||
200 | return; | ||
201 | } | ||
202 | } | ||
156 | OSChatMessage chatFromClient = new OSChatMessage(); | 203 | OSChatMessage chatFromClient = new OSChatMessage(); |
157 | chatFromClient.Channel = channel; | 204 | chatFromClient.Channel = channel; |
158 | chatFromClient.From = Name; | 205 | chatFromClient.From = Name; |
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index a32ab2a..b37aba3 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs | |||
@@ -306,6 +306,16 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
306 | return false; | 306 | return false; |
307 | } | 307 | } |
308 | 308 | ||
309 | public bool Touch(UUID agentID, UUID objectID) | ||
310 | { | ||
311 | lock (m_avatars) | ||
312 | { | ||
313 | if (m_avatars.ContainsKey(agentID)) | ||
314 | return m_avatars[agentID].Touch(objectID); | ||
315 | return false; | ||
316 | } | ||
317 | } | ||
318 | |||
309 | public UUID GetOwner(UUID agentID) | 319 | public UUID GetOwner(UUID agentID) |
310 | { | 320 | { |
311 | lock (m_avatars) | 321 | lock (m_avatars) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index b08d5db..dc0c008 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -74,7 +74,7 @@ public class BSCharacter : PhysicsActor | |||
74 | private float _buoyancy; | 74 | private float _buoyancy; |
75 | 75 | ||
76 | private int _subscribedEventsMs = 0; | 76 | private int _subscribedEventsMs = 0; |
77 | private int _lastCollisionTime = 0; | 77 | private int _nextCollisionOkTime = 0; |
78 | 78 | ||
79 | private Vector3 _PIDTarget; | 79 | private Vector3 _PIDTarget; |
80 | private bool _usePID; | 80 | private bool _usePID; |
@@ -360,17 +360,22 @@ public class BSCharacter : PhysicsActor | |||
360 | } | 360 | } |
361 | //m_lastUpdateSent = false; | 361 | //m_lastUpdateSent = false; |
362 | } | 362 | } |
363 | |||
363 | public override void AddAngularForce(Vector3 force, bool pushforce) { | 364 | public override void AddAngularForce(Vector3 force, bool pushforce) { |
364 | } | 365 | } |
365 | public override void SetMomentum(Vector3 momentum) { | 366 | public override void SetMomentum(Vector3 momentum) { |
366 | } | 367 | } |
368 | |||
369 | // Turn on collision events at a rate no faster than one every the given milliseconds | ||
367 | public override void SubscribeEvents(int ms) { | 370 | public override void SubscribeEvents(int ms) { |
368 | _subscribedEventsMs = ms; | 371 | _subscribedEventsMs = ms; |
369 | _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen | 372 | _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen |
370 | } | 373 | } |
374 | // Stop collision events | ||
371 | public override void UnSubscribeEvents() { | 375 | public override void UnSubscribeEvents() { |
372 | _subscribedEventsMs = 0; | 376 | _subscribedEventsMs = 0; |
373 | } | 377 | } |
378 | // Return 'true' if someone has subscribed to events | ||
374 | public override bool SubscribedEvents() { | 379 | public override bool SubscribedEvents() { |
375 | return (_subscribedEventsMs > 0); | 380 | return (_subscribedEventsMs > 0); |
376 | } | 381 | } |
@@ -386,47 +391,57 @@ public class BSCharacter : PhysicsActor | |||
386 | _mass = _density * _avatarVolume; | 391 | _mass = _density * _avatarVolume; |
387 | } | 392 | } |
388 | 393 | ||
394 | // Set to 'true' if the individual changed items should be checked | ||
395 | // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties) | ||
396 | const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false; | ||
397 | |||
389 | // The physics engine says that properties have updated. Update same and inform | 398 | // The physics engine says that properties have updated. Update same and inform |
390 | // the world that things have changed. | 399 | // the world that things have changed. |
391 | public void UpdateProperties(EntityProperties entprop) | 400 | public void UpdateProperties(EntityProperties entprop) |
392 | { | 401 | { |
393 | bool changed = false; | 402 | bool changed = false; |
394 | // we assign to the local variables so the normal set action does not happen | 403 | if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) { |
395 | if (_position != entprop.Position) | 404 | // we assign to the local variables so the normal set action does not happen |
396 | { | 405 | if (_position != entprop.Position) { |
397 | _position = entprop.Position; | 406 | _position = entprop.Position; |
398 | changed = true; | 407 | changed = true; |
408 | } | ||
409 | if (_orientation != entprop.Rotation) { | ||
410 | _orientation = entprop.Rotation; | ||
411 | changed = true; | ||
412 | } | ||
413 | if (_velocity != entprop.Velocity) { | ||
414 | _velocity = entprop.Velocity; | ||
415 | changed = true; | ||
416 | } | ||
417 | if (_acceleration != entprop.Acceleration) { | ||
418 | _acceleration = entprop.Acceleration; | ||
419 | changed = true; | ||
420 | } | ||
421 | if (_rotationalVelocity != entprop.RotationalVelocity) { | ||
422 | _rotationalVelocity = entprop.RotationalVelocity; | ||
423 | changed = true; | ||
424 | } | ||
425 | if (changed) { | ||
426 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
427 | // Avatar movement is not done by generating this event. There is code in the heartbeat | ||
428 | // loop that updates avatars. | ||
429 | // base.RequestPhysicsterseUpdate(); | ||
430 | } | ||
399 | } | 431 | } |
400 | if (_orientation != entprop.Rotation) | 432 | else { |
401 | { | 433 | _position = entprop.Position; |
402 | _orientation = entprop.Rotation; | 434 | _orientation = entprop.Rotation; |
403 | changed = true; | ||
404 | } | ||
405 | if (_velocity != entprop.Velocity) | ||
406 | { | ||
407 | _velocity = entprop.Velocity; | 435 | _velocity = entprop.Velocity; |
408 | changed = true; | ||
409 | } | ||
410 | if (_acceleration != entprop.Acceleration) | ||
411 | { | ||
412 | _acceleration = entprop.Acceleration; | 436 | _acceleration = entprop.Acceleration; |
413 | changed = true; | ||
414 | } | ||
415 | if (_rotationalVelocity != entprop.RotationalVelocity) | ||
416 | { | ||
417 | _rotationalVelocity = entprop.RotationalVelocity; | 437 | _rotationalVelocity = entprop.RotationalVelocity; |
418 | changed = true; | ||
419 | } | ||
420 | if (changed) | ||
421 | { | ||
422 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
423 | // Avatar movement is not done by generating this event. There is a system that | ||
424 | // checks for avatar updates each heartbeat loop. | ||
425 | // base.RequestPhysicsterseUpdate(); | 438 | // base.RequestPhysicsterseUpdate(); |
426 | } | 439 | } |
427 | } | 440 | } |
428 | 441 | ||
429 | // Called by the scene when a collision with this object is reported | 442 | // Called by the scene when a collision with this object is reported |
443 | // The collision, if it should be reported to the character, is placed in a collection | ||
444 | // that will later be sent to the simulator when SendCollisions() is called. | ||
430 | CollisionEventUpdate collisionCollection = null; | 445 | CollisionEventUpdate collisionCollection = null; |
431 | public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) | 446 | public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) |
432 | { | 447 | { |
@@ -440,29 +455,34 @@ public class BSCharacter : PhysicsActor | |||
440 | } | 455 | } |
441 | 456 | ||
442 | // throttle collisions to the rate specified in the subscription | 457 | // throttle collisions to the rate specified in the subscription |
443 | if (_subscribedEventsMs == 0) return; // don't want collisions | 458 | if (_subscribedEventsMs != 0) { |
444 | int nowTime = _scene.SimulationNowTime; | 459 | int nowTime = _scene.SimulationNowTime; |
445 | if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; | 460 | if (nowTime >= _nextCollisionOkTime) { |
446 | _lastCollisionTime = nowTime; | 461 | _nextCollisionOkTime = nowTime + _subscribedEventsMs; |
447 | 462 | ||
448 | if (collisionCollection == null) | 463 | if (collisionCollection == null) |
449 | collisionCollection = new CollisionEventUpdate(); | 464 | collisionCollection = new CollisionEventUpdate(); |
450 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | 465 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); |
466 | } | ||
467 | } | ||
451 | } | 468 | } |
452 | 469 | ||
453 | public void SendCollisions() | 470 | public void SendCollisions() |
454 | { | 471 | { |
455 | // if (collisionCollection != null) | 472 | /* |
456 | // { | 473 | if (collisionCollection != null && collisionCollection.Count > 0) |
457 | // base.SendCollisionUpdate(collisionCollection); | 474 | { |
458 | // collisionCollection = null; | 475 | base.SendCollisionUpdate(collisionCollection); |
459 | // } | 476 | collisionCollection = null; |
477 | } | ||
478 | */ | ||
460 | // Kludge to make a collision call even if there are no collisions. | 479 | // Kludge to make a collision call even if there are no collisions. |
461 | // This causes the avatar animation to get updated. | 480 | // This causes the avatar animation to get updated. |
462 | if (collisionCollection == null) | 481 | if (collisionCollection == null) |
463 | collisionCollection = new CollisionEventUpdate(); | 482 | collisionCollection = new CollisionEventUpdate(); |
464 | base.SendCollisionUpdate(collisionCollection); | 483 | base.SendCollisionUpdate(collisionCollection); |
465 | collisionCollection = null; | 484 | collisionCollection.Clear(); |
485 | // End kludge | ||
466 | } | 486 | } |
467 | 487 | ||
468 | } | 488 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs index 0730824..0f027b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs | |||
@@ -32,6 +32,14 @@ using OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | /// <summary> | ||
36 | /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. | ||
37 | /// This module interfaces to an unmanaged C++ library which makes the | ||
38 | /// actual calls into the Bullet physics engine. | ||
39 | /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. | ||
40 | /// The unmanaged library is compiled and linked statically with Bullet | ||
41 | /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit). | ||
42 | /// </summary> | ||
35 | public class BSPlugin : IPhysicsPlugin | 43 | public class BSPlugin : IPhysicsPlugin |
36 | { | 44 | { |
37 | //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 45 | //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
@@ -53,6 +61,9 @@ public class BSPlugin : IPhysicsPlugin | |||
53 | { | 61 | { |
54 | if (Util.IsWindows()) | 62 | if (Util.IsWindows()) |
55 | Util.LoadArchSpecificWindowsDll("BulletSim.dll"); | 63 | Util.LoadArchSpecificWindowsDll("BulletSim.dll"); |
64 | // If not Windows, loading is performed by the | ||
65 | // Mono loader as specified in | ||
66 | // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". | ||
56 | 67 | ||
57 | _mScene = new BSScene(sceneIdentifier); | 68 | _mScene = new BSScene(sceneIdentifier); |
58 | } | 69 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 248d1f2..130f1ca 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -90,7 +90,7 @@ public sealed class BSPrim : PhysicsActor | |||
90 | private BSPrim _parentPrim; | 90 | private BSPrim _parentPrim; |
91 | 91 | ||
92 | private int _subscribedEventsMs = 0; | 92 | private int _subscribedEventsMs = 0; |
93 | private int _lastCollisionTime = 0; | 93 | private int _nextCollisionOkTime = 0; |
94 | long _collidingStep; | 94 | long _collidingStep; |
95 | long _collidingGroundStep; | 95 | long _collidingGroundStep; |
96 | 96 | ||
@@ -597,7 +597,8 @@ public sealed class BSPrim : PhysicsActor | |||
597 | } | 597 | } |
598 | public override void SubscribeEvents(int ms) { | 598 | public override void SubscribeEvents(int ms) { |
599 | _subscribedEventsMs = ms; | 599 | _subscribedEventsMs = ms; |
600 | _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen | 600 | // make sure first collision happens |
601 | _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; | ||
601 | } | 602 | } |
602 | public override void UnSubscribeEvents() { | 603 | public override void UnSubscribeEvents() { |
603 | _subscribedEventsMs = 0; | 604 | _subscribedEventsMs = 0; |
@@ -1338,23 +1339,27 @@ public sealed class BSPrim : PhysicsActor | |||
1338 | _collidingGroundStep = _scene.SimulationStep; | 1339 | _collidingGroundStep = _scene.SimulationStep; |
1339 | } | 1340 | } |
1340 | 1341 | ||
1341 | if (_subscribedEventsMs == 0) return; // nothing in the object is waiting for collision events | 1342 | // if someone is subscribed to collision events.... |
1342 | // throttle the collisions to the number of milliseconds specified in the subscription | 1343 | if (_subscribedEventsMs != 0) { |
1343 | int nowTime = _scene.SimulationNowTime; | 1344 | // throttle the collisions to the number of milliseconds specified in the subscription |
1344 | if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; | 1345 | int nowTime = _scene.SimulationNowTime; |
1345 | _lastCollisionTime = nowTime; | 1346 | if (nowTime >= _nextCollisionOkTime) { |
1347 | _nextCollisionOkTime = nowTime + _subscribedEventsMs; | ||
1346 | 1348 | ||
1347 | if (collisionCollection == null) | 1349 | if (collisionCollection == null) |
1348 | collisionCollection = new CollisionEventUpdate(); | 1350 | collisionCollection = new CollisionEventUpdate(); |
1349 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | 1351 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); |
1352 | } | ||
1353 | } | ||
1350 | } | 1354 | } |
1351 | 1355 | ||
1356 | // The scene is telling us it's time to pass our collected collisions into the simulator | ||
1352 | public void SendCollisions() | 1357 | public void SendCollisions() |
1353 | { | 1358 | { |
1354 | if (collisionCollection != null) | 1359 | if (collisionCollection != null && collisionCollection.Count > 0) |
1355 | { | 1360 | { |
1356 | base.SendCollisionUpdate(collisionCollection); | 1361 | base.SendCollisionUpdate(collisionCollection); |
1357 | collisionCollection = null; | 1362 | collisionCollection.Clear(); |
1358 | } | 1363 | } |
1359 | } | 1364 | } |
1360 | } | 1365 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 94a0ccf..417cb5f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -52,6 +52,7 @@ using OpenSim.Region.Framework; | |||
52 | // Should prim.link() and prim.delink() membership checking happen at taint time? | 52 | // Should prim.link() and prim.delink() membership checking happen at taint time? |
53 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once | 53 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once |
54 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect | 54 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect |
55 | // Use collision masks for collision with terrain and phantom objects | ||
55 | // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) | 56 | // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) |
56 | // Implement LockAngularMotion | 57 | // Implement LockAngularMotion |
57 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) | 58 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) |
@@ -62,9 +63,6 @@ using OpenSim.Region.Framework; | |||
62 | // Multiple contact points on collision? | 63 | // Multiple contact points on collision? |
63 | // See code in ode::near... calls to collision_accounting_events() | 64 | // See code in ode::near... calls to collision_accounting_events() |
64 | // (This might not be a problem. ODE collects all the collisions with one object in one tick.) | 65 | // (This might not be a problem. ODE collects all the collisions with one object in one tick.) |
65 | // Use collision masks for collision with terrain and phantom objects | ||
66 | // Figure out how to not allocate a new Dictionary and List for every collision | ||
67 | // in BSPrim.Collide() and BSCharacter.Collide(). Can the same ones be reused? | ||
68 | // Raycast | 66 | // Raycast |
69 | // | 67 | // |
70 | namespace OpenSim.Region.Physics.BulletSPlugin | 68 | namespace OpenSim.Region.Physics.BulletSPlugin |
@@ -405,6 +403,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
405 | // prevent simulation until we've been initialized | 403 | // prevent simulation until we've been initialized |
406 | if (!m_initialized) return 10.0f; | 404 | if (!m_initialized) return 10.0f; |
407 | 405 | ||
406 | long simulateStartTime = Util.EnvironmentTickCount(); | ||
407 | |||
408 | // update the prim states while we know the physics engine is not busy | 408 | // update the prim states while we know the physics engine is not busy |
409 | ProcessTaints(); | 409 | ProcessTaints(); |
410 | 410 | ||
@@ -437,13 +437,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
437 | } | 437 | } |
438 | } | 438 | } |
439 | 439 | ||
440 | // The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator. | 440 | // The above SendCollision's batch up the collisions on the objects. |
441 | // Now push the collisions into the simulator. | ||
441 | foreach (BSPrim bsp in m_primsWithCollisions) | 442 | foreach (BSPrim bsp in m_primsWithCollisions) |
442 | bsp.SendCollisions(); | 443 | bsp.SendCollisions(); |
443 | m_primsWithCollisions.Clear(); | 444 | m_primsWithCollisions.Clear(); |
445 | |||
446 | // This is a kludge to get avatar movement updated. | ||
447 | // Don't send collisions only if there were collisions -- send everytime. | ||
448 | // ODE sends collisions even if there are none and this is used to update | ||
449 | // avatar animations and stuff. | ||
444 | // foreach (BSCharacter bsc in m_avatarsWithCollisions) | 450 | // foreach (BSCharacter bsc in m_avatarsWithCollisions) |
445 | // bsc.SendCollisions(); | 451 | // bsc.SendCollisions(); |
446 | // This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any | ||
447 | foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) | 452 | foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) |
448 | kvp.Value.SendCollisions(); | 453 | kvp.Value.SendCollisions(); |
449 | m_avatarsWithCollisions.Clear(); | 454 | m_avatarsWithCollisions.Clear(); |
@@ -465,10 +470,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
465 | if (m_avatars.TryGetValue(entprop.ID, out actor)) | 470 | if (m_avatars.TryGetValue(entprop.ID, out actor)) |
466 | { | 471 | { |
467 | actor.UpdateProperties(entprop); | 472 | actor.UpdateProperties(entprop); |
473 | continue; | ||
468 | } | 474 | } |
469 | } | 475 | } |
470 | } | 476 | } |
471 | 477 | ||
478 | // If enabled, call into the physics engine to dump statistics | ||
472 | if (m_detailedStatsStep > 0) | 479 | if (m_detailedStatsStep > 0) |
473 | { | 480 | { |
474 | if ((m_simulationStep % m_detailedStatsStep) == 0) | 481 | if ((m_simulationStep % m_detailedStatsStep) == 0) |
@@ -477,6 +484,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
477 | } | 484 | } |
478 | } | 485 | } |
479 | 486 | ||
487 | // this is a waste since the outside routine also calcuates the physics simulation | ||
488 | // period. TODO: There should be a way of computing physics frames from simulator computation. | ||
489 | // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); | ||
490 | // return (timeStep * (float)simulateTotalTime); | ||
491 | |||
480 | // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. | 492 | // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. |
481 | return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; | 493 | return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; |
482 | } | 494 | } |
@@ -528,6 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
528 | public override void SetWaterLevel(float baseheight) | 540 | public override void SetWaterLevel(float baseheight) |
529 | { | 541 | { |
530 | m_waterLevel = baseheight; | 542 | m_waterLevel = baseheight; |
543 | // TODO: pass to physics engine so things will float? | ||
531 | } | 544 | } |
532 | public float GetWaterLevel() | 545 | public float GetWaterLevel() |
533 | { | 546 | { |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 77b659b..b639d36 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -2725,6 +2725,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2725 | } | 2725 | } |
2726 | } | 2726 | } |
2727 | 2727 | ||
2728 | public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num) | ||
2729 | { | ||
2730 | CheckThreatLevel(ThreatLevel.High, "osNpcTouch"); | ||
2731 | m_host.AddScriptLPS(1); | ||
2732 | INPCModule module = World.RequestModuleInterface<INPCModule>(); | ||
2733 | int linkNum = link_num.value; | ||
2734 | if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS)) | ||
2735 | { | ||
2736 | UUID npcId; | ||
2737 | if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID)) | ||
2738 | return; | ||
2739 | SceneObjectPart part = null; | ||
2740 | UUID objectId; | ||
2741 | if (UUID.TryParse(LSL_String.ToString(object_key), out objectId)) | ||
2742 | part = World.GetSceneObjectPart(objectId); | ||
2743 | if (part == null) | ||
2744 | return; | ||
2745 | if (linkNum != ScriptBaseClass.LINK_THIS) | ||
2746 | { | ||
2747 | if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT) | ||
2748 | { // 0 and 1 are treated as root, find the root if the current part isnt it | ||
2749 | if (!part.IsRoot) | ||
2750 | part = part.ParentGroup.RootPart; | ||
2751 | } | ||
2752 | else | ||
2753 | { // Find the prim with the given link number if not found then fail silently | ||
2754 | part = part.ParentGroup.GetLinkNumPart(linkNum); | ||
2755 | if (part == null) | ||
2756 | return; | ||
2757 | } | ||
2758 | } | ||
2759 | module.Touch(npcId, part.UUID); | ||
2760 | } | ||
2761 | } | ||
2762 | |||
2728 | /// <summary> | 2763 | /// <summary> |
2729 | /// Save the current appearance of the script owner permanently to the named notecard. | 2764 | /// Save the current appearance of the script owner permanently to the named notecard. |
2730 | /// </summary> | 2765 | /// </summary> |
@@ -3203,13 +3238,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3203 | { | 3238 | { |
3204 | CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory"); | 3239 | CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory"); |
3205 | 3240 | ||
3241 | m_host.AddScriptLPS(1); | ||
3242 | |||
3243 | ForceAttachToAvatarFromInventory(m_host.OwnerID, itemName, attachmentPoint); | ||
3244 | } | ||
3245 | |||
3246 | public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint) | ||
3247 | { | ||
3248 | CheckThreatLevel(ThreatLevel.Severe, "osForceAttachToOtherAvatarFromInventory"); | ||
3249 | |||
3250 | m_host.AddScriptLPS(1); | ||
3251 | |||
3252 | UUID avatarId; | ||
3253 | |||
3254 | if (!UUID.TryParse(rawAvatarId, out avatarId)) | ||
3255 | return; | ||
3256 | |||
3257 | ForceAttachToAvatarFromInventory(avatarId, itemName, attachmentPoint); | ||
3258 | } | ||
3259 | |||
3260 | public void ForceAttachToAvatarFromInventory(UUID avatarId, string itemName, int attachmentPoint) | ||
3261 | { | ||
3206 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; | 3262 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; |
3207 | 3263 | ||
3208 | if (attachmentsModule == null) | 3264 | if (attachmentsModule == null) |
3209 | return; | 3265 | return; |
3210 | 3266 | ||
3211 | m_host.AddScriptLPS(1); | ||
3212 | |||
3213 | InitLSL(); | 3267 | InitLSL(); |
3214 | 3268 | ||
3215 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); | 3269 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); |
@@ -3232,7 +3286,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3232 | return; | 3286 | return; |
3233 | } | 3287 | } |
3234 | 3288 | ||
3235 | ScenePresence sp = World.GetScenePresence(m_host.OwnerID); | 3289 | ScenePresence sp = World.GetScenePresence(avatarId); |
3236 | 3290 | ||
3237 | if (sp == null) | 3291 | if (sp == null) |
3238 | return; | 3292 | return; |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index a790cdc..1facc96 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | |||
@@ -101,19 +101,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
101 | // Attachment commands | 101 | // Attachment commands |
102 | 102 | ||
103 | /// <summary> | 103 | /// <summary> |
104 | /// Attach the object containing this script to the avatar that owns it without checking for PERMISSION_ATTACH | 104 | /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH |
105 | /// </summary> | 105 | /// </summary> |
106 | /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param> | 106 | /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param> |
107 | void osForceAttachToAvatar(int attachment); | 107 | void osForceAttachToAvatar(int attachment); |
108 | 108 | ||
109 | /// <summary> | 109 | /// <summary> |
110 | /// Attach the inventory item in the object containing this script to the avatar that owns it without checking for PERMISSION_ATTACH | 110 | /// Attach an inventory item in the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH |
111 | /// </summary> | 111 | /// </summary> |
112 | /// <remarks> | ||
113 | /// Nothing happens if the owner is not in the region. | ||
114 | /// </remarks> | ||
112 | /// <param name='itemName'>Tha name of the item. If this is not found then a warning is said to the owner</param> | 115 | /// <param name='itemName'>Tha name of the item. If this is not found then a warning is said to the owner</param> |
113 | /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param> | 116 | /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param> |
114 | void osForceAttachToAvatarFromInventory(string itemName, int attachment); | 117 | void osForceAttachToAvatarFromInventory(string itemName, int attachment); |
115 | 118 | ||
116 | /// <summary> | 119 | /// <summary> |
120 | /// Attach an inventory item in the object containing this script to any avatar in the region without asking for PERMISSION_ATTACH | ||
121 | /// </summary> | ||
122 | /// <remarks> | ||
123 | /// Nothing happens if the avatar is not in the region. | ||
124 | /// </remarks> | ||
125 | /// <param name='rawAvatarId'>The UUID of the avatar to which to attach. Nothing happens if this is not a UUID</para> | ||
126 | /// <param name='itemName'>The name of the item. If this is not found then a warning is said to the owner</param> | ||
127 | /// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param> | ||
128 | void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint); | ||
129 | |||
130 | /// <summary> | ||
117 | /// Detach the object containing this script from the avatar it is attached to without checking for PERMISSION_ATTACH | 131 | /// Detach the object containing this script from the avatar it is attached to without checking for PERMISSION_ATTACH |
118 | /// </summary> | 132 | /// </summary> |
119 | /// <remarks>Nothing happens if the object is not attached.</remarks> | 133 | /// <remarks>Nothing happens if the object is not attached.</remarks> |
@@ -231,6 +245,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
231 | void osNpcRemove(key npc); | 245 | void osNpcRemove(key npc); |
232 | void osNpcPlayAnimation(LSL_Key npc, string animation); | 246 | void osNpcPlayAnimation(LSL_Key npc, string animation); |
233 | void osNpcStopAnimation(LSL_Key npc, string animation); | 247 | void osNpcStopAnimation(LSL_Key npc, string animation); |
248 | void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num); | ||
234 | void osNpcWhisper(key npc, int channel, string message); | 249 | void osNpcWhisper(key npc, int channel, string message); |
235 | 250 | ||
236 | LSL_Key osOwnerSaveAppearance(string notecard); | 251 | LSL_Key osOwnerSaveAppearance(string notecard); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 500ed96..b40bdf0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | |||
@@ -301,6 +301,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
301 | m_OSSL_Functions.osForceAttachToAvatarFromInventory(itemName, attachmentPoint); | 301 | m_OSSL_Functions.osForceAttachToAvatarFromInventory(itemName, attachmentPoint); |
302 | } | 302 | } |
303 | 303 | ||
304 | public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint) | ||
305 | { | ||
306 | m_OSSL_Functions.osForceAttachToOtherAvatarFromInventory(rawAvatarId, itemName, attachmentPoint); | ||
307 | } | ||
308 | |||
304 | public void osForceDetachFromAvatar() | 309 | public void osForceDetachFromAvatar() |
305 | { | 310 | { |
306 | m_OSSL_Functions.osForceDetachFromAvatar(); | 311 | m_OSSL_Functions.osForceDetachFromAvatar(); |
@@ -626,6 +631,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
626 | m_OSSL_Functions.osNpcWhisper(npc, channel, message); | 631 | m_OSSL_Functions.osNpcWhisper(npc, channel, message); |
627 | } | 632 | } |
628 | 633 | ||
634 | public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num) | ||
635 | { | ||
636 | m_OSSL_Functions.osNpcTouch(npcLSL_Key, object_key, link_num); | ||
637 | } | ||
638 | |||
629 | public LSL_Key osOwnerSaveAppearance(string notecard) | 639 | public LSL_Key osOwnerSaveAppearance(string notecard) |
630 | { | 640 | { |
631 | return m_OSSL_Functions.osOwnerSaveAppearance(notecard); | 641 | return m_OSSL_Functions.osOwnerSaveAppearance(notecard); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index 3965734..c8718d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs | |||
@@ -79,7 +79,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
79 | /// Test creation of an NPC where the appearance data comes from a notecard | 79 | /// Test creation of an NPC where the appearance data comes from a notecard |
80 | /// </summary> | 80 | /// </summary> |
81 | [Test] | 81 | [Test] |
82 | public void TestOsNpcCreateFromNotecard() | 82 | public void TestOsNpcCreateUsingAppearanceFromNotecard() |
83 | { | 83 | { |
84 | TestHelpers.InMethod(); | 84 | TestHelpers.InMethod(); |
85 | // log4net.Config.XmlConfigurator.Configure(); | 85 | // log4net.Config.XmlConfigurator.Configure(); |
@@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
90 | 90 | ||
91 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | 91 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); |
92 | sp.Appearance.AvatarHeight = newHeight; | 92 | sp.Appearance.AvatarHeight = newHeight; |
93 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); | 93 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); |
94 | SceneObjectPart part = so.RootPart; | 94 | SceneObjectPart part = so.RootPart; |
95 | m_scene.AddSceneObject(so); | 95 | m_scene.AddSceneObject(so); |
96 | 96 | ||
@@ -114,10 +114,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
114 | /// Test creation of an NPC where the appearance data comes from an avatar already in the region. | 114 | /// Test creation of an NPC where the appearance data comes from an avatar already in the region. |
115 | /// </summary> | 115 | /// </summary> |
116 | [Test] | 116 | [Test] |
117 | public void TestOsNpcCreateFromAvatar() | 117 | public void TestOsNpcCreateUsingAppearanceFromAvatar() |
118 | { | 118 | { |
119 | TestHelpers.InMethod(); | 119 | TestHelpers.InMethod(); |
120 | // log4net.Config.XmlConfigurator.Configure(); | 120 | // TestHelpers.EnableLogging(); |
121 | 121 | ||
122 | // Store an avatar with a different height from default in a notecard. | 122 | // Store an avatar with a different height from default in a notecard. |
123 | UUID userId = TestHelpers.ParseTail(0x1); | 123 | UUID userId = TestHelpers.ParseTail(0x1); |
@@ -125,7 +125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
125 | 125 | ||
126 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | 126 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); |
127 | sp.Appearance.AvatarHeight = newHeight; | 127 | sp.Appearance.AvatarHeight = newHeight; |
128 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); | 128 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); |
129 | SceneObjectPart part = so.RootPart; | 129 | SceneObjectPart part = so.RootPart; |
130 | m_scene.AddSceneObject(so); | 130 | m_scene.AddSceneObject(so); |
131 | 131 | ||
@@ -156,7 +156,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
156 | 156 | ||
157 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | 157 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); |
158 | sp.Appearance.AvatarHeight = newHeight; | 158 | sp.Appearance.AvatarHeight = newHeight; |
159 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); | 159 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); |
160 | SceneObjectPart part = so.RootPart; | 160 | SceneObjectPart part = so.RootPart; |
161 | m_scene.AddSceneObject(so); | 161 | m_scene.AddSceneObject(so); |
162 | 162 | ||
@@ -197,7 +197,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
197 | 197 | ||
198 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId); | 198 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId); |
199 | sp.Appearance.AvatarHeight = newHeight; | 199 | sp.Appearance.AvatarHeight = newHeight; |
200 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId); | 200 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId, 0x10); |
201 | SceneObjectPart part = so.RootPart; | 201 | SceneObjectPart part = so.RootPart; |
202 | m_scene.AddSceneObject(so); | 202 | m_scene.AddSceneObject(so); |
203 | 203 | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs index 537b8aa..5ed1f3d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs | |||
@@ -158,7 +158,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
158 | { | 158 | { |
159 | osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint); | 159 | osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint); |
160 | } | 160 | } |
161 | catch (Exception e) | 161 | catch (Exception) |
162 | { | 162 | { |
163 | exceptionCaught = true; | 163 | exceptionCaught = true; |
164 | } | 164 | } |
@@ -174,5 +174,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
174 | List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments(); | 174 | List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments(); |
175 | Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0)); | 175 | Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0)); |
176 | } | 176 | } |
177 | |||
178 | [Test] | ||
179 | public void TestOsForceAttachToOtherAvatarFromInventory() | ||
180 | { | ||
181 | TestHelpers.InMethod(); | ||
182 | // TestHelpers.EnableLogging(); | ||
183 | |||
184 | string taskInvObjItemName = "sphere"; | ||
185 | UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); | ||
186 | AttachmentPoint attachPoint = AttachmentPoint.Chin; | ||
187 | |||
188 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "one", 0x1, "pass"); | ||
189 | UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "two", 0x2, "pass"); | ||
190 | |||
191 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1); | ||
192 | SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); | ||
193 | TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); | ||
194 | |||
195 | new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); | ||
196 | OSSL_Api osslApi = new OSSL_Api(); | ||
197 | osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); | ||
198 | |||
199 | // Create an object embedded inside the first | ||
200 | TaskInventoryHelpers.AddSceneObject(m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID); | ||
201 | |||
202 | ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2); | ||
203 | |||
204 | osslApi.osForceAttachToOtherAvatarFromInventory(sp2.UUID.ToString(), taskInvObjItemName, (int)attachPoint); | ||
205 | |||
206 | // Check scene presence status | ||
207 | Assert.That(sp.HasAttachments(), Is.False); | ||
208 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
209 | Assert.That(attachments.Count, Is.EqualTo(0)); | ||
210 | |||
211 | Assert.That(sp2.HasAttachments(), Is.True); | ||
212 | List<SceneObjectGroup> attachments2 = sp2.GetAttachments(); | ||
213 | Assert.That(attachments2.Count, Is.EqualTo(1)); | ||
214 | SceneObjectGroup attSo = attachments2[0]; | ||
215 | Assert.That(attSo.Name, Is.EqualTo(taskInvObjItemName)); | ||
216 | Assert.That(attSo.OwnerID, Is.EqualTo(ua2.PrincipalID)); | ||
217 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((uint)attachPoint)); | ||
218 | Assert.That(attSo.IsAttachment); | ||
219 | Assert.That(attSo.UsesPhysics, Is.False); | ||
220 | Assert.That(attSo.IsTemporary, Is.False); | ||
221 | |||
222 | // Check appearance status | ||
223 | List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments(); | ||
224 | Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0)); | ||
225 | |||
226 | List<AvatarAttachment> attachmentsInAppearance2 = sp2.Appearance.GetAttachments(); | ||
227 | Assert.That(attachmentsInAppearance2.Count, Is.EqualTo(1)); | ||
228 | Assert.That(sp2.Appearance.GetAttachpoint(attachmentsInAppearance2[0].ItemID), Is.EqualTo((uint)attachPoint)); | ||
229 | } | ||
177 | } | 230 | } |
178 | } \ No newline at end of file | 231 | } \ No newline at end of file |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index 813e53b..25679a6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs | |||
@@ -97,11 +97,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
97 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | 97 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); |
98 | sp.Appearance.AvatarHeight = newHeight; | 98 | sp.Appearance.AvatarHeight = newHeight; |
99 | 99 | ||
100 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); | 100 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); |
101 | SceneObjectPart part = so.RootPart; | 101 | SceneObjectPart part = so.RootPart; |
102 | m_scene.AddSceneObject(so); | 102 | m_scene.AddSceneObject(so); |
103 | 103 | ||
104 | SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId); | 104 | SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId, 0x20); |
105 | SceneObjectPart otherPart = otherSo.RootPart; | 105 | SceneObjectPart otherPart = otherSo.RootPart; |
106 | m_scene.AddSceneObject(otherSo); | 106 | m_scene.AddSceneObject(otherSo); |
107 | 107 | ||
@@ -148,7 +148,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
148 | 148 | ||
149 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); | 149 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); |
150 | sp.Appearance.AvatarHeight = newHeight; | 150 | sp.Appearance.AvatarHeight = newHeight; |
151 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); | 151 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); |
152 | SceneObjectPart part = so.RootPart; | 152 | SceneObjectPart part = so.RootPart; |
153 | m_scene.AddSceneObject(so); | 153 | m_scene.AddSceneObject(so); |
154 | 154 | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 7364b19..2886344 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -1662,7 +1662,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1662 | { | 1662 | { |
1663 | IScriptInstance instance = GetInstance(itemID); | 1663 | IScriptInstance instance = GetInstance(itemID); |
1664 | if (instance != null) | 1664 | if (instance != null) |
1665 | instance.Stop(0); | 1665 | { |
1666 | // Give the script some time to finish processing its last event. Simply aborting the script thread can | ||
1667 | // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. | ||
1668 | instance.Stop(1000); | ||
1669 | } | ||
1666 | } | 1670 | } |
1667 | 1671 | ||
1668 | public DetectParams GetDetectParams(UUID itemID, int idx) | 1672 | public DetectParams GetDetectParams(UUID itemID, int idx) |