aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/IScene.cs13
-rw-r--r--OpenSim/Framework/Monitoring/AssetStatsCollector.cs (renamed from OpenSim/Framework/Statistics/AssetStatsCollector.cs)2
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs (renamed from OpenSim/Framework/Statistics/BaseStatsCollector.cs)3
-rw-r--r--OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs (renamed from OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs)2
-rw-r--r--OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs (renamed from OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs)2
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs129
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs (renamed from OpenSim/Framework/Statistics/SimExtraStatsCollector.cs)5
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs (renamed from OpenSim/Framework/Statistics/StatsManager.cs)2
-rw-r--r--OpenSim/Framework/Monitoring/UserStatsCollector.cs (renamed from OpenSim/Framework/Statistics/UserStatsCollector.cs)2
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs (renamed from OpenSim/Framework/Watchdog.cs)5
-rw-r--r--OpenSim/Framework/RegionInfo.cs26
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs1
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs1
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs1
-rw-r--r--OpenSim/Region/Application/OpenSim.cs76
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs38
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs61
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs31
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs51
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs20
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs2
-rwxr-xr-xOpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs161
-rw-r--r--OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/World/Access/AccessModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScenePresence.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs69
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs27
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs302
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs73
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs2
-rwxr-xr-xOpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs130
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs69
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs115
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs178
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs187
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs308
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs588
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs796
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs219
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs15
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs30
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs16
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs44
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs23
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs34
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs14
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs22
-rw-r--r--OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs2
-rw-r--r--OpenSim/Region/UserStatistics/Default_Report.cs2
-rw-r--r--OpenSim/Region/UserStatistics/LogLinesAJAX.cs2
-rw-r--r--OpenSim/Region/UserStatistics/SimStatsAJAX.cs2
-rw-r--r--OpenSim/Tests/Common/Helpers/SceneHelpers.cs2
-rw-r--r--OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs22
86 files changed, 3110 insertions, 1220 deletions
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs
index a9432c2..87ec99e 100644
--- a/OpenSim/Framework/IScene.cs
+++ b/OpenSim/Framework/IScene.cs
@@ -66,6 +66,19 @@ namespace OpenSim.Framework
66 66
67 IConfigSource Config { get; } 67 IConfigSource Config { get; }
68 68
69 /// <summary>
70 /// Are logins enabled on this simulator?
71 /// </summary>
72 bool LoginsEnabled { get; set; }
73
74 /// <summary>
75 /// Is this region ready for use?
76 /// </summary>
77 /// <remarks>
78 /// This does not mean that logins are enabled, merely that they can be.
79 /// </remarks>
80 bool Ready { get; set; }
81
69 float TimeDilation { get; } 82 float TimeDilation { get; }
70 83
71 bool AllowScriptCrossings { get; } 84 bool AllowScriptCrossings { get; }
diff --git a/OpenSim/Framework/Statistics/AssetStatsCollector.cs b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
index 7082ef3..2a4d45b 100644
--- a/OpenSim/Framework/Statistics/AssetStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Timers; 29using System.Timers;
30 30
31namespace OpenSim.Framework.Statistics 31namespace OpenSim.Framework.Monitoring
32{ 32{
33 /// <summary> 33 /// <summary>
34 /// Asset service statistics collection 34 /// Asset service statistics collection
diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 3f918f3..9ee0876 100644
--- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -31,8 +31,7 @@ using System.Text;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
33 33
34 34namespace OpenSim.Framework.Monitoring
35namespace OpenSim.Framework.Statistics
36{ 35{
37 /// <summary> 36 /// <summary>
38 /// Statistics which all collectors are interested in reporting 37 /// Statistics which all collectors are interested in reporting
diff --git a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs
index 430e580..86a6620 100644
--- a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs
+++ b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs
@@ -25,7 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28namespace OpenSim.Framework.Statistics.Interfaces 28namespace OpenSim.Framework.Monitoring.Interfaces
29{ 29{
30 /// <summary> 30 /// <summary>
31 /// Implemented by objects which allow statistical information to be pulled from them. 31 /// Implemented by objects which allow statistical information to be pulled from them.
diff --git a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
index 477bbb3..99f75e3 100644
--- a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
@@ -25,7 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28namespace OpenSim.Framework.Statistics 28namespace OpenSim.Framework.Monitoring
29{ 29{
30 /// <summary> 30 /// <summary>
31 /// Implemented by classes which collect up non-viewer statistical information 31 /// Implemented by classes which collect up non-viewer statistical information
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
new file mode 100644
index 0000000..a23cf1f
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -0,0 +1,129 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Threading;
33using log4net;
34
35namespace OpenSim.Framework.Monitoring
36{
37 /// <summary>
38 /// Experimental watchdog for memory usage.
39 /// </summary>
40 public static class MemoryWatchdog
41 {
42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 /// <summary>
45 /// Is this watchdog active?
46 /// </summary>
47 public static bool Enabled
48 {
49 get { return m_enabled; }
50 set
51 {
52// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value);
53
54 if (value && !m_enabled)
55 UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount());
56
57 m_enabled = value;
58 }
59 }
60 private static bool m_enabled;
61
62 /// <summary>
63 /// Average memory churn in bytes per millisecond.
64 /// </summary>
65 public static double AverageMemoryChurn
66 {
67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
68 }
69
70 /// <summary>
71 /// Maximum number of statistical samples.
72 /// </summary>
73 /// <remarks>
74 /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from
75 /// the main Watchdog.
76 /// </remarks>
77 private static int m_maxSamples = 24;
78
79 /// <summary>
80 /// Time when the watchdog was last updated.
81 /// </summary>
82 private static int m_lastUpdateTick;
83
84 /// <summary>
85 /// Memory used at time of last watchdog update.
86 /// </summary>
87 private static long m_lastUpdateMemory;
88
89 /// <summary>
90 /// Memory churn rate per millisecond.
91 /// </summary>
92// private static double m_churnRatePerMillisecond;
93
94 /// <summary>
95 /// Historical samples for calculating moving average.
96 /// </summary>
97 private static Queue<double> m_samples = new Queue<double>(m_maxSamples);
98
99 public static void Update()
100 {
101 int now = Util.EnvironmentTickCount();
102 long memoryNow = GC.GetTotalMemory(false);
103 long memoryDiff = memoryNow - m_lastUpdateMemory;
104
105 if (memoryDiff >= 0)
106 {
107 if (m_samples.Count >= m_maxSamples)
108 m_samples.Dequeue();
109
110 double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick);
111
112 // This should never happen since it's not useful for updates to occur with no time elapsed, but
113 // protect ourselves from a divide-by-zero just in case.
114 if (elapsed == 0)
115 return;
116
117 m_samples.Enqueue(memoryDiff / (double)elapsed);
118 }
119
120 UpdateLastRecord(memoryNow, now);
121 }
122
123 private static void UpdateLastRecord(long memoryNow, int timeNow)
124 {
125 m_lastUpdateMemory = memoryNow;
126 m_lastUpdateTick = timeNow;
127 }
128 }
129} \ No newline at end of file
diff --git a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index a506e3b..cdd7cc7 100644
--- a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -28,12 +28,11 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31
32using OpenMetaverse; 31using OpenMetaverse;
33using OpenSim.Framework.Statistics.Interfaces;
34using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
33using OpenSim.Framework.Monitoring.Interfaces;
35 34
36namespace OpenSim.Framework.Statistics 35namespace OpenSim.Framework.Monitoring
37{ 36{
38 /// <summary> 37 /// <summary>
39 /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane 38 /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane
diff --git a/OpenSim/Framework/Statistics/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 436ce2f..d78fa6a 100644
--- a/OpenSim/Framework/Statistics/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -25,7 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28namespace OpenSim.Framework.Statistics 28namespace OpenSim.Framework.Monitoring
29{ 29{
30 /// <summary> 30 /// <summary>
31 /// Singleton used to provide access to statistics reporters 31 /// Singleton used to provide access to statistics reporters
diff --git a/OpenSim/Framework/Statistics/UserStatsCollector.cs b/OpenSim/Framework/Monitoring/UserStatsCollector.cs
index fd2a9bf..e89c8e6 100644
--- a/OpenSim/Framework/Statistics/UserStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/UserStatsCollector.cs
@@ -27,7 +27,7 @@
27 27
28using System.Timers; 28using System.Timers;
29 29
30namespace OpenSim.Framework.Statistics 30namespace OpenSim.Framework.Monitoring
31{ 31{
32 /// <summary> 32 /// <summary>
33 /// Collects user service statistics 33 /// Collects user service statistics
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 449d014..e4db964 100644
--- a/OpenSim/Framework/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -31,7 +31,7 @@ using System.Linq;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33 33
34namespace OpenSim.Framework 34namespace OpenSim.Framework.Monitoring
35{ 35{
36 /// <summary> 36 /// <summary>
37 /// Manages launching threads and keeping watch over them for timeouts 37 /// Manages launching threads and keeping watch over them for timeouts
@@ -325,6 +325,9 @@ namespace OpenSim.Framework
325 callback(callbackInfo); 325 callback(callbackInfo);
326 } 326 }
327 327
328 if (MemoryWatchdog.Enabled)
329 MemoryWatchdog.Update();
330
328 m_watchdogTimer.Start(); 331 m_watchdogTimer.Start();
329 } 332 }
330 } 333 }
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 1b2f681..4bde7be 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -482,9 +482,16 @@ namespace OpenSim.Framework
482 MainConsole.Instance.Output("=====================================\n"); 482 MainConsole.Instance.Output("=====================================\n");
483 483
484 if (name == String.Empty) 484 if (name == String.Empty)
485 name = MainConsole.Instance.CmdPrompt("New region name", name); 485 {
486 if (name == String.Empty) 486 while (name.Trim() == string.Empty)
487 throw new Exception("Cannot interactively create region with no name"); 487 {
488 name = MainConsole.Instance.CmdPrompt("New region name", name);
489 if (name.Trim() == string.Empty)
490 {
491 MainConsole.Instance.Output("Cannot interactively create region with no name");
492 }
493 }
494 }
488 495
489 source.AddConfig(name); 496 source.AddConfig(name);
490 497
@@ -515,15 +522,20 @@ namespace OpenSim.Framework
515 // 522 //
516 allKeys.Remove("RegionUUID"); 523 allKeys.Remove("RegionUUID");
517 string regionUUID = config.GetString("RegionUUID", string.Empty); 524 string regionUUID = config.GetString("RegionUUID", string.Empty);
518 if (regionUUID == String.Empty) 525 if (!UUID.TryParse(regionUUID.Trim(), out RegionID))
519 { 526 {
520 UUID newID = UUID.Random(); 527 UUID newID = UUID.Random();
521 528 while (RegionID == UUID.Zero)
522 regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); 529 {
530 regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString());
531 if (!UUID.TryParse(regionUUID.Trim(), out RegionID))
532 {
533 MainConsole.Instance.Output("RegionUUID must be a valid UUID");
534 }
535 }
523 config.Set("RegionUUID", regionUUID); 536 config.Set("RegionUUID", regionUUID);
524 } 537 }
525 538
526 RegionID = new UUID(regionUUID);
527 originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?) 539 originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?)
528 540
529 // Location 541 // Location
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 9a2cd0e..cf19002 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -40,9 +40,9 @@ using log4net.Core;
40using log4net.Repository; 40using log4net.Repository;
41using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
43using OpenSim.Framework.Monitoring;
43using OpenSim.Framework.Servers; 44using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer; 45using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Framework.Statistics;
46using Timer=System.Timers.Timer; 46using Timer=System.Timers.Timer;
47 47
48using OpenMetaverse; 48using OpenMetaverse;
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 24f986a..e45cb89 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -45,6 +45,7 @@ using OpenMetaverse.StructuredData;
45using CoolHTTPListener = HttpServer.HttpListener; 45using CoolHTTPListener = HttpServer.HttpListener;
46using HttpListener=System.Net.HttpListener; 46using HttpListener=System.Net.HttpListener;
47using LogPrio=HttpServer.LogPrio; 47using LogPrio=HttpServer.LogPrio;
48using OpenSim.Framework.Monitoring;
48 49
49namespace OpenSim.Framework.Servers.HttpServer 50namespace OpenSim.Framework.Servers.HttpServer
50{ 51{
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index a3bd330..a385110 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using log4net; 32using log4net;
33using HttpServer; 33using HttpServer;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Monitoring;
35 36
36 37
37/* 38/*
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
index 1e3fbf0..1c529b6 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs
@@ -36,6 +36,7 @@ using HttpServer;
36using OpenMetaverse; 36using OpenMetaverse;
37using System.Reflection; 37using System.Reflection;
38using log4net; 38using log4net;
39using OpenSim.Framework.Monitoring;
39 40
40namespace OpenSim.Framework.Servers.HttpServer 41namespace OpenSim.Framework.Servers.HttpServer
41{ 42{
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index e6b57c2..ba8aa9f 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -40,7 +40,7 @@ using OpenMetaverse;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
42using OpenSim.Framework.Servers; 42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Statistics; 43using OpenSim.Framework.Monitoring;
44using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
46 46
@@ -200,9 +200,9 @@ namespace OpenSim
200 PrintFileToConsole("startuplogo.txt"); 200 PrintFileToConsole("startuplogo.txt");
201 201
202 // For now, start at the 'root' level by default 202 // For now, start at the 'root' level by default
203 if (m_sceneManager.Scenes.Count == 1) // If there is only one region, select it 203 if (SceneManager.Scenes.Count == 1) // If there is only one region, select it
204 ChangeSelectedRegion("region", 204 ChangeSelectedRegion("region",
205 new string[] {"change", "region", m_sceneManager.Scenes[0].RegionInfo.RegionName}); 205 new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName});
206 else 206 else
207 ChangeSelectedRegion("region", new string[] {"change", "region", "root"}); 207 ChangeSelectedRegion("region", new string[] {"change", "region", "root"});
208 208
@@ -461,7 +461,7 @@ namespace OpenSim
461 if (cmdparams.Length > 4) 461 if (cmdparams.Length > 4)
462 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); 462 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
463 463
464 IList agents = m_sceneManager.GetCurrentSceneAvatars(); 464 IList agents = SceneManager.GetCurrentSceneAvatars();
465 465
466 foreach (ScenePresence presence in agents) 466 foreach (ScenePresence presence in agents)
467 { 467 {
@@ -542,7 +542,7 @@ namespace OpenSim
542 private void HandleForceUpdate(string module, string[] args) 542 private void HandleForceUpdate(string module, string[] args)
543 { 543 {
544 MainConsole.Instance.Output("Updating all clients"); 544 MainConsole.Instance.Output("Updating all clients");
545 m_sceneManager.ForceCurrentSceneClientUpdate(); 545 SceneManager.ForceCurrentSceneClientUpdate();
546 } 546 }
547 547
548 /// <summary> 548 /// <summary>
@@ -554,7 +554,7 @@ namespace OpenSim
554 { 554 {
555 if (args.Length == 6) 555 if (args.Length == 6)
556 { 556 {
557 m_sceneManager.HandleEditCommandOnCurrentScene(args); 557 SceneManager.HandleEditCommandOnCurrentScene(args);
558 } 558 }
559 else 559 else
560 { 560 {
@@ -765,7 +765,7 @@ namespace OpenSim
765 case "load": 765 case "load":
766 if (cmdparams.Length > 1) 766 if (cmdparams.Length > 1)
767 { 767 {
768 foreach (Scene s in new ArrayList(m_sceneManager.Scenes)) 768 foreach (Scene s in new ArrayList(SceneManager.Scenes))
769 { 769 {
770 MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1])); 770 MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1]));
771 m_moduleLoader.LoadRegionModules(cmdparams[1], s); 771 m_moduleLoader.LoadRegionModules(cmdparams[1], s);
@@ -803,14 +803,14 @@ namespace OpenSim
803 803
804 case "backup": 804 case "backup":
805 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); 805 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
806 m_sceneManager.BackupCurrentScene(); 806 SceneManager.BackupCurrentScene();
807 break; 807 break;
808 808
809 case "remove-region": 809 case "remove-region":
810 string regRemoveName = CombineParams(cmdparams, 0); 810 string regRemoveName = CombineParams(cmdparams, 0);
811 811
812 Scene removeScene; 812 Scene removeScene;
813 if (m_sceneManager.TryGetScene(regRemoveName, out removeScene)) 813 if (SceneManager.TryGetScene(regRemoveName, out removeScene))
814 RemoveRegion(removeScene, false); 814 RemoveRegion(removeScene, false);
815 else 815 else
816 MainConsole.Instance.Output("No region with that name"); 816 MainConsole.Instance.Output("No region with that name");
@@ -820,14 +820,14 @@ namespace OpenSim
820 string regDeleteName = CombineParams(cmdparams, 0); 820 string regDeleteName = CombineParams(cmdparams, 0);
821 821
822 Scene killScene; 822 Scene killScene;
823 if (m_sceneManager.TryGetScene(regDeleteName, out killScene)) 823 if (SceneManager.TryGetScene(regDeleteName, out killScene))
824 RemoveRegion(killScene, true); 824 RemoveRegion(killScene, true);
825 else 825 else
826 MainConsole.Instance.Output("no region with that name"); 826 MainConsole.Instance.Output("no region with that name");
827 break; 827 break;
828 828
829 case "restart": 829 case "restart":
830 m_sceneManager.RestartCurrentScene(); 830 SceneManager.RestartCurrentScene();
831 break; 831 break;
832 } 832 }
833 } 833 }
@@ -842,7 +842,7 @@ namespace OpenSim
842 { 842 {
843 string newRegionName = CombineParams(cmdparams, 2); 843 string newRegionName = CombineParams(cmdparams, 2);
844 844
845 if (!m_sceneManager.TrySetCurrentScene(newRegionName)) 845 if (!SceneManager.TrySetCurrentScene(newRegionName))
846 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); 846 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
847 } 847 }
848 else 848 else
@@ -850,7 +850,7 @@ namespace OpenSim
850 MainConsole.Instance.Output("Usage: change region <region name>"); 850 MainConsole.Instance.Output("Usage: change region <region name>");
851 } 851 }
852 852
853 string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName); 853 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
854 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); 854 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
855 855
856// m_log.DebugFormat("Original prompt is {0}", m_consolePrompt); 856// m_log.DebugFormat("Original prompt is {0}", m_consolePrompt);
@@ -868,7 +868,7 @@ namespace OpenSim
868 }); 868 });
869 869
870 m_console.DefaultPrompt = prompt; 870 m_console.DefaultPrompt = prompt;
871 m_console.ConsoleScene = m_sceneManager.CurrentScene; 871 m_console.ConsoleScene = SceneManager.CurrentScene;
872 } 872 }
873 873
874 /// <summary> 874 /// <summary>
@@ -892,7 +892,7 @@ namespace OpenSim
892 int newDebug; 892 int newDebug;
893 if (int.TryParse(args[2], out newDebug)) 893 if (int.TryParse(args[2], out newDebug))
894 { 894 {
895 m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name); 895 SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
896 // We provide user information elsewhere if any clients had their debug level set. 896 // We provide user information elsewhere if any clients had their debug level set.
897// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug); 897// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
898 } 898 }
@@ -907,7 +907,7 @@ namespace OpenSim
907 case "scene": 907 case "scene":
908 if (args.Length == 4) 908 if (args.Length == 4)
909 { 909 {
910 if (m_sceneManager.CurrentScene == null) 910 if (SceneManager.CurrentScene == null)
911 { 911 {
912 MainConsole.Instance.Output("Please use 'change region <regioname>' first"); 912 MainConsole.Instance.Output("Please use 'change region <regioname>' first");
913 } 913 }
@@ -915,7 +915,7 @@ namespace OpenSim
915 { 915 {
916 string key = args[2]; 916 string key = args[2];
917 string value = args[3]; 917 string value = args[3];
918 m_sceneManager.CurrentScene.SetSceneCoreDebug( 918 SceneManager.CurrentScene.SetSceneCoreDebug(
919 new Dictionary<string, string>() { { key, value } }); 919 new Dictionary<string, string>() { { key, value } });
920 920
921 MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value); 921 MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value);
@@ -954,10 +954,10 @@ namespace OpenSim
954 IList agents; 954 IList agents;
955 if (showParams.Length > 1 && showParams[1] == "full") 955 if (showParams.Length > 1 && showParams[1] == "full")
956 { 956 {
957 agents = m_sceneManager.GetCurrentScenePresences(); 957 agents = SceneManager.GetCurrentScenePresences();
958 } else 958 } else
959 { 959 {
960 agents = m_sceneManager.GetCurrentSceneAvatars(); 960 agents = SceneManager.GetCurrentSceneAvatars();
961 } 961 }
962 962
963 MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count)); 963 MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count));
@@ -1037,7 +1037,7 @@ namespace OpenSim
1037 MainConsole.Instance.Output("Shared Module: " + module.Name); 1037 MainConsole.Instance.Output("Shared Module: " + module.Name);
1038 } 1038 }
1039 1039
1040 m_sceneManager.ForEachScene( 1040 SceneManager.ForEachScene(
1041 delegate(Scene scene) { 1041 delegate(Scene scene) {
1042 m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); 1042 m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
1043 foreach (IRegionModule module in scene.Modules.Values) 1043 foreach (IRegionModule module in scene.Modules.Values)
@@ -1050,7 +1050,7 @@ namespace OpenSim
1050 } 1050 }
1051 ); 1051 );
1052 1052
1053 m_sceneManager.ForEachScene( 1053 SceneManager.ForEachScene(
1054 delegate(Scene scene) { 1054 delegate(Scene scene) {
1055 MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:"); 1055 MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:");
1056 foreach (IRegionModuleBase module in scene.RegionModules.Values) 1056 foreach (IRegionModuleBase module in scene.RegionModules.Values)
@@ -1066,7 +1066,7 @@ namespace OpenSim
1066 break; 1066 break;
1067 1067
1068 case "regions": 1068 case "regions":
1069 m_sceneManager.ForEachScene( 1069 SceneManager.ForEachScene(
1070 delegate(Scene scene) 1070 delegate(Scene scene)
1071 { 1071 {
1072 MainConsole.Instance.Output(String.Format( 1072 MainConsole.Instance.Output(String.Format(
@@ -1080,7 +1080,7 @@ namespace OpenSim
1080 break; 1080 break;
1081 1081
1082 case "ratings": 1082 case "ratings":
1083 m_sceneManager.ForEachScene( 1083 SceneManager.ForEachScene(
1084 delegate(Scene scene) 1084 delegate(Scene scene)
1085 { 1085 {
1086 string rating = ""; 1086 string rating = "";
@@ -1115,7 +1115,7 @@ namespace OpenSim
1115 cdt.AddColumn("IP", 16); 1115 cdt.AddColumn("IP", 16);
1116 cdt.AddColumn("Viewer Name", 24); 1116 cdt.AddColumn("Viewer Name", 24);
1117 1117
1118 m_sceneManager.ForEachScene( 1118 SceneManager.ForEachScene(
1119 s => 1119 s =>
1120 { 1120 {
1121 foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values) 1121 foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
@@ -1140,13 +1140,13 @@ namespace OpenSim
1140 cdt.AddColumn("Endpoint", 23); 1140 cdt.AddColumn("Endpoint", 23);
1141 cdt.AddColumn("Active?", 7); 1141 cdt.AddColumn("Active?", 7);
1142 1142
1143 m_sceneManager.ForEachScene( 1143 SceneManager.ForEachScene(
1144 s => s.ForEachClient( 1144 s => s.ForEachClient(
1145 c => cdt.AddRow( 1145 c => cdt.AddRow(
1146 s.Name, 1146 s.Name,
1147 c.Name, 1147 c.Name,
1148 c.RemoteEndPoint.ToString(),
1149 c.CircuitCode.ToString(), 1148 c.CircuitCode.ToString(),
1149 c.RemoteEndPoint.ToString(),
1150 c.IsActive.ToString()))); 1150 c.IsActive.ToString())));
1151 1151
1152 MainConsole.Instance.Output(cdt.ToString()); 1152 MainConsole.Instance.Output(cdt.ToString());
@@ -1161,11 +1161,11 @@ namespace OpenSim
1161 { 1161 {
1162 if (cmdparams.Length > 5) 1162 if (cmdparams.Length > 5)
1163 { 1163 {
1164 m_sceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]); 1164 SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
1165 } 1165 }
1166 else 1166 else
1167 { 1167 {
1168 m_sceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME); 1168 SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
1169 } 1169 }
1170 } 1170 }
1171 1171
@@ -1180,11 +1180,11 @@ namespace OpenSim
1180 1180
1181 if (cmdparams.Length > 0) 1181 if (cmdparams.Length > 0)
1182 { 1182 {
1183 m_sceneManager.SaveCurrentSceneToXml(cmdparams[2]); 1183 SceneManager.SaveCurrentSceneToXml(cmdparams[2]);
1184 } 1184 }
1185 else 1185 else
1186 { 1186 {
1187 m_sceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME); 1187 SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
1188 } 1188 }
1189 } 1189 }
1190 1190
@@ -1221,13 +1221,13 @@ namespace OpenSim
1221 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z)); 1221 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
1222 } 1222 }
1223 } 1223 }
1224 m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset); 1224 SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset);
1225 } 1225 }
1226 else 1226 else
1227 { 1227 {
1228 try 1228 try
1229 { 1229 {
1230 m_sceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset); 1230 SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
1231 } 1231 }
1232 catch (FileNotFoundException) 1232 catch (FileNotFoundException)
1233 { 1233 {
@@ -1244,11 +1244,11 @@ namespace OpenSim
1244 { 1244 {
1245 if (cmdparams.Length > 2) 1245 if (cmdparams.Length > 2)
1246 { 1246 {
1247 m_sceneManager.SaveCurrentSceneToXml2(cmdparams[2]); 1247 SceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
1248 } 1248 }
1249 else 1249 else
1250 { 1250 {
1251 m_sceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME); 1251 SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
1252 } 1252 }
1253 } 1253 }
1254 1254
@@ -1263,7 +1263,7 @@ namespace OpenSim
1263 { 1263 {
1264 try 1264 try
1265 { 1265 {
1266 m_sceneManager.LoadCurrentSceneFromXml2(cmdparams[2]); 1266 SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
1267 } 1267 }
1268 catch (FileNotFoundException) 1268 catch (FileNotFoundException)
1269 { 1269 {
@@ -1274,7 +1274,7 @@ namespace OpenSim
1274 { 1274 {
1275 try 1275 try
1276 { 1276 {
1277 m_sceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME); 1277 SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
1278 } 1278 }
1279 catch (FileNotFoundException) 1279 catch (FileNotFoundException)
1280 { 1280 {
@@ -1291,7 +1291,7 @@ namespace OpenSim
1291 { 1291 {
1292 try 1292 try
1293 { 1293 {
1294 m_sceneManager.LoadArchiveToCurrentScene(cmdparams); 1294 SceneManager.LoadArchiveToCurrentScene(cmdparams);
1295 } 1295 }
1296 catch (Exception e) 1296 catch (Exception e)
1297 { 1297 {
@@ -1305,7 +1305,7 @@ namespace OpenSim
1305 /// <param name="cmdparams"></param> 1305 /// <param name="cmdparams"></param>
1306 protected void SaveOar(string module, string[] cmdparams) 1306 protected void SaveOar(string module, string[] cmdparams)
1307 { 1307 {
1308 m_sceneManager.SaveCurrentSceneToArchive(cmdparams); 1308 SceneManager.SaveCurrentSceneToArchive(cmdparams);
1309 } 1309 }
1310 1310
1311 private static string CombineParams(string[] commandParams, int pos) 1311 private static string CombineParams(string[] commandParams, int pos)
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 76ac246..f378153 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -40,7 +40,7 @@ using OpenSim.Framework.Communications;
40using OpenSim.Framework.Console; 40using OpenSim.Framework.Console;
41using OpenSim.Framework.Servers; 41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer; 42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Framework.Statistics; 43using OpenSim.Framework.Monitoring;
44using OpenSim.Region.ClientStack; 44using OpenSim.Region.ClientStack;
45using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; 45using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts;
46using OpenSim.Region.Framework; 46using OpenSim.Region.Framework;
@@ -300,7 +300,7 @@ namespace OpenSim
300 300
301 private void HandleCommanderCommand(string module, string[] cmd) 301 private void HandleCommanderCommand(string module, string[] cmd)
302 { 302 {
303 m_sceneManager.SendCommandToPluginModules(cmd); 303 SceneManager.SendCommandToPluginModules(cmd);
304 } 304 }
305 305
306 private void HandleCommanderHelp(string module, string[] cmd) 306 private void HandleCommanderHelp(string module, string[] cmd)
@@ -318,7 +318,10 @@ namespace OpenSim
318 // Called from base.StartUp() 318 // Called from base.StartUp()
319 319
320 m_httpServerPort = m_networkServersInfo.HttpListenerPort; 320 m_httpServerPort = m_networkServersInfo.HttpListenerPort;
321 m_sceneManager.OnRestartSim += handleRestartRegion; 321 SceneManager.OnRestartSim += handleRestartRegion;
322
323 // Only start the memory watchdog once all regions are ready
324 SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady;
322 } 325 }
323 326
324 /// <summary> 327 /// <summary>
@@ -480,7 +483,7 @@ namespace OpenSim
480 scene.SnmpService.BootInfo("ScriptEngine started", scene); 483 scene.SnmpService.BootInfo("ScriptEngine started", scene);
481 } 484 }
482 485
483 m_sceneManager.Add(scene); 486 SceneManager.Add(scene);
484 487
485 if (m_autoCreateClientStack) 488 if (m_autoCreateClientStack)
486 { 489 {
@@ -510,7 +513,6 @@ namespace OpenSim
510 } 513 }
511 514
512 scene.Start(); 515 scene.Start();
513
514 scene.StartScripts(); 516 scene.StartScripts();
515 517
516 return clientServer; 518 return clientServer;
@@ -644,14 +646,14 @@ namespace OpenSim
644 { 646 {
645 // only need to check this if we are not at the 647 // only need to check this if we are not at the
646 // root level 648 // root level
647 if ((m_sceneManager.CurrentScene != null) && 649 if ((SceneManager.CurrentScene != null) &&
648 (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) 650 (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
649 { 651 {
650 m_sceneManager.TrySetCurrentScene(".."); 652 SceneManager.TrySetCurrentScene("..");
651 } 653 }
652 654
653 scene.DeleteAllSceneObjects(); 655 scene.DeleteAllSceneObjects();
654 m_sceneManager.CloseScene(scene); 656 SceneManager.CloseScene(scene);
655 ShutdownClientServer(scene.RegionInfo); 657 ShutdownClientServer(scene.RegionInfo);
656 658
657 if (!cleanup) 659 if (!cleanup)
@@ -693,7 +695,7 @@ namespace OpenSim
693 public void RemoveRegion(string name, bool cleanUp) 695 public void RemoveRegion(string name, bool cleanUp)
694 { 696 {
695 Scene target; 697 Scene target;
696 if (m_sceneManager.TryGetScene(name, out target)) 698 if (SceneManager.TryGetScene(name, out target))
697 RemoveRegion(target, cleanUp); 699 RemoveRegion(target, cleanUp);
698 } 700 }
699 701
@@ -706,13 +708,13 @@ namespace OpenSim
706 { 708 {
707 // only need to check this if we are not at the 709 // only need to check this if we are not at the
708 // root level 710 // root level
709 if ((m_sceneManager.CurrentScene != null) && 711 if ((SceneManager.CurrentScene != null) &&
710 (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) 712 (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
711 { 713 {
712 m_sceneManager.TrySetCurrentScene(".."); 714 SceneManager.TrySetCurrentScene("..");
713 } 715 }
714 716
715 m_sceneManager.CloseScene(scene); 717 SceneManager.CloseScene(scene);
716 ShutdownClientServer(scene.RegionInfo); 718 ShutdownClientServer(scene.RegionInfo);
717 } 719 }
718 720
@@ -724,7 +726,7 @@ namespace OpenSim
724 public void CloseRegion(string name) 726 public void CloseRegion(string name)
725 { 727 {
726 Scene target; 728 Scene target;
727 if (m_sceneManager.TryGetScene(name, out target)) 729 if (SceneManager.TryGetScene(name, out target))
728 CloseRegion(target); 730 CloseRegion(target);
729 } 731 }
730 732
@@ -980,7 +982,7 @@ namespace OpenSim
980 982
981 try 983 try
982 { 984 {
983 m_sceneManager.Close(); 985 SceneManager.Close();
984 } 986 }
985 catch (Exception e) 987 catch (Exception e)
986 { 988 {
@@ -1005,7 +1007,7 @@ namespace OpenSim
1005 /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param> 1007 /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param>
1006 public void GetAvatarNumber(out int usernum) 1008 public void GetAvatarNumber(out int usernum)
1007 { 1009 {
1008 usernum = m_sceneManager.GetCurrentSceneAvatars().Count; 1010 usernum = SceneManager.GetCurrentSceneAvatars().Count;
1009 } 1011 }
1010 1012
1011 /// <summary> 1013 /// <summary>
@@ -1014,7 +1016,7 @@ namespace OpenSim
1014 /// <param name="regionnum">The first out parameter describing the number of regions</param> 1016 /// <param name="regionnum">The first out parameter describing the number of regions</param>
1015 public void GetRegionNumber(out int regionnum) 1017 public void GetRegionNumber(out int regionnum)
1016 { 1018 {
1017 regionnum = m_sceneManager.Scenes.Count; 1019 regionnum = SceneManager.Scenes.Count;
1018 } 1020 }
1019 1021
1020 /// <summary> 1022 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index ad9074c..f7bb817 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -41,7 +41,7 @@ using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
42using OpenSim.Framework; 42using OpenSim.Framework;
43using OpenSim.Framework.Client; 43using OpenSim.Framework.Client;
44using OpenSim.Framework.Statistics; 44using OpenSim.Framework.Monitoring;
45using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
@@ -355,8 +355,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
355 private int m_animationSequenceNumber = 1; 355 private int m_animationSequenceNumber = 1;
356 private bool m_SendLogoutPacketWhenClosing = true; 356 private bool m_SendLogoutPacketWhenClosing = true;
357 private AgentUpdateArgs lastarg; 357 private AgentUpdateArgs lastarg;
358 private bool m_IsActive = true;
359 private bool m_IsLoggingOut = false;
360 358
361 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 359 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
362 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 360 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -428,16 +426,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
428 public uint CircuitCode { get { return m_circuitCode; } } 426 public uint CircuitCode { get { return m_circuitCode; } }
429 public int MoneyBalance { get { return m_moneyBalance; } } 427 public int MoneyBalance { get { return m_moneyBalance; } }
430 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } 428 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
431 public bool IsActive 429
432 { 430 /// <summary>
433 get { return m_IsActive; } 431 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
434 set { m_IsActive = value; } 432 /// prevent race conditions by different threads calling Close().
435 } 433 /// </summary>
436 public bool IsLoggingOut 434 public bool IsActive { get; set; }
437 { 435
438 get { return m_IsLoggingOut; } 436 /// <summary>
439 set { m_IsLoggingOut = value; } 437 /// Used to synchronise threads when client is being closed.
440 } 438 /// </summary>
439 public Object CloseSyncLock { get; private set; }
440
441 public bool IsLoggingOut { get; set; }
441 442
442 public bool DisableFacelights 443 public bool DisableFacelights
443 { 444 {
@@ -462,6 +463,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
462 { 463 {
463// DebugPacketLevel = 1; 464// DebugPacketLevel = 1;
464 465
466 CloseSyncLock = new Object();
467
465 RegisterInterface<IClientIM>(this); 468 RegisterInterface<IClientIM>(this);
466 RegisterInterface<IClientInventory>(this); 469 RegisterInterface<IClientInventory>(this);
467 RegisterInterface<IClientChat>(this); 470 RegisterInterface<IClientChat>(this);
@@ -494,13 +497,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 m_prioritizer = new Prioritizer(m_scene); 497 m_prioritizer = new Prioritizer(m_scene);
495 498
496 RegisterLocalPacketHandlers(); 499 RegisterLocalPacketHandlers();
500
501 IsActive = true;
497 } 502 }
498 503
499 #region Client Methods 504 #region Client Methods
500 505
501 506
502 /// <summary> 507 /// <summary>
503 /// Shut down the client view 508 /// Close down the client view
504 /// </summary> 509 /// </summary>
505 public void Close() 510 public void Close()
506 { 511 {
@@ -513,7 +518,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 public void Close(bool sendStop) 518 public void Close(bool sendStop)
514 { 519 {
515 IsActive = false; 520 IsActive = false;
521 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
522 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
523 lock (CloseSyncLock)
524 {
525 if (!IsActive)
526 return;
527
528 IsActive = false;
529 CloseWithoutChecks(sendStop);
530 }
531 }
516 532
533 /// <summary>
534 /// Closes down the client view without first checking whether it is active.
535 /// </summary>
536 /// <remarks>
537 /// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling
538 /// CloseWithoutIsActiveCheck asynchronously.
539 ///
540 /// Callers must lock ClosingSyncLock before calling.
541 /// </remarks>
542 public void CloseWithoutChecks(bool sendStop)
543 {
517 m_log.DebugFormat( 544 m_log.DebugFormat(
518 "[CLIENT]: Close has been called for {0} attached to scene {1}", 545 "[CLIENT]: Close has been called for {0} attached to scene {1}",
519 Name, m_scene.RegionInfo.RegionName); 546 Name, m_scene.RegionInfo.RegionName);
@@ -3634,7 +3661,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3634 3661
3635 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 3662 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
3636 { 3663 {
3637 if (!IsActive) return; // We don't need to update inactive clients. 3664 // We don't need to update inactive clients.
3665 if (!IsActive)
3666 return;
3638 3667
3639 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); 3668 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
3640 loc.Header.Reliable = false; 3669 loc.Header.Reliable = false;
@@ -5267,7 +5296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5267 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5296 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
5268 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); 5297 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate);
5269 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); 5298 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
5270 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false); 5299 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage);
5271 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); 5300 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
5272 AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); 5301 AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship);
5273 AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship); 5302 AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index ae72175..c472176 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -279,7 +279,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
279 public string GetStats() 279 public string GetStats()
280 { 280 {
281 return string.Format( 281 return string.Format(
282 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}", 282 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}",
283 Util.EnvironmentTickCountSubtract(TickLastPacketReceived),
283 PacketsReceived, 284 PacketsReceived,
284 PacketsSent, 285 PacketsSent,
285 PacketsResent, 286 PacketsResent,
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index f5f9c02..7042c9a 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,7 +37,7 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse; 42using OpenMetaverse;
43 43
@@ -1181,22 +1181,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1181 /// regular client pings. 1181 /// regular client pings.
1182 /// </remarks> 1182 /// </remarks>
1183 /// <param name='client'></param> 1183 /// <param name='client'></param>
1184 private void DeactivateClientDueToTimeout(IClientAPI client) 1184 private void DeactivateClientDueToTimeout(LLClientView client)
1185 { 1185 {
1186 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even 1186 lock (client.CloseSyncLock)
1187 // though it's set later on by LLClientView.Close() 1187 {
1188 client.IsActive = false; 1188 m_log.WarnFormat(
1189 1189 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
1190 m_log.WarnFormat( 1190 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
1191 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", 1191
1192 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); 1192 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1193 1193
1194 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); 1194 if (!client.SceneAgent.IsChildAgent)
1195 1195 client.Kick("Simulator logged you out due to connection timeout");
1196 if (!client.SceneAgent.IsChildAgent) 1196
1197 client.Kick("Simulator logged you out due to connection timeout"); 1197 client.CloseWithoutChecks(true);
1198 1198 }
1199 Util.FireAndForget(o => client.Close());
1200 } 1199 }
1201 1200
1202 private void IncomingPacketHandler() 1201 private void IncomingPacketHandler()
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index c4324e8..4672f8a 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -53,9 +53,8 @@ namespace OpenSim.Region.ClientStack
53 protected ISimulationDataService m_simulationDataService; 53 protected ISimulationDataService m_simulationDataService;
54 protected IEstateDataService m_estateDataService; 54 protected IEstateDataService m_estateDataService;
55 protected ClientStackManager m_clientStackManager; 55 protected ClientStackManager m_clientStackManager;
56 protected SceneManager m_sceneManager = new SceneManager();
57 56
58 public SceneManager SceneManager { get { return m_sceneManager; } } 57 public SceneManager SceneManager { get; protected set; }
59 public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } } 58 public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } }
60 public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } } 59 public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } }
61 public IEstateDataService EstateDataService { get { return m_estateDataService; } } 60 public IEstateDataService EstateDataService { get { return m_estateDataService; } }
@@ -77,6 +76,7 @@ namespace OpenSim.Region.ClientStack
77 76
78 protected override void StartupSpecific() 77 protected override void StartupSpecific()
79 { 78 {
79 SceneManager = new SceneManager();
80 m_clientStackManager = CreateClientStackManager(); 80 m_clientStackManager = CreateClientStackManager();
81 81
82 Initialize(); 82 Initialize();
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 31e8a2e..b588704 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -626,10 +626,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
626 626
627 m_scene.InventoryService.UpdateItem(item); 627 m_scene.InventoryService.UpdateItem(item);
628 628
629 // this gets called when the agent logs off! 629 // If the name of the object has been changed whilst attached then we want to update the inventory
630 // item in the viewer.
630 if (sp.ControllingClient != null) 631 if (sp.ControllingClient != null)
631 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); 632 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
632 } 633 }
634
633 grp.HasGroupChanged = false; // Prevent it being saved over and over 635 grp.HasGroupChanged = false; // Prevent it being saved over and over
634 } 636 }
635// else 637// else
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index cd1e1c1..273e290 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -47,6 +47,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.CoreModules.World.Serialiser; 47using OpenSim.Region.CoreModules.World.Serialiser;
48using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Interfaces; 49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.ScriptEngine.Interfaces;
50using OpenSim.Region.ScriptEngine.XEngine; 51using OpenSim.Region.ScriptEngine.XEngine;
51using OpenSim.Services.Interfaces; 52using OpenSim.Services.Interfaces;
52using OpenSim.Tests.Common; 53using OpenSim.Tests.Common;
@@ -289,21 +290,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
289 { 290 {
290 TestHelpers.InMethod(); 291 TestHelpers.InMethod();
291 292
292 Scene scene = CreateTestScene(); 293 Scene scene = CreateScriptingEnabledTestScene();
293 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 294 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
294 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); 295 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
295 296
296 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); 297 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
297 TaskInventoryHelpers.AddScript(scene, so.RootPart); 298 TaskInventoryItem scriptItem
299 = TaskInventoryHelpers.AddScript(
300 scene,
301 so.RootPart,
302 "scriptItem",
303 "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }");
304
298 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); 305 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
299 306
307 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
308 // In the future, we need to be able to do this programatically more predicably.
309 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
310
300 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 311 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
301 312
313 m_chatEvent.WaitOne(60000);
314
302 // TODO: Need to have a test that checks the script is actually started but this involves a lot more 315 // TODO: Need to have a test that checks the script is actually started but this involves a lot more
303 // plumbing of the script engine and either pausing for events or more infrastructure to turn off various 316 // plumbing of the script engine and either pausing for events or more infrastructure to turn off various
304 // script engine delays/asychronicity that isn't helpful in an automated regression testing context. 317 // script engine delays/asychronicity that isn't helpful in an automated regression testing context.
305 SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name); 318 SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name);
306 Assert.That(attSo.ContainsScripts(), Is.True); 319 Assert.That(attSo.ContainsScripts(), Is.True);
320
321 TaskInventoryItem reRezzedScriptItem = attSo.RootPart.Inventory.GetInventoryItem(scriptItem.Name);
322 IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>();
323 Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True);
307 } 324 }
308 325
309 [Test] 326 [Test]
@@ -379,29 +396,49 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
379 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 396 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
380 397
381 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); 398 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
382 TaskInventoryHelpers.AddScript(scene, so.RootPart); 399 TaskInventoryItem scriptTaskItem
400 = TaskInventoryHelpers.AddScript(
401 scene,
402 so.RootPart,
403 "scriptItem",
404 "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }");
405
383 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); 406 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
384 407
385 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. 408 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
386 // In the future, we need to be able to do this programatically more predicably. 409 // In the future, we need to be able to do this programatically more predicably.
387 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 410 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
388 411
389 SceneObjectGroup soRezzed 412 SceneObjectGroup rezzedSo
390 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 413 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
391 414
392 // Wait for chat to signal rezzed script has been started. 415 // Wait for chat to signal rezzed script has been started.
393 m_chatEvent.WaitOne(60000); 416 m_chatEvent.WaitOne(60000);
394 417
395 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed); 418 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo);
396 419
397 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); 420 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem);
398 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); 421 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
399 422
423 // TODO: It would probably be better here to check script state via the saving and retrieval of state
424 // information at a higher level, rather than having to inspect the serialization.
400 XmlDocument soXml = new XmlDocument(); 425 XmlDocument soXml = new XmlDocument();
401 soXml.LoadXml(Encoding.UTF8.GetString(asset.Data)); 426 soXml.LoadXml(Encoding.UTF8.GetString(asset.Data));
402 427
403 XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState"); 428 XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState");
404 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 429 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
430
431 // Re-rez the attachment to check script running state
432 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
433
434 // Wait for chat to signal rezzed script has been started.
435 m_chatEvent.WaitOne(60000);
436
437 TaskInventoryItem reRezzedScriptItem = reRezzedSo.RootPart.Inventory.GetInventoryItem(scriptTaskItem.Name);
438 IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>();
439 Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True);
440
441// Console.WriteLine(soXml.OuterXml);
405 } 442 }
406 443
407 /// <summary> 444 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
index 4bcd2ac..764adf9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43 43
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
index 31363e5..b258e13 100644
--- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
@@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
96 96
97 scene.EventManager.OnNewClient += OnNewClient; 97 scene.EventManager.OnNewClient += OnNewClient;
98 scene.EventManager.OnClientClosed += OnClientClosed; 98 scene.EventManager.OnClientClosed += OnClientClosed;
99 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 99// scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
100 } 100 }
101 101
102 public void PostInitialise() 102 public void PostInitialise()
@@ -133,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
133 private void OnNewClient(IClientAPI client) 133 private void OnNewClient(IClientAPI client)
134 { 134 {
135 // Subscribe to instant messages 135 // Subscribe to instant messages
136 client.OnInstantMessage += OnInstantMessage; 136// client.OnInstantMessage += OnInstantMessage;
137 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; 137 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
138 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; 138 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
139 lock (m_ClientMap) 139 lock (m_ClientMap)
@@ -171,15 +171,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
171 ActiveGroupTitle); 171 ActiveGroupTitle);
172 } 172 }
173 173
174 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 174// private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
175 { 175// {
176 } 176// }
177 177
178 private void OnGridInstantMessage(GridInstantMessage msg) 178// private void OnGridInstantMessage(GridInstantMessage msg)
179 { 179// {
180 // Trigger the above event handler 180// // Trigger the above event handler
181 OnInstantMessage(null, msg); 181// OnInstantMessage(null, msg);
182 } 182// }
183 183
184 private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) 184 private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client)
185 { 185 {
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 6064ddc..1406aae 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -141,13 +141,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
141 foreach (Scene scene in m_Scenes) 141 foreach (Scene scene in m_Scenes)
142 { 142 {
143// m_log.DebugFormat( 143// m_log.DebugFormat(
144// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", 144// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
145// toAgentID.ToString(), scene.RegionInfo.RegionName); 145// toAgentID.ToString(), scene.RegionInfo.RegionName);
146
146 ScenePresence sp = scene.GetScenePresence(toAgentID); 147 ScenePresence sp = scene.GetScenePresence(toAgentID);
147 if (sp != null && !sp.IsChildAgent) 148 if (sp != null && !sp.IsChildAgent)
148 { 149 {
149 // Local message 150 // Local message
150// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); 151 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
152
151 sp.ControllingClient.SendInstantMessage(im); 153 sp.ControllingClient.SendInstantMessage(im);
152 154
153 // Message sent 155 // Message sent
@@ -159,13 +161,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 // try child avatar second 161 // try child avatar second
160 foreach (Scene scene in m_Scenes) 162 foreach (Scene scene in m_Scenes)
161 { 163 {
162// m_log.DebugFormat( 164 m_log.DebugFormat(
163// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 165 "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
166
164 ScenePresence sp = scene.GetScenePresence(toAgentID); 167 ScenePresence sp = scene.GetScenePresence(toAgentID);
165 if (sp != null) 168 if (sp != null)
166 { 169 {
167 // Local message 170 // Local message
168// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); 171 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
172
169 sp.ControllingClient.SendInstantMessage(im); 173 sp.ControllingClient.SendInstantMessage(im);
170 174
171 // Message sent 175 // Message sent
@@ -174,10 +178,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
174 } 178 }
175 } 179 }
176 180
177// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 181 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
178 SendGridInstantMessageViaXMLRPC(im, result);
179 182
180 return; 183 SendGridInstantMessageViaXMLRPC(im, result);
181 } 184 }
182 185
183 private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) 186 private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index 80554fb..81de29c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -313,8 +313,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); 313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
314 } 314 }
315 } 315 }
316 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined || 316 else if (
317 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined) 317 im.dialog == (byte)InstantMessageDialog.InventoryDeclined
318 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
318 { 319 {
319 // Here, the recipient is local and we can assume that the 320 // Here, the recipient is local and we can assume that the
320 // inventory is loaded. Courtesy of the above bulk update, 321 // inventory is loaded. Courtesy of the above bulk update,
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index d30c2e2..9a56f42 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -204,8 +204,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
204 204
205 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); 205 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
206 m_Scene.AssetService.Store(asset); 206 m_Scene.AssetService.Store(asset);
207 207 m_Scene.CreateNewInventoryItem(
208 m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); 208 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
209 name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
209 } 210 }
210 else 211 else
211 { 212 {
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
index a75ff62..fb74cc6 100644
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
@@ -39,7 +39,7 @@ using OpenSim.Region.Framework;
39using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41 41
42namespace OpenSim.Region.CoreModules.Avatar.Attachments 42namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
43{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")]
45 public class BinaryLoggingModule : INonSharedRegionModule 45 public class BinaryLoggingModule : INonSharedRegionModule
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
new file mode 100755
index 0000000..65e4c90
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -0,0 +1,161 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Text;
31using log4net;
32
33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
34{
35 /// <summary>
36 /// Class for writing a high performance, high volume log file.
37 /// Sometimes, to debug, one has a high volume logging to do and the regular
38 /// log file output is not appropriate.
39 /// Create a new instance with the parameters needed and
40 /// call Write() to output a line. Call Close() when finished.
41 /// If created with no parameters, it will not log anything.
42 /// </summary>
43 public class LogWriter : IDisposable
44 {
45 public bool Enabled { get; private set; }
46
47 private string m_logDirectory = ".";
48 private int m_logMaxFileTimeMin = 5; // 5 minutes
49 public String LogFileHeader { get; set; }
50
51 private StreamWriter m_logFile = null;
52 private TimeSpan m_logFileLife;
53 private DateTime m_logFileEndTime;
54 private Object m_logFileWriteLock = new Object();
55
56 // set externally when debugging. If let 'null', this does not write any error messages.
57 public ILog ErrorLogger = null;
58 private string LogHeader = "[LOG WRITER]";
59
60 /// <summary>
61 /// Create a log writer that will not write anything. Good for when not enabled
62 /// but the write statements are still in the code.
63 /// </summary>
64 public LogWriter()
65 {
66 Enabled = false;
67 m_logFile = null;
68 }
69
70 /// <summary>
71 /// Create a log writer instance.
72 /// </summary>
73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
76 public LogWriter(string dir, string headr, int maxFileTime)
77 {
78 m_logDirectory = dir == null ? "." : dir;
79
80 LogFileHeader = headr == null ? "log-" : headr;
81
82 m_logMaxFileTimeMin = maxFileTime;
83 if (m_logMaxFileTimeMin < 1)
84 m_logMaxFileTimeMin = 5;
85
86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
87 m_logFileEndTime = DateTime.Now + m_logFileLife;
88
89 Enabled = true;
90 }
91
92 public void Dispose()
93 {
94 this.Close();
95 }
96
97 public void Close()
98 {
99 Enabled = false;
100 if (m_logFile != null)
101 {
102 m_logFile.Close();
103 m_logFile.Dispose();
104 m_logFile = null;
105 }
106 }
107
108 public void Write(string line, params object[] args)
109 {
110 if (!Enabled) return;
111 Write(String.Format(line, args));
112 }
113
114 public void Write(string line)
115 {
116 if (!Enabled) return;
117 try
118 {
119 lock (m_logFileWriteLock)
120 {
121 DateTime now = DateTime.Now;
122 if (m_logFile == null || now > m_logFileEndTime)
123 {
124 if (m_logFile != null)
125 {
126 m_logFile.Close();
127 m_logFile.Dispose();
128 m_logFile = null;
129 }
130
131 // First log file or time has expired, start writing to a new log file
132 m_logFileEndTime = now + m_logFileLife;
133 string path = (m_logDirectory.Length > 0 ? m_logDirectory
134 + System.IO.Path.DirectorySeparatorChar.ToString() : "")
135 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
136 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
137 }
138 if (m_logFile != null)
139 {
140 StringBuilder buff = new StringBuilder(line.Length + 25);
141 buff.Append(now.ToString("yyyyMMddHHmmssfff"));
142 // buff.Append(now.ToString("yyyyMMddHHmmss"));
143 buff.Append(",");
144 buff.Append(line);
145 buff.Append("\r\n");
146 m_logFile.Write(buff.ToString());
147 }
148 }
149 }
150 catch (Exception e)
151 {
152 if (ErrorLogger != null)
153 {
154 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
155 }
156 Enabled = false;
157 }
158 return;
159 }
160 }
161} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
index a6e2548..4a76b00 100644
--- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
+++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
@@ -40,6 +40,7 @@ using OpenMetaverse;
40using OpenMetaverse.StructuredData; 40using OpenMetaverse.StructuredData;
41using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Framework.Capabilities; 42using OpenSim.Framework.Capabilities;
43using OpenSim.Framework.Monitoring;
43using OpenSim.Framework.Servers; 44using OpenSim.Framework.Servers;
44using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 990dffb..11e0150 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -31,7 +31,7 @@ using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Statistics; 34using OpenSim.Framework.Monitoring;
35using OpenSim.Services.Connectors; 35using OpenSim.Services.Connectors;
36using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 6cd077a..e4c6c1a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -134,11 +134,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
134 ///<summary> 134 ///<summary>
135 /// 135 ///
136 ///</summary> 136 ///</summary>
137
138
139 ///<summary>
140 ///
141 ///</summary>
142 public void AddRegion(Scene scene) 137 public void AddRegion(Scene scene)
143 { 138 {
144 if (! m_enabled) 139 if (! m_enabled)
@@ -149,10 +144,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
149 lock (m_scenes) 144 lock (m_scenes)
150 m_scenes[scene.RegionInfo.RegionID] = scene; 145 m_scenes[scene.RegionInfo.RegionID] = scene;
151 146
152 scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; 147 scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) UploadMapTile(s); };
153 } 148 }
154 149
155
156 ///<summary> 150 ///<summary>
157 /// 151 ///
158 ///</summary> 152 ///</summary>
@@ -166,21 +160,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
166 } 160 }
167 161
168 #endregion ISharedRegionModule 162 #endregion ISharedRegionModule
169 163
170 void OnLoginsEnabled(string regionName)
171 {
172 Scene scene = null;
173 foreach (Scene s in m_scenes.Values)
174 if (s.RegionInfo.RegionName == regionName)
175 {
176 scene = s;
177 break;
178 }
179 if (scene != null)
180 UploadMapTile(scene);
181 }
182
183
184 ///<summary> 164 ///<summary>
185 /// 165 ///
186 ///</summary> 166 ///</summary>
diff --git a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
index 553a32d..e7b1454 100644
--- a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
+++ b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
@@ -129,18 +129,18 @@ namespace OpenSim.Region.CoreModules.World
129 switch (cmd[1]) 129 switch (cmd[1])
130 { 130 {
131 case "enable": 131 case "enable":
132 scene.LoginsDisabled = false; 132 scene.LoginsEnabled = true;
133 MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName)); 133 MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName));
134 break; 134 break;
135 case "disable": 135 case "disable":
136 scene.LoginsDisabled = true; 136 scene.LoginsEnabled = false;
137 MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName)); 137 MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName));
138 break; 138 break;
139 case "status": 139 case "status":
140 if (scene.LoginsDisabled) 140 if (scene.LoginsEnabled)
141 MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName));
142 else
143 MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName)); 141 MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName));
142 else
143 MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName));
144 break; 144 break;
145 default: 145 default:
146 MainConsole.Instance.Output("Syntax: login enable|disable|status"); 146 MainConsole.Instance.Output("Syntax: login enable|disable|status");
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index e5cd3e2..09f6758 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43 43
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
index 2838e0c..7d35473 100644
--- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43 43
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 309856f..26b406e 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -42,6 +42,7 @@ using OpenMetaverse.Imaging;
42using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43using OpenSim.Framework; 43using OpenSim.Framework;
44using OpenSim.Framework.Capabilities; 44using OpenSim.Framework.Capabilities;
45using OpenSim.Framework.Monitoring;
45using OpenSim.Framework.Servers; 46using OpenSim.Framework.Servers;
46using OpenSim.Framework.Servers.HttpServer; 47using OpenSim.Framework.Servers.HttpServer;
47using OpenSim.Region.Framework.Interfaces; 48using OpenSim.Region.Framework.Interfaces;
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs
index aa4a757..136ca92 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs
@@ -25,14 +25,23 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28
29using System; 28using System;
29using OpenSim.Framework;
30 30
31namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface IRegionReadyModule 33 public interface IRegionReadyModule
34 { 34 {
35 void OarLoadingAlert(string msg); 35 void OarLoadingAlert(string msg);
36
37 /// <summary>
38 /// Trigger region ready status manually.
39 /// </summary>
40 /// <remarks>
41 /// This should be called by the scene if the IRegionReadyModule has set Scene.LoginLock == true
42 /// </remarks>
43 /// <param name='scene'></param>
44 void TriggerRegionReady(IScene scene);
36 } 45 }
37} 46}
38 47
diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
index 3f68ee0..0fe681f 100644
--- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
@@ -40,8 +40,6 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// </remarks> 40 /// </remarks>
41 public interface IScenePresence : ISceneAgent 41 public interface IScenePresence : ISceneAgent
42 { 42 {
43 PresenceType PresenceType { get; }
44
45 /// <summary> 43 /// <summary>
46 /// Copy of the script states while the agent is in transit. This state may 44 /// Copy of the script states while the agent is in transit. This state may
47 /// need to be placed back in case of transfer fail. 45 /// need to be placed back in case of transfer fail.
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 9ddac19..50a176b 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -551,11 +551,5 @@ namespace OpenSim.Region.Framework.Scenes.Animation
551 551
552 SendAnimPack(animIDs, sequenceNums, objectIDs); 552 SendAnimPack(animIDs, sequenceNums, objectIDs);
553 } 553 }
554
555 public void Close()
556 {
557 m_animations = null;
558 m_scenePresence = null;
559 }
560 } 554 }
561} 555} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index d783e57..7cb3811 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -500,15 +500,24 @@ namespace OpenSim.Region.Framework.Scenes
500 public delegate void RegionHeartbeatEnd(Scene scene); 500 public delegate void RegionHeartbeatEnd(Scene scene);
501 public event RegionHeartbeatEnd OnRegionHeartbeatEnd; 501 public event RegionHeartbeatEnd OnRegionHeartbeatEnd;
502 502
503 public delegate void LoginsEnabled(string regionName); 503 /// <summary>
504 /// Fired when logins to a region are enabled or disabled.
505 /// </summary>
506 /// <remarks>
507 ///
508 /// </remarks>
509 /// Fired
510 public event RegionLoginsStatusChange OnRegionLoginsStatusChange;
511 public delegate void RegionLoginsStatusChange(IScene scene);
504 512
505 /// <summary> 513 /// <summary>
506 /// This should only fire in all circumstances if the RegionReady module is active. 514 /// Fired when a region is considered ready for use.
507 /// </summary> 515 /// </summary>
508 /// <remarks> 516 /// <remarks>
509 /// TODO: Fire this even when the RegionReady module is not active. 517 /// A region is considered ready when startup operations such as loading of scripts already on the region
518 /// have been completed.
510 /// </remarks> 519 /// </remarks>
511 public event LoginsEnabled OnLoginsEnabled; 520 public event Action<IScene> OnRegionReadyStatusChange;
512 521
513 public delegate void PrimsLoaded(Scene s); 522 public delegate void PrimsLoaded(Scene s);
514 public event PrimsLoaded OnPrimsLoaded; 523 public event PrimsLoaded OnPrimsLoaded;
@@ -2502,21 +2511,42 @@ namespace OpenSim.Region.Framework.Scenes
2502 } 2511 }
2503 } 2512 }
2504 2513
2505 public void TriggerLoginsEnabled (string regionName) 2514 public void TriggerRegionLoginsStatusChange(IScene scene)
2506 { 2515 {
2507 LoginsEnabled handler = OnLoginsEnabled; 2516 RegionLoginsStatusChange handler = OnRegionLoginsStatusChange;
2508 2517
2509 if ( handler != null) 2518 if (handler != null)
2510 { 2519 {
2511 foreach (LoginsEnabled d in handler.GetInvocationList()) 2520 foreach (RegionLoginsStatusChange d in handler.GetInvocationList())
2512 { 2521 {
2513 try 2522 try
2514 { 2523 {
2515 d(regionName); 2524 d(scene);
2525 }
2526 catch (Exception e)
2527 {
2528 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionLoginsStatusChange failed - continuing {0} - {1}",
2529 e.Message, e.StackTrace);
2530 }
2531 }
2532 }
2533 }
2534
2535 public void TriggerRegionReadyStatusChange(IScene scene)
2536 {
2537 Action<IScene> handler = OnRegionReadyStatusChange;
2538
2539 if (handler != null)
2540 {
2541 foreach (Action<IScene> d in handler.GetInvocationList())
2542 {
2543 try
2544 {
2545 d(scene);
2516 } 2546 }
2517 catch (Exception e) 2547 catch (Exception e)
2518 { 2548 {
2519 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}", 2549 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionReadyStatusChange failed - continuing {0} - {1}",
2520 e.Message, e.StackTrace); 2550 e.Message, e.StackTrace);
2521 } 2551 }
2522 } 2552 }
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index 1365831..c11174d 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -39,7 +39,7 @@ using OpenSim.Framework.Communications;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Framework.Statistics; 42using OpenSim.Framework.Monitoring;
43using OpenSim.Region.Framework; 43using OpenSim.Region.Framework;
44using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 98b8fcc..672d95a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -811,16 +811,20 @@ namespace OpenSim.Region.Framework.Scenes
811 && oldAgentID == LibraryService.LibraryRootFolder.Owner)) 811 && oldAgentID == LibraryService.LibraryRootFolder.Owner))
812 { 812 {
813 CreateNewInventoryItem( 813 CreateNewInventoryItem(
814 remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType, 814 remoteClient, item.CreatorId, item.CreatorData, newFolderID,
815 item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); 815 newName, item.Description, item.Flags, callbackID, asset, (sbyte)item.InvType,
816 item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions,
817 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
816 } 818 }
817 else 819 else
818 { 820 {
819 // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item. 821 // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item.
820 if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) && (m_permissions.BypassPermissions() || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID))) 822 if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0)
823 && (m_permissions.BypassPermissions()
824 || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID)))
821 { 825 {
822 CreateNewInventoryItem( 826 CreateNewInventoryItem(
823 remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, 827 remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Description, item.Flags, callbackID,
824 asset, (sbyte) item.InvType, 828 asset, (sbyte) item.InvType,
825 item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions, 829 item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions,
826 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); 830 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
@@ -885,32 +889,50 @@ namespace OpenSim.Region.Framework.Scenes
885 /// <summary> 889 /// <summary>
886 /// Create a new inventory item. 890 /// Create a new inventory item.
887 /// </summary> 891 /// </summary>
888 /// <param name="remoteClient"></param> 892 /// <param name="remoteClient">Client creating this inventory item.</param>
889 /// <param name="folderID"></param> 893 /// <param name="creatorID"></param>
890 /// <param name="callbackID"></param> 894 /// <param name="creatorData"></param>
891 /// <param name="asset"></param> 895 /// <param name="folderID">UUID of folder in which this item should be placed.</param>
892 /// <param name="invType"></param> 896 /// <param name="name">Item name.</para>
893 /// <param name="nextOwnerMask"></param> 897 /// <param name="description">Item description.</param>
894 public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, 898 /// <param name="flags">Item flags</param>
895 AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) 899 /// <param name="callbackID">Generated by the client.</para>
900 /// <param name="asset">Asset to which this item refers.</param>
901 /// <param name="invType">Type of inventory item.</param>
902 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
903 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
904 public void CreateNewInventoryItem(
905 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
906 string name, string description, uint flags, uint callbackID,
907 AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate)
896 { 908 {
897 CreateNewInventoryItem( 909 CreateNewInventoryItem(
898 remoteClient, creatorID, creatorData, folderID, name, flags, callbackID, asset, invType, 910 remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType,
899 (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); 911 (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate);
900 } 912 }
901 913
902 /// <summary> 914 /// <summary>
903 /// Create a new Inventory Item 915 /// Create a new Inventory Item
904 /// </summary> 916 /// </summary>
905 /// <param name="remoteClient"></param> 917 /// <param name="remoteClient">Client creating this inventory item.</param>
906 /// <param name="folderID"></param> 918 /// <param name="creatorID"></param>
907 /// <param name="callbackID"></param> 919 /// <param name="creatorData"></param>
908 /// <param name="asset"></param> 920 /// <param name="folderID">UUID of folder in which this item should be placed.</param>
909 /// <param name="invType"></param> 921 /// <param name="name">Item name.</para>
910 /// <param name="nextOwnerMask"></param> 922 /// <param name="description">Item description.</param>
911 /// <param name="creationDate"></param> 923 /// <param name="flags">Item flags</param>
924 /// <param name="callbackID">Generated by the client.</para>
925 /// <param name="asset">Asset to which this item refers.</param>
926 /// <param name="invType">Type of inventory item.</param>
927 /// <param name="baseMask">Base permissions mask.</param>
928 /// <param name="currentMask">Current permissions mask.</param>
929 /// <param name="everyoneMask">Everyone permissions mask.</param>
930 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
931 /// <param name="groupMask">Group permissions mask.</param>
932 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
912 private void CreateNewInventoryItem( 933 private void CreateNewInventoryItem(
913 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, 934 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
935 string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
914 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) 936 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
915 { 937 {
916 InventoryItemBase item = new InventoryItemBase(); 938 InventoryItemBase item = new InventoryItemBase();
@@ -919,8 +941,8 @@ namespace OpenSim.Region.Framework.Scenes
919 item.CreatorData = creatorData; 941 item.CreatorData = creatorData;
920 item.ID = UUID.Random(); 942 item.ID = UUID.Random();
921 item.AssetID = asset.FullID; 943 item.AssetID = asset.FullID;
922 item.Description = asset.Description;
923 item.Name = name; 944 item.Name = name;
945 item.Description = description;
924 item.Flags = flags; 946 item.Flags = flags;
925 item.AssetType = asset.Type; 947 item.AssetType = asset.Type;
926 item.InvType = invType; 948 item.InvType = invType;
@@ -1002,7 +1024,8 @@ namespace OpenSim.Region.Framework.Scenes
1002 asset.Description = description; 1024 asset.Description = description;
1003 1025
1004 CreateNewInventoryItem( 1026 CreateNewInventoryItem(
1005 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, 0, callbackID, asset, invType, 1027 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
1028 name, description, 0, callbackID, asset, invType,
1006 (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, 1029 (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All,
1007 (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); 1030 (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch());
1008 } 1031 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index ad9e91d..f7d74db 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -40,6 +40,7 @@ using OpenMetaverse;
40using OpenMetaverse.Packets; 40using OpenMetaverse.Packets;
41using OpenMetaverse.Imaging; 41using OpenMetaverse.Imaging;
42using OpenSim.Framework; 42using OpenSim.Framework;
43using OpenSim.Framework.Monitoring;
43using OpenSim.Services.Interfaces; 44using OpenSim.Services.Interfaces;
44using OpenSim.Framework.Communications; 45using OpenSim.Framework.Communications;
45using OpenSim.Framework.Console; 46using OpenSim.Framework.Console;
@@ -129,9 +130,10 @@ namespace OpenSim.Region.Framework.Scenes
129 public bool m_strictAccessControl = true; 130 public bool m_strictAccessControl = true;
130 public bool m_seeIntoBannedRegion = false; 131 public bool m_seeIntoBannedRegion = false;
131 public int MaxUndoCount = 5; 132 public int MaxUndoCount = 5;
133
132 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 134 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
133 public bool LoginLock = false; 135 public bool LoginLock = false;
134 public bool LoginsDisabled = true; 136
135 public bool StartDisabled = false; 137 public bool StartDisabled = false;
136 public bool LoadingPrims; 138 public bool LoadingPrims;
137 public IXfer XferManager; 139 public IXfer XferManager;
@@ -727,6 +729,8 @@ namespace OpenSim.Region.Framework.Scenes
727 { 729 {
728 IConfig startupConfig = m_config.Configs["Startup"]; 730 IConfig startupConfig = m_config.Configs["Startup"];
729 731
732 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
733
730 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); 734 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
731 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); 735 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
732 if (!m_useBackup) 736 if (!m_useBackup)
@@ -1229,15 +1233,17 @@ namespace OpenSim.Region.Framework.Scenes
1229 avatar.ControllingClient.SendShutdownConnectionNotice(); 1233 avatar.ControllingClient.SendShutdownConnectionNotice();
1230 }); 1234 });
1231 1235
1236 // Stop updating the scene objects and agents.
1237 m_shuttingDown = true;
1238
1232 // Wait here, or the kick messages won't actually get to the agents before the scene terminates. 1239 // Wait here, or the kick messages won't actually get to the agents before the scene terminates.
1240 // We also need to wait to avoid a race condition with the scene update loop which might not yet
1241 // have checked ShuttingDown.
1233 Thread.Sleep(500); 1242 Thread.Sleep(500);
1234 1243
1235 // Stop all client threads. 1244 // Stop all client threads.
1236 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1245 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); });
1237 1246
1238 // Stop updating the scene objects and agents.
1239 m_shuttingDown = true;
1240
1241 m_log.Debug("[SCENE]: Persisting changed objects"); 1247 m_log.Debug("[SCENE]: Persisting changed objects");
1242 EventManager.TriggerSceneShuttingDown(this); 1248 EventManager.TriggerSceneShuttingDown(this);
1243 1249
@@ -1252,6 +1258,15 @@ namespace OpenSim.Region.Framework.Scenes
1252 1258
1253 m_sceneGraph.Close(); 1259 m_sceneGraph.Close();
1254 1260
1261 if (PhysicsScene != null)
1262 {
1263 PhysicsScene phys = PhysicsScene;
1264 // remove the physics engine from both Scene and SceneGraph
1265 PhysicsScene = null;
1266 phys.Dispose();
1267 phys = null;
1268 }
1269
1255 if (!GridService.DeregisterRegion(RegionInfo.RegionID)) 1270 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1256 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); 1271 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1257 1272
@@ -1530,7 +1545,7 @@ namespace OpenSim.Region.Framework.Scenes
1530 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1545 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1531 //} 1546 //}
1532 1547
1533 if (LoginsDisabled && Frame == 20) 1548 if (!LoginsEnabled && Frame == 20)
1534 { 1549 {
1535 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); 1550 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
1536 1551
@@ -1538,31 +1553,34 @@ namespace OpenSim.Region.Framework.Scenes
1538 // this is a rare case where we know we have just went through a long cycle of heap 1553 // this is a rare case where we know we have just went through a long cycle of heap
1539 // allocations, and there is no more work to be done until someone logs in 1554 // allocations, and there is no more work to be done until someone logs in
1540 GC.Collect(); 1555 GC.Collect();
1541 1556
1542 IConfig startupConfig = m_config.Configs["Startup"]; 1557 if (!LoginLock)
1543 if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
1544 { 1558 {
1545 // This handles a case of a region having no scripts for the RegionReady module 1559 if (!StartDisabled)
1546 if (m_sceneGraph.GetActiveScriptsCount() == 0)
1547 {
1548 // need to be able to tell these have changed in RegionReady
1549 LoginLock = false;
1550 EventManager.TriggerLoginsEnabled(RegionInfo.RegionName);
1551 }
1552
1553 // For RegionReady lockouts
1554 if (!LoginLock)
1555 { 1560 {
1556 m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); 1561 m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1557 LoginsDisabled = false; 1562 LoginsEnabled = true;
1558 } 1563 }
1559 1564
1560 m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); 1565 m_sceneGridService.InformNeighborsThatRegionisUp(
1566 RequestModuleInterface<INeighbourService>(), RegionInfo);
1567
1568 // Region ready should always be set
1569 Ready = true;
1561 } 1570 }
1562 else 1571 else
1563 { 1572 {
1564 StartDisabled = true; 1573 // This handles a case of a region having no scripts for the RegionReady module
1565 LoginsDisabled = true; 1574 if (m_sceneGraph.GetActiveScriptsCount() == 0)
1575 {
1576 // In this case, we leave it to the IRegionReadyModule to enable logins
1577
1578 // LoginLock can currently only be set by a region module implementation.
1579 // If somehow this hasn't been done then the quickest way to bugfix is to see the
1580 // NullReferenceException
1581 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>();
1582 rrm.TriggerRegionReady(this);
1583 }
1566 } 1584 }
1567 } 1585 }
1568 } 1586 }
@@ -3477,25 +3495,31 @@ namespace OpenSim.Region.Framework.Scenes
3477 if (AgentTransactionsModule != null) 3495 if (AgentTransactionsModule != null)
3478 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3496 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3479 3497
3480 avatar.Close();
3481
3482 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3498 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3483 m_log.Debug("[Scene] The avatar has left the building"); 3499 m_log.Debug("[Scene] The avatar has left the building");
3484 } 3500 }
3485 catch (Exception e) 3501 catch (Exception e)
3486 { 3502 {
3487 m_log.Error( 3503 m_log.Error(
3488 string.Format("[SCENE]: Exception removing {0} from {1}, ", avatar.Name, RegionInfo.RegionName), e); 3504 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
3489 } 3505 }
3490 finally 3506 finally
3491 { 3507 {
3492 // Always clean these structures up so that any failure above doesn't cause them to remain in the 3508 try
3493 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering 3509 {
3494 // the same cleanup exception continually. 3510 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3495 // TODO: This should probably extend to the whole method, but we don't want to also catch the NRE 3511 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3496 // since this would hide the underlying failure and other associated problems. 3512 // the same cleanup exception continually.
3497 m_sceneGraph.RemoveScenePresence(agentID); 3513 m_sceneGraph.RemoveScenePresence(agentID);
3498 m_clientManager.Remove(agentID); 3514 m_clientManager.Remove(agentID);
3515
3516 avatar.Close();
3517 }
3518 catch (Exception e)
3519 {
3520 m_log.Error(
3521 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3522 }
3499 } 3523 }
3500 3524
3501 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3525 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
@@ -3609,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes
3609 agent.startpos 3633 agent.startpos
3610 ); 3634 );
3611 3635
3612 if (LoginsDisabled) 3636 if (!LoginsEnabled)
3613 { 3637 {
3614 reason = "Logins Disabled"; 3638 reason = "Logins Disabled";
3615 return false; 3639 return false;
@@ -3666,8 +3690,8 @@ namespace OpenSim.Region.Framework.Scenes
3666 // We have a zombie from a crashed session. 3690 // We have a zombie from a crashed session.
3667 // Or the same user is trying to be root twice here, won't work. 3691 // Or the same user is trying to be root twice here, won't work.
3668 // Kill it. 3692 // Kill it.
3669 m_log.DebugFormat( 3693 m_log.WarnFormat(
3670 "[SCENE]: Zombie scene presence detected for {0} {1} in {2}", 3694 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3671 sp.Name, sp.UUID, RegionInfo.RegionName); 3695 sp.Name, sp.UUID, RegionInfo.RegionName);
3672 3696
3673 sp.ControllingClient.Close(); 3697 sp.ControllingClient.Close();
@@ -4658,6 +4682,23 @@ namespace OpenSim.Region.Framework.Scenes
4658 } 4682 }
4659 4683
4660 /// <summary> 4684 /// <summary>
4685 /// Gets all the scene presences in this scene.
4686 /// </summary>
4687 /// <remarks>
4688 /// This method will return both root and child scene presences.
4689 ///
4690 /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not
4691 /// involving creating a new List object.
4692 /// </remarks>
4693 /// <returns>
4694 /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene.
4695 /// </returns>
4696 public List<ScenePresence> GetScenePresences()
4697 {
4698 return new List<ScenePresence>(m_sceneGraph.GetScenePresences());
4699 }
4700
4701 /// <summary>
4661 /// Performs action on all avatars in the scene (root scene presences) 4702 /// Performs action on all avatars in the scene (root scene presences)
4662 /// Avatars may be an NPC or a 'real' client. 4703 /// Avatars may be an NPC or a 'real' client.
4663 /// </summary> 4704 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 8db4397..7c8bd88 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -106,6 +106,42 @@ namespace OpenSim.Region.Framework.Scenes
106 106
107 protected readonly ClientManager m_clientManager = new ClientManager(); 107 protected readonly ClientManager m_clientManager = new ClientManager();
108 108
109 public bool LoginsEnabled
110 {
111 get
112 {
113 return m_loginsEnabled;
114 }
115
116 set
117 {
118 if (m_loginsEnabled != value)
119 {
120 m_loginsEnabled = value;
121 EventManager.TriggerRegionLoginsStatusChange(this);
122 }
123 }
124 }
125 private bool m_loginsEnabled;
126
127 public bool Ready
128 {
129 get
130 {
131 return m_ready;
132 }
133
134 set
135 {
136 if (m_ready != value)
137 {
138 m_ready = value;
139 EventManager.TriggerRegionReadyStatusChange(this);
140 }
141 }
142 }
143 private bool m_ready;
144
109 public float TimeDilation 145 public float TimeDilation
110 { 146 {
111 get { return 1.0f; } 147 get { return 1.0f; }
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index c3d66eb..e0260e2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -848,7 +848,7 @@ namespace OpenSim.Region.Framework.Scenes
848 /// pass a delegate to ForEachScenePresence. 848 /// pass a delegate to ForEachScenePresence.
849 /// </summary> 849 /// </summary>
850 /// <returns></returns> 850 /// <returns></returns>
851 private List<ScenePresence> GetScenePresences() 851 protected internal List<ScenePresence> GetScenePresences()
852 { 852 {
853 return m_scenePresenceArray; 853 return m_scenePresenceArray;
854 } 854 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index e3fed49..f1b09ca 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -47,6 +47,48 @@ namespace OpenSim.Region.Framework.Scenes
47 47
48 public event RestartSim OnRestartSim; 48 public event RestartSim OnRestartSim;
49 49
50 /// <summary>
51 /// Fired when either all regions are ready for use or at least one region has become unready for use where
52 /// previously all regions were ready.
53 /// </summary>
54 public event Action<SceneManager> OnRegionsReadyStatusChange;
55
56 /// <summary>
57 /// Are all regions ready for use?
58 /// </summary>
59 public bool AllRegionsReady
60 {
61 get
62 {
63 return m_allRegionsReady;
64 }
65
66 private set
67 {
68 if (m_allRegionsReady != value)
69 {
70 m_allRegionsReady = value;
71 Action<SceneManager> handler = OnRegionsReadyStatusChange;
72 if (handler != null)
73 {
74 foreach (Action<SceneManager> d in handler.GetInvocationList())
75 {
76 try
77 {
78 d(this);
79 }
80 catch (Exception e)
81 {
82 m_log.ErrorFormat("[SCENE MANAGER]: Delegate for OnRegionsReadyStatusChange failed - continuing {0} - {1}",
83 e.Message, e.StackTrace);
84 }
85 }
86 }
87 }
88 }
89 }
90 private bool m_allRegionsReady;
91
50 private static SceneManager m_instance = null; 92 private static SceneManager m_instance = null;
51 public static SceneManager Instance 93 public static SceneManager Instance
52 { 94 {
@@ -128,9 +170,11 @@ namespace OpenSim.Region.Framework.Scenes
128 170
129 public void Add(Scene scene) 171 public void Add(Scene scene)
130 { 172 {
131 scene.OnRestart += HandleRestart; 173 lock (m_localScenes)
174 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
132 175
133 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene); 176 scene.OnRestart += HandleRestart;
177 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange;
134 } 178 }
135 179
136 public void HandleRestart(RegionInfo rdata) 180 public void HandleRestart(RegionInfo rdata)
@@ -138,12 +182,19 @@ namespace OpenSim.Region.Framework.Scenes
138 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); 182 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main");
139 int RegionSceneElement = -1; 183 int RegionSceneElement = -1;
140 184
141 m_localScenes.Remove(rdata.RegionID); 185 lock (m_localScenes)
186 m_localScenes.Remove(rdata.RegionID);
142 187
143 // Send signal to main that we're restarting this sim. 188 // Send signal to main that we're restarting this sim.
144 OnRestartSim(rdata); 189 OnRestartSim(rdata);
145 } 190 }
146 191
192 private void HandleRegionReadyStatusChange(IScene scene)
193 {
194 lock (m_localScenes)
195 AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0;
196 }
197
147 public void SendSimOnlineNotification(ulong regionHandle) 198 public void SendSimOnlineNotification(ulong regionHandle)
148 { 199 {
149 RegionInfo Result = null; 200 RegionInfo Result = null;
@@ -483,7 +534,8 @@ namespace OpenSim.Region.Framework.Scenes
483 534
484 public void CloseScene(Scene scene) 535 public void CloseScene(Scene scene)
485 { 536 {
486 m_localScenes.Remove(scene.RegionInfo.RegionID); 537 lock (m_localScenes)
538 m_localScenes.Remove(scene.RegionInfo.RegionID);
487 539
488 scene.Close(); 540 scene.Close();
489 } 541 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 6ab0027..08c7a58 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1991,7 +1991,7 @@ namespace OpenSim.Region.Framework.Scenes
1991 try 1991 try
1992 { 1992 {
1993 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart 1993 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1994 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things 1994 !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things
1995 m_scene.LoadingPrims) // Land may not be valid yet 1995 m_scene.LoadingPrims) // Land may not be valid yet
1996 1996
1997 { 1997 {
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cdabd45..4d3ab51 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -110,15 +110,10 @@ namespace OpenSim.Region.Framework.Scenes
110 110
111 public UUID currentParcelUUID = UUID.Zero; 111 public UUID currentParcelUUID = UUID.Zero;
112 112
113 protected ScenePresenceAnimator m_animator;
114 /// <value> 113 /// <value>
115 /// The animator for this avatar 114 /// The animator for this avatar
116 /// </value> 115 /// </value>
117 public ScenePresenceAnimator Animator 116 public ScenePresenceAnimator Animator { get; private set; }
118 {
119 get { return m_animator; }
120 private set { m_animator = value; }
121 }
122 117
123 /// <summary> 118 /// <summary>
124 /// Attachments recorded on this avatar. 119 /// Attachments recorded on this avatar.
@@ -2763,8 +2758,7 @@ namespace OpenSim.Region.Framework.Scenes
2763 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 2758 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
2764 2759
2765 avatar.ControllingClient.SendAvatarDataImmediate(this); 2760 avatar.ControllingClient.SendAvatarDataImmediate(this);
2766 if (Animator != null) 2761 Animator.SendAnimPackToClient(avatar.ControllingClient);
2767 Animator.SendAnimPackToClient(avatar.ControllingClient);
2768 } 2762 }
2769 2763
2770 /// <summary> 2764 /// <summary>
@@ -3440,6 +3434,16 @@ namespace OpenSim.Region.Framework.Scenes
3440 if (IsChildAgent) 3434 if (IsChildAgent)
3441 return; 3435 return;
3442 3436
3437 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3438 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3439 // as of this comment the interval is set in AddToPhysicalScene
3440
3441// if (m_updateCount > 0)
3442// {
3443 Animator.UpdateMovementAnimations();
3444// m_updateCount--;
3445// }
3446
3443 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3447 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3444 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3448 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3445 3449
@@ -3453,7 +3457,7 @@ namespace OpenSim.Region.Framework.Scenes
3453// m_lastColCount = coldata.Count; 3457// m_lastColCount = coldata.Count;
3454// } 3458// }
3455 3459
3456 if (coldata.Count != 0 && Animator != null) 3460 if (coldata.Count != 0)
3457 { 3461 {
3458 switch (Animator.CurrentMovementAnimation) 3462 switch (Animator.CurrentMovementAnimation)
3459 { 3463 {
@@ -3565,7 +3569,7 @@ namespace OpenSim.Region.Framework.Scenes
3565 ControllingClient.SendHealth(Health); 3569 ControllingClient.SendHealth(Health);
3566 } 3570 }
3567 3571
3568 public void Close() 3572 protected internal void Close()
3569 { 3573 {
3570 // Clear known regions 3574 // Clear known regions
3571 KnownRegions = new Dictionary<ulong, string>(); 3575 KnownRegions = new Dictionary<ulong, string>();
@@ -3581,9 +3585,6 @@ namespace OpenSim.Region.Framework.Scenes
3581 // m_reprioritizationTimer.Dispose(); 3585 // m_reprioritizationTimer.Dispose();
3582 3586
3583 RemoveFromPhysicalScene(); 3587 RemoveFromPhysicalScene();
3584 if(Animator != null)
3585 Animator.Close();
3586 Animator = null;
3587 } 3588 }
3588 3589
3589 public void AddAttachment(SceneObjectGroup gobj) 3590 public void AddAttachment(SceneObjectGroup gobj)
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index d6ff5a2..20919a1 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -30,7 +30,7 @@ using System.Collections.Generic;
30using System.Timers; 30using System.Timers;
31using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Statistics; 33using OpenSim.Framework.Monitoring;
34using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35 35
36namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 02c45ef..5758869 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -53,62 +53,94 @@ namespace OpenSim.Region.Framework.Scenes.Tests
53 /// Scene presence tests 53 /// Scene presence tests
54 /// </summary> 54 /// </summary>
55 [TestFixture] 55 [TestFixture]
56 public class ScenePresenceAgentTests 56 public class ScenePresenceAgentTests : OpenSimTestCase
57 { 57 {
58 public Scene scene, scene2, scene3; 58// public Scene scene, scene2, scene3;
59 public UUID agent1, agent2, agent3; 59// public UUID agent1, agent2, agent3;
60 public static Random random; 60// public static Random random;
61 public ulong region1,region2,region3; 61// public ulong region1, region2, region3;
62 public AgentCircuitData acd1; 62// public AgentCircuitData acd1;
63 public SceneObjectGroup sog1, sog2, sog3; 63// public TestClient testclient;
64 public TestClient testclient; 64
65 65// [TestFixtureSetUp]
66 [TestFixtureSetUp] 66// public void Init()
67 public void Init() 67// {
68//// TestHelpers.InMethod();
69////
70//// SceneHelpers sh = new SceneHelpers();
71////
72//// scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000);
73//// scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000);
74//// scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000);
75////
76//// ISharedRegionModule interregionComms = new LocalSimulationConnectorModule();
77//// interregionComms.Initialise(new IniConfigSource());
78//// interregionComms.PostInitialise();
79//// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms);
80//// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms);
81//// SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms);
82//
83//// agent1 = UUID.Random();
84//// agent2 = UUID.Random();
85//// agent3 = UUID.Random();
86//
87//// region1 = scene.RegionInfo.RegionHandle;
88//// region2 = scene2.RegionInfo.RegionHandle;
89//// region3 = scene3.RegionInfo.RegionHandle;
90// }
91
92 [Test]
93 public void TestCreateRootScenePresence()
68 { 94 {
69 TestHelpers.InMethod(); 95 TestHelpers.InMethod();
96// TestHelpers.EnableLogging();
97
98 UUID spUuid = TestHelpers.ParseTail(0x1);
70 99
71 SceneHelpers sh = new SceneHelpers(); 100 TestScene scene = new SceneHelpers().SetupScene();
72 101 SceneHelpers.AddScenePresence(scene, spUuid);
73 scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); 102
74 scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); 103 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
75 scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); 104 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
76 105
77 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); 106 ScenePresence sp = scene.GetScenePresence(spUuid);
78 interregionComms.Initialise(new IniConfigSource()); 107 Assert.That(sp, Is.Not.Null);
79 interregionComms.PostInitialise(); 108 Assert.That(sp.IsChildAgent, Is.False);
80 SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); 109 Assert.That(sp.UUID, Is.EqualTo(spUuid));
81 SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); 110
82 SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); 111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
83
84 agent1 = UUID.Random();
85 agent2 = UUID.Random();
86 agent3 = UUID.Random();
87 random = new Random();
88 sog1 = SceneHelpers.CreateSceneObject(1, agent1);
89 scene.AddSceneObject(sog1);
90 sog2 = SceneHelpers.CreateSceneObject(1, agent1);
91 scene.AddSceneObject(sog2);
92 sog3 = SceneHelpers.CreateSceneObject(1, agent1);
93 scene.AddSceneObject(sog3);
94
95 region1 = scene.RegionInfo.RegionHandle;
96 region2 = scene2.RegionInfo.RegionHandle;
97 region3 = scene3.RegionInfo.RegionHandle;
98 } 112 }
99 113
100 [Test] 114 [Test]
101 public void TestCloseAgent() 115 public void TestCreateDuplicateRootScenePresence()
102 { 116 {
103 TestHelpers.InMethod(); 117 TestHelpers.InMethod();
104// TestHelpers.EnableLogging(); 118// TestHelpers.EnableLogging();
105 119
120 UUID spUuid = TestHelpers.ParseTail(0x1);
121
106 TestScene scene = new SceneHelpers().SetupScene(); 122 TestScene scene = new SceneHelpers().SetupScene();
107 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 123 SceneHelpers.AddScenePresence(scene, spUuid);
124 SceneHelpers.AddScenePresence(scene, spUuid);
108 125
109 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null); 126 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
110 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 127 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
111 128
129 ScenePresence sp = scene.GetScenePresence(spUuid);
130 Assert.That(sp, Is.Not.Null);
131 Assert.That(sp.IsChildAgent, Is.False);
132 Assert.That(sp.UUID, Is.EqualTo(spUuid));
133 }
134
135 [Test]
136 public void TestCloseAgent()
137 {
138 TestHelpers.InMethod();
139// TestHelpers.EnableLogging();
140
141 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143
112 scene.IncomingCloseAgent(sp.UUID); 144 scene.IncomingCloseAgent(sp.UUID);
113 145
114 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
@@ -266,99 +298,99 @@ namespace OpenSim.Region.Framework.Scenes.Tests
266 // but things are synchronous among them. So there should be 298 // but things are synchronous among them. So there should be
267 // 3 threads in here. 299 // 3 threads in here.
268 //[Test] 300 //[Test]
269 public void T021_TestCrossToNewRegion() 301// public void T021_TestCrossToNewRegion()
270 { 302// {
271 TestHelpers.InMethod(); 303// TestHelpers.InMethod();
272 304//
273 scene.RegisterRegionWithGrid(); 305// scene.RegisterRegionWithGrid();
274 scene2.RegisterRegionWithGrid(); 306// scene2.RegisterRegionWithGrid();
275 307//
276 // Adding child agent to region 1001 308// // Adding child agent to region 1001
277 string reason; 309// string reason;
278 scene2.NewUserConnection(acd1,0, out reason); 310// scene2.NewUserConnection(acd1,0, out reason);
279 scene2.AddNewClient(testclient, PresenceType.User); 311// scene2.AddNewClient(testclient, PresenceType.User);
280 312//
281 ScenePresence presence = scene.GetScenePresence(agent1); 313// ScenePresence presence = scene.GetScenePresence(agent1);
282 presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); 314// presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true);
283 315//
284 ScenePresence presence2 = scene2.GetScenePresence(agent1); 316// ScenePresence presence2 = scene2.GetScenePresence(agent1);
285 317//
286 // Adding neighbour region caps info to presence2 318// // Adding neighbour region caps info to presence2
287 319//
288 string cap = presence.ControllingClient.RequestClientInfo().CapsPath; 320// string cap = presence.ControllingClient.RequestClientInfo().CapsPath;
289 presence2.AddNeighbourRegion(region1, cap); 321// presence2.AddNeighbourRegion(region1, cap);
290 322//
291 Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); 323// Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region.");
292 Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); 324// Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region.");
293 325//
294 // Cross to x+1 326// // Cross to x+1
295 presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); 327// presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100);
296 presence.Update(); 328// presence.Update();
297 329//
298 EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); 330// EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
299 331//
300 // Mimicking communication between client and server, by waiting OK from client 332// // Mimicking communication between client and server, by waiting OK from client
301 // sent by TestClient.CrossRegion call. Originally, this is network comm. 333// // sent by TestClient.CrossRegion call. Originally, this is network comm.
302 if (!wh.WaitOne(5000,false)) 334// if (!wh.WaitOne(5000,false))
303 { 335// {
304 presence.Update(); 336// presence.Update();
305 if (!wh.WaitOne(8000,false)) 337// if (!wh.WaitOne(8000,false))
306 throw new ArgumentException("1 - Timeout waiting for signal/variable."); 338// throw new ArgumentException("1 - Timeout waiting for signal/variable.");
307 } 339// }
308 340//
309 // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which 341// // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which
310 // would normally be fired after receiving the reply packet from comm. done on the last line. 342// // would normally be fired after receiving the reply packet from comm. done on the last line.
311 testclient.CompleteMovement(); 343// testclient.CompleteMovement();
312 344//
313 // Crossings are asynchronous 345// // Crossings are asynchronous
314 int timer = 10; 346// int timer = 10;
315 347//
316 // Make sure cross hasn't already finished 348// // Make sure cross hasn't already finished
317 if (!presence.IsInTransit && !presence.IsChildAgent) 349// if (!presence.IsInTransit && !presence.IsChildAgent)
318 { 350// {
319 // If not and not in transit yet, give it some more time 351// // If not and not in transit yet, give it some more time
320 Thread.Sleep(5000); 352// Thread.Sleep(5000);
321 } 353// }
322 354//
323 // Enough time, should at least be in transit by now. 355// // Enough time, should at least be in transit by now.
324 while (presence.IsInTransit && timer > 0) 356// while (presence.IsInTransit && timer > 0)
325 { 357// {
326 Thread.Sleep(1000); 358// Thread.Sleep(1000);
327 timer-=1; 359// timer-=1;
328 } 360// }
329 361//
330 Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); 362// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1.");
331 Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); 363// Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected.");
332 Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); 364// Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent.");
333 365//
334 // Cross Back 366// // Cross Back
335 presence2.AbsolutePosition = new Vector3(-10, 3, 100); 367// presence2.AbsolutePosition = new Vector3(-10, 3, 100);
336 presence2.Update(); 368// presence2.Update();
337 369//
338 if (!wh.WaitOne(5000,false)) 370// if (!wh.WaitOne(5000,false))
339 { 371// {
340 presence2.Update(); 372// presence2.Update();
341 if (!wh.WaitOne(8000,false)) 373// if (!wh.WaitOne(8000,false))
342 throw new ArgumentException("2 - Timeout waiting for signal/variable."); 374// throw new ArgumentException("2 - Timeout waiting for signal/variable.");
343 } 375// }
344 testclient.CompleteMovement(); 376// testclient.CompleteMovement();
345 377//
346 if (!presence2.IsInTransit && !presence2.IsChildAgent) 378// if (!presence2.IsInTransit && !presence2.IsChildAgent)
347 { 379// {
348 // If not and not in transit yet, give it some more time 380// // If not and not in transit yet, give it some more time
349 Thread.Sleep(5000); 381// Thread.Sleep(5000);
350 } 382// }
351 383//
352 // Enough time, should at least be in transit by now. 384// // Enough time, should at least be in transit by now.
353 while (presence2.IsInTransit && timer > 0) 385// while (presence2.IsInTransit && timer > 0)
354 { 386// {
355 Thread.Sleep(1000); 387// Thread.Sleep(1000);
356 timer-=1; 388// timer-=1;
357 } 389// }
358 390//
359 Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); 391// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2.");
360 Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); 392// Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected.");
361 Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); 393// Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again.");
362 } 394// }
363 } 395 }
364} \ No newline at end of file 396} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index a407f01..37b5184 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -301,7 +301,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
301 sp.AbsolutePosition = preTeleportPosition; 301 sp.AbsolutePosition = preTeleportPosition;
302 302
303 // Make sceneB refuse CreateAgent 303 // Make sceneB refuse CreateAgent
304 sceneB.LoginsDisabled = true; 304 sceneB.LoginsEnabled = false;
305 305
306 sceneA.RequestTeleportLocation( 306 sceneA.RequestTeleportLocation(
307 sp.ControllingClient, 307 sp.ControllingClient,
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 86f33eb..3b83e58 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -38,6 +38,7 @@ using OpenMetaverse;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Client; 40using OpenSim.Framework.Client;
41using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42 43
43namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server 44namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
index a7c5020..9d27386 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
@@ -34,6 +34,7 @@ using System.Text;
34using System.Threading; 34using System.Threading;
35using log4net; 35using log4net;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Monitoring;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
38 39
39namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server 40namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index a7ebecc..5fe5948 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -35,7 +35,7 @@ using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Console; 37using OpenSim.Framework.Console;
38using OpenSim.Framework.Statistics; 38using OpenSim.Framework.Monitoring;
39using OpenSim.Region.ClientStack.LindenUDP; 39using OpenSim.Region.ClientStack.LindenUDP;
40using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
@@ -82,18 +82,6 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
82 m_scenes[scene.RegionInfo.RegionID] = scene; 82 m_scenes[scene.RegionInfo.RegionID] = scene;
83 83
84 scene.AddCommand( 84 scene.AddCommand(
85 "Comms", this, "image queues clear",
86 "image queues clear <first-name> <last-name>",
87 "Clear the image queues (textures downloaded via UDP) for a particular client.",
88 (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd)));
89
90 scene.AddCommand(
91 "Comms", this, "image queues show",
92 "image queues show <first-name> <last-name>",
93 "Show the image queues (textures downloaded via UDP) for a particular client.",
94 (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd)));
95
96 scene.AddCommand(
97 "Comms", this, "show pqueues", 85 "Comms", this, "show pqueues",
98 "show pqueues [full]", 86 "show pqueues [full]",
99 "Show priority queue data for each client", 87 "Show priority queue data for each client",
@@ -105,8 +93,15 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
105 "Comms", this, "show queues", 93 "Comms", this, "show queues",
106 "show queues [full]", 94 "show queues [full]",
107 "Show queue data for each client", 95 "Show queue data for each client",
108 "Without the 'full' option, only root agents are shown." 96 "Without the 'full' option, only root agents are shown.\n"
109 + " With the 'full' option child agents are also shown.", 97 + "With the 'full' option child agents are also shown.\n\n"
98 + "Type - Rt is a root (avatar) client whilst cd is a child (neighbour interacting) client.\n"
99 + "Since Last In - Time in milliseconds since last packet received.\n"
100 + "Pkts In - Number of packets processed from the client.\n"
101 + "Pkts Out - Number of packets sent to the client.\n"
102 + "Pkts Resent - Number of packets resent to the client.\n"
103 + "Bytes Unacked - Number of bytes transferred to the client that are awaiting acknowledgement.\n"
104 + "Q Pkts * - Number of packets of various types (land, wind, etc.) to be sent to the client that are waiting for available bandwidth.\n",
110 (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd))); 105 (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd)));
111 106
112 scene.AddCommand( 107 scene.AddCommand(
@@ -114,6 +109,12 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
114 "show image queues <first-name> <last-name>", 109 "show image queues <first-name> <last-name>",
115 "Show the image queues (textures downloaded via UDP) for a particular client.", 110 "Show the image queues (textures downloaded via UDP) for a particular client.",
116 (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); 111 (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd)));
112
113 scene.AddCommand(
114 "Comms", this, "clear image queues",
115 "clear image queues <first-name> <last-name>",
116 "Clear the image queues (textures downloaded via UDP) for a particular client.",
117 (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd)));
117 118
118 scene.AddCommand( 119 scene.AddCommand(
119 "Comms", this, "show throttles", 120 "Comms", this, "show throttles",
@@ -373,17 +374,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
373 int maxNameLength = 18; 374 int maxNameLength = 18;
374 int maxRegionNameLength = 14; 375 int maxRegionNameLength = 14;
375 int maxTypeLength = 4; 376 int maxTypeLength = 4;
376 int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding; 377
378 int totalInfoFieldsLength
379 = maxNameLength + columnPadding
380 + maxRegionNameLength + columnPadding
381 + maxTypeLength + columnPadding;
377 382
378 report.Append(GetColumnEntry("User", maxNameLength, columnPadding)); 383 report.Append(GetColumnEntry("User", maxNameLength, columnPadding));
379 report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding)); 384 report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding));
380 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); 385 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
381 386
382 report.AppendFormat( 387 report.AppendFormat(
383 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", 388 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n",
389 "Since",
390 "Pkts",
384 "Pkts", 391 "Pkts",
385 "Pkts", 392 "Pkts",
386 "Pkts",
387 "Bytes", 393 "Bytes",
388 "Q Pkts", 394 "Q Pkts",
389 "Q Pkts", 395 "Q Pkts",
@@ -396,7 +402,8 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
396 402
397 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); 403 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
398 report.AppendFormat( 404 report.AppendFormat(
399 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", 405 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n",
406 "Last In",
400 "In", 407 "In",
401 "Out", 408 "Out",
402 "Resent", 409 "Resent",
@@ -417,22 +424,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
417 scene.ForEachClient( 424 scene.ForEachClient(
418 delegate(IClientAPI client) 425 delegate(IClientAPI client)
419 { 426 {
420 if (client is IStatsCollector) 427 bool isChild = client.SceneAgent.IsChildAgent;
421 { 428 if (isChild && !showChildren)
422 bool isChild = client.SceneAgent.IsChildAgent; 429 return;
423 if (isChild && !showChildren) 430
424 return; 431 string name = client.Name;
425 432 if (pname != "" && name != pname)
426 string name = client.Name; 433 return;
427 if (pname != "" && name != pname)
428 return;
429 434
430 string regionName = scene.RegionInfo.RegionName; 435 string regionName = scene.RegionInfo.RegionName;
431 436
432 report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); 437 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
433 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); 438 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
434 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); 439 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
435 440
441 if (client is IStatsCollector)
442 {
436 IStatsCollector stats = (IStatsCollector)client; 443 IStatsCollector stats = (IStatsCollector)client;
437 444
438 report.AppendLine(stats.Report()); 445 report.AppendLine(stats.Report());
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
index 6bb6729..d718a2f 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
@@ -36,7 +36,7 @@ using Nini.Config;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Console; 38using OpenSim.Framework.Console;
39using OpenSim.Framework.Statistics; 39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP; 40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
index 1b9e3ac..d68aabc 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
@@ -36,7 +36,7 @@ using Nini.Config;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Console; 38using OpenSim.Framework.Console;
39using OpenSim.Framework.Statistics; 39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP; 40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index cd401a6..ca956fb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -37,6 +37,7 @@ using OpenMetaverse;
37using log4net; 37using log4net;
38using Nini.Config; 38using Nini.Config;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Monitoring;
40using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42 43
diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
index 2602050..4e84364 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.ClientStack.LindenUDP; 41using OpenSim.Region.ClientStack.LindenUDP;
42using OpenSim.Region.CoreModules.Avatar.Friends; 42using OpenSim.Region.CoreModules.Avatar.Friends;
43using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
index e452124..40f7fbc 100755
--- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
+++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")]
48 public class PhysicsParameters : ISharedRegionModule 48 public class PhysicsParameters : ISharedRegionModule
49 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51// private static string LogHeader = "[PHYSICS PARAMETERS]"; 51// private static string LogHeader = "[PHYSICS PARAMETERS]";
52 52
53 private List<Scene> m_scenes = new List<Scene>(); 53 private List<Scene> m_scenes = new List<Scene>();
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index 600cafb..fff3a32 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -31,16 +31,14 @@ using System.Reflection;
31using System.Net; 31using System.Net;
32using System.IO; 32using System.IO;
33using System.Text; 33using System.Text;
34
35using log4net; 34using log4net;
36using Nini.Config; 35using Nini.Config;
37using OpenMetaverse; 36using OpenMetaverse;
38using OpenMetaverse.StructuredData; 37using OpenMetaverse.StructuredData;
39using OpenSim.Services.Interfaces;
40
41using OpenSim.Framework; 38using OpenSim.Framework;
42using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
44 42
45namespace OpenSim.Region.OptionalModules.Scripting.RegionReady 43namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
46{ 44{
@@ -50,16 +48,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 49
52 private IConfig m_config = null; 50 private IConfig m_config = null;
53 private bool m_ScriptRez;
54 private bool m_firstEmptyCompileQueue; 51 private bool m_firstEmptyCompileQueue;
55 private bool m_oarFileLoading; 52 private bool m_oarFileLoading;
56 private bool m_lastOarLoadedOk; 53 private bool m_lastOarLoadedOk;
57 private int m_channelNotify = -1000; 54 private int m_channelNotify = -1000;
58 private bool m_enabled = false; 55 private bool m_enabled = false;
59 private bool m_disable_logins = false; 56 private bool m_disable_logins;
60 private string m_uri = string.Empty; 57 private string m_uri = string.Empty;
61 58
62 Scene m_scene = null; 59 Scene m_scene;
63 60
64 #region INonSharedRegionModule interface 61 #region INonSharedRegionModule interface
65 62
@@ -93,53 +90,40 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
93 90
94 m_scene.RegisterModuleInterface<IRegionReadyModule>(this); 91 m_scene.RegisterModuleInterface<IRegionReadyModule>(this);
95 92
96 m_ScriptRez = false;
97 m_firstEmptyCompileQueue = true; 93 m_firstEmptyCompileQueue = true;
98 m_oarFileLoading = false; 94 m_oarFileLoading = false;
99 m_lastOarLoadedOk = true; 95 m_lastOarLoadedOk = true;
100 96
101 m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; 97 m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded;
102 m_scene.EventManager.OnRezScript += OnRezScript;
103 m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
104 98
105 m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); 99 m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName);
106 100
107 if (m_disable_logins == true) 101 if (m_disable_logins)
108 { 102 {
109 scene.LoginLock = true; 103 m_scene.LoginLock = true;
110 scene.LoginsDisabled = true; 104 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
111 m_log.InfoFormat("[RegionReady]: Region {0} - logins disabled during initialization.",m_scene.RegionInfo.RegionName); 105
106 m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name);
112 107
113 if(m_uri != string.Empty) 108 if (m_uri != string.Empty)
114 { 109 {
115 RRAlert("disabled"); 110 RRAlert("disabled");
116 } 111 }
117 } 112 }
118 } 113 }
119 114
120 void OnRezScript (uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
121 {
122 if (!m_ScriptRez)
123 {
124 m_ScriptRez = true;
125 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
126 m_scene.EventManager.OnRezScript -= OnRezScript;
127 }
128 }
129
130 public void RemoveRegion(Scene scene) 115 public void RemoveRegion(Scene scene)
131 { 116 {
132 if (!m_enabled) 117 if (!m_enabled)
133 return; 118 return;
134 119
135 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
136 m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; 120 m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded;
137 m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled;
138 121
139 if(m_uri != string.Empty) 122 if (m_disable_logins)
140 { 123 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
124
125 if (m_uri != string.Empty)
141 RRAlert("shutdown"); 126 RRAlert("shutdown");
142 }
143 127
144 m_scene = null; 128 m_scene = null;
145 } 129 }
@@ -159,7 +143,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
159 143
160 #endregion 144 #endregion
161 145
162
163 void OnEmptyScriptCompileQueue(int numScriptsFailed, string message) 146 void OnEmptyScriptCompileQueue(int numScriptsFailed, string message)
164 { 147 {
165 m_log.DebugFormat("[RegionReady]: Script compile queue empty!"); 148 m_log.DebugFormat("[RegionReady]: Script compile queue empty!");
@@ -193,75 +176,80 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
193 m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); 176 m_scene.RegionInfo.RegionName, c.Message, m_channelNotify);
194 177
195 m_scene.EventManager.TriggerOnChatBroadcast(this, c); 178 m_scene.EventManager.TriggerOnChatBroadcast(this, c);
196 m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); 179
197 m_scene.SceneGridService.InformNeighborsThatRegionisUp(m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo); 180 TriggerRegionReady(m_scene);
198 } 181 }
199 } 182 }
200 183
201 void OnOarFileLoaded(Guid requestId, string message) 184 void OnOarFileLoaded(Guid requestId, string message)
202 { 185 {
203 m_oarFileLoading = true; 186 m_oarFileLoading = true;
187
204 if (message==String.Empty) 188 if (message==String.Empty)
205 { 189 {
206 m_lastOarLoadedOk = true; 190 m_lastOarLoadedOk = true;
207 } else { 191 }
192 else
193 {
208 m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message); 194 m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message);
209 m_lastOarLoadedOk = false; 195 m_lastOarLoadedOk = false;
210 } 196 }
211 } 197 }
212 198
213 // This will be triggerd by Scene if we have no scripts 199 /// <summary>
214 // m_ScriptsRezzing will be false if there were none 200 /// This will be triggered by Scene directly if it contains no scripts on startup. Otherwise it is triggered
215 // else it will be true and we should wait on the 201 /// when the script compile queue is empty after initial region startup.
216 // empty compile queue 202 /// </summary>
217 void OnLoginsEnabled(string regionName) 203 /// <param name='scene'></param>
204 public void TriggerRegionReady(IScene scene)
218 { 205 {
219 if (m_disable_logins == true) 206 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
207 m_scene.LoginLock = false;
208
209 if (!m_scene.StartDisabled)
220 { 210 {
221 if (m_scene.StartDisabled == false) 211 m_scene.LoginsEnabled = true;
222 {
223 m_scene.LoginsDisabled = false;
224 m_scene.LoginLock = false;
225 212
226 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; 213 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
214 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
227 215
228 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", 216 m_log.InfoFormat(
229 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); 217 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
218 }
230 219
231 m_log.InfoFormat( 220 m_scene.SceneGridService.InformNeighborsThatRegionisUp(
232 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); 221 m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo);
233 222
234 if (m_uri != string.Empty) 223 if (m_uri != string.Empty)
235 { 224 {
236 RRAlert("enabled"); 225 RRAlert("enabled");
237 }
238 }
239 } 226 }
227
228 m_scene.Ready = true;
240 } 229 }
241 230
242 public void OarLoadingAlert(string msg) 231 public void OarLoadingAlert(string msg)
243 { 232 {
244 // Let's bypass this for now until some better feedback can be established 233 // Let's bypass this for now until some better feedback can be established
245 // 234 //
246 return;
247 235
248 if (msg == "load") 236// if (msg == "load")
249 { 237// {
250 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; 238// m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
251 m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; 239// m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded;
252 m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; 240// m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
253 m_scene.EventManager.OnRezScript += OnRezScript; 241// m_scene.EventManager.OnRezScript += OnRezScript;
254 m_oarFileLoading = true; 242// m_oarFileLoading = true;
255 m_firstEmptyCompileQueue = true; 243// m_firstEmptyCompileQueue = true;
256 244//
257 m_scene.LoginsDisabled = true; 245// m_scene.LoginsDisabled = true;
258 m_scene.LoginLock = true; 246// m_scene.LoginLock = true;
259 if ( m_uri != string.Empty ) 247// if ( m_uri != string.Empty )
260 { 248// {
261 RRAlert("loading oar"); 249// RRAlert("loading oar");
262 RRAlert("disabled"); 250// RRAlert("disabled");
263 } 251// }
264 } 252// }
265 } 253 }
266 254
267 public void RRAlert(string status) 255 public void RRAlert(string status)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index dc0c008..09e1f0c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -41,7 +41,7 @@ public class BSCharacter : PhysicsActor
41 41
42 private BSScene _scene; 42 private BSScene _scene;
43 private String _avName; 43 private String _avName;
44 private bool _stopped; 44 // private bool _stopped;
45 private Vector3 _size; 45 private Vector3 _size;
46 private Vector3 _scale; 46 private Vector3 _scale;
47 private PrimitiveBaseShape _pbs; 47 private PrimitiveBaseShape _pbs;
@@ -134,9 +134,9 @@ public class BSCharacter : PhysicsActor
134 { 134 {
135 base.RequestPhysicsterseUpdate(); 135 base.RequestPhysicsterseUpdate();
136 } 136 }
137 137 // No one calls this method so I don't know what it could possibly mean
138 public override bool Stopped { 138 public override bool Stopped {
139 get { return _stopped; } 139 get { return false; }
140 } 140 }
141 public override Vector3 Size { 141 public override Vector3 Size {
142 get { return _size; } 142 get { return _size; }
@@ -391,52 +391,47 @@ public class BSCharacter : PhysicsActor
391 _mass = _density * _avatarVolume; 391 _mass = _density * _avatarVolume;
392 } 392 }
393 393
394 // Set to 'true' if the individual changed items should be checked
395 // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties)
396 const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false;
397
398 // The physics engine says that properties have updated. Update same and inform 394 // The physics engine says that properties have updated. Update same and inform
399 // the world that things have changed. 395 // the world that things have changed.
400 public void UpdateProperties(EntityProperties entprop) 396 public void UpdateProperties(EntityProperties entprop)
401 { 397 {
398 /*
402 bool changed = false; 399 bool changed = false;
403 if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) { 400 // we assign to the local variables so the normal set action does not happen
404 // we assign to the local variables so the normal set action does not happen 401 if (_position != entprop.Position) {
405 if (_position != entprop.Position) {
406 _position = entprop.Position;
407 changed = true;
408 }
409 if (_orientation != entprop.Rotation) {
410 _orientation = entprop.Rotation;
411 changed = true;
412 }
413 if (_velocity != entprop.Velocity) {
414 _velocity = entprop.Velocity;
415 changed = true;
416 }
417 if (_acceleration != entprop.Acceleration) {
418 _acceleration = entprop.Acceleration;
419 changed = true;
420 }
421 if (_rotationalVelocity != entprop.RotationalVelocity) {
422 _rotationalVelocity = entprop.RotationalVelocity;
423 changed = true;
424 }
425 if (changed) {
426 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
427 // Avatar movement is not done by generating this event. There is code in the heartbeat
428 // loop that updates avatars.
429 // base.RequestPhysicsterseUpdate();
430 }
431 }
432 else {
433 _position = entprop.Position; 402 _position = entprop.Position;
403 changed = true;
404 }
405 if (_orientation != entprop.Rotation) {
434 _orientation = entprop.Rotation; 406 _orientation = entprop.Rotation;
407 changed = true;
408 }
409 if (_velocity != entprop.Velocity) {
435 _velocity = entprop.Velocity; 410 _velocity = entprop.Velocity;
411 changed = true;
412 }
413 if (_acceleration != entprop.Acceleration) {
436 _acceleration = entprop.Acceleration; 414 _acceleration = entprop.Acceleration;
415 changed = true;
416 }
417 if (_rotationalVelocity != entprop.RotationalVelocity) {
437 _rotationalVelocity = entprop.RotationalVelocity; 418 _rotationalVelocity = entprop.RotationalVelocity;
419 changed = true;
420 }
421 if (changed) {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is code in the heartbeat
424 // loop that updates avatars.
438 // base.RequestPhysicsterseUpdate(); 425 // base.RequestPhysicsterseUpdate();
439 } 426 }
427 */
428 _position = entprop.Position;
429 _orientation = entprop.Rotation;
430 _velocity = entprop.Velocity;
431 _acceleration = entprop.Acceleration;
432 _rotationalVelocity = entprop.RotationalVelocity;
433 // Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop.
434 // base.RequestPhysicsterseUpdate();
440 } 435 }
441 436
442 // Called by the scene when a collision with this object is reported 437 // Called by the scene when a collision with this object is reported
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
new file mode 100755
index 0000000..fbb9e21
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -0,0 +1,115 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public class BSConstraint : IDisposable
36{
37 private BulletSim m_world;
38 private BulletBody m_body1;
39 private BulletBody m_body2;
40 private BulletConstraint m_constraint;
41 private bool m_enabled = false;
42
43 public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
44 Vector3 frame1, Quaternion frame1rot,
45 Vector3 frame2, Quaternion frame2rot
46 )
47 {
48 m_world = world;
49 m_body1 = obj1;
50 m_body2 = obj2;
51 m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
52 frame1, frame1rot,
53 frame2, frame2rot));
54 m_enabled = true;
55 }
56
57 public void Dispose()
58 {
59 if (m_enabled)
60 {
61 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
62 BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
63 m_enabled = false;
64 }
65 }
66
67 public BulletBody Body1 { get { return m_body1; } }
68 public BulletBody Body2 { get { return m_body2; } }
69
70 public bool SetLinearLimits(Vector3 low, Vector3 high)
71 {
72 bool ret = false;
73 if (m_enabled)
74 ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high);
75 return ret;
76 }
77
78 public bool SetAngularLimits(Vector3 low, Vector3 high)
79 {
80 bool ret = false;
81 if (m_enabled)
82 ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high);
83 return ret;
84 }
85
86 public bool UseFrameOffset(bool useOffset)
87 {
88 bool ret = false;
89 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
90 if (m_enabled)
91 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
92 return ret;
93 }
94
95 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
96 {
97 bool ret = false;
98 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
99 if (m_enabled)
100 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
101 return ret;
102 }
103
104 public bool CalculateTransforms()
105 {
106 bool ret = false;
107 if (m_enabled)
108 {
109 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
110 ret = true;
111 }
112 return ret;
113 }
114}
115}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
new file mode 100755
index 0000000..a2650fb
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -0,0 +1,178 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using log4net;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public class BSConstraintCollection : IDisposable
37{
38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
40
41 delegate bool ConstraintAction(BSConstraint constrain);
42
43 private List<BSConstraint> m_constraints;
44 private BulletSim m_world;
45
46 public BSConstraintCollection(BulletSim world)
47 {
48 m_world = world;
49 m_constraints = new List<BSConstraint>();
50 }
51
52 public void Dispose()
53 {
54 this.Clear();
55 }
56
57 public void Clear()
58 {
59 foreach (BSConstraint cons in m_constraints)
60 {
61 cons.Dispose();
62 }
63 m_constraints.Clear();
64 }
65
66 public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
67 Vector3 frame1, Quaternion frame1rot,
68 Vector3 frame2, Quaternion frame2rot)
69 {
70 BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
71
72 this.AddConstraint(constrain);
73 return constrain;
74 }
75
76 public bool AddConstraint(BSConstraint cons)
77 {
78 // There is only one constraint between any bodies. Remove any old just to make sure.
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80
81 m_constraints.Add(cons);
82
83 return true;
84 }
85
86 // Get the constraint between two bodies. There can be only one the way we're using them.
87 public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint)
88 {
89 bool found = false;
90 BSConstraint foundConstraint = null;
91
92 uint lookingID1 = body1.ID;
93 uint lookingID2 = body2.ID;
94 ForEachConstraint(delegate(BSConstraint constrain)
95 {
96 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
97 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
98 {
99 foundConstraint = constrain;
100 found = true;
101 }
102 return found;
103 });
104 returnConstraint = foundConstraint;
105 return found;
106 }
107
108 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
109 {
110 // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
111
112 bool ret = false;
113 BSConstraint constrain;
114
115 if (this.TryGetConstraint(body1, body2, out constrain))
116 {
117 // remove the constraint from our collection
118 m_constraints.Remove(constrain);
119 // tell the engine that all its structures need to be freed
120 constrain.Dispose();
121 // we destroyed something
122 ret = true;
123 }
124
125 return ret;
126 }
127
128 public bool RemoveAndDestroyConstraint(BulletBody body1)
129 {
130 // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
131
132 List<BSConstraint> toRemove = new List<BSConstraint>();
133 uint lookingID = body1.ID;
134 ForEachConstraint(delegate(BSConstraint constrain)
135 {
136 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
137 {
138 toRemove.Add(constrain);
139 }
140 return false;
141 });
142 lock (m_constraints)
143 {
144 foreach (BSConstraint constrain in toRemove)
145 {
146 m_constraints.Remove(constrain);
147 constrain.Dispose();
148 }
149 }
150 return (toRemove.Count > 0);
151 }
152
153 public bool RecalculateAllConstraints()
154 {
155 foreach (BSConstraint constrain in m_constraints)
156 {
157 constrain.CalculateTransforms();
158 }
159 return true;
160 }
161
162 // Lock the constraint list and loop through it.
163 // The constraint action returns 'true' if it wants the loop aborted.
164 private void ForEachConstraint(ConstraintAction action)
165 {
166 lock (m_constraints)
167 {
168 foreach (BSConstraint constrain in m_constraints)
169 {
170 if (action(constrain))
171 break;
172 }
173 }
174 }
175
176
177}
178}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index eb20eb3..c197e61 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -57,7 +57,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
57 private int frcount = 0; // Used to limit dynamics debug output to 57 private int frcount = 0; // Used to limit dynamics debug output to
58 // every 100th frame 58 // every 100th frame
59 59
60 // private BSScene m_parentScene = null;
61 private BSPrim m_prim; // the prim this dynamic controller belongs to 60 private BSPrim m_prim; // the prim this dynamic controller belongs to
62 61
63 // Vehicle properties 62 // Vehicle properties
@@ -131,8 +130,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
131 m_type = Vehicle.TYPE_NONE; 130 m_type = Vehicle.TYPE_NONE;
132 } 131 }
133 132
134 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) 133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
135 { 134 {
135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
136 switch (pParam) 136 switch (pParam)
137 { 137 {
138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
@@ -229,8 +229,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
229 } 229 }
230 }//end ProcessFloatVehicleParam 230 }//end ProcessFloatVehicleParam
231 231
232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) 232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
233 { 233 {
234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
234 switch (pParam) 235 switch (pParam)
235 { 236 {
236 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 237 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@@ -265,6 +266,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
265 266
266 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
267 { 268 {
269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
268 switch (pParam) 270 switch (pParam)
269 { 271 {
270 case Vehicle.REFERENCE_FRAME: 272 case Vehicle.REFERENCE_FRAME:
@@ -278,6 +280,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
278 280
279 internal void ProcessVehicleFlags(int pParam, bool remove) 281 internal void ProcessVehicleFlags(int pParam, bool remove)
280 { 282 {
283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
281 if (remove) 284 if (remove)
282 { 285 {
283 if (pParam == -1) 286 if (pParam == -1)
@@ -434,6 +437,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
434 437
435 internal void ProcessTypeChange(Vehicle pType) 438 internal void ProcessTypeChange(Vehicle pType)
436 { 439 {
440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
437 // Set Defaults For Type 441 // Set Defaults For Type
438 m_type = pType; 442 m_type = pType;
439 switch (pType) 443 switch (pType)
@@ -594,11 +598,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
594 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
595 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); 599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
596 break; 600 break;
597
598 } 601 }
599 }//end SetDefaultsForType 602 }//end SetDefaultsForType
600 603
601 internal void Step(float pTimestep, BSScene pParentScene) 604 internal void Step(float pTimestep)
602 { 605 {
603 if (m_type == Vehicle.TYPE_NONE) return; 606 if (m_type == Vehicle.TYPE_NONE) return;
604 607
@@ -606,21 +609,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin
606 if (frcount > 100) 609 if (frcount > 100)
607 frcount = 0; 610 frcount = 0;
608 611
609 MoveLinear(pTimestep, pParentScene); 612 MoveLinear(pTimestep);
610 MoveAngular(pTimestep); 613 MoveAngular(pTimestep);
611 LimitRotation(pTimestep); 614 LimitRotation(pTimestep);
615
616 DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}",
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
612 }// end Step 618 }// end Step
613 619
614 private void MoveLinear(float pTimestep, BSScene _pParentScene) 620 private void MoveLinear(float pTimestep)
615 { 621 {
616 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant 622 // requested m_linearMotorDirection is significant
623 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
624 if (m_linearMotorDirection.LengthSquared() > 0.0001f)
617 { 625 {
626 Vector3 origDir = m_linearMotorDirection;
627 Vector3 origVel = m_lastLinearVelocityVector;
628
618 // add drive to body 629 // add drive to body
619 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); 630 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
620 m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? 631 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale);
632 // lastLinearVelocityVector is the current body velocity vector?
633 // RA: Not sure what the *10 is for. A correction for pTimestep?
634 // m_lastLinearVelocityVector += (addAmount*10);
635 m_lastLinearVelocityVector += addAmount;
621 636
622 // This will work temporarily, but we really need to compare speed on an axis 637 // This will work temporarily, but we really need to compare speed on an axis
623 // KF: Limit body velocity to applied velocity? 638 // KF: Limit body velocity to applied velocity?
639 // Limit the velocity vector to less than the last set linear motor direction
624 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) 640 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
625 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; 641 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
626 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) 642 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
@@ -630,76 +646,93 @@ namespace OpenSim.Region.Physics.BulletSPlugin
630 646
631 // decay applied velocity 647 // decay applied velocity
632 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); 648 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
633 //Console.WriteLine("decay: " + decayfraction);
634 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; 649 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
635 //Console.WriteLine("actual: " + m_linearMotorDirection); 650
651 /*
652 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
653 m_lastLinearVelocityVector += addAmount;
654
655 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
656 m_linearMotorDirection *= decayfraction;
657
658 */
659
660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
636 } 662 }
637 else 663 else
638 { // requested is not significant 664 {
639 // if what remains of applied is small, zero it. 665 // if what remains of applied is small, zero it.
640 if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) 666 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
641 m_lastLinearVelocityVector = Vector3.Zero; 667 // m_lastLinearVelocityVector = Vector3.Zero;
668 m_linearMotorDirection = Vector3.Zero;
669 m_lastLinearVelocityVector = Vector3.Zero;
642 } 670 }
643 671
644 // convert requested object velocity to world-referenced vector 672 // convert requested object velocity to world-referenced vector
645 m_dir = m_lastLinearVelocityVector; 673 Quaternion rotq = m_prim.Orientation;
646 Quaternion rot = m_prim.Orientation; 674 m_dir = m_lastLinearVelocityVector * rotq;
647 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object 675
648 m_dir *= rotq; // apply obj rotation to velocity vector 676 // Add the various forces into m_dir which will be our new direction vector (velocity)
649 677
650 // add Gravity andBuoyancy 678 // add Gravity and Buoyancy
651 // KF: So far I have found no good method to combine a script-requested 679 // KF: So far I have found no good method to combine a script-requested
652 // .Z velocity and gravity. Therefore only 0g will used script-requested 680 // .Z velocity and gravity. Therefore only 0g will used script-requested
653 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. 681 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
654 Vector3 grav = Vector3.Zero; 682 Vector3 grav = Vector3.Zero;
655 // There is some gravity, make a gravity force vector 683 // There is some gravity, make a gravity force vector that is applied after object velocity.
656 // that is applied after object velocity.
657 float objMass = m_prim.Mass;
658 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 684 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
659 grav.Z = _pParentScene.DefaultGravity.Z * objMass * (1f - m_VehicleBuoyancy); 685 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy);
660 // Preserve the current Z velocity 686 // Preserve the current Z velocity
661 Vector3 vel_now = m_prim.Velocity; 687 Vector3 vel_now = m_prim.Velocity;
662 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 688 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
663 689
664 Vector3 pos = m_prim.Position; 690 Vector3 pos = m_prim.Position;
691 Vector3 posChange = pos;
665// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 692// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
666 Vector3 posChange = new Vector3();
667 posChange.X = pos.X - m_lastPositionVector.X;
668 posChange.Y = pos.Y - m_lastPositionVector.Y;
669 posChange.Z = pos.Z - m_lastPositionVector.Z;
670 double Zchange = Math.Abs(posChange.Z); 693 double Zchange = Math.Abs(posChange.Z);
671 if (m_BlockingEndPoint != Vector3.Zero) 694 if (m_BlockingEndPoint != Vector3.Zero)
672 { 695 {
696 bool changed = false;
673 if (pos.X >= (m_BlockingEndPoint.X - (float)1)) 697 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
674 { 698 {
675 pos.X -= posChange.X + 1; 699 pos.X -= posChange.X + 1;
676 m_prim.Position = pos; 700 changed = true;
677 } 701 }
678 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) 702 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
679 { 703 {
680 pos.Y -= posChange.Y + 1; 704 pos.Y -= posChange.Y + 1;
681 m_prim.Position = pos; 705 changed = true;
682 } 706 }
683 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) 707 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
684 { 708 {
685 pos.Z -= posChange.Z + 1; 709 pos.Z -= posChange.Z + 1;
686 m_prim.Position = pos; 710 changed = true;
687 } 711 }
688 if (pos.X <= 0) 712 if (pos.X <= 0)
689 { 713 {
690 pos.X += posChange.X + 1; 714 pos.X += posChange.X + 1;
691 m_prim.Position = pos; 715 changed = true;
692 } 716 }
693 if (pos.Y <= 0) 717 if (pos.Y <= 0)
694 { 718 {
695 pos.Y += posChange.Y + 1; 719 pos.Y += posChange.Y + 1;
720 changed = true;
721 }
722 if (changed)
723 {
696 m_prim.Position = pos; 724 m_prim.Position = pos;
725 DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
726 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
697 } 727 }
698 } 728 }
699 if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) 729
730 // If below the terrain, move us above the ground a little.
731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
700 { 732 {
701 pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; 733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
702 m_prim.Position = pos; 734 m_prim.Position = pos;
735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
703 } 736 }
704 737
705 // Check if hovering 738 // Check if hovering
@@ -708,11 +741,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
708 // We should hover, get the target height 741 // We should hover, get the target height
709 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) 742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
710 { 743 {
711 m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; 744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
712 } 745 }
713 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
714 { 747 {
715 m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
716 } 749 }
717 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
718 { 751 {
@@ -746,6 +779,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
746 } 779 }
747 } 780 }
748 781
782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
783
749// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
750// m_VhoverTimescale = 0f; // time to acheive height 785// m_VhoverTimescale = 0f; // time to acheive height
751// pTimestep is time since last frame,in secs 786// pTimestep is time since last frame,in secs
@@ -774,12 +809,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
774 { 809 {
775 grav.Z = (float)(grav.Z * 1.125); 810 grav.Z = (float)(grav.Z * 1.125);
776 } 811 }
777 float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); 812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
778 float postemp = (pos.Z - terraintemp); 813 float postemp = (pos.Z - terraintemp);
779 if (postemp > 2.5f) 814 if (postemp > 2.5f)
780 { 815 {
781 grav.Z = (float)(grav.Z * 1.037125); 816 grav.Z = (float)(grav.Z * 1.037125);
782 } 817 }
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
783 //End Experimental Values 819 //End Experimental Values
784 } 820 }
785 if ((m_flags & (VehicleFlag.NO_X)) != 0) 821 if ((m_flags & (VehicleFlag.NO_X)) != 0)
@@ -800,32 +836,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
800 // Apply velocity 836 // Apply velocity
801 m_prim.Velocity = m_dir; 837 m_prim.Velocity = m_dir;
802 // apply gravity force 838 // apply gravity force
803 m_prim.Force = grav; 839 // Why is this set here? The physics engine already does gravity.
804 840 // m_prim.AddForce(grav, false);
841 // m_prim.Force = grav;
805 842
806 // apply friction 843 // Apply friction
807 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
808 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
846
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
849
809 } // end MoveLinear() 850 } // end MoveLinear()
810 851
811 private void MoveAngular(float pTimestep) 852 private void MoveAngular(float pTimestep)
812 { 853 {
813 /* 854 // m_angularMotorDirection // angular velocity requested by LSL motor
814 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 855 // m_angularMotorApply // application frame counter
815 private int m_angularMotorApply = 0; // application frame counter 856 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
816 private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) 857 // m_angularMotorTimescale // motor angular velocity ramp up rate
817 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate 858 // m_angularMotorDecayTimescale // motor angular velocity decay rate
818 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 859 // m_angularFrictionTimescale // body angular velocity decay rate
819 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 860 // m_lastAngularVelocity // what was last applied to body
820 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
821 */
822 861
823 // Get what the body is doing, this includes 'external' influences 862 // Get what the body is doing, this includes 'external' influences
824 Vector3 angularVelocity = m_prim.RotationalVelocity; 863 Vector3 angularVelocity = m_prim.RotationalVelocity;
825 // Vector3 angularVelocity = Vector3.Zero;
826 864
827 if (m_angularMotorApply > 0) 865 if (m_angularMotorApply > 0)
828 { 866 {
867 // Rather than snapping the angular motor velocity from the old value to
868 // a newly set velocity, this routine steps the value from the previous
869 // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
870 // There are m_angularMotorApply steps.
871 Vector3 origAngularVelocity = m_angularMotorVelocity;
829 // ramp up to new value 872 // ramp up to new value
830 // current velocity += error / (time to get there / step interval) 873 // current velocity += error / (time to get there / step interval)
831 // requested speed - last motor speed 874 // requested speed - last motor speed
@@ -833,23 +876,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
833 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); 876 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
834 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); 877 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
835 878
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
881
836 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
837 // velocity may still be acheived. 883 // velocity may still be acheived.
838 } 884 }
839 else 885 else
840 { 886 {
841 // no motor recently applied, keep the body velocity 887 // No motor recently applied, keep the body velocity
842 /* m_angularMotorVelocity.X = angularVelocity.X;
843 m_angularMotorVelocity.Y = angularVelocity.Y;
844 m_angularMotorVelocity.Z = angularVelocity.Z; */
845
846 // and decay the velocity 888 // and decay the velocity
847 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); 889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
848 } // end motor section 890 } // end motor section
849 891
850 // Vertical attractor section 892 // Vertical attractor section
851 Vector3 vertattr = Vector3.Zero; 893 Vector3 vertattr = Vector3.Zero;
852
853 if (m_verticalAttractionTimescale < 300) 894 if (m_verticalAttractionTimescale < 300)
854 { 895 {
855 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 896 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
@@ -871,7 +912,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
871 // Error is 0 (no error) to +/- 2 (max error) 912 // Error is 0 (no error) to +/- 2 (max error)
872 // scale it by VAservo 913 // scale it by VAservo
873 verterr = verterr * VAservo; 914 verterr = verterr * VAservo;
874//if (frcount == 0) Console.WriteLine("VAerr=" + verterr);
875 915
876 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so 916 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
877 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. 917 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
@@ -884,11 +924,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
884 vertattr.X += bounce * angularVelocity.X; 924 vertattr.X += bounce * angularVelocity.X;
885 vertattr.Y += bounce * angularVelocity.Y; 925 vertattr.Y += bounce * angularVelocity.Y;
886 926
927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
928 m_prim.LocalID, verterr, bounce, vertattr);
929
887 } // else vertical attractor is off 930 } // else vertical attractor is off
888 931
889 // m_lastVertAttractor = vertattr; 932 // m_lastVertAttractor = vertattr;
890 933
891 // Bank section tba 934 // Bank section tba
935
892 // Deflection section tba 936 // Deflection section tba
893 937
894 // Sum velocities 938 // Sum velocities
@@ -898,11 +942,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
898 { 942 {
899 m_lastAngularVelocity.X = 0; 943 m_lastAngularVelocity.X = 0;
900 m_lastAngularVelocity.Y = 0; 944 m_lastAngularVelocity.Y = 0;
945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
901 } 946 }
902 947
903 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
904 { 949 {
905 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
906 } 952 }
907 953
908 // apply friction 954 // apply friction
@@ -912,10 +958,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
912 // Apply to the body 958 // Apply to the body
913 m_prim.RotationalVelocity = m_lastAngularVelocity; 959 m_prim.RotationalVelocity = m_lastAngularVelocity;
914 960
961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
915 } //end MoveAngular 962 } //end MoveAngular
963
916 internal void LimitRotation(float timestep) 964 internal void LimitRotation(float timestep)
917 { 965 {
918 Quaternion rotq = m_prim.Orientation; // rotq = rotation of object 966 Quaternion rotq = m_prim.Orientation;
919 Quaternion m_rot = rotq; 967 Quaternion m_rot = rotq;
920 bool changed = false; 968 bool changed = false;
921 if (m_RollreferenceFrame != Quaternion.Identity) 969 if (m_RollreferenceFrame != Quaternion.Identity)
@@ -923,18 +971,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
923 if (rotq.X >= m_RollreferenceFrame.X) 971 if (rotq.X >= m_RollreferenceFrame.X)
924 { 972 {
925 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); 973 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
974 changed = true;
926 } 975 }
927 if (rotq.Y >= m_RollreferenceFrame.Y) 976 if (rotq.Y >= m_RollreferenceFrame.Y)
928 { 977 {
929 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); 978 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
979 changed = true;
930 } 980 }
931 if (rotq.X <= -m_RollreferenceFrame.X) 981 if (rotq.X <= -m_RollreferenceFrame.X)
932 { 982 {
933 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); 983 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
984 changed = true;
934 } 985 }
935 if (rotq.Y <= -m_RollreferenceFrame.Y) 986 if (rotq.Y <= -m_RollreferenceFrame.Y)
936 { 987 {
937 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); 988 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
989 changed = true;
938 } 990 }
939 changed = true; 991 changed = true;
940 } 992 }
@@ -944,8 +996,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
944 m_rot.Y = 0; 996 m_rot.Y = 0;
945 changed = true; 997 changed = true;
946 } 998 }
999 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
1000 {
1001 m_rot.X = 0;
1002 m_rot.Y = 0;
1003 changed = true;
1004 }
947 if (changed) 1005 if (changed)
948 m_prim.Orientation = m_rot; 1006 m_prim.Orientation = m_rot;
1007
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
1009 }
1010
1011 // Invoke the detailed logger and output something if it's enabled.
1012 private void DetailLog(string msg, params Object[] args)
1013 {
1014 if (m_prim.Scene.VehicleLoggingEnabled)
1015 m_prim.Scene.PhysicsLogging.Write(msg, args);
949 } 1016 }
950 } 1017 }
951} 1018}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
new file mode 100755
index 0000000..3bc2100
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -0,0 +1,308 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public class BSLinkset
36{
37 private static string LogHeader = "[BULLETSIM LINKSET]";
38
39 private BSPrim m_linksetRoot;
40 public BSPrim Root { get { return m_linksetRoot; } }
41
42 private BSScene m_scene;
43
44 private List<BSPrim> m_children;
45
46 // We lock the diddling of linkset classes to prevent any badness.
47 // This locks the modification of the instances of this class. Changes
48 // to the physical representation is done via the tainting mechenism.
49 private object m_linksetActivityLock = new Object();
50
51 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
52 private float m_mass;
53 public float LinksetMass
54 {
55 get
56 {
57 m_mass = ComputeLinksetMass();
58 return m_mass;
59 }
60 }
61
62 public OMV.Vector3 CenterOfMass
63 {
64 get { return ComputeLinksetCenterOfMass(); }
65 }
66
67 public OMV.Vector3 GeometricCenter
68 {
69 get { return ComputeLinksetGeometricCenter(); }
70 }
71
72 public BSLinkset(BSScene scene, BSPrim parent)
73 {
74 // A simple linkset of one (no children)
75 m_scene = scene;
76 m_linksetRoot = parent;
77 m_children = new List<BSPrim>();
78 m_mass = parent.MassRaw;
79 }
80
81 // Link to a linkset where the child knows the parent.
82 // Parent changing should not happen so do some sanity checking.
83 // We return the parent's linkset so the child can track it's membership.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent)
85 {
86 lock (m_linksetActivityLock)
87 {
88 parent.Linkset.AddChildToLinkset(child);
89 }
90 return parent.Linkset;
91 }
92
93 public BSLinkset RemoveMeFromLinkset(BSPrim child)
94 {
95 lock (m_linksetActivityLock)
96 {
97 if (IsRoot(child))
98 {
99 // if root of linkset, take the linkset apart
100 while (m_children.Count > 0)
101 {
102 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]);
105 }
106 m_children.Clear(); // just to make sure
107 }
108 else
109 {
110 // Just removing a child from an existing linkset
111 RemoveChildFromLinkset(child);
112 }
113 }
114
115 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child);
117 }
118
119 // An existing linkset had one of its members rebuilt or something.
120 // Undo all the physical linking and rebuild the physical linkset.
121 public bool RefreshLinkset(BSPrim requestor)
122 {
123 return true;
124 }
125
126
127 // Return 'true' if the passed object is the root object of this linkset
128 public bool IsRoot(BSPrim requestor)
129 {
130 return (requestor.LocalID == m_linksetRoot.LocalID);
131 }
132
133 // Return 'true' if this linkset has any children (more than the root member)
134 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
135
136 // Return 'true' if this child is in this linkset
137 public bool HasChild(BSPrim child)
138 {
139 bool ret = false;
140 foreach (BSPrim bp in m_children)
141 {
142 if (child.LocalID == bp.LocalID)
143 {
144 ret = true;
145 break;
146 }
147 }
148 return ret;
149 }
150
151 private float ComputeLinksetMass()
152 {
153 float mass = m_linksetRoot.MassRaw;
154 foreach (BSPrim bp in m_children)
155 {
156 mass += bp.MassRaw;
157 }
158 return mass;
159 }
160
161 private OMV.Vector3 ComputeLinksetCenterOfMass()
162 {
163 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
164 float totalMass = m_linksetRoot.MassRaw;
165
166 foreach (BSPrim bp in m_children)
167 {
168 com += bp.Position * bp.MassRaw;
169 totalMass += bp.MassRaw;
170 }
171 com /= totalMass;
172
173 return com;
174 }
175
176 private OMV.Vector3 ComputeLinksetGeometricCenter()
177 {
178 OMV.Vector3 com = m_linksetRoot.Position;
179
180 foreach (BSPrim bp in m_children)
181 {
182 com += bp.Position * bp.MassRaw;
183 }
184 com /= m_children.Count + 1;
185
186 return com;
187 }
188
189 // I am the root of a linkset and a new child is being added
190 public void AddChildToLinkset(BSPrim pchild)
191 {
192 BSPrim child = pchild;
193 if (!HasChild(child))
194 {
195 m_children.Add(child);
196
197 m_scene.TaintedObject(delegate()
198 {
199 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
200 DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
201 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child
202 });
203 }
204 return;
205 }
206
207 // I am the root of a linkset and one of my children is being removed.
208 // Safe to call even if the child is not really in my linkset.
209 public void RemoveChildFromLinkset(BSPrim pchild)
210 {
211 BSPrim child = pchild;
212
213 if (m_children.Remove(child))
214 {
215 m_scene.TaintedObject(delegate()
216 {
217 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
218 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
219
220 if (m_children.Count == 0)
221 {
222 // if the linkset is empty, make sure all linkages have been removed
223 PhysicallyUnlinkAllChildrenFromRoot();
224 }
225 else
226 {
227 PhysicallyUnlinkAChildFromRoot(pchild);
228 }
229 });
230 }
231 else
232 {
233 // This will happen if we remove the root of the linkset first. Non-fatal occurance.
234 // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
235 }
236 return;
237 }
238
239 // Create a constraint between me (root of linkset) and the passed prim (the child).
240 // Called at taint time!
241 private void PhysicallyLinkAChildToRoot(BSPrim childPrim)
242 {
243 // Zero motion for children so they don't interpolate
244 childPrim.ZeroMotion();
245
246 // relative position normalized to the root prim
247 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation);
248 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation;
249
250 // relative rotation of the child to the parent
251 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
252
253 // create a constraint that allows no freedom of movement between the two objects
254 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
255 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
256 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
257 BSConstraint constrain = m_scene.Constraints.CreateConstraint(
258 m_scene.World, m_linksetRoot.Body, childPrim.Body,
259 childRelativePosition,
260 childRelativeRotation,
261 OMV.Vector3.Zero,
262 OMV.Quaternion.Identity);
263 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
264 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
265
266 // tweek the constraint to increase stability
267 constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset));
268 constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor),
269 m_scene.Params.linkConstraintTransMotorMaxVel,
270 m_scene.Params.linkConstraintTransMotorMaxForce);
271
272 }
273
274 // Remove linkage between myself and a particular child
275 // Called at taint time!
276 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim)
277 {
278 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
279 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID);
280 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
281 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
282 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body);
283 }
284
285 // Remove linkage between myself and any possible children I might have
286 // Called at taint time!
287 private void PhysicallyUnlinkAllChildrenFromRoot()
288 {
289 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
290 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID);
291 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body);
292 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
293 }
294
295 // Invoke the detailed logger and output something if it's enabled.
296 private void DebugLog(string msg, params Object[] args)
297 {
298 m_scene.Logger.DebugFormat(msg, args);
299 }
300
301 // Invoke the detailed logger and output something if it's enabled.
302 private void DetailLog(string msg, params Object[] args)
303 {
304 m_scene.PhysicsLogging.Write(msg, args);
305 }
306
307}
308}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 130f1ca..7590d93 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -42,6 +42,8 @@ public sealed class BSPrim : PhysicsActor
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); }
46
45 private IMesh _mesh; 47 private IMesh _mesh;
46 private PrimitiveBaseShape _pbs; 48 private PrimitiveBaseShape _pbs;
47 private ShapeData.PhysicsShapeType _shapeType; 49 private ShapeData.PhysicsShapeType _shapeType;
@@ -50,6 +52,7 @@ public sealed class BSPrim : PhysicsActor
50 private List<ConvexResult> _hulls; 52 private List<ConvexResult> _hulls;
51 53
52 private BSScene _scene; 54 private BSScene _scene;
55 public BSScene Scene { get { return _scene; } }
53 private String _avName; 56 private String _avName;
54 private uint _localID = 0; 57 private uint _localID = 0;
55 58
@@ -63,7 +66,7 @@ public sealed class BSPrim : PhysicsActor
63 private bool _isSelected; 66 private bool _isSelected;
64 private bool _isVolumeDetect; 67 private bool _isVolumeDetect;
65 private OMV.Vector3 _position; 68 private OMV.Vector3 _position;
66 private float _mass; 69 private float _mass; // the mass of this object
67 private float _density; 70 private float _density;
68 private OMV.Vector3 _force; 71 private OMV.Vector3 _force;
69 private OMV.Vector3 _velocity; 72 private OMV.Vector3 _velocity;
@@ -86,14 +89,22 @@ public sealed class BSPrim : PhysicsActor
86 private bool _kinematic; 89 private bool _kinematic;
87 private float _buoyancy; 90 private float _buoyancy;
88 91
89 private List<BSPrim> _childrenPrims; 92 // Membership in a linkset is controlled by this class.
90 private BSPrim _parentPrim; 93 private BSLinkset _linkset;
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
91 99
92 private int _subscribedEventsMs = 0; 100 private int _subscribedEventsMs = 0;
93 private int _nextCollisionOkTime = 0; 101 private int _nextCollisionOkTime = 0;
94 long _collidingStep; 102 long _collidingStep;
95 long _collidingGroundStep; 103 long _collidingGroundStep;
96 104
105 private BulletBody m_body;
106 public BulletBody Body { get { return m_body; } }
107
97 private BSDynamics _vehicle; 108 private BSDynamics _vehicle;
98 109
99 private OMV.Vector3 _PIDTarget; 110 private OMV.Vector3 _PIDTarget;
@@ -127,17 +138,18 @@ public sealed class BSPrim : PhysicsActor
127 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 138 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
128 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 139 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
129 _restitution = _scene.Params.defaultRestitution; 140 _restitution = _scene.Params.defaultRestitution;
130 _parentPrim = null; // not a child or a parent 141 _linkset = new BSLinkset(_scene, this); // a linkset of one
131 _vehicle = new BSDynamics(this); // add vehicleness 142 _vehicle = new BSDynamics(this); // add vehicleness
132 _childrenPrims = new List<BSPrim>(); 143 _mass = CalculateMass();
133 if (_isPhysical)
134 _mass = CalculateMass();
135 else
136 _mass = 0f;
137 // do the actual object creation at taint time 144 // do the actual object creation at taint time
138 _scene.TaintedObject(delegate() 145 _scene.TaintedObject(delegate()
139 { 146 {
140 RecreateGeomAndObject(); 147 RecreateGeomAndObject();
148
149 // Get the pointer to the physical body for this object.
150 // At the moment, we're still letting BulletSim manage the creation and destruction
151 // of the object. Someday we'll move that into the C# code.
152 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
141 }); 153 });
142 } 154 }
143 155
@@ -145,13 +157,19 @@ public sealed class BSPrim : PhysicsActor
145 public void Destroy() 157 public void Destroy()
146 { 158 {
147 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 159 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
160 // DetailLog("{0},Destroy", LocalID);
161
148 // Undo any vehicle properties 162 // Undo any vehicle properties
149 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 163 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
150 _scene.RemoveVehiclePrim(this); // just to make sure 164 _scene.RemoveVehiclePrim(this); // just to make sure
165
151 _scene.TaintedObject(delegate() 166 _scene.TaintedObject(delegate()
152 { 167 {
168 // Undo any links between me and any other object
169 _linkset = _linkset.RemoveMeFromLinkset(this);
170
153 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 171 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
154 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 172 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
155 }); 173 });
156 } 174 }
157 175
@@ -164,8 +182,8 @@ public sealed class BSPrim : PhysicsActor
164 _size = value; 182 _size = value;
165 _scene.TaintedObject(delegate() 183 _scene.TaintedObject(delegate()
166 { 184 {
167 if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass 185 _mass = CalculateMass(); // changing size changes the mass
168 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical); 186 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
169 RecreateGeomAndObject(); 187 RecreateGeomAndObject();
170 }); 188 });
171 } 189 }
@@ -175,7 +193,7 @@ public sealed class BSPrim : PhysicsActor
175 _pbs = value; 193 _pbs = value;
176 _scene.TaintedObject(delegate() 194 _scene.TaintedObject(delegate()
177 { 195 {
178 if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass 196 _mass = CalculateMass(); // changing the shape changes the mass
179 RecreateGeomAndObject(); 197 RecreateGeomAndObject();
180 }); 198 });
181 } 199 }
@@ -202,33 +220,10 @@ public sealed class BSPrim : PhysicsActor
202 // link me to the specified parent 220 // link me to the specified parent
203 public override void link(PhysicsActor obj) { 221 public override void link(PhysicsActor obj) {
204 BSPrim parent = obj as BSPrim; 222 BSPrim parent = obj as BSPrim;
205 // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 223 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
206 // TODO: decide if this parent checking needs to happen at taint time 224 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
207 if (_parentPrim == null) 225
208 { 226 _linkset = _linkset.AddMeToLinkset(this, parent);
209 if (parent != null)
210 {
211 // I don't have a parent so I am joining a linkset
212 parent.AddChildToLinkset(this);
213 }
214 }
215 else
216 {
217 // I already have a parent, is parenting changing?
218 if (parent != _parentPrim)
219 {
220 if (parent == null)
221 {
222 // we are being removed from a linkset
223 _parentPrim.RemoveChildFromLinkset(this);
224 }
225 else
226 {
227 // asking to reparent a prim should not happen
228 m_log.ErrorFormat("{0}: Reparenting a prim. ", LogHeader);
229 }
230 }
231 }
232 return; 227 return;
233 } 228 }
234 229
@@ -236,101 +231,92 @@ public sealed class BSPrim : PhysicsActor
236 public override void delink() { 231 public override void delink() {
237 // TODO: decide if this parent checking needs to happen at taint time 232 // TODO: decide if this parent checking needs to happen at taint time
238 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 233 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
239 // m_log.DebugFormat("{0}: delink {1}/{2}", LogHeader, _avName, _localID); 234 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
240 if (_parentPrim != null) 235 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
241 { 236 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
242 _parentPrim.RemoveChildFromLinkset(this);
243 }
244 return;
245 }
246
247 // I am the root of a linkset and a new child is being added
248 public void AddChildToLinkset(BSPrim pchild)
249 {
250 BSPrim child = pchild;
251 _scene.TaintedObject(delegate()
252 {
253 if (!_childrenPrims.Contains(child))
254 {
255 _childrenPrims.Add(child);
256 child.ParentPrim = this; // the child has gained a parent
257 RecreateGeomAndObject(); // rebuild my shape with the new child added
258 }
259 });
260 return;
261 }
262
263 // I am the root of a linkset and one of my children is being removed.
264 // Safe to call even if the child is not really in my linkset.
265 public void RemoveChildFromLinkset(BSPrim pchild)
266 {
267 BSPrim child = pchild;
268 _scene.TaintedObject(delegate()
269 {
270 if (_childrenPrims.Contains(child))
271 {
272 BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID);
273 _childrenPrims.Remove(child);
274 child.ParentPrim = null; // the child has lost its parent
275 RecreateGeomAndObject(); // rebuild my shape with the child removed
276 }
277 else
278 {
279 m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset");
280 }
281 });
282 return;
283 }
284
285 public BSPrim ParentPrim
286 {
287 set { _parentPrim = value; }
288 }
289 237
290 // return true if we are the root of a linkset (there are children to manage) 238 _linkset.RemoveMeFromLinkset(this);
291 public bool IsRootOfLinkset 239 return;
292 {
293 get { return (_parentPrim == null && _childrenPrims.Count != 0); }
294 } 240 }
295 241
296 // Set motion values to zero. 242 // Set motion values to zero.
297 // Do it to the properties so the values get set in the physics engine. 243 // Do it to the properties so the values get set in the physics engine.
298 // Push the setting of the values to the viewer. 244 // Push the setting of the values to the viewer.
299 private void ZeroMotion() 245 // Called at taint time!
246 public void ZeroMotion()
300 { 247 {
301 Velocity = OMV.Vector3.Zero; 248 _velocity = OMV.Vector3.Zero;
302 _acceleration = OMV.Vector3.Zero; 249 _acceleration = OMV.Vector3.Zero;
303 RotationalVelocity = OMV.Vector3.Zero; 250 _rotationalVelocity = OMV.Vector3.Zero;
304 base.RequestPhysicsterseUpdate(); 251
252 // Zero some other properties directly into the physics engine
253 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
254 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
255 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
256 BulletSimAPI.ClearForces2(Body.Ptr);
305 } 257 }
306 258
307 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 259 public override void LockAngularMotion(OMV.Vector3 axis)
260 {
261 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis);
262 return;
263 }
308 264
309 public override OMV.Vector3 Position { 265 public override OMV.Vector3 Position {
310 get { 266 get {
311 // don't do the following GetObjectPosition because this function is called a zillion times 267 if (!_linkset.IsRoot(this))
268 // child prims move around based on their parent. Need to get the latest location
269 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
270
271 // don't do the GetObjectPosition for root elements because this function is called a zillion times
312 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 272 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
313 return _position; 273 return _position;
314 } 274 }
315 set { 275 set {
316 _position = value; 276 _position = value;
277 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
317 _scene.TaintedObject(delegate() 278 _scene.TaintedObject(delegate()
318 { 279 {
280 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
319 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 281 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
320 // m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position);
321 }); 282 });
322 } 283 }
323 } 284 }
324 public override float Mass { 285
325 get { return _mass; } 286 // Return the effective mass of the object.
287 // If there are multiple items in the linkset, add them together for the root
288 public override float Mass
289 {
290 get
291 {
292 return _linkset.LinksetMass;
293 }
294 }
295
296 // used when we only want this prim's mass and not the linkset thing
297 public float MassRaw { get { return _mass; } }
298
299 // Is this used?
300 public override OMV.Vector3 CenterOfMass
301 {
302 get { return _linkset.CenterOfMass; }
326 } 303 }
304
305 // Is this used?
306 public override OMV.Vector3 GeometricCenter
307 {
308 get { return _linkset.GeometricCenter; }
309 }
310
327 public override OMV.Vector3 Force { 311 public override OMV.Vector3 Force {
328 get { return _force; } 312 get { return _force; }
329 set { 313 set {
330 _force = value; 314 _force = value;
331 _scene.TaintedObject(delegate() 315 _scene.TaintedObject(delegate()
332 { 316 {
333 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 317 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
318 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
319 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
334 }); 320 });
335 } 321 }
336 } 322 }
@@ -341,15 +327,22 @@ public sealed class BSPrim : PhysicsActor
341 } 327 }
342 set { 328 set {
343 Vehicle type = (Vehicle)value; 329 Vehicle type = (Vehicle)value;
344 _vehicle.ProcessTypeChange(type);
345 _scene.TaintedObject(delegate() 330 _scene.TaintedObject(delegate()
346 { 331 {
332 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type);
333 _vehicle.ProcessTypeChange(type);
347 if (type == Vehicle.TYPE_NONE) 334 if (type == Vehicle.TYPE_NONE)
348 { 335 {
349 _scene.RemoveVehiclePrim(this); 336 _scene.RemoveVehiclePrim(this);
350 } 337 }
351 else 338 else
352 { 339 {
340 _scene.TaintedObject(delegate()
341 {
342 // Tell the physics engine to clear state
343 BulletSimAPI.ClearForces2(this.Body.Ptr);
344 });
345
353 // make it so the scene will call us each tick to do vehicle things 346 // make it so the scene will call us each tick to do vehicle things
354 _scene.AddVehiclePrim(this); 347 _scene.AddVehiclePrim(this);
355 } 348 }
@@ -359,47 +352,59 @@ public sealed class BSPrim : PhysicsActor
359 } 352 }
360 public override void VehicleFloatParam(int param, float value) 353 public override void VehicleFloatParam(int param, float value)
361 { 354 {
362 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 355 _scene.TaintedObject(delegate()
356 {
357 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
358 });
363 } 359 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 360 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 361 {
366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 362 _scene.TaintedObject(delegate()
363 {
364 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
365 });
367 } 366 }
368 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 367 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
369 { 368 {
370 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 369 _scene.TaintedObject(delegate()
370 {
371 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
372 });
371 } 373 }
372 public override void VehicleFlags(int param, bool remove) 374 public override void VehicleFlags(int param, bool remove)
373 { 375 {
374 _vehicle.ProcessVehicleFlags(param, remove); 376 _scene.TaintedObject(delegate()
377 {
378 _vehicle.ProcessVehicleFlags(param, remove);
379 });
375 } 380 }
376 // Called each simulation step to advance vehicle characteristics 381
382 // Called each simulation step to advance vehicle characteristics.
383 // Called from Scene when doing simulation step so we're in taint processing time.
377 public void StepVehicle(float timeStep) 384 public void StepVehicle(float timeStep)
378 { 385 {
379 _vehicle.Step(timeStep, _scene); 386 if (IsPhysical)
387 _vehicle.Step(timeStep);
380 } 388 }
381 389
382 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 390 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
383 public override void SetVolumeDetect(int param) { 391 public override void SetVolumeDetect(int param) {
384 bool newValue = (param != 0); 392 bool newValue = (param != 0);
385 if (_isVolumeDetect != newValue) 393 _isVolumeDetect = newValue;
394 _scene.TaintedObject(delegate()
386 { 395 {
387 _isVolumeDetect = newValue; 396 SetObjectDynamic();
388 _scene.TaintedObject(delegate() 397 });
389 {
390 SetObjectDynamic();
391 });
392 }
393 return; 398 return;
394 } 399 }
395 400
396 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
397 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
398 public override OMV.Vector3 Velocity { 401 public override OMV.Vector3 Velocity {
399 get { return _velocity; } 402 get { return _velocity; }
400 set { _velocity = value; 403 set {
404 _velocity = value;
401 _scene.TaintedObject(delegate() 405 _scene.TaintedObject(delegate()
402 { 406 {
407 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity);
403 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 408 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
404 }); 409 });
405 } 410 }
@@ -407,6 +412,7 @@ public sealed class BSPrim : PhysicsActor
407 public override OMV.Vector3 Torque { 412 public override OMV.Vector3 Torque {
408 get { return _torque; } 413 get { return _torque; }
409 set { _torque = value; 414 set { _torque = value;
415 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque);
410 } 416 }
411 } 417 }
412 public override float CollisionScore { 418 public override float CollisionScore {
@@ -419,13 +425,21 @@ public sealed class BSPrim : PhysicsActor
419 set { _acceleration = value; } 425 set { _acceleration = value; }
420 } 426 }
421 public override OMV.Quaternion Orientation { 427 public override OMV.Quaternion Orientation {
422 get { return _orientation; } 428 get {
429 if (!_linkset.IsRoot(this))
430 {
431 // Children move around because tied to parent. Get a fresh value.
432 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
433 }
434 return _orientation;
435 }
423 set { 436 set {
424 _orientation = value; 437 _orientation = value;
425 // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); 438 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
426 _scene.TaintedObject(delegate() 439 _scene.TaintedObject(delegate()
427 { 440 {
428 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 441 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
442 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
429 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 443 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
430 }); 444 });
431 } 445 }
@@ -458,25 +472,22 @@ public sealed class BSPrim : PhysicsActor
458 get { return !IsPhantom && !_isVolumeDetect; } 472 get { return !IsPhantom && !_isVolumeDetect; }
459 } 473 }
460 474
461 // make gravity work if the object is physical and not selected 475 // Make gravity work if the object is physical and not selected
462 // no locking here because only called when it is safe 476 // No locking here because only called when it is safe
477 // Only called at taint time so it is save to call into Bullet.
463 private void SetObjectDynamic() 478 private void SetObjectDynamic()
464 { 479 {
465 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); 480 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid);
466 // non-physical things work best with a mass of zero
467 if (IsStatic)
468 {
469 _mass = 0f;
470 }
471 else
472 {
473 _mass = CalculateMass();
474 // If it's dynamic, make sure the hull has been created for it
475 // This shouldn't do much work if the object had previously been built
476 RecreateGeomAndObject();
477 481
478 } 482 RecreateGeomAndObject();
479 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); 483
484 float mass = _mass;
485 // Bullet wants static objects have a mass of zero
486 if (IsStatic)
487 mass = 0f;
488
489 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
490 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
480 } 491 }
481 492
482 // prims don't fly 493 // prims don't fly
@@ -516,11 +527,24 @@ public sealed class BSPrim : PhysicsActor
516 set { _floatOnWater = value; } 527 set { _floatOnWater = value; }
517 } 528 }
518 public override OMV.Vector3 RotationalVelocity { 529 public override OMV.Vector3 RotationalVelocity {
519 get { return _rotationalVelocity; } 530 get {
520 set { _rotationalVelocity = value; 531 /*
532 OMV.Vector3 pv = OMV.Vector3.Zero;
533 // if close to zero, report zero
534 // This is copied from ODE but I'm not sure why it returns zero but doesn't
535 // zero the property in the physics engine.
536 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
537 return pv;
538 */
539
540 return _rotationalVelocity;
541 }
542 set {
543 _rotationalVelocity = value;
521 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 544 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
522 _scene.TaintedObject(delegate() 545 _scene.TaintedObject(delegate()
523 { 546 {
547 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
524 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 548 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
525 }); 549 });
526 } 550 }
@@ -533,11 +557,13 @@ public sealed class BSPrim : PhysicsActor
533 } 557 }
534 public override float Buoyancy { 558 public override float Buoyancy {
535 get { return _buoyancy; } 559 get { return _buoyancy; }
536 set { _buoyancy = value; 560 set {
537 _scene.TaintedObject(delegate() 561 _buoyancy = value;
538 { 562 _scene.TaintedObject(delegate()
539 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 563 {
540 }); 564 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
565 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
566 });
541 } 567 }
542 } 568 }
543 569
@@ -573,27 +599,45 @@ public sealed class BSPrim : PhysicsActor
573 public override float APIDStrength { set { return; } } 599 public override float APIDStrength { set { return; } }
574 public override float APIDDamping { set { return; } } 600 public override float APIDDamping { set { return; } }
575 601
602 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
576 public override void AddForce(OMV.Vector3 force, bool pushforce) { 603 public override void AddForce(OMV.Vector3 force, bool pushforce) {
577 if (force.IsFinite()) 604 if (force.IsFinite())
578 { 605 {
579 _force.X += force.X; 606 // _force += force;
580 _force.Y += force.Y; 607 lock (m_accumulatedForces)
581 _force.Z += force.Z; 608 m_accumulatedForces.Add(new OMV.Vector3(force));
582 } 609 }
583 else 610 else
584 { 611 {
585 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 612 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
613 return;
586 } 614 }
587 _scene.TaintedObject(delegate() 615 _scene.TaintedObject(delegate()
588 { 616 {
589 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 617 lock (m_accumulatedForces)
618 {
619 if (m_accumulatedForces.Count > 0)
620 {
621 OMV.Vector3 fSum = OMV.Vector3.Zero;
622 foreach (OMV.Vector3 v in m_accumulatedForces)
623 {
624 fSum += v;
625 }
626 m_accumulatedForces.Clear();
627
628 DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
629 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
630 }
631 }
590 }); 632 });
591 } 633 }
592 634
593 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 635 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
636 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
594 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 637 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
595 } 638 }
596 public override void SetMomentum(OMV.Vector3 momentum) { 639 public override void SetMomentum(OMV.Vector3 momentum) {
640 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum);
597 } 641 }
598 public override void SubscribeEvents(int ms) { 642 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 643 _subscribedEventsMs = ms;
@@ -885,6 +929,9 @@ public sealed class BSPrim : PhysicsActor
885 929
886 returnMass = _density * volume; 930 returnMass = _density * volume;
887 931
932 /*
933 * This change means each object keeps its own mass and the Mass property
934 * will return the sum if we're part of a linkset.
888 if (IsRootOfLinkset) 935 if (IsRootOfLinkset)
889 { 936 {
890 foreach (BSPrim prim in _childrenPrims) 937 foreach (BSPrim prim in _childrenPrims)
@@ -892,6 +939,7 @@ public sealed class BSPrim : PhysicsActor
892 returnMass += prim.CalculateMass(); 939 returnMass += prim.CalculateMass();
893 } 940 }
894 } 941 }
942 */
895 943
896 if (returnMass <= 0) 944 if (returnMass <= 0)
897 returnMass = 0.0001f; 945 returnMass = 0.0001f;
@@ -907,9 +955,11 @@ public sealed class BSPrim : PhysicsActor
907 // The objects needs a hull if it's physical otherwise a mesh is enough 955 // The objects needs a hull if it's physical otherwise a mesh is enough
908 // No locking here because this is done when we know physics is not simulating 956 // No locking here because this is done when we know physics is not simulating
909 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 957 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
910 private void CreateGeom(bool forceRebuild) 958 // Returns 'true' if the geometry was rebuilt
959 private bool CreateGeom(bool forceRebuild)
911 { 960 {
912 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. 961 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
962 bool ret = false;
913 if (!_scene.NeedsMeshing(_pbs)) 963 if (!_scene.NeedsMeshing(_pbs))
914 { 964 {
915 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 965 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -917,16 +967,26 @@ public sealed class BSPrim : PhysicsActor
917 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 967 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
918 { 968 {
919 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 969 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
920 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 970 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)
921 // Bullet native objects are scaled by the Bullet engine so pass the size in 971 {
922 _scale = _size; 972 DetailLog("{0},CreateGeom,sphere", LocalID);
973 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
974 ret = true;
975 // Bullet native objects are scaled by the Bullet engine so pass the size in
976 _scale = _size;
977 }
923 } 978 }
924 } 979 }
925 else 980 else
926 { 981 {
927 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); 982 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
928 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 983 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)
929 _scale = _size; 984 {
985 DetailLog("{0},CreateGeom,box", LocalID);
986 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
987 ret = true;
988 _scale = _size;
989 }
930 } 990 }
931 } 991 }
932 else 992 else
@@ -938,6 +998,7 @@ public sealed class BSPrim : PhysicsActor
938 // physical objects require a hull for interaction. 998 // physical objects require a hull for interaction.
939 // This will create the mesh if it doesn't already exist 999 // This will create the mesh if it doesn't already exist
940 CreateGeomHull(); 1000 CreateGeomHull();
1001 ret = true;
941 } 1002 }
942 } 1003 }
943 else 1004 else
@@ -946,9 +1007,11 @@ public sealed class BSPrim : PhysicsActor
946 { 1007 {
947 // Static (non-physical) objects only need a mesh for bumping into 1008 // Static (non-physical) objects only need a mesh for bumping into
948 CreateGeomMesh(); 1009 CreateGeomMesh();
1010 ret = true;
949 } 1011 }
950 } 1012 }
951 } 1013 }
1014 return ret;
952 } 1015 }
953 1016
954 // No locking here because this is done when we know physics is not simulating 1017 // No locking here because this is done when we know physics is not simulating
@@ -961,10 +1024,12 @@ public sealed class BSPrim : PhysicsActor
961 // if this new shape is the same as last time, don't recreate the mesh 1024 // if this new shape is the same as last time, don't recreate the mesh
962 if (_meshKey == newMeshKey) return; 1025 if (_meshKey == newMeshKey) return;
963 1026
1027 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey);
964 // Since we're recreating new, get rid of any previously generated shape 1028 // Since we're recreating new, get rid of any previously generated shape
965 if (_meshKey != 0) 1029 if (_meshKey != 0)
966 { 1030 {
967 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1031 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1032 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
968 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1033 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
969 _mesh = null; 1034 _mesh = null;
970 _meshKey = 0; 1035 _meshKey = 0;
@@ -981,7 +1046,6 @@ public sealed class BSPrim : PhysicsActor
981 int vi = 0; 1046 int vi = 0;
982 foreach (OMV.Vector3 vv in vertices) 1047 foreach (OMV.Vector3 vv in vertices)
983 { 1048 {
984 // m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z);
985 verticesAsFloats[vi++] = vv.X; 1049 verticesAsFloats[vi++] = vv.X;
986 verticesAsFloats[vi++] = vv.Y; 1050 verticesAsFloats[vi++] = vv.Y;
987 verticesAsFloats[vi++] = vv.Z; 1051 verticesAsFloats[vi++] = vv.Z;
@@ -995,6 +1059,7 @@ public sealed class BSPrim : PhysicsActor
995 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1059 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
996 // meshes are already scaled by the meshmerizer 1060 // meshes are already scaled by the meshmerizer
997 _scale = new OMV.Vector3(1f, 1f, 1f); 1061 _scale = new OMV.Vector3(1f, 1f, 1f);
1062 DetailLog("{0},CreateGeomMesh,done", LocalID);
998 return; 1063 return;
999 } 1064 }
1000 1065
@@ -1008,13 +1073,17 @@ public sealed class BSPrim : PhysicsActor
1008 // if the hull hasn't changed, don't rebuild it 1073 // if the hull hasn't changed, don't rebuild it
1009 if (newHullKey == _hullKey) return; 1074 if (newHullKey == _hullKey) return;
1010 1075
1076 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey);
1077
1011 // Since we're recreating new, get rid of any previously generated shape 1078 // Since we're recreating new, get rid of any previously generated shape
1012 if (_hullKey != 0) 1079 if (_hullKey != 0)
1013 { 1080 {
1014 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1081 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1082 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
1015 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1083 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1016 _hullKey = 0; 1084 _hullKey = 0;
1017 _hulls.Clear(); 1085 _hulls.Clear();
1086 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1018 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1087 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1019 _mesh = null; // the mesh cannot match either 1088 _mesh = null; // the mesh cannot match either
1020 _meshKey = 0; 1089 _meshKey = 0;
@@ -1111,6 +1180,7 @@ public sealed class BSPrim : PhysicsActor
1111 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1180 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1112 // meshes are already scaled by the meshmerizer 1181 // meshes are already scaled by the meshmerizer
1113 _scale = new OMV.Vector3(1f, 1f, 1f); 1182 _scale = new OMV.Vector3(1f, 1f, 1f);
1183 DetailLog("{0},CreateGeomHull,done", LocalID);
1114 return; 1184 return;
1115 } 1185 }
1116 1186
@@ -1126,45 +1196,18 @@ public sealed class BSPrim : PhysicsActor
1126 // No locking here because this is done when the physics engine is not simulating 1196 // No locking here because this is done when the physics engine is not simulating
1127 private void CreateObject() 1197 private void CreateObject()
1128 { 1198 {
1129 if (IsRootOfLinkset) 1199 // this routine is called when objects are rebuilt.
1130 {
1131 // Create a linkset around this object
1132 // CreateLinksetWithCompoundHull();
1133 CreateLinksetWithConstraints();
1134 }
1135 else
1136 {
1137 // simple object
1138 // the mesh or hull must have already been created in Bullet
1139 ShapeData shape;
1140 FillShapeInfo(out shape);
1141 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1142 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1143 }
1144 }
1145 1200
1146 // Create a linkset by creating a compound hull at the root prim that consists of all 1201 // the mesh or hull must have already been created in Bullet
1147 // the children. 1202 ShapeData shape;
1148 // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution 1203 FillShapeInfo(out shape);
1149 void CreateLinksetWithCompoundHull() 1204 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1150 { 1205 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1151 // If I am the root prim of a linkset, replace my physical shape with all the 1206 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1152 // pieces of the children. 1207 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
1153 // All of the children should have called CreateGeom so they have a hull 1208
1154 // in the physics engine already. Here we pull together all of those hulls 1209 // The root object could have been recreated. Make sure everything linksety is up to date.
1155 // into one shape. 1210 _linkset.RefreshLinkset(this);
1156 int totalPrimsInLinkset = _childrenPrims.Count + 1;
1157 // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset);
1158 ShapeData[] shapes = new ShapeData[totalPrimsInLinkset];
1159 FillShapeInfo(out shapes[0]);
1160 int ii = 1;
1161 foreach (BSPrim prim in _childrenPrims)
1162 {
1163 // m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID);
1164 prim.FillShapeInfo(out shapes[ii]);
1165 ii++;
1166 }
1167 BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
1168 } 1211 }
1169 1212
1170 // Copy prim's info into the BulletSim shape description structure 1213 // Copy prim's info into the BulletSim shape description structure
@@ -1186,44 +1229,6 @@ public sealed class BSPrim : PhysicsActor
1186 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1229 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1187 } 1230 }
1188 1231
1189 // Create the linkset by putting constraints between the objects of the set so they cannot move
1190 // relative to each other.
1191 // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added
1192 void CreateLinksetWithConstraints()
1193 {
1194 // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
1195
1196 // remove any constraints that might be in place
1197 foreach (BSPrim prim in _childrenPrims)
1198 {
1199 // m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1200 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
1201 }
1202 // create constraints between the root prim and each of the children
1203 foreach (BSPrim prim in _childrenPrims)
1204 {
1205 // m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1206
1207 // Zero motion for children so they don't interpolate
1208 prim.ZeroMotion();
1209
1210 // relative position normalized to the root prim
1211 OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation);
1212
1213 // relative rotation of the child to the parent
1214 OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation;
1215
1216 // this is a constraint that allows no freedom of movement between the two objects
1217 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
1218 BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
1219 childRelativePosition,
1220 relativeRotation,
1221 OMV.Vector3.Zero,
1222 OMV.Quaternion.Identity,
1223 OMV.Vector3.Zero, OMV.Vector3.Zero,
1224 OMV.Vector3.Zero, OMV.Vector3.Zero);
1225 }
1226 }
1227 1232
1228 // Rebuild the geometry and object. 1233 // Rebuild the geometry and object.
1229 // This is called when the shape changes so we need to recreate the mesh/hull. 1234 // This is called when the shape changes so we need to recreate the mesh/hull.
@@ -1252,78 +1257,71 @@ public sealed class BSPrim : PhysicsActor
1252 const float POSITION_TOLERANCE = 0.05f; 1257 const float POSITION_TOLERANCE = 0.05f;
1253 const float ACCELERATION_TOLERANCE = 0.01f; 1258 const float ACCELERATION_TOLERANCE = 0.01f;
1254 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1259 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1255 const bool SHOULD_DAMP_UPDATES = false;
1256 1260
1257 public void UpdateProperties(EntityProperties entprop) 1261 public void UpdateProperties(EntityProperties entprop)
1258 { 1262 {
1263 /*
1259 UpdatedProperties changed = 0; 1264 UpdatedProperties changed = 0;
1260 if (SHOULD_DAMP_UPDATES) 1265 // assign to the local variables so the normal set action does not happen
1266 // if (_position != entprop.Position)
1267 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1261 { 1268 {
1262 // assign to the local variables so the normal set action does not happen 1269 _position = entprop.Position;
1263 // if (_position != entprop.Position) 1270 changed |= UpdatedProperties.Position;
1264 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1265 {
1266 _position = entprop.Position;
1267 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position);
1268 changed |= UpdatedProperties.Position;
1269 }
1270 // if (_orientation != entprop.Rotation)
1271 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1272 {
1273 _orientation = entprop.Rotation;
1274 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation);
1275 changed |= UpdatedProperties.Rotation;
1276 }
1277 // if (_velocity != entprop.Velocity)
1278 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1279 {
1280 _velocity = entprop.Velocity;
1281 // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
1282 changed |= UpdatedProperties.Velocity;
1283 }
1284 // if (_acceleration != entprop.Acceleration)
1285 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1286 {
1287 _acceleration = entprop.Acceleration;
1288 // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
1289 changed |= UpdatedProperties.Acceleration;
1290 }
1291 // if (_rotationalVelocity != entprop.RotationalVelocity)
1292 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1293 {
1294 _rotationalVelocity = entprop.RotationalVelocity;
1295 // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
1296 changed |= UpdatedProperties.RotationalVel;
1297 }
1298 if (changed != 0)
1299 {
1300 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1301 // Only update the position of single objects and linkset roots
1302 if (this._parentPrim == null)
1303 {
1304 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1305 base.RequestPhysicsterseUpdate();
1306 }
1307 }
1308 } 1271 }
1309 else 1272 // if (_orientation != entprop.Rotation)
1273 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1310 { 1274 {
1311 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1275 _orientation = entprop.Rotation;
1312 1276 changed |= UpdatedProperties.Rotation;
1313 // Only updates only for individual prims and for the root object of a linkset. 1277 }
1278 // if (_velocity != entprop.Velocity)
1279 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1280 {
1281 _velocity = entprop.Velocity;
1282 changed |= UpdatedProperties.Velocity;
1283 }
1284 // if (_acceleration != entprop.Acceleration)
1285 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1286 {
1287 _acceleration = entprop.Acceleration;
1288 changed |= UpdatedProperties.Acceleration;
1289 }
1290 // if (_rotationalVelocity != entprop.RotationalVelocity)
1291 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1292 {
1293 _rotationalVelocity = entprop.RotationalVelocity;
1294 changed |= UpdatedProperties.RotationalVel;
1295 }
1296 if (changed != 0)
1297 {
1298 // Only update the position of single objects and linkset roots
1314 if (this._parentPrim == null) 1299 if (this._parentPrim == null)
1315 { 1300 {
1316 // Assign to the local variables so the normal set action does not happen
1317 _position = entprop.Position;
1318 _orientation = entprop.Rotation;
1319 _velocity = entprop.Velocity;
1320 _acceleration = entprop.Acceleration;
1321 _rotationalVelocity = entprop.RotationalVelocity;
1322 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1323 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1324 base.RequestPhysicsterseUpdate(); 1301 base.RequestPhysicsterseUpdate();
1325 } 1302 }
1326 } 1303 }
1304 */
1305
1306 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1307
1308 // Updates only for individual prims and for the root object of a linkset.
1309 if (_linkset.IsRoot(this))
1310 {
1311 // Assign to the local variables so the normal set action does not happen
1312 _position = entprop.Position;
1313 _orientation = entprop.Rotation;
1314 _velocity = entprop.Velocity;
1315 _acceleration = entprop.Acceleration;
1316 _rotationalVelocity = entprop.RotationalVelocity;
1317
1318 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1319 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1320 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1321 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1322
1323 base.RequestPhysicsterseUpdate();
1324 }
1327 } 1325 }
1328 1326
1329 // I've collided with something 1327 // I've collided with something
@@ -1362,5 +1360,11 @@ public sealed class BSPrim : PhysicsActor
1362 collisionCollection.Clear(); 1360 collisionCollection.Clear();
1363 } 1361 }
1364 } 1362 }
1363
1364 // Invoke the detailed logger and output something if it's enabled.
1365 private void DetailLog(string msg, params Object[] args)
1366 {
1367 Scene.PhysicsLogging.Write(msg, args);
1368 }
1365} 1369}
1366} 1370}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 417cb5f..c6d622b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -29,12 +29,14 @@ using System.Collections.Generic;
29using System.Runtime.InteropServices; 29using System.Runtime.InteropServices;
30using System.Text; 30using System.Text;
31using System.Threading; 31using System.Threading;
32using Nini.Config;
33using log4net;
34using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Framework;
34using OpenSim.Region.CoreModules;
35using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging;
35using OpenSim.Region.Physics.Manager; 36using OpenSim.Region.Physics.Manager;
37using Nini.Config;
38using log4net;
36using OpenMetaverse; 39using OpenMetaverse;
37using OpenSim.Region.Framework;
38 40
39// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
40// Debug linkset 42// Debug linkset
@@ -44,15 +46,17 @@ using OpenSim.Region.Framework;
44// Compute physics FPS reasonably 46// Compute physics FPS reasonably
45// Based on material, set density and friction 47// Based on material, set density and friction
46// More efficient memory usage when passing hull information from BSPrim to BulletSim 48// More efficient memory usage when passing hull information from BSPrim to BulletSim
49// Move all logic out of the C++ code and into the C# code for easier future modifications.
47// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 50// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
48// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 51// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
49// At the moment, physical and phantom causes object to drop through the terrain 52// At the moment, physical and phantom causes object to drop through the terrain
50// Physical phantom objects and related typing (collision options ) 53// Physical phantom objects and related typing (collision options )
54// Use collision masks for collision with terrain and phantom objects
51// Check out llVolumeDetect. Must do something for that. 55// Check out llVolumeDetect. Must do something for that.
52// Should prim.link() and prim.delink() membership checking happen at taint time? 56// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root.
53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
55// Use collision masks for collision with terrain and phantom objects
56// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
57// Implement LockAngularMotion 61// Implement LockAngularMotion
58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -60,9 +64,6 @@ using OpenSim.Region.Framework;
60// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
61// Add PID movement operations. What does ScenePresence.MoveToTarget do? 65// Add PID movement operations. What does ScenePresence.MoveToTarget do?
62// Check terrain size. 128 or 127? 66// Check terrain size. 128 or 127?
63// Multiple contact points on collision?
64// See code in ode::near... calls to collision_accounting_events()
65// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
66// Raycast 67// Raycast
67// 68//
68namespace OpenSim.Region.Physics.BulletSPlugin 69namespace OpenSim.Region.Physics.BulletSPlugin
@@ -72,6 +73,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
72 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
73 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
74 75
76 public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
77
75 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
76 79
77 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
@@ -84,6 +87,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
84 private uint m_worldID; 87 private uint m_worldID;
85 public uint WorldID { get { return m_worldID; } } 88 public uint WorldID { get { return m_worldID; } }
86 89
90 // let my minuions use my logger
91 public ILog Logger { get { return m_log; } }
92
87 private bool m_initialized = false; 93 private bool m_initialized = false;
88 94
89 private int m_detailedStatsStep = 0; 95 private int m_detailedStatsStep = 0;
@@ -100,11 +106,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
100 get { return m_sculptLOD; } 106 get { return m_sculptLOD; }
101 } 107 }
102 108
109 private BulletSim m_worldSim;
110 public BulletSim World
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119
103 private int m_maxSubSteps; 120 private int m_maxSubSteps;
104 private float m_fixedTimeStep; 121 private float m_fixedTimeStep;
105 private long m_simulationStep = 0; 122 private long m_simulationStep = 0;
106 public long SimulationStep { get { return m_simulationStep; } } 123 public long SimulationStep { get { return m_simulationStep; } }
107 124
125 public float LastSimulatedTimestep { get; private set; }
126
108 // A value of the time now so all the collision and update routines do not have to get their own 127 // A value of the time now so all the collision and update routines do not have to get their own
109 // Set to 'now' just before all the prims and actors are called for collisions and updates 128 // Set to 'now' just before all the prims and actors are called for collisions and updates
110 private int m_simulationNowTime; 129 private int m_simulationNowTime;
@@ -121,6 +140,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
121 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 140 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
122 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 141 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
123 142
143 public float PID_D { get; private set; } // derivative
144 public float PID_P { get; private set; } // proportional
145
124 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 146 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
125 public const uint GROUNDPLANE_ID = 1; 147 public const uint GROUNDPLANE_ID = 1;
126 148
@@ -147,8 +169,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
147 ConfigurationParameters[] m_params; 169 ConfigurationParameters[] m_params;
148 GCHandle m_paramsHandle; 170 GCHandle m_paramsHandle;
149 171
172 public bool shouldDebugLog { get; private set; }
173
150 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 174 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
151 175
176 // Sometimes you just have to log everything.
177 public Logging.LogWriter PhysicsLogging;
178 private bool m_physicsLoggingEnabled;
179 private string m_physicsLoggingDir;
180 private string m_physicsLoggingPrefix;
181 private int m_physicsLoggingFileMinutes;
182
183 private bool m_vehicleLoggingEnabled;
184 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
185
152 public BSScene(string identifier) 186 public BSScene(string identifier)
153 { 187 {
154 m_initialized = false; 188 m_initialized = false;
@@ -169,17 +203,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters
169 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 203 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
170 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 204 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
171 205
206 // Enable very detailed logging.
207 // By creating an empty logger when not logging, the log message invocation code
208 // can be left in and every call doesn't have to check for null.
209 if (m_physicsLoggingEnabled)
210 {
211 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
212 }
213 else
214 {
215 PhysicsLogging = new Logging.LogWriter();
216 }
217
172 // Get the version of the DLL 218 // Get the version of the DLL
173 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 219 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
174 // BulletSimVersion = BulletSimAPI.GetVersion(); 220 // BulletSimVersion = BulletSimAPI.GetVersion();
175 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); 221 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
176 222
177 // if Debug, enable logging from the unmanaged code 223 // if Debug, enable logging from the unmanaged code
178 if (m_log.IsDebugEnabled) 224 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
179 { 225 {
180 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 226 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
181 // the handle is saved to it doesn't get freed after this call 227 if (PhysicsLogging.Enabled)
182 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 228 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
229 else
230 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
231 // the handle is saved in a variable to make sure it doesn't get freed after this call
183 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); 232 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
184 } 233 }
185 234
@@ -194,6 +243,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
194 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 243 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
195 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 244 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
196 245
246 // Initialization to support the transition to a new API which puts most of the logic
247 // into the C# code so it is easier to modify and add to.
248 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID));
249 m_constraintCollection = new BSConstraintCollection(World);
250
197 m_initialized = true; 251 m_initialized = true;
198 } 252 }
199 253
@@ -202,110 +256,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
202 private void GetInitialParameterValues(IConfigSource config) 256 private void GetInitialParameterValues(IConfigSource config)
203 { 257 {
204 ConfigurationParameters parms = new ConfigurationParameters(); 258 ConfigurationParameters parms = new ConfigurationParameters();
259 m_params[0] = parms;
205 260
206 _meshSculptedPrim = true; // mesh sculpted prims 261 SetParameterDefaultValues();
207 _forceSimplePrimMeshing = false; // use complex meshing if called for
208
209 m_meshLOD = 8f;
210 m_sculptLOD = 32f;
211
212 m_detailedStatsStep = 0; // disabled
213
214 m_maxSubSteps = 10;
215 m_fixedTimeStep = 1f / 60f;
216 m_maxCollisionsPerFrame = 2048;
217 m_maxUpdatesPerFrame = 2048;
218 m_maximumObjectMass = 10000.01f;
219
220 parms.defaultFriction = 0.5f;
221 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
222 parms.defaultRestitution = 0f;
223 parms.collisionMargin = 0.0f;
224 parms.gravity = -9.80665f;
225
226 parms.linearDamping = 0.0f;
227 parms.angularDamping = 0.0f;
228 parms.deactivationTime = 0.2f;
229 parms.linearSleepingThreshold = 0.8f;
230 parms.angularSleepingThreshold = 1.0f;
231 parms.ccdMotionThreshold = 0.0f; // set to zero to disable
232 parms.ccdSweptSphereRadius = 0.0f;
233 parms.contactProcessingThreshold = 0.1f;
234
235 parms.terrainFriction = 0.5f;
236 parms.terrainHitFraction = 0.8f;
237 parms.terrainRestitution = 0f;
238 parms.avatarFriction = 0.5f;
239 parms.avatarRestitution = 0.0f;
240 parms.avatarDensity = 60f;
241 parms.avatarCapsuleRadius = 0.37f;
242 parms.avatarCapsuleHeight = 1.5f; // 2.140599f
243 parms.avatarContactProcessingThreshold = 0.1f;
244
245 parms.maxPersistantManifoldPoolSize = 0f;
246 parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue;
247 parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse;
248 parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse;
249 parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse;
250 parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse;
251 parms.numberOfSolverIterations = 0f; // means use default
252 262
253 if (config != null) 263 if (config != null)
254 { 264 {
255 // If there are specifications in the ini file, use those values 265 // If there are specifications in the ini file, use those values
256 // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini
257 // ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS.
258 IConfig pConfig = config.Configs["BulletSim"]; 266 IConfig pConfig = config.Configs["BulletSim"];
259 if (pConfig != null) 267 if (pConfig != null)
260 { 268 {
261 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); 269 SetParameterConfigurationValues(pConfig);
262 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); 270
263 271 // Very detailed logging for physics debugging
264 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); 272 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
265 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); 273 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
266 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); 274 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-");
267 275 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
268 m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps); 276 // Very detailed logging for vehicle debugging
269 m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep); 277 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
270 m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame);
271 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
272 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
273
274 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
275 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
276 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
277 parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin);
278 parms.gravity = pConfig.GetFloat("Gravity", parms.gravity);
279
280 parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping);
281 parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping);
282 parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime);
283 parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold);
284 parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold);
285 parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold);
286 parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius);
287 parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold);
288
289 parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction);
290 parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction);
291 parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
292 parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
293 parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution);
294 parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
295 parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
296 parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
297 parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold);
298
299 parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize);
300 parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation);
301 parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs);
302 parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder);
303 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
304 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
305 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
306 } 278 }
307 } 279 }
308 m_params[0] = parms;
309 } 280 }
310 281
311 // A helper function that handles a true/false parameter and returns the proper float number encoding 282 // A helper function that handles a true/false parameter and returns the proper float number encoding
@@ -323,12 +294,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
323 return ret; 294 return ret;
324 } 295 }
325 296
326
327 // Called directly from unmanaged code so don't do much 297 // Called directly from unmanaged code so don't do much
328 private void BulletLogger(string msg) 298 private void BulletLogger(string msg)
329 { 299 {
330 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 300 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
331 } 301 }
302
303 // Called directly from unmanaged code so don't do much
304 private void BulletLoggerPhysLog(string msg)
305 {
306 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
307 }
332 308
333 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 309 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
334 { 310 {
@@ -347,34 +323,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
347 public override void RemoveAvatar(PhysicsActor actor) 323 public override void RemoveAvatar(PhysicsActor actor)
348 { 324 {
349 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); 325 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader);
350 if (actor is BSCharacter) 326 BSCharacter bsactor = actor as BSCharacter;
351 { 327 if (bsactor != null)
352 ((BSCharacter)actor).Destroy();
353 }
354 try
355 { 328 {
356 lock (m_avatars) m_avatars.Remove(actor.LocalID); 329 try
357 } 330 {
358 catch (Exception e) 331 lock (m_avatars) m_avatars.Remove(actor.LocalID);
359 { 332 }
360 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); 333 catch (Exception e)
334 {
335 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e);
336 }
337 bsactor.Destroy();
338 // bsactor.dispose();
361 } 339 }
362 } 340 }
363 341
364 public override void RemovePrim(PhysicsActor prim) 342 public override void RemovePrim(PhysicsActor prim)
365 { 343 {
366 // m_log.DebugFormat("{0}: RemovePrim", LogHeader); 344 BSPrim bsprim = prim as BSPrim;
367 if (prim is BSPrim) 345 if (bsprim != null)
368 { 346 {
369 ((BSPrim)prim).Destroy(); 347 m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
370 } 348 try
371 try 349 {
372 { 350 lock (m_prims) m_prims.Remove(bsprim.LocalID);
373 lock (m_prims) m_prims.Remove(prim.LocalID); 351 }
352 catch (Exception e)
353 {
354 m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e);
355 }
356 bsprim.Destroy();
357 // bsprim.dispose();
374 } 358 }
375 catch (Exception e) 359 else
376 { 360 {
377 m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); 361 m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader);
378 } 362 }
379 } 363 }
380 364
@@ -400,6 +384,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 int collidersCount; 384 int collidersCount;
401 IntPtr collidersPtr; 385 IntPtr collidersPtr;
402 386
387 LastSimulatedTimestep = timeStep;
388
403 // prevent simulation until we've been initialized 389 // prevent simulation until we've been initialized
404 if (!m_initialized) return 10.0f; 390 if (!m_initialized) return 10.0f;
405 391
@@ -459,7 +445,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
459 for (int ii = 0; ii < updatedEntityCount; ii++) 445 for (int ii = 0; ii < updatedEntityCount; ii++)
460 { 446 {
461 EntityProperties entprop = m_updateArray[ii]; 447 EntityProperties entprop = m_updateArray[ii];
462 // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position);
463 BSPrim prim; 448 BSPrim prim;
464 if (m_prims.TryGetValue(entprop.ID, out prim)) 449 if (m_prims.TryGetValue(entprop.ID, out prim))
465 { 450 {
@@ -532,8 +517,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
532 }); 517 });
533 } 518 }
534 519
520 // Someday we will have complex terrain with caves and tunnels
521 // For the moment, it's flat and convex
522 public float GetTerrainHeightAtXYZ(Vector3 loc)
523 {
524 return GetTerrainHeightAtXY(loc.X, loc.Y);
525 }
526
535 public float GetTerrainHeightAtXY(float tX, float tY) 527 public float GetTerrainHeightAtXY(float tX, float tY)
536 { 528 {
529 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
530 return 30;
537 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; 531 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
538 } 532 }
539 533
@@ -555,6 +549,33 @@ public class BSScene : PhysicsScene, IPhysicsParameters
555 public override void Dispose() 549 public override void Dispose()
556 { 550 {
557 // m_log.DebugFormat("{0}: Dispose()", LogHeader); 551 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
552
553 // make sure no stepping happens while we're deleting stuff
554 m_initialized = false;
555
556 if (m_constraintCollection != null)
557 {
558 m_constraintCollection.Dispose();
559 m_constraintCollection = null;
560 }
561
562 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
563 {
564 kvp.Value.Destroy();
565 }
566 m_avatars.Clear();
567
568 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
569 {
570 kvp.Value.Destroy();
571 }
572 m_prims.Clear();
573
574 // Anything left in the unmanaged code should be cleaned out
575 BulletSimAPI.Shutdown(WorldID);
576
577 // Not logging any more
578 PhysicsLogging.Close();
558 } 579 }
559 580
560 public override Dictionary<uint, float> GetTopColliders() 581 public override Dictionary<uint, float> GetTopColliders()
@@ -680,10 +701,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
680 } 701 }
681 702
682 // The calls to the PhysicsActors can't directly call into the physics engine 703 // The calls to the PhysicsActors can't directly call into the physics engine
683 // because it might be busy. We we delay changes to a known time. 704 // because it might be busy. We delay changes to a known time.
684 // We rely on C#'s closure to save and restore the context for the delegate. 705 // We rely on C#'s closure to save and restore the context for the delegate.
685 public void TaintedObject(TaintCallback callback) 706 public void TaintedObject(TaintCallback callback)
686 { 707 {
708 if (!m_initialized) return;
709
687 lock (_taintLock) 710 lock (_taintLock)
688 _taintedObjects.Add(callback); 711 _taintedObjects.Add(callback);
689 return; 712 return;
@@ -757,61 +780,371 @@ public class BSScene : PhysicsScene, IPhysicsParameters
757 } 780 }
758 #endregion Vehicles 781 #endregion Vehicles
759 782
760 #region Runtime settable parameters 783 #region Parameters
761 public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] 784
762 { 785 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
763 new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"), 786 delegate float ParamGet(BSScene scene);
764 new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"), 787 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
765 new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), 788
766 new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), 789 private struct ParameterDefn
767 new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), 790 {
768 new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), 791 public string name;
769 792 public string desc;
770 new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), 793 public float defaultValue;
771 new PhysParameterEntry("DefaultDensity", "Density for new objects" ), 794 public ParamUser userParam;
772 new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ), 795 public ParamGet getter;
773 // new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ), 796 public ParamSet setter;
774 new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ), 797 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
775 798 {
776 new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ), 799 name = n;
777 new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ), 800 desc = d;
778 new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), 801 defaultValue = v;
779 new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), 802 userParam = u;
780 new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), 803 getter = g;
781 new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ), 804 setter = s;
782 new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ), 805 }
783 new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), 806 }
784 // Can only change the following at initialization time. Change the INI file and reboot. 807
785 new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"), 808 // List of all of the externally visible parameters.
786 new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"), 809 // For each parameter, this table maps a text name to getter and setters.
787 new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"), 810 // A ParameterDefn() takes the following parameters:
788 new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"), 811 // -- the text name of the parameter. This is used for console input and ini file.
789 new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"), 812 // -- a short text description of the parameter. This shows up in the console listing.
790 new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"), 813 // -- a delegate for fetching the parameter from the ini file.
791 new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"), 814 // Should handle fetching the right type from the ini file and converting it.
792 815 // -- a delegate for getting the value as a float
793 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 816 // -- a delegate for setting the value from a float
794 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 817 //
795 818 // To add a new variable, it is best to find an existing definition and copy it.
796 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 819 private ParameterDefn[] ParameterDefinitions =
797 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 820 {
798 821 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
799 new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), 822 ConfigurationParameters.numericTrue,
800 new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), 823 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
801 new PhysParameterEntry("TerrainRestitution", "Bouncyness" ), 824 (s) => { return s.NumericBool(s._meshSculptedPrim); },
802 new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ), 825 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
803 new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), 826 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
804 new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), 827 ConfigurationParameters.numericFalse,
805 new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), 828 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
806 new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ), 829 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
807 new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions") 830 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
831
832 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
833 8f,
834 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
835 (s) => { return (float)s.m_meshLOD; },
836 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
837 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
838 32,
839 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
840 (s) => { return (float)s.m_sculptLOD; },
841 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
842
843 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
844 10f,
845 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
846 (s) => { return (float)s.m_maxSubSteps; },
847 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
848 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
849 1f / 60f,
850 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
851 (s) => { return (float)s.m_fixedTimeStep; },
852 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
853 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
854 2048f,
855 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
856 (s) => { return (float)s.m_maxCollisionsPerFrame; },
857 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
858 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
859 8000f,
860 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
861 (s) => { return (float)s.m_maxUpdatesPerFrame; },
862 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
863 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
864 10000.01f,
865 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
866 (s) => { return (float)s.m_maximumObjectMass; },
867 (s,p,l,v) => { s.m_maximumObjectMass = v; } ),
868
869 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
870 2200f,
871 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
872 (s) => { return (float)s.PID_D; },
873 (s,p,l,v) => { s.PID_D = v; } ),
874 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
875 900f,
876 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
877 (s) => { return (float)s.PID_P; },
878 (s,p,l,v) => { s.PID_P = v; } ),
879
880 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
881 0.5f,
882 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
883 (s) => { return s.m_params[0].defaultFriction; },
884 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
885 new ParameterDefn("DefaultDensity", "Density for new objects" ,
886 10.000006836f, // Aluminum g/cm3
887 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
888 (s) => { return s.m_params[0].defaultDensity; },
889 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
890 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
891 0f,
892 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
893 (s) => { return s.m_params[0].defaultRestitution; },
894 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
895 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
896 0f,
897 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
898 (s) => { return s.m_params[0].collisionMargin; },
899 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
900 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
901 -9.80665f,
902 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
903 (s) => { return s.m_params[0].gravity; },
904 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ),
905
906
907 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
908 0f,
909 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
910 (s) => { return s.m_params[0].linearDamping; },
911 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
912 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
913 0f,
914 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
915 (s) => { return s.m_params[0].angularDamping; },
916 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
917 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
918 0.2f,
919 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
920 (s) => { return s.m_params[0].deactivationTime; },
921 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
922 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
923 0.8f,
924 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
925 (s) => { return s.m_params[0].linearSleepingThreshold; },
926 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
927 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
928 1.0f,
929 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
930 (s) => { return s.m_params[0].angularSleepingThreshold; },
931 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
932 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
933 0f, // set to zero to disable
934 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
935 (s) => { return s.m_params[0].ccdMotionThreshold; },
936 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
937 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
938 0f,
939 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
940 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
941 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
942 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
943 0.1f,
944 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
945 (s) => { return s.m_params[0].contactProcessingThreshold; },
946 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
947
948 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
949 0.5f,
950 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
951 (s) => { return s.m_params[0].terrainFriction; },
952 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ),
953 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
954 0.8f,
955 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
956 (s) => { return s.m_params[0].terrainHitFraction; },
957 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ),
958 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
959 0f,
960 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
961 (s) => { return s.m_params[0].terrainRestitution; },
962 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
963 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
964 0.5f,
965 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
966 (s) => { return s.m_params[0].avatarFriction; },
967 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
968 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
969 60f,
970 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
971 (s) => { return s.m_params[0].avatarDensity; },
972 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
973 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
974 0f,
975 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
976 (s) => { return s.m_params[0].avatarRestitution; },
977 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
978 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
979 0.37f,
980 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
981 (s) => { return s.m_params[0].avatarCapsuleRadius; },
982 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
983 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
984 1.5f,
985 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
986 (s) => { return s.m_params[0].avatarCapsuleHeight; },
987 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
988 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
989 0.1f,
990 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
991 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
992 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
993
994
995 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)",
996 0f, // zero to disable
997 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
999 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1000 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1001 ConfigurationParameters.numericTrue,
1002 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1003 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1004 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1005 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1006 ConfigurationParameters.numericFalse,
1007 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1008 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1009 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1010 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1011 ConfigurationParameters.numericFalse,
1012 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1013 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1014 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1015 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1016 ConfigurationParameters.numericFalse,
1017 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1018 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1019 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1020 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1021 ConfigurationParameters.numericFalse,
1022 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1023 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1024 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1025 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1026 0f, // zero says use Bullet default
1027 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1028 (s) => { return s.m_params[0].numberOfSolverIterations; },
1029 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1030
1031 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1032 ConfigurationParameters.numericFalse,
1033 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1034 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1035 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1036 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1037 ConfigurationParameters.numericTrue,
1038 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1039 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1040 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1041 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1042 5.0f,
1043 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1044 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1045 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1046 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1047 0.1f,
1048 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1050 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1051
1052 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1053 0f,
1054 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1055 (s) => { return (float)s.m_detailedStatsStep; },
1056 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1057 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1058 ConfigurationParameters.numericFalse,
1059 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1060 (s) => { return s.NumericBool(s.shouldDebugLog); },
1061 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ),
808 1062
809 }; 1063 };
810 1064
1065 // Convert a boolean to our numeric true and false values
1066 public float NumericBool(bool b)
1067 {
1068 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1069 }
1070
1071 // Convert numeric true and false values to a boolean
1072 public bool BoolNumeric(float b)
1073 {
1074 return (b == ConfigurationParameters.numericTrue ? true : false);
1075 }
1076
1077 // Search through the parameter definitions and return the matching
1078 // ParameterDefn structure.
1079 // Case does not matter as names are compared after converting to lower case.
1080 // Returns 'false' if the parameter is not found.
1081 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1082 {
1083 bool ret = false;
1084 ParameterDefn foundDefn = new ParameterDefn();
1085 string pName = paramName.ToLower();
1086
1087 foreach (ParameterDefn parm in ParameterDefinitions)
1088 {
1089 if (pName == parm.name.ToLower())
1090 {
1091 foundDefn = parm;
1092 ret = true;
1093 break;
1094 }
1095 }
1096 defn = foundDefn;
1097 return ret;
1098 }
1099
1100 // Pass through the settable parameters and set the default values
1101 private void SetParameterDefaultValues()
1102 {
1103 foreach (ParameterDefn parm in ParameterDefinitions)
1104 {
1105 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1106 }
1107 }
1108
1109 // Get user set values out of the ini file.
1110 private void SetParameterConfigurationValues(IConfig cfg)
1111 {
1112 foreach (ParameterDefn parm in ParameterDefinitions)
1113 {
1114 parm.userParam(this, cfg, parm.name, parm.defaultValue);
1115 }
1116 }
1117
1118 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1119
1120 private void BuildParameterTable()
1121 {
1122 if (SettableParameters.Length < ParameterDefinitions.Length)
1123 {
1124
1125 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1126 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1127 {
1128 ParameterDefn pd = ParameterDefinitions[ii];
1129 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
1130 }
1131
1132 // make the list in alphabetical order for estetic reasons
1133 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1134 {
1135 return ppe1.name.CompareTo(ppe2.name);
1136 });
1137
1138 SettableParameters = entries.ToArray();
1139 }
1140 }
1141
1142
811 #region IPhysicsParameters 1143 #region IPhysicsParameters
812 // Get the list of parameters this physics engine supports 1144 // Get the list of parameters this physics engine supports
813 public PhysParameterEntry[] GetParameterList() 1145 public PhysParameterEntry[] GetParameterList()
814 { 1146 {
1147 BuildParameterTable();
815 return SettableParameters; 1148 return SettableParameters;
816 } 1149 }
817 1150
@@ -823,63 +1156,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
823 // value activated ('terrainFriction' for instance). 1156 // value activated ('terrainFriction' for instance).
824 public bool SetPhysicsParameter(string parm, float val, uint localID) 1157 public bool SetPhysicsParameter(string parm, float val, uint localID)
825 { 1158 {
826 bool ret = true; 1159 bool ret = false;
827 string lparm = parm.ToLower(); 1160 ParameterDefn theParam;
828 switch (lparm) 1161 if (TryGetParameter(parm, out theParam))
829 { 1162 {
830 case "detailedstats": m_detailedStatsStep = (int)val; break; 1163 theParam.setter(this, parm, localID, val);
831 1164 ret = true;
832 case "meshlod": m_meshLOD = (int)val; break;
833 case "sculptlod": m_sculptLOD = (int)val; break;
834 case "maxsubstep": m_maxSubSteps = (int)val; break;
835 case "fixedtimestep": m_fixedTimeStep = val; break;
836 case "maxobjectmass": m_maximumObjectMass = val; break;
837
838 case "defaultfriction": m_params[0].defaultFriction = val; break;
839 case "defaultdensity": m_params[0].defaultDensity = val; break;
840 case "defaultrestitution": m_params[0].defaultRestitution = val; break;
841 case "collisionmargin": m_params[0].collisionMargin = val; break;
842 case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break;
843
844 case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break;
845 case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
846 case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break;
847 case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break;
848 case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
849 case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break;
850 case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break;
851 case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break;
852 // the following are used only at initialization time so setting them makes no sense
853 // case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break;
854 // case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break;
855 // case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break;
856 // case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break;
857 // case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break;
858 // case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break;
859 // case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break;
860
861 case "friction": TaintedUpdateParameter(lparm, localID, val); break;
862 case "restitution": TaintedUpdateParameter(lparm, localID, val); break;
863
864 // set a terrain physical feature and cause terrain to be recalculated
865 case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break;
866 case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break;
867 case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break;
868 // set an avatar physical feature and cause avatar(s) to be recalculated
869 case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break;
870 case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break;
871 case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break;
872 case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break;
873 case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break;
874 case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break;
875
876 default: ret = false; break;
877 } 1165 }
878 return ret; 1166 return ret;
879 } 1167 }
880 1168
881 // check to see if we are updating a parameter for a particular or all of the prims 1169 // check to see if we are updating a parameter for a particular or all of the prims
882 private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1170 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
883 { 1171 {
884 List<uint> operateOn; 1172 List<uint> operateOn;
885 lock (m_prims) operateOn = new List<uint>(m_prims.Keys); 1173 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
@@ -887,7 +1175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
887 } 1175 }
888 1176
889 // check to see if we are updating a parameter for a particular or all of the avatars 1177 // check to see if we are updating a parameter for a particular or all of the avatars
890 private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) 1178 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
891 { 1179 {
892 List<uint> operateOn; 1180 List<uint> operateOn;
893 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1181 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
@@ -898,7 +1186,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
898 // If the local ID is APPLY_TO_NONE, just change the default value 1186 // If the local ID is APPLY_TO_NONE, just change the default value
899 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1187 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
900 // If the localID is a specific object, apply the parameter change to only that object 1188 // If the localID is a specific object, apply the parameter change to only that object
901 private void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1189 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
902 { 1190 {
903 switch (localID) 1191 switch (localID)
904 { 1192 {
@@ -925,7 +1213,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
925 } 1213 }
926 1214
927 // schedule the actual updating of the paramter to when the phys engine is not busy 1215 // schedule the actual updating of the paramter to when the phys engine is not busy
928 private void TaintedUpdateParameter(string parm, uint localID, float val) 1216 protected void TaintedUpdateParameter(string parm, uint localID, float val)
929 { 1217 {
930 uint xlocalID = localID; 1218 uint xlocalID = localID;
931 string xparm = parm.ToLower(); 1219 string xparm = parm.ToLower();
@@ -940,50 +1228,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
940 public bool GetPhysicsParameter(string parm, out float value) 1228 public bool GetPhysicsParameter(string parm, out float value)
941 { 1229 {
942 float val = 0f; 1230 float val = 0f;
943 bool ret = true; 1231 bool ret = false;
944 switch (parm.ToLower()) 1232 ParameterDefn theParam;
945 { 1233 if (TryGetParameter(parm, out theParam))
946 case "detailedstats": val = (int)m_detailedStatsStep; break; 1234 {
947 case "meshlod": val = (float)m_meshLOD; break; 1235 val = theParam.getter(this);
948 case "sculptlod": val = (float)m_sculptLOD; break; 1236 ret = true;
949 case "maxsubstep": val = (float)m_maxSubSteps; break;
950 case "fixedtimestep": val = m_fixedTimeStep; break;
951 case "maxobjectmass": val = m_maximumObjectMass; break;
952
953 case "defaultfriction": val = m_params[0].defaultFriction; break;
954 case "defaultdensity": val = m_params[0].defaultDensity; break;
955 case "defaultrestitution": val = m_params[0].defaultRestitution; break;
956 case "collisionmargin": val = m_params[0].collisionMargin; break;
957 case "gravity": val = m_params[0].gravity; break;
958
959 case "lineardamping": val = m_params[0].linearDamping; break;
960 case "angulardamping": val = m_params[0].angularDamping; break;
961 case "deactivationtime": val = m_params[0].deactivationTime; break;
962 case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break;
963 case "angularsleepingthreshold": val = m_params[0].angularDamping; break;
964 case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break;
965 case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break;
966 case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break;
967 case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break;
968 case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break;
969 case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break;
970 case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break;
971 case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break;
972 case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break;
973 case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break;
974
975 case "terrainfriction": val = m_params[0].terrainFriction; break;
976 case "terrainhitfraction": val = m_params[0].terrainHitFraction; break;
977 case "terrainrestitution": val = m_params[0].terrainRestitution; break;
978
979 case "avatarfriction": val = m_params[0].avatarFriction; break;
980 case "avatardensity": val = m_params[0].avatarDensity; break;
981 case "avatarrestitution": val = m_params[0].avatarRestitution; break;
982 case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break;
983 case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break;
984 case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break;
985 default: ret = false; break;
986
987 } 1237 }
988 value = val; 1238 value = val;
989 return ret; 1239 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 086f0dc..65e3145 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -32,6 +32,28 @@ using OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API
36public struct BulletSim
37{
38 public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; }
39 public IntPtr Ptr;
40 public uint ID;
41}
42
43public struct BulletBody
44{
45 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
46 public IntPtr Ptr;
47 public uint ID;
48}
49
50public struct BulletConstraint
51{
52 public BulletConstraint(IntPtr xx) { Ptr = xx; }
53 public IntPtr Ptr;
54}
55
56// ===============================================================================
35[StructLayout(LayoutKind.Sequential)] 57[StructLayout(LayoutKind.Sequential)]
36public struct ConvexHull 58public struct ConvexHull
37{ 59{
@@ -142,10 +164,32 @@ public struct ConfigurationParameters
142 public float shouldEnableFrictionCaching; 164 public float shouldEnableFrictionCaching;
143 public float numberOfSolverIterations; 165 public float numberOfSolverIterations;
144 166
167 public float linkConstraintUseFrameOffset;
168 public float linkConstraintEnableTransMotor;
169 public float linkConstraintTransMotorMaxVel;
170 public float linkConstraintTransMotorMaxForce;
171
145 public const float numericTrue = 1f; 172 public const float numericTrue = 1f;
146 public const float numericFalse = 0f; 173 public const float numericFalse = 0f;
147} 174}
148 175
176// Values used by Bullet and BulletSim to control collisions
177public enum CollisionFlags : uint
178{
179 STATIC_OBJECT = 1 << 0,
180 KINEMATIC_OBJECT = 1 << 1,
181 NO_CONTACT_RESPONSE = 1 << 2,
182 CUSTOM_MATERIAL_CALLBACK = 1 << 3,
183 CHARACTER_OBJECT = 1 << 4,
184 DISABLE_VISUALIZE_OBJECT = 1 << 5,
185 DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
186 // Following used by BulletSim to control collisions
187 VOLUME_DETECT_OBJECT = 1 << 10,
188 PHANTOM_OBJECT = 1 << 11,
189 PHYSICAL_OBJECT = 1 << 12,
190};
191
192// ===============================================================================
149static class BulletSimAPI { 193static class BulletSimAPI {
150 194
151[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 195[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -195,6 +239,7 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
195[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 239[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
196public static extern bool CreateObject(uint worldID, ShapeData shapeData); 240public static extern bool CreateObject(uint worldID, ShapeData shapeData);
197 241
242/* Remove old functionality
198[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 243[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
199public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); 244public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
200 245
@@ -209,11 +254,15 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1);
209 254
210[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 255[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
211public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); 256public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
257 */
212 258
213[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 259[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
214public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 260public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
215 261
216[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 262[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
263public static extern Quaternion GetObjectOrientation(uint WorldID, uint id);
264
265[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
217public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); 266public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation);
218 267
219[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 268[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -268,5 +317,175 @@ public static extern void DumpBulletStatistics();
268public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); 317public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
269[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 318[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
270public static extern void SetDebugLogCallback(DebugLogCallback callback); 319public static extern void SetDebugLogCallback(DebugLogCallback callback);
320
321// ===============================================================================
322// ===============================================================================
323// ===============================================================================
324// A new version of the API that enables moving all the logic out of the C++ code and into
325// the C# code. This will make modifications easier for the next person.
326// This interface passes the actual pointers to the objects in the unmanaged
327// address space. All the management (calls for creation/destruction/lookup)
328// is done in the C# code.
329// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
330// and the old code is removed.
331
332[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
333public static extern IntPtr GetSimHandle2(uint worldID);
334
335[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
336public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
337
338[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
339public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id);
340
341// ===============================================================================
342[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
343public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
344 int maxCollisions, IntPtr collisionArray,
345 int maxUpdates, IntPtr updateArray);
346
347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
348public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value);
349
350[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
351public static extern void SetHeightmap2(IntPtr sim, float[] heightmap);
352
353[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
354public static extern void Shutdown2(IntPtr sim);
355
356[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
357public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep,
358 out int updatedEntityCount,
359 out IntPtr updatedEntitiesPtr,
360 out int collidersCount,
361 out IntPtr collidersPtr);
362
363/*
364[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
365public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices );
366
367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
368public static extern bool BuildHull2(IntPtr sim, IntPtr mesh);
369
370[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
371public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh);
372
373[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
374public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh);
375
376[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
377public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData);
378*/
379
380[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
381public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2,
382 Vector3 frame1loc, Quaternion frame1rot,
383 Vector3 frame2loc, Quaternion frame2rot);
384
385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
386public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
387
388[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
389public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
390
391[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
392public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
393
394[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
395public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
396
397[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
398public static extern bool CalculateTransforms2(IntPtr constrain);
399
400[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
401public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain);
402
403[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
404public static extern Vector3 GetPosition2(IntPtr obj);
405
406[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
407public static extern Quaternion GetOrientation2(IntPtr obj);
408
409[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
410public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
411
412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
413public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity);
414
415[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
416public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
417
418[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
419public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
420
421[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
422public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
423
424[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
425public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val);
426
427[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
428public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
429
430[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
431public static extern bool SetDeactivationTime2(IntPtr obj, float val);
432
433[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
434public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
435
436[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
437public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
438
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
440public static extern bool SetFriction2(IntPtr obj, float val);
441
442[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
443public static extern bool SetRestitution2(IntPtr obj, float val);
444
445[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
446public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
447
448[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
449public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
450
451[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
452public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags);
453
454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
455public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags);
456
457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
458public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags);
459
460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
461public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
462
463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern bool UpdateInertiaTensor2(IntPtr obj);
465
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern bool SetGravity2(IntPtr obj, Vector3 val);
468
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern IntPtr ClearForces2(IntPtr obj);
471
472[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
473public static extern bool SetMargin2(IntPtr obj, float val);
474
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
477
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
480
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
483
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern bool DestroyObject2(IntPtr world, uint id);
486
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern void DumpPhysicsStatistics2(IntPtr sim);
489
271} 490}
272} 491}
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 32e81e2..929b019 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -290,7 +290,6 @@ namespace OpenSim.Region.Physics.OdePlugin
290 290
291 private readonly IntPtr contactgroup; 291 private readonly IntPtr contactgroup;
292 292
293 internal IntPtr LandGeom;
294 internal IntPtr WaterGeom; 293 internal IntPtr WaterGeom;
295 294
296 private float nmTerrainContactFriction = 255.0f; 295 private float nmTerrainContactFriction = 255.0f;
@@ -489,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
489 /// </summary> 488 /// </summary>
490 internal Object OdeLock = new Object(); 489 internal Object OdeLock = new Object();
491 490
491 private bool _worldInitialized = false;
492
492 public IMesher mesher; 493 public IMesher mesher;
493 494
494 private IConfigSource m_config; 495 private IConfigSource m_config;
@@ -875,6 +876,8 @@ namespace OpenSim.Region.Physics.OdePlugin
875 staticPrimspace[i, j] = IntPtr.Zero; 876 staticPrimspace[i, j] = IntPtr.Zero;
876 } 877 }
877 } 878 }
879
880 _worldInitialized = true;
878 } 881 }
879 882
880// internal void waitForSpaceUnlock(IntPtr space) 883// internal void waitForSpaceUnlock(IntPtr space)
@@ -1508,8 +1511,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1508 { 1511 {
1509 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) 1512 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f)
1510 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) 1513 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f)
1511 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) 1514 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1512 && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1513 { 1515 {
1514 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) 1516 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1515 { 1517 {
@@ -1538,7 +1540,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1538 //d.GeomGetAABB(contactGeom.g2, out aabb2); 1540 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1539 //d.GeomGetAABB(contactGeom.g1, out aabb1); 1541 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1540 //aabb1. 1542 //aabb1.
1541 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) 1543 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1542 { 1544 {
1543 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) 1545 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1544 { 1546 {
@@ -2896,6 +2898,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2896 /// <returns>The number of frames simulated over that period.</returns> 2898 /// <returns>The number of frames simulated over that period.</returns>
2897 public override float Simulate(float timeStep) 2899 public override float Simulate(float timeStep)
2898 { 2900 {
2901 if (!_worldInitialized) return 11f;
2902
2899 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0; 2903 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
2900 int tempTick = 0, tempTick2 = 0; 2904 int tempTick = 0, tempTick2 = 0;
2901 2905
@@ -4017,6 +4021,8 @@ namespace OpenSim.Region.Physics.OdePlugin
4017 4021
4018 public override void Dispose() 4022 public override void Dispose()
4019 { 4023 {
4024 _worldInitialized = false;
4025
4020 m_rayCastManager.Dispose(); 4026 m_rayCastManager.Dispose();
4021 m_rayCastManager = null; 4027 m_rayCastManager = null;
4022 4028
@@ -4037,6 +4043,7 @@ namespace OpenSim.Region.Physics.OdePlugin
4037 d.WorldDestroy(world); 4043 d.WorldDestroy(world);
4038 //d.CloseODE(); 4044 //d.CloseODE();
4039 } 4045 }
4046
4040 } 4047 }
4041 4048
4042 public override Dictionary<uint, float> GetTopColliders() 4049 public override Dictionary<uint, float> GetTopColliders()
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 204c4ff..3144d76 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -99,6 +99,8 @@ namespace OpenSim.Region.RegionCombinerModule
99 99
100 public void RemoveRegion(Scene scene) 100 public void RemoveRegion(Scene scene)
101 { 101 {
102 lock (m_startingScenes)
103 m_startingScenes.Remove(scene.RegionInfo.originRegionID);
102 } 104 }
103 105
104 public void RegionLoaded(Scene scene) 106 public void RegionLoaded(Scene scene)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 693992a..94fd940 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Threading; 31using System.Threading;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
34using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.ScriptEngine.Interfaces; 36using OpenSim.Region.ScriptEngine.Interfaces;
36using OpenSim.Region.ScriptEngine.Shared; 37using OpenSim.Region.ScriptEngine.Shared;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index cd72dc2..ce1c364 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -6885,22 +6885,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6885 if (folderID == UUID.Zero) 6885 if (folderID == UUID.Zero)
6886 return; 6886 return;
6887 6887
6888 byte[] bucket = new byte[1];
6889 bucket[0] = (byte)AssetType.Folder;
6890 //byte[] objBytes = folderID.GetBytes();
6891 //Array.Copy(objBytes, 0, bucket, 1, 16);
6892
6893 GridInstantMessage msg = new GridInstantMessage(World,
6894 m_host.OwnerID, m_host.Name, destID,
6895 (byte)InstantMessageDialog.TaskInventoryOffered,
6896 false, category+". "+m_host.Name+" is located at "+
6897 World.RegionInfo.RegionName+" "+
6898 m_host.AbsolutePosition.ToString(),
6899 folderID, true, m_host.AbsolutePosition,
6900 bucket);
6901
6902 if (m_TransferModule != null) 6888 if (m_TransferModule != null)
6889 {
6890 byte[] bucket = new byte[] { (byte)AssetType.Folder };
6891
6892 GridInstantMessage msg = new GridInstantMessage(World,
6893 m_host.UUID, m_host.Name + ", an object owned by " +
6894 resolveName(m_host.OwnerID) + ",", destID,
6895 (byte)InstantMessageDialog.TaskInventoryOffered,
6896 false, category + "\n" + m_host.Name + " is located at " +
6897 World.RegionInfo.RegionName + " " +
6898 m_host.AbsolutePosition.ToString(),
6899 folderID, true, m_host.AbsolutePosition,
6900 bucket);
6901
6903 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 6902 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
6903 }
6904 } 6904 }
6905 6905
6906 public void llSetVehicleType(int type) 6906 public void llSetVehicleType(int type)
@@ -11847,7 +11847,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11847 break; 11847 break;
11848 case ScriptBaseClass.OBJECT_ROT: 11848 case ScriptBaseClass.OBJECT_ROT:
11849 { 11849 {
11850 Quaternion rot = Quaternion.Identity; 11850 Quaternion rot = Quaternion.Identity;
11851 11851
11852 if (obj.ParentGroup.RootPart == obj) 11852 if (obj.ParentGroup.RootPart == obj)
11853 rot = obj.ParentGroup.GroupRotation; 11853 rot = obj.ParentGroup.GroupRotation;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 4bd3dff..7844c75 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -200,24 +200,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
200 for (int i = 0; i < result.Length; i++) 200 for (int i = 0; i < result.Length; i++)
201 { 201 {
202 if (result[i] is string) 202 if (result[i] is string)
203 {
203 llist[i] = new LSL_String((string)result[i]); 204 llist[i] = new LSL_String((string)result[i]);
205 }
204 else if (result[i] is int) 206 else if (result[i] is int)
207 {
205 llist[i] = new LSL_Integer((int)result[i]); 208 llist[i] = new LSL_Integer((int)result[i]);
209 }
206 else if (result[i] is float) 210 else if (result[i] is float)
211 {
207 llist[i] = new LSL_Float((float)result[i]); 212 llist[i] = new LSL_Float((float)result[i]);
213 }
214 else if (result[i] is UUID)
215 {
216 llist[i] = new LSL_Key(result[i].ToString());
217 }
208 else if (result[i] is OpenMetaverse.Vector3) 218 else if (result[i] is OpenMetaverse.Vector3)
209 { 219 {
210 OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i]; 220 OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i];
211 llist[i] = new LSL_Vector(vresult.X,vresult.Y,vresult.Z); 221 llist[i] = new LSL_Vector(vresult.X, vresult.Y, vresult.Z);
212 } 222 }
213 else if (result[i] is OpenMetaverse.Quaternion) 223 else if (result[i] is OpenMetaverse.Quaternion)
214 { 224 {
215 OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i]; 225 OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i];
216 llist[i] = new LSL_Rotation(qresult.X,qresult.Y,qresult.Z,qresult.W); 226 llist[i] = new LSL_Rotation(qresult.X, qresult.Y, qresult.Z, qresult.W);
217 } 227 }
218 else 228 else
219 { 229 {
220 MODError(String.Format("unknown list element returned by {0}",fname)); 230 MODError(String.Format("unknown list element {1} returned by {0}", fname, result[i].GetType().Name));
221 } 231 }
222 } 232 }
223 233
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 29d0342..1181c10 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3290,8 +3290,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3290 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName)); 3290 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName));
3291 3291
3292 throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName)); 3292 throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName));
3293
3294 return;
3295 } 3293 }
3296 3294
3297 ScenePresence sp = World.GetScenePresence(avatarId); 3295 ScenePresence sp = World.GetScenePresence(avatarId);
@@ -3322,5 +3320,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3322 InitLSL(); 3320 InitLSL();
3323 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3321 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3324 } 3322 }
3323
3324 /// <summary>
3325 /// Checks if thing is a UUID.
3326 /// </summary>
3327 /// <param name="thing"></param>
3328 /// <returns>1 if thing is a valid UUID, 0 otherwise</returns>
3329 public LSL_Integer osIsUUID(string thing)
3330 {
3331 CheckThreatLevel(ThreatLevel.None, "osIsUUID");
3332 m_host.AddScriptLPS(1);
3333
3334 UUID test;
3335 return UUID.TryParse(thing, out test) ? 1 : 0;
3336 }
3337
3338 /// <summary>
3339 /// Wraps to Math.Min()
3340 /// </summary>
3341 /// <param name="a"></param>
3342 /// <param name="b"></param>
3343 /// <returns></returns>
3344 public LSL_Float osMin(double a, double b)
3345 {
3346 CheckThreatLevel(ThreatLevel.None, "osMin");
3347 m_host.AddScriptLPS(1);
3348
3349 return Math.Min(a, b);
3350 }
3351
3352 /// <summary>
3353 /// Wraps to Math.max()
3354 /// </summary>
3355 /// <param name="a"></param>
3356 /// <param name="b"></param>
3357 /// <returns></returns>
3358 public LSL_Float osMax(double a, double b)
3359 {
3360 CheckThreatLevel(ThreatLevel.None, "osMax");
3361 m_host.AddScriptLPS(1);
3362
3363 return Math.Max(a, b);
3364 }
3325 } 3365 }
3326} 3366}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 1facc96..aba66d3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -276,5 +276,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
276 276
277 void osSetTerrainTexture(int level, LSL_Key texture); 277 void osSetTerrainTexture(int level, LSL_Key texture);
278 void osSetTerrainTextureHeight(int corner, double low, double high); 278 void osSetTerrainTextureHeight(int corner, double low, double high);
279
280 /// <summary>
281 /// Checks if thing is a UUID.
282 /// </summary>
283 /// <param name="thing"></param>
284 /// <returns>1 if thing is a valid UUID, 0 otherwise</returns>
285 LSL_Integer osIsUUID(string thing);
286
287 /// <summary>
288 /// Wraps to Math.Min()
289 /// </summary>
290 /// <param name="a"></param>
291 /// <param name="b"></param>
292 /// <returns></returns>
293 LSL_Float osMin(double a, double b);
294
295 /// <summary>
296 /// Wraps to Math.max()
297 /// </summary>
298 /// <param name="a"></param>
299 /// <param name="b"></param>
300 /// <returns></returns>
301 LSL_Float osMax(double a, double b);
279 } 302 }
280} 303}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index b40bdf0..53daa13 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -930,5 +930,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
930 { 930 {
931 m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high); 931 m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high);
932 } 932 }
933
934 public LSL_Integer osIsUUID(string thing)
935 {
936 return m_OSSL_Functions.osIsUUID(thing);
937 }
938
939 public LSL_Float osMin(double a, double b)
940 {
941 return m_OSSL_Functions.osMin(a, b);
942 }
943
944 public LSL_Float osMax(double a, double b)
945 {
946 return m_OSSL_Functions.osMax(a, b);
947 }
933 } 948 }
934} 949}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 5c9d30f..9e5fb24 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -36,6 +36,7 @@ using OpenSim.Framework;
36using OpenSim.Region.CoreModules; 36using OpenSim.Region.CoreModules;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
39using OpenSim.Region.Framework.Interfaces;
39 40
40namespace OpenSim.Region.ScriptEngine.Shared 41namespace OpenSim.Region.ScriptEngine.Shared
41{ 42{
@@ -83,6 +84,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
83 84
84 public class DetectParams 85 public class DetectParams
85 { 86 {
87 public const int AGENT = 1;
88 public const int ACTIVE = 2;
89 public const int PASSIVE = 4;
90 public const int SCRIPTED = 8;
91 public const int OS_NPC = 0x01000000;
92
86 public DetectParams() 93 public DetectParams()
87 { 94 {
88 Key = UUID.Zero; 95 Key = UUID.Zero;
@@ -199,8 +206,27 @@ namespace OpenSim.Region.ScriptEngine.Shared
199 Type = 0x01; // Avatar 206 Type = 0x01; // Avatar
200 if (presence.PresenceType == PresenceType.Npc) 207 if (presence.PresenceType == PresenceType.Npc)
201 Type = 0x20; 208 Type = 0x20;
209
210 // Cope Impl. We don't use OS_NPC.
211 //if (presence.PresenceType != PresenceType.Npc)
212 //{
213 // Type = AGENT;
214 //}
215 //else
216 //{
217 // Type = OS_NPC;
218
219 // INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
220 // INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene);
221
222 // if (npcData.SenseAsAgent)
223 // {
224 // Type |= AGENT;
225 // }
226 //}
227
202 if (presence.Velocity != Vector3.Zero) 228 if (presence.Velocity != Vector3.Zero)
203 Type |= 0x02; // Active 229 Type |= ACTIVE;
204 230
205 Group = presence.ControllingClient.ActiveGroupId; 231 Group = presence.ControllingClient.ActiveGroupId;
206 232
@@ -215,15 +241,15 @@ namespace OpenSim.Region.ScriptEngine.Shared
215 Name = part.Name; 241 Name = part.Name;
216 Owner = part.OwnerID; 242 Owner = part.OwnerID;
217 if (part.Velocity == Vector3.Zero) 243 if (part.Velocity == Vector3.Zero)
218 Type = 0x04; // Passive 244 Type = PASSIVE;
219 else 245 else
220 Type = 0x02; // Passive 246 Type = ACTIVE;
221 247
222 foreach (SceneObjectPart p in part.ParentGroup.Parts) 248 foreach (SceneObjectPart p in part.ParentGroup.Parts)
223 { 249 {
224 if (p.Inventory.ContainsScripts()) 250 if (p.Inventory.ContainsScripts())
225 { 251 {
226 Type |= 0x08; // Scripted 252 Type |= SCRIPTED; // Scripted
227 break; 253 break;
228 } 254 }
229 } 255 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 983eed2..771db0c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -312,11 +312,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
312 part.SetScriptEvents(ItemID, 312 part.SetScriptEvents(ItemID,
313 (int)m_Script.GetStateEventFlags(State)); 313 (int)m_Script.GetStateEventFlags(State));
314 314
315 Running = false; 315 if (!Running)
316
317 if (ShuttingDown)
318 m_startOnInit = false; 316 m_startOnInit = false;
319 317
318 Running = false;
319
320 // we get new rez events on sim restart, too 320 // we get new rez events on sim restart, too
321 // but if there is state, then we fire the change 321 // but if there is state, then we fire the change
322 // event 322 // event
@@ -352,12 +352,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
352 352
353 public void Init() 353 public void Init()
354 { 354 {
355 if (!m_startOnInit) 355 if (ShuttingDown)
356 return; 356 return;
357 357
358 if (m_startedFromSavedState) 358 if (m_startedFromSavedState)
359 { 359 {
360 Start(); 360 if (m_startOnInit)
361 Start();
361 if (m_postOnRez) 362 if (m_postOnRez)
362 { 363 {
363 PostEvent(new EventParams("on_rez", 364 PostEvent(new EventParams("on_rez",
@@ -389,7 +390,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
389 } 390 }
390 else 391 else
391 { 392 {
392 Start(); 393 if (m_startOnInit)
394 Start();
393 PostEvent(new EventParams("state_entry", 395 PostEvent(new EventParams("state_entry",
394 new Object[0], new DetectParams[0])); 396 new Object[0], new DetectParams[0]));
395 if (m_postOnRez) 397 if (m_postOnRez)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 35a0200..f6cb7df 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -109,6 +109,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
109 private bool m_KillTimedOutScripts; 109 private bool m_KillTimedOutScripts;
110 private string m_ScriptEnginesPath = null; 110 private string m_ScriptEnginesPath = null;
111 111
112 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
113
112 /// <summary> 114 /// <summary>
113 /// Is the entire simulator in the process of shutting down? 115 /// Is the entire simulator in the process of shutting down?
114 /// </summary> 116 /// </summary>
@@ -715,6 +717,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
715 m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning; 717 m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning;
716 m_Scene.EventManager.OnShutdown += OnShutdown; 718 m_Scene.EventManager.OnShutdown += OnShutdown;
717 719
720 // If region ready has been triggered, then the region had no scripts to compile and completed its other
721 // work.
722 m_Scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) m_InitialStartup = false; };
723
718 if (m_SleepTime > 0) 724 if (m_SleepTime > 0)
719 { 725 {
720 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance), 726 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance),
@@ -1269,7 +1275,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1269 1275
1270 if (instance!=null) 1276 if (instance!=null)
1271 instance.Init(); 1277 instance.Init();
1272 1278
1279 bool runIt;
1280 if (m_runFlags.TryGetValue(itemID, out runIt))
1281 {
1282 if (!runIt)
1283 StopScript(itemID);
1284 m_runFlags.Remove(itemID);
1285 }
1286
1273 return true; 1287 return true;
1274 } 1288 }
1275 1289
@@ -1660,6 +1674,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1660 IScriptInstance instance = GetInstance(itemID); 1674 IScriptInstance instance = GetInstance(itemID);
1661 if (instance != null) 1675 if (instance != null)
1662 instance.Start(); 1676 instance.Start();
1677 else
1678 m_runFlags.AddOrUpdate(itemID, true, 240);
1663 } 1679 }
1664 1680
1665 public void StopScript(UUID itemID) 1681 public void StopScript(UUID itemID)
@@ -1671,6 +1687,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1671 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. 1687 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1672 instance.Stop(1000); 1688 instance.Stop(1000);
1673 } 1689 }
1690 else
1691 {
1692 m_runFlags.AddOrUpdate(itemID, false, 240);
1693 }
1674 } 1694 }
1675 1695
1676 public DetectParams GetDetectParams(UUID itemID, int idx) 1696 public DetectParams GetDetectParams(UUID itemID, int idx)
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
index dcbd717..3243a9a 100644
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
@@ -34,7 +34,7 @@ using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Statistics; 37using OpenSim.Framework.Monitoring;
38 38
39namespace OpenSim.Region.UserStatistics 39namespace OpenSim.Region.UserStatistics
40{ 40{
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs
index 0e17630..cdc615c 100644
--- a/OpenSim/Region/UserStatistics/Default_Report.cs
+++ b/OpenSim/Region/UserStatistics/Default_Report.cs
@@ -33,7 +33,7 @@ using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Statistics; 36using OpenSim.Framework.Monitoring;
37 37
38 38
39namespace OpenSim.Region.UserStatistics 39namespace OpenSim.Region.UserStatistics
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
index 811baba..74de46b 100644
--- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
+++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
@@ -34,7 +34,7 @@ using System.Text.RegularExpressions;
34using Mono.Data.SqliteClient; 34using Mono.Data.SqliteClient;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Statistics; 37using OpenSim.Framework.Monitoring;
38 38
39namespace OpenSim.Region.UserStatistics 39namespace OpenSim.Region.UserStatistics
40{ 40{
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
index 8c04e71..28051fb 100644
--- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
@@ -33,7 +33,7 @@ using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Statistics; 36using OpenSim.Framework.Monitoring;
37 37
38namespace OpenSim.Region.UserStatistics 38namespace OpenSim.Region.UserStatistics
39{ 39{
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index 769de83..7598cc3 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -190,7 +190,7 @@ namespace OpenSim.Tests.Common
190 = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test"); 190 = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test");
191 191
192 testScene.RegionInfo.EstateSettings = new EstateSettings(); 192 testScene.RegionInfo.EstateSettings = new EstateSettings();
193 testScene.LoginsDisabled = false; 193 testScene.LoginsEnabled = true;
194 testScene.RegisterRegionWithGrid(); 194 testScene.RegisterRegionWithGrid();
195 195
196 SceneManager.Add(testScene); 196 SceneManager.Add(testScene);
diff --git a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs
index fba03ab..0a2b30a 100644
--- a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs
@@ -80,8 +80,26 @@ namespace OpenSim.Tests.Common
80 /// <returns>The item that was added</returns> 80 /// <returns>The item that was added</returns>
81 public static TaskInventoryItem AddScript(Scene scene, SceneObjectPart part) 81 public static TaskInventoryItem AddScript(Scene scene, SceneObjectPart part)
82 { 82 {
83 return AddScript(scene, part, "scriptItem", "default { state_entry() { llSay(0, \"Hello World\"); } }");
84 }
85
86 /// <summary>
87 /// Add a simple script to the given part.
88 /// </summary>
89 /// <remarks>
90 /// TODO: Accept input for item and asset IDs to avoid mysterious script failures that try to use any of these
91 /// functions more than once in a test.
92 /// </remarks>
93 /// <param name="scene"></param>
94 /// <param name="part"></param>
95 /// <param name="scriptName">Name of the script to add</param>
96 /// <param name="scriptSource">LSL script source</param>
97 /// <returns>The item that was added</returns>
98 public static TaskInventoryItem AddScript(
99 Scene scene, SceneObjectPart part, string scriptName, string scriptSource)
100 {
83 AssetScriptText ast = new AssetScriptText(); 101 AssetScriptText ast = new AssetScriptText();
84 ast.Source = "default { state_entry() { llSay(0, \"Hello World\"); } }"; 102 ast.Source = scriptSource;
85 ast.Encode(); 103 ast.Encode();
86 104
87 UUID assetUuid = new UUID("00000000-0000-0000-1000-000000000000"); 105 UUID assetUuid = new UUID("00000000-0000-0000-1000-000000000000");
@@ -91,7 +109,7 @@ namespace OpenSim.Tests.Common
91 scene.AssetService.Store(asset); 109 scene.AssetService.Store(asset);
92 TaskInventoryItem item 110 TaskInventoryItem item
93 = new TaskInventoryItem 111 = new TaskInventoryItem
94 { Name = "scriptItem", AssetID = assetUuid, ItemID = itemUuid, 112 { Name = scriptName, AssetID = assetUuid, ItemID = itemUuid,
95 Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL }; 113 Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL };
96 part.Inventory.AddInventoryItem(item, true); 114 part.Inventory.AddInventoryItem(item, true);
97 115