diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 474609bb08..dbed8f65d7 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -1069,8 +1069,6 @@ namespace OpenSim.Data.Tests regionInfo.RegionLocX = 0; regionInfo.RegionLocY = 0; - Scene scene = new Scene(regionInfo); - SceneObjectPart sop = new SceneObjectPart(); sop.Name = name; sop.Description = name; @@ -1081,7 +1079,7 @@ namespace OpenSim.Data.Tests sop.Shape = PrimitiveBaseShape.Default; SceneObjectGroup sog = new SceneObjectGroup(sop); - sog.SetScene(scene); +// sog.SetScene(scene); return sog; } diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs index 2b3a719daf..8a74f538f7 100644 --- a/OpenSim/Framework/Watchdog.cs +++ b/OpenSim/Framework/Watchdog.cs @@ -101,12 +101,24 @@ namespace OpenSim.Framework private static Dictionary m_threads; private static System.Timers.Timer m_watchdogTimer; + /// + /// Last time the watchdog thread ran. + /// + /// + /// Should run every WATCHDOG_INTERVAL_MS + /// + public static int LastWatchdogThreadTick { get; private set; } + static Watchdog() { m_threads = new Dictionary(); m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); m_watchdogTimer.AutoReset = false; m_watchdogTimer.Elapsed += WatchdogTimerElapsed; + + // Set now so we don't get alerted on the first run + LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; + m_watchdogTimer.Start(); } @@ -264,6 +276,16 @@ namespace OpenSim.Framework /// private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { + int now = Environment.TickCount & Int32.MaxValue; + int msElapsed = now - LastWatchdogThreadTick; + + if (msElapsed > WATCHDOG_INTERVAL_MS * 2) + m_log.WarnFormat( + "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms", + msElapsed, WATCHDOG_INTERVAL_MS); + + LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; + Action callback = OnWatchdogTimeout; if (callback != null) @@ -272,8 +294,6 @@ namespace OpenSim.Framework lock (m_threads) { - int now = Environment.TickCount & Int32.MaxValue; - foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) { if (threadInfo.Thread.ThreadState == ThreadState.Stopped) diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index c1300380cf..ebfebc4443 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -92,9 +92,14 @@ namespace OpenSim m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); } - m_log.DebugFormat( + m_log.InfoFormat( "[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture); + string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU"); + + m_log.InfoFormat( + "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset"); + // Increase the number of IOCP threads available. Mono defaults to a tragically low number int workerThreads, iocpThreads; System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); @@ -109,7 +114,6 @@ namespace OpenSim // Check if the system is compatible with OpenSimulator. // Ensures that the minimum system requirements are met - m_log.Info("Performing compatibility checks... \n"); string supported = String.Empty; if (Util.IsEnvironmentSupported(ref supported)) { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index af30a8e68e..9eb0e383c0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -292,31 +292,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments group.AttachmentPoint = attachmentPt; group.AbsolutePosition = attachPos; - - // We also don't want to do any of the inventory operations for an NPC. + if (sp.PresenceType != PresenceType.Npc) - { - // Remove any previous attachments - List attachments = sp.GetAttachments(attachmentPt); - - // At the moment we can only deal with a single attachment - if (attachments.Count != 0) - { - if (attachments[0].FromItemID != UUID.Zero) - DetachSingleAttachmentToInvInternal(sp, attachments[0]); - else - m_log.WarnFormat( - "[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!", - attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); - } - - // Add the new attachment to inventory if we don't already have it. - UUID newAttachmentItemID = group.FromItemID; - if (newAttachmentItemID == UUID.Zero) - newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; - - ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); - } + UpdateUserInventoryWithAttachment(sp, group, attachmentPt); AttachToAgent(sp, group, attachmentPt, attachPos, silent); } @@ -324,6 +302,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return true; } + private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt) + { + // Remove any previous attachments + List attachments = sp.GetAttachments(attachmentPt); + + // At the moment we can only deal with a single attachment + if (attachments.Count != 0) + { + if (attachments[0].FromItemID != UUID.Zero) + DetachSingleAttachmentToInvInternal(sp, attachments[0]); + else + m_log.WarnFormat( + "[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!", + attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); + } + + // Add the new attachment to inventory if we don't already have it. + UUID newAttachmentItemID = group.FromItemID; + if (newAttachmentItemID == UUID.Zero) + newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; + + ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); + } + public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) { if (!Enabled) @@ -652,11 +654,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", // grp.Name, grp.LocalId, remoteClient.Name); - InventoryItemBase newItem = m_invAccessModule.CopyToInventory( - DeRezAction.TakeCopy, - m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID, - new List { grp }, - sp.ControllingClient, true)[0]; + InventoryItemBase newItem + = m_invAccessModule.CopyToInventory( + DeRezAction.TakeCopy, + m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID, + new List { grp }, + sp.ControllingClient, true)[0]; // sets itemID so client can show item as 'attached' in inventory grp.FromItemID = newItem.ID; @@ -782,7 +785,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments item = m_scene.InventoryService.GetItem(item); bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); if (changed && m_scene.AvatarFactory != null) + { +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()", +// sp.Name, att.Name, AttachmentPt); + m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); + } } #endregion diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 78569539c6..5dcbd28f59 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -149,6 +149,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); + Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); + // TestHelpers.DisableLogging(); } @@ -181,6 +183,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Check appearance status Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); + + Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); } [Test] @@ -239,6 +243,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Check item status Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); + + Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); } /// @@ -300,6 +306,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID)); Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID)); Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); + + Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); } [Test] @@ -399,6 +407,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name)); Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest)); + Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1)); + // Check attachments have been removed from sceneA ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID); @@ -410,6 +420,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // This is the actual attachment, which should no longer exist List actualSceneAAttachments = afterTeleportSceneASp.GetAttachments(); Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); + + Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); } // 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 dc6efed1e1..424e0ab384 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -79,7 +79,6 @@ \ \ - \ diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index c1c6b49705..724533b0cb 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 { if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout)) { - m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted region {0}", regionhandle); + m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle); m_blacklistedregions.Remove(regionhandle); } @@ -781,7 +781,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) { - m_log.DebugFormat("[WORLDMAP]: Unblock blacklisted URL {0}", httpserver); + m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver); m_blacklistedurls.Remove(httpserver); } @@ -1343,7 +1343,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (terrain == null) return; - m_log.DebugFormat("[WORLDMAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName); + m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName); byte[] data = terrain.WriteJpeg2000Image(); if (data == null) @@ -1365,7 +1365,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap asset.Flags = AssetFlags.Maptile; // Store the new one - m_log.DebugFormat("[WORLDMAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName); + m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName); m_scene.AssetService.Store(asset); diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs index 860483d461..d582149d57 100644 --- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs +++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs @@ -183,6 +183,14 @@ namespace OpenSim.Region.Framework.Interfaces /// true if the stand succeeded, false if not bool Stand(UUID agentID, Scene scene); + /// + /// Get the NPC to touch an object. + /// + /// + /// + /// true if the touch is actually attempted, false if not + bool Touch(UUID agentID, UUID partID); + /// /// Delete an NPC. /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 36d39eac79..ec911a52d4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2495,7 +2495,16 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.WarnFormat("[SCENE]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); + m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace); + return false; + } + + // If the user is banned, we won't let any of their objects + // enter. Period. + // + if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID)) + { + m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID); return false; } @@ -2504,14 +2513,28 @@ namespace OpenSim.Region.Framework.Scenes if (!AddSceneObject(newObject)) { - m_log.DebugFormat("[SCENE]: Problem adding scene object {0} in {1} ", sog.UUID, RegionInfo.RegionName); + m_log.DebugFormat( + "[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName); return false; } - // For attachments, we need to wait until the agent is root - // before we restart the scripts, or else some functions won't work. if (!newObject.IsAttachment) { + // FIXME: It would be better to never add the scene object at all rather than add it and then delete + // it + if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition)) + { + // Deny non attachments based on parcel settings + // + m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings"); + + DeleteSceneObject(newObject, false); + + return false; + } + + // For attachments, we need to wait until the agent is root + // before we restart the scripts, or else some functions won't work. newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); newObject.ResumeScripts(); } @@ -2531,18 +2554,6 @@ namespace OpenSim.Region.Framework.Scenes /// True if the SceneObjectGroup was added, False if it was not public bool AddSceneObject(SceneObjectGroup sceneObject) { - // If the user is banned, we won't let any of their objects - // enter. Period. - // - if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) - { - m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); - - return false; - } - - sceneObject.SetScene(this); - // Force allocation of new LocalId // SceneObjectPart[] parts = sceneObject.Parts; @@ -2587,18 +2598,6 @@ namespace OpenSim.Region.Framework.Scenes else { AddRestoredSceneObject(sceneObject, true, false); - - if (!Permissions.CanObjectEntry(sceneObject.UUID, - true, sceneObject.AbsolutePosition)) - { - // Deny non attachments based on parcel settings - // - m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings"); - - DeleteSceneObject(sceneObject, false); - - return false; - } } return true; @@ -4460,6 +4459,17 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGraph.ForEachScenePresence(action); } + /// + /// Get all the scene object groups. + /// + /// + /// The scene object groups. If the scene is empty then an empty list is returned. + /// + public List GetSceneObjectGroups() + { + return m_sceneGraph.GetSceneObjectGroups(); + } + /// /// Get a group via its UUID /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index a59758f5dc..2be5364a93 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -355,9 +355,9 @@ namespace OpenSim.Region.Framework.Scenes if (Entities.ContainsKey(sceneObject.UUID)) { -// m_log.DebugFormat( -// "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", -// m_parentScene.RegionInfo.RegionName, sceneObject.UUID); + m_log.DebugFormat( + "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", + m_parentScene.RegionInfo.RegionName, sceneObject.UUID); return false; } @@ -957,6 +957,18 @@ namespace OpenSim.Region.Framework.Scenes return result; } + /// + /// Get all the scene object groups. + /// + /// + /// The scene object groups. If the scene is empty then an empty list is returned. + /// + protected internal List GetSceneObjectGroups() + { + lock (SceneObjectGroupsByFullID) + return new List(SceneObjectGroupsByFullID.Values); + } + /// /// Get a group in the scene /// @@ -1100,11 +1112,7 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void ForEachSOG(Action action) { - List objlist; - lock (SceneObjectGroupsByFullID) - objlist = new List(SceneObjectGroupsByFullID.Values); - - foreach (SceneObjectGroup obj in objlist) + foreach (SceneObjectGroup obj in GetSceneObjectGroups()) { try { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 96cc3766be..4e0e183b5f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1055,16 +1055,6 @@ namespace OpenSim.Region.Framework.Scenes { return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); } - - /// - /// Added as a way for the storage provider to reset the scene, - /// most likely a better way to do this sort of thing but for now... - /// - /// - public void SetScene(Scene scene) - { - m_scene = scene; - } /// /// Set a part to act as the root part for this scene object diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 0b9f875e89..600cafb7c4 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 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); - m_log.InfoFormat("[RegionReady]: Initialization complete - logins enabled for {0}", m_scene.RegionInfo.RegionName); + m_log.InfoFormat( + "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); - if ( m_uri != string.Empty ) + if (m_uri != string.Empty) { RRAlert("enabled"); } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index b3e10698fd..9b3400da78 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 OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment"); } + public bool Touch(UUID target) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(target); + if (part == null) + return false; + bool objectTouchable = hasTouchEvents(part); // Only touch an object that is scripted to respond + if (!objectTouchable && !part.IsRoot) + objectTouchable = hasTouchEvents(part.ParentGroup.RootPart); + if (!objectTouchable) + return false; + // Set up the surface args as if the touch is from a client that does not support this + SurfaceTouchEventArgs surfaceArgs = new SurfaceTouchEventArgs(); + surfaceArgs.FaceIndex = -1; // TOUCH_INVALID_FACE + surfaceArgs.Binormal = Vector3.Zero; // TOUCH_INVALID_VECTOR + surfaceArgs.Normal = Vector3.Zero; // TOUCH_INVALID_VECTOR + surfaceArgs.STCoord = new Vector3(-1.0f, -1.0f, 0.0f); // TOUCH_INVALID_TEXCOORD + surfaceArgs.UVCoord = surfaceArgs.STCoord; // TOUCH_INVALID_TEXCOORD + List touchArgs = new List(); + touchArgs.Add(surfaceArgs); + Vector3 offset = part.OffsetPosition * -1.0f; + if (OnGrabObject == null) + return false; + OnGrabObject(part.LocalId, offset, this, touchArgs); + if (OnGrabUpdate != null) + OnGrabUpdate(part.UUID, offset, part.ParentGroup.RootPart.GroupPosition, this, touchArgs); + if (OnDeGrabObject != null) + OnDeGrabObject(part.LocalId, this, touchArgs); + return true; + } + + private bool hasTouchEvents(SceneObjectPart part) + { + if ((part.ScriptEvents & scriptEvents.touch) != 0 || + (part.ScriptEvents & scriptEvents.touch_start) != 0 || + (part.ScriptEvents & scriptEvents.touch_end) != 0) + return true; + return false; + } + public void InstantMessage(UUID target, string message) { OnInstantMessage(this, new GridInstantMessage(m_scene, @@ -153,6 +192,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC private void SendOnChatFromClient(int channel, string message, ChatTypeEnum chatType) { + if (channel == 0) + { + message = message.Trim(); + if (string.IsNullOrEmpty(message)) + { + return; + } + } OSChatMessage chatFromClient = new OSChatMessage(); chatFromClient.Channel = channel; chatFromClient.From = Name; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index d3456ab61a..1e85fb4089 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -305,6 +305,16 @@ namespace OpenSim.Region.OptionalModules.World.NPC return false; } + public bool Touch(UUID agentID, UUID objectID) + { + lock (m_avatars) + { + if (m_avatars.ContainsKey(agentID)) + return m_avatars[agentID].Touch(objectID); + return false; + } + } + public UUID GetOwner(UUID agentID) { lock (m_avatars) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index b08d5dba4d..dc0c0083f8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -74,7 +74,7 @@ public class BSCharacter : PhysicsActor private float _buoyancy; private int _subscribedEventsMs = 0; - private int _lastCollisionTime = 0; + private int _nextCollisionOkTime = 0; private Vector3 _PIDTarget; private bool _usePID; @@ -360,17 +360,22 @@ public class BSCharacter : PhysicsActor } //m_lastUpdateSent = false; } + public override void AddAngularForce(Vector3 force, bool pushforce) { } public override void SetMomentum(Vector3 momentum) { } + + // Turn on collision events at a rate no faster than one every the given milliseconds public override void SubscribeEvents(int ms) { _subscribedEventsMs = ms; - _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen + _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen } + // Stop collision events public override void UnSubscribeEvents() { _subscribedEventsMs = 0; } + // Return 'true' if someone has subscribed to events public override bool SubscribedEvents() { return (_subscribedEventsMs > 0); } @@ -386,47 +391,57 @@ public class BSCharacter : PhysicsActor _mass = _density * _avatarVolume; } + // Set to 'true' if the individual changed items should be checked + // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties) + const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false; + // The physics engine says that properties have updated. Update same and inform // the world that things have changed. public void UpdateProperties(EntityProperties entprop) { bool changed = false; - // we assign to the local variables so the normal set action does not happen - if (_position != entprop.Position) - { + if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) { + // we assign to the local variables so the normal set action does not happen + if (_position != entprop.Position) { + _position = entprop.Position; + changed = true; + } + if (_orientation != entprop.Rotation) { + _orientation = entprop.Rotation; + changed = true; + } + if (_velocity != entprop.Velocity) { + _velocity = entprop.Velocity; + changed = true; + } + if (_acceleration != entprop.Acceleration) { + _acceleration = entprop.Acceleration; + changed = true; + } + if (_rotationalVelocity != entprop.RotationalVelocity) { + _rotationalVelocity = entprop.RotationalVelocity; + changed = true; + } + if (changed) { + // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); + // Avatar movement is not done by generating this event. There is code in the heartbeat + // loop that updates avatars. + // base.RequestPhysicsterseUpdate(); + } + } + else { _position = entprop.Position; - changed = true; - } - if (_orientation != entprop.Rotation) - { _orientation = entprop.Rotation; - changed = true; - } - if (_velocity != entprop.Velocity) - { _velocity = entprop.Velocity; - changed = true; - } - if (_acceleration != entprop.Acceleration) - { _acceleration = entprop.Acceleration; - changed = true; - } - if (_rotationalVelocity != entprop.RotationalVelocity) - { _rotationalVelocity = entprop.RotationalVelocity; - changed = true; - } - if (changed) - { - // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); - // Avatar movement is not done by generating this event. There is a system that - // checks for avatar updates each heartbeat loop. // base.RequestPhysicsterseUpdate(); } } // Called by the scene when a collision with this object is reported + // The collision, if it should be reported to the character, is placed in a collection + // that will later be sent to the simulator when SendCollisions() is called. CollisionEventUpdate collisionCollection = null; public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) { @@ -440,29 +455,34 @@ public class BSCharacter : PhysicsActor } // throttle collisions to the rate specified in the subscription - if (_subscribedEventsMs == 0) return; // don't want collisions - int nowTime = _scene.SimulationNowTime; - if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; - _lastCollisionTime = nowTime; + if (_subscribedEventsMs != 0) { + int nowTime = _scene.SimulationNowTime; + if (nowTime >= _nextCollisionOkTime) { + _nextCollisionOkTime = nowTime + _subscribedEventsMs; - if (collisionCollection == null) - collisionCollection = new CollisionEventUpdate(); - collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + } + } } public void SendCollisions() { - // if (collisionCollection != null) - // { - // base.SendCollisionUpdate(collisionCollection); - // collisionCollection = null; - // } + /* + if (collisionCollection != null && collisionCollection.Count > 0) + { + base.SendCollisionUpdate(collisionCollection); + collisionCollection = null; + } + */ // Kludge to make a collision call even if there are no collisions. // This causes the avatar animation to get updated. if (collisionCollection == null) collisionCollection = new CollisionEventUpdate(); base.SendCollisionUpdate(collisionCollection); - collisionCollection = null; + collisionCollection.Clear(); + // End kludge } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs index 0730824ce1..0f027b8d6a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs @@ -32,6 +32,14 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { + /// + /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. + /// This module interfaces to an unmanaged C++ library which makes the + /// actual calls into the Bullet physics engine. + /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. + /// The unmanaged library is compiled and linked statically with Bullet + /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit). + /// public class BSPlugin : IPhysicsPlugin { //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -53,6 +61,9 @@ public class BSPlugin : IPhysicsPlugin { if (Util.IsWindows()) Util.LoadArchSpecificWindowsDll("BulletSim.dll"); + // If not Windows, loading is performed by the + // Mono loader as specified in + // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". _mScene = new BSScene(sceneIdentifier); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 248d1f2786..130f1ca145 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -90,7 +90,7 @@ public sealed class BSPrim : PhysicsActor private BSPrim _parentPrim; private int _subscribedEventsMs = 0; - private int _lastCollisionTime = 0; + private int _nextCollisionOkTime = 0; long _collidingStep; long _collidingGroundStep; @@ -597,7 +597,8 @@ public sealed class BSPrim : PhysicsActor } public override void SubscribeEvents(int ms) { _subscribedEventsMs = ms; - _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen + // make sure first collision happens + _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; } public override void UnSubscribeEvents() { _subscribedEventsMs = 0; @@ -1338,23 +1339,27 @@ public sealed class BSPrim : PhysicsActor _collidingGroundStep = _scene.SimulationStep; } - if (_subscribedEventsMs == 0) return; // nothing in the object is waiting for collision events - // throttle the collisions to the number of milliseconds specified in the subscription - int nowTime = _scene.SimulationNowTime; - if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; - _lastCollisionTime = nowTime; + // if someone is subscribed to collision events.... + if (_subscribedEventsMs != 0) { + // throttle the collisions to the number of milliseconds specified in the subscription + int nowTime = _scene.SimulationNowTime; + if (nowTime >= _nextCollisionOkTime) { + _nextCollisionOkTime = nowTime + _subscribedEventsMs; - if (collisionCollection == null) - collisionCollection = new CollisionEventUpdate(); - collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + } + } } + // The scene is telling us it's time to pass our collected collisions into the simulator public void SendCollisions() { - if (collisionCollection != null) + if (collisionCollection != null && collisionCollection.Count > 0) { base.SendCollisionUpdate(collisionCollection); - collisionCollection = null; + collisionCollection.Clear(); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 94a0ccf276..417cb5f3f0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -52,6 +52,7 @@ using OpenSim.Region.Framework; // Should prim.link() and prim.delink() membership checking happen at taint time? // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect +// Use collision masks for collision with terrain and phantom objects // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) // Implement LockAngularMotion // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) @@ -62,9 +63,6 @@ using OpenSim.Region.Framework; // Multiple contact points on collision? // See code in ode::near... calls to collision_accounting_events() // (This might not be a problem. ODE collects all the collisions with one object in one tick.) -// Use collision masks for collision with terrain and phantom objects -// Figure out how to not allocate a new Dictionary and List for every collision -// in BSPrim.Collide() and BSCharacter.Collide(). Can the same ones be reused? // Raycast // namespace OpenSim.Region.Physics.BulletSPlugin @@ -405,6 +403,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters // prevent simulation until we've been initialized if (!m_initialized) return 10.0f; + long simulateStartTime = Util.EnvironmentTickCount(); + // update the prim states while we know the physics engine is not busy ProcessTaints(); @@ -437,13 +437,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator. + // The above SendCollision's batch up the collisions on the objects. + // Now push the collisions into the simulator. foreach (BSPrim bsp in m_primsWithCollisions) bsp.SendCollisions(); m_primsWithCollisions.Clear(); + + // This is a kludge to get avatar movement updated. + // Don't send collisions only if there were collisions -- send everytime. + // ODE sends collisions even if there are none and this is used to update + // avatar animations and stuff. // foreach (BSCharacter bsc in m_avatarsWithCollisions) // bsc.SendCollisions(); - // This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any foreach (KeyValuePair kvp in m_avatars) kvp.Value.SendCollisions(); m_avatarsWithCollisions.Clear(); @@ -465,10 +470,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (m_avatars.TryGetValue(entprop.ID, out actor)) { actor.UpdateProperties(entprop); + continue; } } } + // If enabled, call into the physics engine to dump statistics if (m_detailedStatsStep > 0) { if ((m_simulationStep % m_detailedStatsStep) == 0) @@ -477,6 +484,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } + // this is a waste since the outside routine also calcuates the physics simulation + // period. TODO: There should be a way of computing physics frames from simulator computation. + // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); + // return (timeStep * (float)simulateTotalTime); + // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; } @@ -528,6 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void SetWaterLevel(float baseheight) { m_waterLevel = baseheight; + // TODO: pass to physics engine so things will float? } public float GetWaterLevel() { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index fa9364d809..61394afe91 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2125,7 +2125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osFormatString(string str, LSL_List strings) { - CheckThreatLevel(ThreatLevel.Low, "osFormatString"); + CheckThreatLevel(ThreatLevel.VeryLow, "osFormatString"); m_host.AddScriptLPS(1); return String.Format(str, strings.Data); @@ -2133,7 +2133,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List osMatchString(string src, string pattern, int start) { - CheckThreatLevel(ThreatLevel.High, "osMatchString"); + CheckThreatLevel(ThreatLevel.VeryLow, "osMatchString"); m_host.AddScriptLPS(1); LSL_List result = new LSL_List(); @@ -2175,7 +2175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osReplaceString(string src, string pattern, string replace, int count, int start) { - CheckThreatLevel(ThreatLevel.High, "osReplaceString"); + CheckThreatLevel(ThreatLevel.VeryLow, "osReplaceString"); m_host.AddScriptLPS(1); // Normalize indices (if negative). @@ -2677,6 +2677,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num) + { + CheckThreatLevel(ThreatLevel.High, "osNpcTouch"); + m_host.AddScriptLPS(1); + INPCModule module = World.RequestModuleInterface(); + int linkNum = link_num.value; + if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS)) + { + UUID npcId; + if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID)) + return; + SceneObjectPart part = null; + UUID objectId; + if (UUID.TryParse(LSL_String.ToString(object_key), out objectId)) + part = World.GetSceneObjectPart(objectId); + if (part == null) + return; + if (linkNum != ScriptBaseClass.LINK_THIS) + { + if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT) + { // 0 and 1 are treated as root, find the root if the current part isnt it + if (!part.IsRoot) + part = part.ParentGroup.RootPart; + } + else + { // Find the prim with the given link number if not found then fail silently + part = part.ParentGroup.GetLinkNumPart(linkNum); + if (part == null) + return; + } + } + module.Touch(npcId, part.UUID); + } + } + /// /// Save the current appearance of the script owner permanently to the named notecard. /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index a8335aac37..d38709e2b9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -231,6 +231,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osNpcRemove(key npc); void osNpcPlayAnimation(LSL_Key npc, string animation); void osNpcStopAnimation(LSL_Key npc, string animation); + void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num); void osNpcWhisper(key npc, int channel, string message); 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 500ed96685..692bb0a510 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -626,6 +626,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osNpcWhisper(npc, channel, message); } + public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num) + { + m_OSSL_Functions.osNpcTouch(npcLSL_Key, object_key, link_num); + } + public LSL_Key osOwnerSaveAppearance(string notecard) { 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 3965734435..c8718d9603 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 /// Test creation of an NPC where the appearance data comes from a notecard /// [Test] - public void TestOsNpcCreateFromNotecard() + public void TestOsNpcCreateUsingAppearanceFromNotecard() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); SceneObjectPart part = so.RootPart; m_scene.AddSceneObject(so); @@ -114,10 +114,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests /// Test creation of an NPC where the appearance data comes from an avatar already in the region. /// [Test] - public void TestOsNpcCreateFromAvatar() + public void TestOsNpcCreateUsingAppearanceFromAvatar() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); // Store an avatar with a different height from default in a notecard. UUID userId = TestHelpers.ParseTail(0x1); @@ -125,7 +125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); SceneObjectPart part = so.RootPart; m_scene.AddSceneObject(so); @@ -156,7 +156,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); SceneObjectPart part = so.RootPart; m_scene.AddSceneObject(so); @@ -197,7 +197,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId); sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId); + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId, 0x10); SceneObjectPart part = so.RootPart; m_scene.AddSceneObject(so); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs index 537b8aa0e5..78db2c6a48 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 { osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint); } - catch (Exception e) + catch (Exception) { exceptionCaught = true; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index 813e53b954..25679a65c0 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 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); SceneObjectPart part = so.RootPart; m_scene.AddSceneObject(so); - SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId); + SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId, 0x20); SceneObjectPart otherPart = otherSo.RootPart; m_scene.AddSceneObject(otherSo); @@ -148,7 +148,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); SceneObjectPart part = so.RootPart; m_scene.AddSceneObject(so); diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 9acba114da..495dc5297c 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -257,7 +257,9 @@ namespace OpenSim.Services.LLLoginService if (!am.Success) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is not allowed", clientVersion); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: client {2} is not allowed", + firstName, lastName, clientVersion); return LLFailedLoginResponse.LoginBlockedProblem; } } @@ -269,7 +271,9 @@ namespace OpenSim.Services.LLLoginService if (dm.Success) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is denied", clientVersion); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: client {2} is denied", + firstName, lastName, clientVersion); return LLFailedLoginResponse.LoginBlockedProblem; } } @@ -280,13 +284,16 @@ namespace OpenSim.Services.LLLoginService UserAccount account = m_UserAccountService.GetUserAccount(scopeID, firstName, lastName); if (account == null) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: user not found"); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user not found", firstName, lastName); return LLFailedLoginResponse.UserProblem; } if (account.UserLevel < m_MinLoginLevel) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: login is blocked for user level {0}", account.UserLevel); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}", + firstName, lastName, m_MinLoginLevel, account.UserLevel); return LLFailedLoginResponse.LoginBlockedProblem; } @@ -297,7 +304,8 @@ namespace OpenSim.Services.LLLoginService { if (account.ScopeID != scopeID && account.ScopeID != UUID.Zero) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: user not found"); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed, reason: user {0} {1} not found", firstName, lastName); return LLFailedLoginResponse.UserProblem; } } @@ -316,7 +324,9 @@ namespace OpenSim.Services.LLLoginService UUID secureSession = UUID.Zero; if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession))) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: authentication failed"); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: authentication failed", + firstName, lastName); return LLFailedLoginResponse.UserProblem; } @@ -325,13 +335,18 @@ namespace OpenSim.Services.LLLoginService // if (m_RequireInventory && m_InventoryService == null) { - m_log.WarnFormat("[LLOGIN SERVICE]: Login failed, reason: inventory service not set up"); + m_log.WarnFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: inventory service not set up", + firstName, lastName); return LLFailedLoginResponse.InventoryProblem; } + List inventorySkel = m_InventoryService.GetInventorySkeleton(account.PrincipalID); if (m_RequireInventory && ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0))) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: unable to retrieve user inventory"); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed, for {0} {1}, reason: unable to retrieve user inventory", + firstName, lastName); return LLFailedLoginResponse.InventoryProblem; } @@ -345,9 +360,12 @@ namespace OpenSim.Services.LLLoginService if (m_PresenceService != null) { success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession); + if (!success) { - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: could not login presence"); + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: could not login presence", + firstName, lastName); return LLFailedLoginResponse.GridProblem; } } @@ -380,9 +398,18 @@ namespace OpenSim.Services.LLLoginService if (destination == null) { m_PresenceService.LogoutAgent(session); - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: destination not found"); + + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: destination not found", + firstName, lastName); return LLFailedLoginResponse.GridProblem; } + else + { + m_log.DebugFormat( + "[LLOGIN SERVICE]: Found destination {0}, endpoint {1} for {2} {3}", + destination.RegionName, destination.ExternalEndPoint, firstName, lastName); + } if (account.UserLevel >= 200) flags |= TeleportFlags.Godlike; @@ -406,7 +433,7 @@ namespace OpenSim.Services.LLLoginService if (aCircuit == null) { m_PresenceService.LogoutAgent(session); - m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: {0}", reason); + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed for {0} {1}, reason: {2}", firstName, lastName, reason); return new LLFailedLoginResponse("key", reason, "false"); } @@ -427,7 +454,8 @@ namespace OpenSim.Services.LLLoginService where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, m_MapTileURL, m_ProfileURL, m_OpenIDURL, m_SearchURL, m_Currency, m_DSTZone); - m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to client."); + m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName); + return response; } catch (Exception e) @@ -446,7 +474,9 @@ namespace OpenSim.Services.LLLoginService { flags = TeleportFlags.ViaLogin; - m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation); + m_log.DebugFormat( + "[LLOGIN SERVICE]: Finding destination matching start location {0} for {1}", + startLocation, account.Name); gatekeeper = null; where = "home"; diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 3a2e42082e..d5354cbcac 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -601,19 +601,36 @@ namespace OpenSim.Tests.Common ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) { Name = name, UUID = id, Scale = new Vector3(1, 1, 1) }; } - + /// /// Create a scene object but do not add it to the scene. /// /// - /// UUID always starts at 00000000-0000-0000-0000-000000000001 + /// UUID always starts at 00000000-0000-0000-0000-000000000001. For some purposes, (e.g. serializing direct + /// to another object's inventory) we do not need a scene unique ID. So it would be better to add the + /// UUID when we actually add an object to a scene rather than on creation. /// /// The number of parts that should be in the scene object /// /// public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId) { - return CreateSceneObject(parts, ownerId, "", 0x1); + return CreateSceneObject(parts, ownerId, 0x1); + } + + /// + /// Create a scene object but do not add it to the scene. + /// + /// The number of parts that should be in the scene object + /// + /// + /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" + /// will be given to the root part, and incremented for each part thereafter. + /// + /// + public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, int uuidTail) + { + return CreateSceneObject(parts, ownerId, "", uuidTail); } /// diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 741877e7ab..c07e1abeea 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -673,8 +673,11 @@ ; AllowLightShareFunctions = false ;# {OSFunctionThreatLevel} {Enabled:true AllowOSFunctions:true} {OSFunction threat level? (DANGEROUS!)} {None VeryLow Low Moderate High VeryHigh Severe} VeryLow - ;; Threat level to allow, one of None, VeryLow, Low, Moderate, High, - ;; VeryHigh, Severe + ;; Threat level to allow, one of None, VeryLow, Low, Moderate, High, VeryHigh, Severe + ;; See http://opensimulator.org/wiki/Threat_level for more information on these levels. + ;; We do not recommend that use set a general level above Low unless you have a high level of trust + ;; in all the users that can run scripts in your simulator. It is safer to explicitly + ;; allow certain types of user to run higher threat level OSSL functions, as detailed later on. OSFunctionThreatLevel = VeryLow ; OS Functions enable/disable @@ -691,10 +694,10 @@ ; Allow_osSetRegionWaterHeight = 888760cb-a3cf-43ac-8ea4-8732fd3ee2bb ; Comma separated list of owner classes that allow the function for a particular class of owners. Choices are - ; - PARCEL_GROUP_MEMBER: allow if objectgroup is the same group as the parcel - ; - PARCEL_OWNER: allow if the objectowner is parcelowner - ; - ESTATE_MANAGER: allow if the object owner is a estate manager - ; - ESTATE_OWNER: allow if objectowner is estateowner + ; - PARCEL_GROUP_MEMBER: allow if the object group is the same group as the parcel + ; - PARCEL_OWNER: allow if the object owner is the parcel owner + ; - ESTATE_MANAGER: allow if the object owner is an estate manager + ; - ESTATE_OWNER: allow if the object owner is the estate owner ; Allow_osSetRegionWaterHeight = 888760cb-a3cf-43ac-8ea4-8732fd3ee2bb, PARCEL_OWNER, ESTATE_OWNER>, ... ; You can also use script creators as the uuid diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index 2c28063f4c..a3ccb98b88 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index f40f446213..0b286aa96e 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index d9e5e89874..d91dac159e 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 06770a4e69..891c956bc7 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ