Merge branch 'master' of /home/opensim/var/repo/opensim
						commit
						d3d9e3923c
					
				|  | @ -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; | ||||
|         } | ||||
|  |  | |||
|  | @ -101,12 +101,24 @@ namespace OpenSim.Framework | |||
|         private static Dictionary<int, ThreadWatchdogInfo> m_threads; | ||||
|         private static System.Timers.Timer m_watchdogTimer; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Last time the watchdog thread ran. | ||||
|         /// </summary> | ||||
|         /// <remarks> | ||||
|         /// Should run every WATCHDOG_INTERVAL_MS | ||||
|         /// </remarks> | ||||
|         public static int LastWatchdogThreadTick { get; private set; } | ||||
| 
 | ||||
|         static Watchdog() | ||||
|         { | ||||
|             m_threads = new Dictionary<int, ThreadWatchdogInfo>(); | ||||
|             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 | |||
|         /// <param name="e"></param> | ||||
|         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<ThreadWatchdogInfo> 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) | ||||
|  |  | |||
|  | @ -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)) | ||||
|             { | ||||
|  |  | |||
|  | @ -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<SceneObjectGroup> 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<SceneObjectGroup> 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<SceneObjectGroup> { grp }, | ||||
|                 sp.ControllingClient, true)[0]; | ||||
|             InventoryItemBase newItem | ||||
|                 = m_invAccessModule.CopyToInventory( | ||||
|                     DeRezAction.TakeCopy, | ||||
|                     m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID, | ||||
|                     new List<SceneObjectGroup> { 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 | ||||
|  |  | |||
|  | @ -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)); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -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<SceneObjectGroup> 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  | ||||
|  |  | |||
|  | @ -79,7 +79,6 @@ | |||
|         <RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" /> | ||||
|         <RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" />    \ | ||||
|         <RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" />    \ | ||||
|         <RegionModule id="Warp3DImageModule" type="OpenSim.Region.CoreModules.World.Warp3DMap.Warp3DImageModule" />    \ | ||||
| 
 | ||||
|     </Extension> | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -183,6 +183,14 @@ namespace OpenSim.Region.Framework.Interfaces | |||
|         /// <returns>true if the stand succeeded, false if not</returns> | ||||
|         bool Stand(UUID agentID, Scene scene); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Get the NPC to touch an object. | ||||
|         /// </summary> | ||||
|         /// <param name="agentID"></param> | ||||
|         /// <param name="partID"></param> | ||||
|         /// <returns>true if the touch is actually attempted, false if not</returns> | ||||
|         bool Touch(UUID agentID, UUID partID); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Delete an NPC. | ||||
|         /// </summary> | ||||
|  |  | |||
|  | @ -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 | |||
|         /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> | ||||
|         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); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Get all the scene object groups. | ||||
|         /// </summary> | ||||
|         /// <returns> | ||||
|         /// The scene object groups.  If the scene is empty then an empty list is returned. | ||||
|         /// </returns> | ||||
|         public List<SceneObjectGroup> GetSceneObjectGroups() | ||||
|         { | ||||
|             return m_sceneGraph.GetSceneObjectGroups(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Get a group via its UUID | ||||
|         /// </summary> | ||||
|  |  | |||
|  | @ -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; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Get all the scene object groups. | ||||
|         /// </summary> | ||||
|         /// <returns> | ||||
|         /// The scene object groups.  If the scene is empty then an empty list is returned. | ||||
|         /// </returns> | ||||
|         protected internal List<SceneObjectGroup> GetSceneObjectGroups() | ||||
|         { | ||||
|             lock (SceneObjectGroupsByFullID) | ||||
|                 return new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Get a group in the scene | ||||
|         /// </summary> | ||||
|  | @ -1100,11 +1112,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         /// <param name="action"></param> | ||||
|         protected internal void ForEachSOG(Action<SceneObjectGroup> action) | ||||
|         { | ||||
|             List<SceneObjectGroup> objlist; | ||||
|             lock (SceneObjectGroupsByFullID) | ||||
|                 objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); | ||||
| 
 | ||||
|             foreach (SceneObjectGroup obj in objlist) | ||||
|             foreach (SceneObjectGroup obj in GetSceneObjectGroups()) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|  |  | |||
|  | @ -1055,16 +1055,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         { | ||||
|             return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 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... | ||||
|         /// </summary> | ||||
|         /// <param name="scene"></param> | ||||
|         public void SetScene(Scene scene) | ||||
|         { | ||||
|             m_scene = scene; | ||||
|         } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Set a part to act as the root part for this scene object | ||||
|  |  | |||
|  | @ -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"); | ||||
|                     } | ||||
|  |  | |||
|  | @ -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<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>(); | ||||
|             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; | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -32,6 +32,14 @@ using OpenMetaverse; | |||
| 
 | ||||
| namespace OpenSim.Region.Physics.BulletSPlugin | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 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). | ||||
|     /// </summary> | ||||
| 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); | ||||
|         } | ||||
|  |  | |||
|  | @ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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<uint, BSCharacter> 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() | ||||
|     { | ||||
|  |  | |||
|  | @ -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<INPCModule>(); | ||||
|             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); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Save the current appearance of the script owner permanently to the named notecard. | ||||
|         /// </summary> | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -79,7 +79,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
|         /// Test creation of an NPC where the appearance data comes from a notecard | ||||
|         /// </summary> | ||||
|         [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. | ||||
|         /// </summary> | ||||
|         [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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -158,7 +158,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests | |||
|             { | ||||
|                 osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             catch (Exception) | ||||
|             { | ||||
|                 exceptionCaught = true; | ||||
|             } | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<InventoryFolderBase> 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"; | ||||
|  |  | |||
|  | @ -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) };             | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Create a scene object but do not add it to the scene. | ||||
|         /// </summary> | ||||
|         /// <remarks> | ||||
|         /// 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. | ||||
|         /// </remarks> | ||||
|         /// <param name="parts">The number of parts that should be in the scene object</param> | ||||
|         /// <param name="ownerId"></param> | ||||
|         /// <returns></returns> | ||||
|         public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId) | ||||
|         {             | ||||
|             return CreateSceneObject(parts, ownerId, "", 0x1); | ||||
|             return CreateSceneObject(parts, ownerId, 0x1); | ||||
|         } | ||||
|          | ||||
|         /// <summary> | ||||
|         /// Create a scene object but do not add it to the scene. | ||||
|         /// </summary> | ||||
|         /// <param name="parts">The number of parts that should be in the scene object</param> | ||||
|         /// <param name="ownerId"></param> | ||||
|         /// <param name="uuidTail"> | ||||
|         /// 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. | ||||
|         /// </param> | ||||
|         /// <returns></returns> | ||||
|         public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, int uuidTail) | ||||
|         {             | ||||
|             return CreateSceneObject(parts, ownerId, "", uuidTail); | ||||
|         }           | ||||
|          | ||||
|         /// <summary> | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	 BlueWall
						BlueWall