aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs43
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs66
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs319
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs76
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs82
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs52
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs17
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs133
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs73
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs18
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs256
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs377
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs29
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs16
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs61
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs126
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs (renamed from OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs)2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs269
38 files changed, 1719 insertions, 431 deletions
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
index 2027ca6..30e99b0 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
@@ -26,9 +26,11 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenSim.Framework; 31using OpenSim.Framework;
31using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.ScriptEngine.Shared;
32 34
33namespace OpenSim.Region.ScriptEngine.Interfaces 35namespace OpenSim.Region.ScriptEngine.Interfaces
34{ 36{
@@ -38,11 +40,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
38 /// Initialize the API 40 /// Initialize the API
39 /// </summary> 41 /// </summary>
40 /// <remarks> 42 /// <remarks>
41 /// Each API has an identifier, which is used to load the 43 /// Each API has an identifier, which is used to load the proper runtime assembly at load time.
42 /// proper runtime assembly at load time. 44 /// <param name='scriptEngine'>/param>
43 /// <param name='engine'>/param> 45 /// <param name='host'>/param>
44 /// <param name='part'></param> 46 /// <param name='item'>/param>
45 /// <param name='item'></param> 47 /// <param name='coopSleepHandle'>/param>
46 void Initialize(IScriptEngine engine, SceneObjectPart part, TaskInventoryItem item); 48 void Initialize(
49 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle);
47 } 50 }
48} \ No newline at end of file 51} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
index 17c2708..b8fdd01 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
@@ -25,16 +25,17 @@
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
28using log4net;
29using System; 28using System;
30using OpenSim.Region.ScriptEngine.Shared; 29using System.Reflection;
30using OpenSim.Framework;
31using OpenSim.Region.Framework.Scenes; 31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using OpenMetaverse;
34using Nini.Config;
35using OpenSim.Region.ScriptEngine.Interfaces; 33using OpenSim.Region.ScriptEngine.Interfaces;
34using OpenSim.Region.ScriptEngine.Shared;
36using Amib.Threading; 35using Amib.Threading;
37using OpenSim.Framework; 36using log4net;
37using Nini.Config;
38using OpenMetaverse;
38 39
39namespace OpenSim.Region.ScriptEngine.Interfaces 40namespace OpenSim.Region.ScriptEngine.Interfaces
40{ 41{
@@ -76,6 +77,38 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
76 IConfigSource ConfigSource { get; } 77 IConfigSource ConfigSource { get; }
77 string ScriptEngineName { get; } 78 string ScriptEngineName { get; }
78 string ScriptEnginePath { get; } 79 string ScriptEnginePath { get; }
80
81 /// <summary>
82 /// Return the name of the class that will be used for all running scripts.
83 /// </summary>
84 /// <remarks>
85 /// Each class goes in its own assembly so we don't need to otherwise distinguish the class name.
86 /// </remarks>
87 string ScriptClassName { get; }
88
89 /// <summary>
90 /// Return the name of the base class that will be used for all running scripts.
91 /// </summary>
92 string ScriptBaseClassName { get; }
93
94 /// <summary>
95 /// Assemblies that need to be referenced when compiling scripts.
96 /// </summary>
97 /// <remarks>
98 /// These are currently additional to those always referenced by the compiler, BUT THIS MAY CHANGE IN THE
99 /// FUTURE.
100 /// This can be null if there are no additional assemblies.
101 /// </remarks>
102 string[] ScriptReferencedAssemblies { get; }
103
104 /// <summary>
105 /// Parameters for the generated script's constructor.
106 /// </summary>
107 /// <remarks>
108 /// Can be null if there are no parameters
109 /// </remarks>
110 ParameterInfo[] ScriptBaseClassParameters { get; }
111
79 IScriptApi GetApi(UUID itemID, string name); 112 IScriptApi GetApi(UUID itemID, string name);
80 } 113 }
81} 114}
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b04f6b6..f68612c 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -28,9 +28,11 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Threading;
31using OpenMetaverse; 32using OpenMetaverse;
32using log4net; 33using log4net;
33using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.ScriptEngine.Shared; 36using OpenSim.Region.ScriptEngine.Shared;
35using OpenSim.Region.ScriptEngine.Interfaces; 37using OpenSim.Region.ScriptEngine.Interfaces;
36 38
@@ -59,6 +61,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
59 public interface IScriptInstance 61 public interface IScriptInstance
60 { 62 {
61 /// <summary> 63 /// <summary>
64 /// Debug level for this script instance.
65 /// </summary>
66 /// <remarks>
67 /// Level == 0, no extra data is logged.
68 /// Level >= 1, state changes are logged.
69 /// Level >= 2, event firing is logged.
70 /// <value>
71 /// The debug level.
72 /// </value>
73 int DebugLevel { get; set; }
74
75 /// <summary>
62 /// Is the script currently running? 76 /// Is the script currently running?
63 /// </summary> 77 /// </summary>
64 bool Running { get; set; } 78 bool Running { get; set; }
@@ -93,6 +107,11 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
93 /// </summary> 107 /// </summary>
94 long MeasurementPeriodExecutionTime { get; } 108 long MeasurementPeriodExecutionTime { get; }
95 109
110 /// <summary>
111 /// Scene part in which this script instance is contained.
112 /// </summary>
113 SceneObjectPart Part { get; }
114
96 IScriptEngine Engine { get; } 115 IScriptEngine Engine { get; }
97 UUID AppDomain { get; set; } 116 UUID AppDomain { get; set; }
98 string PrimName { get; } 117 string PrimName { get; }
@@ -112,8 +131,24 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
112 131
113 uint LocalID { get; } 132 uint LocalID { get; }
114 UUID AssetID { get; } 133 UUID AssetID { get; }
134
135 /// <summary>
136 /// Inventory item containing the script used.
137 /// </summary>
138 TaskInventoryItem ScriptTask { get; }
139
115 Queue EventQueue { get; } 140 Queue EventQueue { get; }
116 141
142 /// <summary>
143 /// Number of events queued for processing.
144 /// </summary>
145 long EventsQueued { get; }
146
147 /// <summary>
148 /// Number of events processed by this script instance.
149 /// </summary>
150 long EventsProcessed { get; }
151
117 void ClearQueue(); 152 void ClearQueue();
118 int StartParam { get; set; } 153 int StartParam { get; set; }
119 154
@@ -125,7 +160,13 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
125 /// <summary> 160 /// <summary>
126 /// Stop the script instance. 161 /// Stop the script instance.
127 /// </summary> 162 /// </summary>
163 /// <remarks>
164 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
165 /// there is a danger that it will self-abort and not complete the reset.
166 /// </remarks>
128 /// <param name="timeout"></param> 167 /// <param name="timeout"></param>
168 /// How many milliseconds we will wait for an existing script event to finish before
169 /// forcibly aborting that event.
129 /// <returns>true if the script was successfully stopped, false otherwise</returns> 170 /// <returns>true if the script was successfully stopped, false otherwise</returns>
130 bool Stop(int timeout); 171 bool Stop(int timeout);
131 172
@@ -147,8 +188,31 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
147 object EventProcessor(); 188 object EventProcessor();
148 189
149 int EventTime(); 190 int EventTime();
150 void ResetScript(); 191
192 /// <summary>
193 /// Reset the script.
194 /// </summary>
195 /// <remarks>
196 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
197 /// there is a danger that it will self-abort and not complete the reset. Such a thread must call
198 /// ApiResetScript() instead.
199 /// </remarks>
200 /// <param name='timeout'>
201 /// How many milliseconds we will wait for an existing script event to finish before
202 /// forcibly aborting that event prior to script reset.
203 /// </param>
204 void ResetScript(int timeout);
205
206 /// <summary>
207 /// Reset the script.
208 /// </summary>
209 /// <remarks>
210 /// This must not be called by any thread other than the one executing the scripts current event. This is
211 /// because there is no wait or abort logic if another thread is in the middle of processing a script event.
212 /// Such an external thread should use ResetScript() instead.
213 /// </remarks>
151 void ApiResetScript(); 214 void ApiResetScript();
215
152 Dictionary<string, object> GetVars(); 216 Dictionary<string, object> GetVars();
153 void SetVars(Dictionary<string, object> vars); 217 void SetVars(Dictionary<string, object> vars);
154 DetectParams GetDetectParams(int idx); 218 DetectParams GetDetectParams(int idx);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
index b5fa6de..fce8ff8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
29using System.Reflection; 30using System.Reflection;
30using System.Collections; 31using System.Collections;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -62,7 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
62 internal TaskInventoryItem m_item; 63 internal TaskInventoryItem m_item;
63 internal bool m_CMFunctionsEnabled = false; 64 internal bool m_CMFunctionsEnabled = false;
64 65
65 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
66 { 67 {
67 m_ScriptEngine = ScriptEngine; 68 m_ScriptEngine = ScriptEngine;
68 m_host = host; 69 m_host = host;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 53c6e5c..38a9cb0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -87,10 +87,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
87 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 87 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
88 { 88 {
89 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 89 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
90
90 protected IScriptEngine m_ScriptEngine; 91 protected IScriptEngine m_ScriptEngine;
91 protected SceneObjectPart m_host; 92 protected SceneObjectPart m_host;
92 93
93 /// <summary> 94 /// <summary>
95 /// Used for script sleeps when we are using co-operative script termination.
96 /// </summary>
97 /// <remarks>null if co-operative script termination is not active</remarks>
98 WaitHandle m_coopSleepHandle;
99
100 /// <summary>
94 /// The item that hosts this script 101 /// The item that hosts this script
95 /// </summary> 102 /// </summary>
96 protected TaskInventoryItem m_item; 103 protected TaskInventoryItem m_item;
@@ -100,6 +107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
100 protected float m_ScriptDelayFactor = 1.0f; 107 protected float m_ScriptDelayFactor = 1.0f;
101 protected float m_ScriptDistanceFactor = 1.0f; 108 protected float m_ScriptDistanceFactor = 1.0f;
102 protected float m_MinTimerInterval = 0.5f; 109 protected float m_MinTimerInterval = 0.5f;
110 protected float m_recoilScaleFactor = 0.0f;
103 111
104 protected DateTime m_timer = DateTime.Now; 112 protected DateTime m_timer = DateTime.Now;
105 protected bool m_waitingForScriptAnswer = false; 113 protected bool m_waitingForScriptAnswer = false;
@@ -141,33 +149,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 {"TURNRIGHT", "Turning Right"} 149 {"TURNRIGHT", "Turning Right"}
142 }; 150 };
143 151
144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 152 public void Initialize(
153 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
145 { 154 {
146/*
147 m_ShoutSayTimer = new Timer(1000);
148 m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed;
149 m_ShoutSayTimer.AutoReset = true;
150 m_ShoutSayTimer.Start();
151*/
152 m_lastSayShoutCheck = DateTime.UtcNow; 155 m_lastSayShoutCheck = DateTime.UtcNow;
153 156
154 m_ScriptEngine = ScriptEngine; 157 m_ScriptEngine = scriptEngine;
155 m_host = host; 158 m_host = host;
156 m_item = item; 159 m_item = item;
157 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 160 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
161 m_coopSleepHandle = coopSleepHandle;
158 162
159 LoadLimits(); // read script limits from config. 163 LoadConfig();
160 164
161 m_TransferModule = 165 m_TransferModule =
162 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 166 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
163 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 167 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
164 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); 168 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
165 169
166 AsyncCommands = new AsyncCommandManager(ScriptEngine); 170 AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
167 } 171 }
168 172
169 /* load configuration items that affect script, object and run-time behavior. */ 173 /// <summary>
170 private void LoadLimits() 174 /// Load configuration items that affect script, object and run-time behavior. */
175 /// </summary>
176 private void LoadConfig()
171 { 177 {
172 m_ScriptDelayFactor = 178 m_ScriptDelayFactor =
173 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 179 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -181,12 +187,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
181 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255); 187 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
182 if (m_notecardLineReadCharsMax > 65535) 188 if (m_notecardLineReadCharsMax > 65535)
183 m_notecardLineReadCharsMax = 65535; 189 m_notecardLineReadCharsMax = 65535;
190
184 // load limits for particular subsystems. 191 // load limits for particular subsystems.
185 IConfig SMTPConfig; 192 IConfig SMTPConfig;
186 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) { 193 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) {
187 // there's an smtp config, so load in the snooze time. 194 // there's an smtp config, so load in the snooze time.
188 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); 195 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
189 } 196 }
197
198 // Rezzing an object with a velocity can create recoil. This feature seems to have been
199 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
200 // it by this factor. May be zero to turn off recoil all together.
201 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
190 } 202 }
191 203
192 public override Object InitializeLifetimeService() 204 public override Object InitializeLifetimeService()
@@ -207,7 +219,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
207 delay = (int)((float)delay * m_ScriptDelayFactor); 219 delay = (int)((float)delay * m_ScriptDelayFactor);
208 if (delay == 0) 220 if (delay == 0)
209 return; 221 return;
210 System.Threading.Thread.Sleep(delay); 222
223 Sleep(delay);
224 }
225
226 protected virtual void Sleep(int delay)
227 {
228 if (m_coopSleepHandle == null)
229 System.Threading.Thread.Sleep(delay);
230 else
231 CheckForCoopTermination(delay);
232 }
233
234 /// <summary>
235 /// Check for co-operative termination.
236 /// </summary>
237 /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param>
238 protected virtual void CheckForCoopTermination(int delay)
239 {
240 if (m_coopSleepHandle.WaitOne(delay))
241 throw new ScriptCoopStopException();
211 } 242 }
212 243
213 public Scene World 244 public Scene World
@@ -1483,19 +1514,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1483 return 0; 1514 return 0;
1484 1515
1485 case ScriptBaseClass.STATUS_ROTATE_X: 1516 case ScriptBaseClass.STATUS_ROTATE_X:
1486 if (m_host.GetAxisRotation(2) == 2) 1517 // if (m_host.GetAxisRotation(2) != 0)
1518 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
1487 return 1; 1519 return 1;
1488 else 1520 else
1489 return 0; 1521 return 0;
1490 1522
1491 case ScriptBaseClass.STATUS_ROTATE_Y: 1523 case ScriptBaseClass.STATUS_ROTATE_Y:
1492 if (m_host.GetAxisRotation(4) == 4) 1524 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
1493 return 1; 1525 return 1;
1494 else 1526 else
1495 return 0; 1527 return 0;
1496 1528
1497 case ScriptBaseClass.STATUS_ROTATE_Z: 1529 case ScriptBaseClass.STATUS_ROTATE_Z:
1498 if (m_host.GetAxisRotation(8) == 8) 1530 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
1499 return 1; 1531 return 1;
1500 else 1532 else
1501 return 0; 1533 return 0;
@@ -1875,10 +1907,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1875 part.Shape.FlexiForceX = (float)Force.x; 1907 part.Shape.FlexiForceX = (float)Force.x;
1876 part.Shape.FlexiForceY = (float)Force.y; 1908 part.Shape.FlexiForceY = (float)Force.y;
1877 part.Shape.FlexiForceZ = (float)Force.z; 1909 part.Shape.FlexiForceZ = (float)Force.z;
1878 part.Shape.PathCurve = 0x80; 1910 part.Shape.PathCurve = (byte)Extrusion.Flexible;
1879 part.ParentGroup.HasGroupChanged = true;
1880 part.ScheduleFullUpdate();
1881 } 1911 }
1912 else
1913 {
1914 // Other values not set, they do not seem to be sent to the viewer
1915 // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off
1916 part.Shape.PathCurve = (byte)Extrusion.Straight;
1917 part.Shape.FlexiEntry = false;
1918 }
1919 part.ParentGroup.HasGroupChanged = true;
1920 part.ScheduleFullUpdate();
1882 } 1921 }
1883 1922
1884 /// <summary> 1923 /// <summary>
@@ -3141,11 +3180,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3141 3180
3142 PhysicsActor pa = new_group.RootPart.PhysActor; 3181 PhysicsActor pa = new_group.RootPart.PhysActor;
3143 3182
3183 //Recoil.
3144 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3184 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3145 { 3185 {
3146 float groupmass = new_group.GetMass(); 3186 float groupmass = new_group.GetMass();
3147 vel *= -groupmass; 3187 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3148 llApplyImpulse(vel, 0); 3188 if (recoil != Vector3.Zero)
3189 {
3190 llApplyImpulse(recoil, 0);
3191 }
3149 } 3192 }
3150 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3193 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3151 return; 3194 return;
@@ -3220,7 +3263,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3220 { 3263 {
3221// m_log.Info("llSleep snoozing " + sec + "s."); 3264// m_log.Info("llSleep snoozing " + sec + "s.");
3222 m_host.AddScriptLPS(1); 3265 m_host.AddScriptLPS(1);
3223 Thread.Sleep((int)(sec * 1000)); 3266
3267 Sleep((int)(sec * 1000));
3224 } 3268 }
3225 3269
3226 public LSL_Float llGetMass() 3270 public LSL_Float llGetMass()
@@ -3322,7 +3366,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3322 /// <summary> 3366 /// <summary>
3323 /// Attach the object containing this script to the avatar that owns it. 3367 /// Attach the object containing this script to the avatar that owns it.
3324 /// </summary> 3368 /// </summary>
3325 /// <param name='attachment'>The attachment point (e.g. ATTACH_CHEST)</param> 3369 /// <param name='attachmentPoint'>
3370 /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>)
3371 /// </param>
3326 /// <returns>true if the attach suceeded, false if it did not</returns> 3372 /// <returns>true if the attach suceeded, false if it did not</returns>
3327 public bool AttachToAvatar(int attachmentPoint) 3373 public bool AttachToAvatar(int attachmentPoint)
3328 { 3374 {
@@ -3680,7 +3726,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3680 if (animID == UUID.Zero) 3726 if (animID == UUID.Zero)
3681 presence.Animator.RemoveAnimation(anim); 3727 presence.Animator.RemoveAnimation(anim);
3682 else 3728 else
3683 presence.Animator.RemoveAnimation(animID); 3729 presence.Animator.RemoveAnimation(animID, true);
3684 } 3730 }
3685 } 3731 }
3686 } 3732 }
@@ -3753,21 +3799,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3753 } 3799 }
3754 else 3800 else
3755 { 3801 {
3756 bool sitting = false; 3802 if (m_host.ParentGroup.GetSittingAvatars().Contains(agentID))
3757 if (m_host.SitTargetAvatar == agentID)
3758 {
3759 sitting = true;
3760 }
3761 else
3762 {
3763 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3764 {
3765 if (p.SitTargetAvatar == agentID)
3766 sitting = true;
3767 }
3768 }
3769
3770 if (sitting)
3771 { 3803 {
3772 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3804 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3773 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3805 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
@@ -3809,7 +3841,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3809 INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); 3841 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
3810 if (npcModule != null && npcModule.IsNPC(agentID, World)) 3842 if (npcModule != null && npcModule.IsNPC(agentID, World))
3811 { 3843 {
3812 if (agentID == m_host.ParentGroup.OwnerID || npcModule.GetOwner(agentID) == m_host.ParentGroup.OwnerID) 3844 if (npcModule.CheckPermissions(agentID, m_host.OwnerID))
3813 { 3845 {
3814 lock (m_host.TaskInventory) 3846 lock (m_host.TaskInventory)
3815 { 3847 {
@@ -4184,62 +4216,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4184 public LSL_String llGetLinkName(int linknum) 4216 public LSL_String llGetLinkName(int linknum)
4185 { 4217 {
4186 m_host.AddScriptLPS(1); 4218 m_host.AddScriptLPS(1);
4187 // simplest case, this prims link number
4188 if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS)
4189 return m_host.Name;
4190 4219
4191 // parse for sitting avatare-names 4220 if (linknum < 0)
4192 List<String> nametable = new List<String>();
4193 World.ForEachRootScenePresence(delegate(ScenePresence presence)
4194 { 4221 {
4195 SceneObjectPart sitPart = presence.ParentPart; 4222 if (linknum == ScriptBaseClass.LINK_THIS)
4196 if (sitPart != null && m_host.ParentGroup.ContainsPart(sitPart.LocalId))
4197 nametable.Add(presence.ControllingClient.Name);
4198 });
4199
4200 int totalprims = m_host.ParentGroup.PrimCount + nametable.Count;
4201 if (totalprims > m_host.ParentGroup.PrimCount)
4202 {
4203 // sitting Avatar-Name with negativ linknum / SinglePrim
4204 if (linknum < 0 && m_host.ParentGroup.PrimCount == 1 && nametable.Count == 1)
4205 return nametable[0];
4206 // Prim-Name / SinglePrim Sitting Avatar
4207 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && nametable.Count == 1)
4208 return m_host.Name; 4223 return m_host.Name;
4209 // LinkNumber > of Real PrimSet = AvatarName 4224 else
4210 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims) 4225 return ScriptBaseClass.NULL_KEY;
4211 return nametable[totalprims - linknum];
4212 } 4226 }
4213 4227
4214 // Single prim 4228 int actualPrimCount = m_host.ParentGroup.PrimCount;
4215 if (m_host.LinkNum == 0) 4229 List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars();
4230 int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count;
4231
4232 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
4233 // prim that has any avatars sat upon it (in which case the root prim is link 1).
4234 if (linknum == 0)
4216 { 4235 {
4217 if (linknum == 0 || linknum == ScriptBaseClass.LINK_ROOT) 4236 if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
4218 return m_host.Name; 4237 return m_host.Name;
4219 else
4220 return UUID.Zero.ToString();
4221 }
4222 4238
4223 // Link set 4239 return ScriptBaseClass.NULL_KEY;
4224 SceneObjectPart part = null; 4240 }
4225 if (m_host.LinkNum == 1) // this is the Root prim 4241 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
4242 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
4243 else if (linknum == 1 && actualPrimCount == 1)
4226 { 4244 {
4227 if (linknum < 0) 4245 if (sittingAvatarIds.Count > 0)
4228 part = m_host.ParentGroup.GetLinkNumPart(2); 4246 return m_host.ParentGroup.RootPart.Name;
4229 else 4247 else
4230 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4248 return ScriptBaseClass.NULL_KEY;
4231 } 4249 }
4232 else // this is a child prim 4250 else if (linknum <= adjustedPrimCount)
4233 { 4251 {
4234 if (linknum < 2) 4252 if (linknum <= actualPrimCount)
4235 part = m_host.ParentGroup.GetLinkNumPart(1); 4253 {
4254 return m_host.ParentGroup.GetLinkNumPart(linknum).Name;
4255 }
4236 else 4256 else
4237 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4257 {
4258 ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]);
4259 if (sp != null)
4260 return sp.Name;
4261 else
4262 return ScriptBaseClass.NULL_KEY;
4263 }
4238 } 4264 }
4239 if (part != null)
4240 return part.Name;
4241 else 4265 else
4242 return UUID.Zero.ToString(); 4266 {
4267 return ScriptBaseClass.NULL_KEY;
4268 }
4243 } 4269 }
4244 4270
4245 public LSL_Integer llGetInventoryNumber(int type) 4271 public LSL_Integer llGetInventoryNumber(int type)
@@ -5852,9 +5878,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5852 } 5878 }
5853 5879
5854 /// <summary> 5880 /// <summary>
5855 /// Insert the list identified by <src> into the 5881 /// Insert the list identified by <paramref name="src"/> into the
5856 /// list designated by <dest> such that the first 5882 /// list designated by <paramref name="dest"/> such that the first
5857 /// new element has the index specified by <index> 5883 /// new element has the index specified by <paramref name="index"/>
5858 /// </summary> 5884 /// </summary>
5859 5885
5860 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) 5886 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
@@ -6220,13 +6246,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6220 if (parcelOwned && land.LandData.OwnerID == id || 6246 if (parcelOwned && land.LandData.OwnerID == id ||
6221 parcel && land.LandData.GlobalID == id) 6247 parcel && land.LandData.GlobalID == id)
6222 { 6248 {
6223 result.Add(ssp.UUID.ToString()); 6249 result.Add(new LSL_Key(ssp.UUID.ToString()));
6224 } 6250 }
6225 } 6251 }
6226 } 6252 }
6227 else 6253 else
6228 { 6254 {
6229 result.Add(ssp.UUID.ToString()); 6255 result.Add(new LSL_Key(ssp.UUID.ToString()));
6230 } 6256 }
6231 } 6257 }
6232 // Maximum of 100 results 6258 // Maximum of 100 results
@@ -6687,6 +6713,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6687 ps.BurstSpeedMax = 1.0f; 6713 ps.BurstSpeedMax = 1.0f;
6688 ps.BurstRate = 0.1f; 6714 ps.BurstRate = 0.1f;
6689 ps.PartMaxAge = 10.0f; 6715 ps.PartMaxAge = 10.0f;
6716 ps.BurstPartCount = 1;
6690 return ps; 6717 return ps;
6691 } 6718 }
6692 6719
@@ -6708,10 +6735,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6708 SetParticleSystem(m_host, rules); 6735 SetParticleSystem(m_host, rules);
6709 } 6736 }
6710 6737
6711 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) 6738 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6712 { 6739 {
6713
6714
6715 if (rules.Length == 0) 6740 if (rules.Length == 0)
6716 { 6741 {
6717 part.RemoveParticleSystem(); 6742 part.RemoveParticleSystem();
@@ -7371,6 +7396,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7371 public void llCloseRemoteDataChannel(string channel) 7396 public void llCloseRemoteDataChannel(string channel)
7372 { 7397 {
7373 m_host.AddScriptLPS(1); 7398 m_host.AddScriptLPS(1);
7399
7400 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
7401 if (xmlRpcRouter != null)
7402 {
7403 xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID);
7404 }
7405
7374 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7406 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7375 if (xmlrpcMod != null) 7407 if (xmlrpcMod != null)
7376 xmlrpcMod.CloseXMLRPCChannel((UUID)channel); 7408 xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
@@ -11517,6 +11549,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11517 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11549 case ScriptBaseClass.OBJECT_PHYSICS_COST:
11518 ret.Add(new LSL_Float(0)); 11550 ret.Add(new LSL_Float(0));
11519 break; 11551 break;
11552 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
11553 ret.Add(new LSL_Float(0));
11554 break;
11555 case ScriptBaseClass.OBJECT_ROOT:
11556 SceneObjectPart p = av.ParentPart;
11557 if (p != null)
11558 {
11559 ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString()));
11560 }
11561 else
11562 {
11563 ret.Add(new LSL_String(id));
11564 }
11565 break;
11566 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
11567 ret.Add(new LSL_Integer(0));
11568 break;
11569 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding
11570 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR));
11571 break;
11572 case ScriptBaseClass.OBJECT_PHYSICS:
11573 ret.Add(new LSL_Integer(0));
11574 break;
11575 case ScriptBaseClass.OBJECT_PHANTOM:
11576 ret.Add(new LSL_Integer(0));
11577 break;
11578 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
11579 ret.Add(new LSL_Integer(0));
11580 break;
11520 default: 11581 default:
11521 // Invalid or unhandled constant. 11582 // Invalid or unhandled constant.
11522 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 11583 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -11608,6 +11669,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11608 // The value returned in SL for normal prims is prim count 11669 // The value returned in SL for normal prims is prim count
11609 ret.Add(new LSL_Float(obj.PhysicsCost)); 11670 ret.Add(new LSL_Float(obj.PhysicsCost));
11610 break; 11671 break;
11672 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
11673 ret.Add(new LSL_Float(0));
11674 break;
11675 case ScriptBaseClass.OBJECT_ROOT:
11676 ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString()));
11677 break;
11678 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
11679 ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint));
11680 break;
11681 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE:
11682 byte pcode = obj.Shape.PCode;
11683 if (obj.ParentGroup.AttachmentPoint != 0
11684 || pcode == (byte)PCode.Grass
11685 || pcode == (byte)PCode.Tree
11686 || pcode == (byte)PCode.NewTree)
11687 {
11688 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER));
11689 }
11690 else
11691 {
11692 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET));
11693 }
11694 break;
11695 case ScriptBaseClass.OBJECT_PHYSICS:
11696 if (obj.ParentGroup.AttachmentPoint != 0)
11697 {
11698 ret.Add(new LSL_Integer(0)); // Always false if attached
11699 }
11700 else
11701 {
11702 ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0));
11703 }
11704 break;
11705 case ScriptBaseClass.OBJECT_PHANTOM:
11706 if (obj.ParentGroup.AttachmentPoint != 0)
11707 {
11708 ret.Add(new LSL_Integer(0)); // Always false if attached
11709 }
11710 else
11711 {
11712 ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0));
11713 }
11714 break;
11715 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
11716 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0));
11717 break;
11611 default: 11718 default:
11612 // Invalid or unhandled constant. 11719 // Invalid or unhandled constant.
11613 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 11720 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -11991,12 +12098,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11991 radius = Math.Abs(maxY); 12098 radius = Math.Abs(maxY);
11992 if (Math.Abs(maxZ) > radius) 12099 if (Math.Abs(maxZ) > radius)
11993 radius = Math.Abs(maxZ); 12100 radius = Math.Abs(maxZ);
11994 12101 radius = radius*1.413f;
11995 Vector3 ac = group.AbsolutePosition - rayStart; 12102 Vector3 ac = group.AbsolutePosition - rayStart;
11996 Vector3 bc = group.AbsolutePosition - rayEnd; 12103 Vector3 bc = group.AbsolutePosition - rayEnd;
11997 12104
11998 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 12105 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11999 12106
12000 // Too far off ray, don't bother 12107 // Too far off ray, don't bother
12001 if (d > radius) 12108 if (d > radius)
12002 return; 12109 return;
@@ -12006,11 +12113,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12006 if (d2 > 0) 12113 if (d2 > 0)
12007 return; 12114 return;
12008 12115
12116 ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
12009 EntityIntersection intersection = group.TestIntersection(ray, true, false); 12117 EntityIntersection intersection = group.TestIntersection(ray, true, false);
12010 // Miss. 12118 // Miss.
12011 if (!intersection.HitTF) 12119 if (!intersection.HitTF)
12012 return; 12120 return;
12013 12121
12122 Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ);
12123 Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ);
12124 //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z);
12125 if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
12126 intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
12127 intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
12128 return;
12129
12014 ContactResult result = new ContactResult (); 12130 ContactResult result = new ContactResult ();
12015 result.ConsumerID = group.LocalId; 12131 result.ConsumerID = group.LocalId;
12016// result.Depth = intersection.distance; 12132// result.Depth = intersection.distance;
@@ -12284,8 +12400,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12284 if (checkPhysical || checkNonPhysical || detectPhantom) 12400 if (checkPhysical || checkNonPhysical || detectPhantom)
12285 { 12401 {
12286 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 12402 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
12287 foreach (ContactResult r in objectHits) 12403 for (int iter = 0; iter < objectHits.Length; iter++)
12288 results.Add(r); 12404 {
12405 // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
12406 objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
12407 results.Add(objectHits[iter]);
12408 }
12289 } 12409 }
12290 } 12410 }
12291 12411
@@ -13271,7 +13391,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13271 /// Get a notecard line. 13391 /// Get a notecard line.
13272 /// </summary> 13392 /// </summary>
13273 /// <param name="assetID"></param> 13393 /// <param name="assetID"></param>
13274 /// <param name="line">Lines start at index 0</param> 13394 /// <param name="lineNumber">Lines start at index 0</param>
13275 /// <returns></returns> 13395 /// <returns></returns>
13276 public static string GetLine(UUID assetID, int lineNumber) 13396 public static string GetLine(UUID assetID, int lineNumber)
13277 { 13397 {
@@ -13300,9 +13420,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13300 /// Get a notecard line. 13420 /// Get a notecard line.
13301 /// </summary> 13421 /// </summary>
13302 /// <param name="assetID"></param> 13422 /// <param name="assetID"></param>
13303 /// <param name="line">Lines start at index 0</param> 13423 /// <param name="lineNumber">Lines start at index 0</param>
13304 /// <param name="maxLength">Maximum length of the returned line. Longer lines will be truncated</para> 13424 /// <param name="maxLength">
13305 /// <returns></returns> 13425 /// Maximum length of the returned line.
13426 /// </param>
13427 /// <returns>
13428 /// If the line length is longer than <paramref name="maxLength"/>,
13429 /// the return string will be truncated.
13430 /// </returns>
13306 public static string GetLine(UUID assetID, int lineNumber, int maxLength) 13431 public static string GetLine(UUID assetID, int lineNumber, int maxLength)
13307 { 13432 {
13308 string line = GetLine(assetID, lineNumber); 13433 string line = GetLine(assetID, lineNumber);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index ceb4660..1d6cb6d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -30,6 +30,7 @@ using System.Reflection;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
33using System.Threading;
33using OpenMetaverse; 34using OpenMetaverse;
34using Nini.Config; 35using Nini.Config;
35using OpenSim; 36using OpenSim;
@@ -61,9 +62,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
61 internal bool m_LSFunctionsEnabled = false; 62 internal bool m_LSFunctionsEnabled = false;
62 internal IScriptModuleComms m_comms = null; 63 internal IScriptModuleComms m_comms = null;
63 64
64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 65 public void Initialize(
66 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
65 { 67 {
66 m_ScriptEngine = ScriptEngine; 68 m_ScriptEngine = scriptEngine;
67 m_host = host; 69 m_host = host;
68 70
69 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) 71 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false))
@@ -92,10 +94,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
92 get { return m_ScriptEngine.World; } 94 get { return m_ScriptEngine.World; }
93 } 95 }
94 96
95 // 97 /// <summary>
96 //Dumps an error message on the debug console. 98 /// Dumps an error message on the debug console.
97 // 99 /// </summary>
98
99 internal void LSShoutError(string message) 100 internal void LSShoutError(string message)
100 { 101 {
101 if (message.Length > 1023) 102 if (message.Length > 1023)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 8f34833..9045672 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -30,6 +30,7 @@ using System.Reflection;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
33using System.Threading;
33using OpenMetaverse; 34using OpenMetaverse;
34using Nini.Config; 35using Nini.Config;
35using OpenSim; 36using OpenSim;
@@ -61,9 +62,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
61 internal bool m_MODFunctionsEnabled = false; 62 internal bool m_MODFunctionsEnabled = false;
62 internal IScriptModuleComms m_comms = null; 63 internal IScriptModuleComms m_comms = null;
63 64
64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 65 public void Initialize(
66 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
65 { 67 {
66 m_ScriptEngine = ScriptEngine; 68 m_ScriptEngine = scriptEngine;
67 m_host = host; 69 m_host = host;
68 m_item = item; 70 m_item = item;
69 71
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7c2f8ed..6ff6b00 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -143,9 +143,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
143 143
144 protected IUrlModule m_UrlModule = null; 144 protected IUrlModule m_UrlModule = null;
145 145
146 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 146 public void Initialize(
147 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
147 { 148 {
148 m_ScriptEngine = ScriptEngine; 149 m_ScriptEngine = scriptEngine;
149 m_host = host; 150 m_host = host;
150 m_item = item; 151 m_item = item;
151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 152 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
@@ -254,11 +255,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
254 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); 255 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
255 } 256 }
256 257
258 // Returns of the function is allowed. Throws a script exception if not allowed.
257 public void CheckThreatLevel(ThreatLevel level, string function) 259 public void CheckThreatLevel(ThreatLevel level, string function)
258 { 260 {
259 if (!m_OSFunctionsEnabled) 261 if (!m_OSFunctionsEnabled)
260 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws 262 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws
261 263
264 string reasonWhyNot = CheckThreatLevelTest(level, function);
265 if (!String.IsNullOrEmpty(reasonWhyNot))
266 {
267 OSSLError(reasonWhyNot);
268 }
269 }
270
271 // Check to see if function is allowed. Returns an empty string if function permitted
272 // or a string explaining why this function can't be used.
273 private string CheckThreatLevelTest(ThreatLevel level, string function)
274 {
262 if (!m_FunctionPerms.ContainsKey(function)) 275 if (!m_FunctionPerms.ContainsKey(function))
263 { 276 {
264 FunctionPerms perms = new FunctionPerms(); 277 FunctionPerms perms = new FunctionPerms();
@@ -338,10 +351,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
338 { 351 {
339 // Allow / disallow by threat level 352 // Allow / disallow by threat level
340 if (level > m_MaxThreatLevel) 353 if (level > m_MaxThreatLevel)
341 OSSLError( 354 return
342 String.Format( 355 String.Format(
343 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.", 356 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.",
344 function, m_MaxThreatLevel, level)); 357 function, m_MaxThreatLevel, level);
345 } 358 }
346 else 359 else
347 { 360 {
@@ -351,7 +364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
351 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID)) 364 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
352 { 365 {
353 // prim owner is in the list of allowed owners 366 // prim owner is in the list of allowed owners
354 return; 367 return String.Empty;
355 } 368 }
356 369
357 UUID ownerID = m_item.OwnerID; 370 UUID ownerID = m_item.OwnerID;
@@ -363,7 +376,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
363 376
364 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) 377 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
365 { 378 {
366 return; 379 return String.Empty;
367 } 380 }
368 } 381 }
369 382
@@ -374,7 +387,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
374 387
375 if (land.LandData.OwnerID == ownerID) 388 if (land.LandData.OwnerID == ownerID)
376 { 389 {
377 return; 390 return String.Empty;
378 } 391 }
379 } 392 }
380 393
@@ -384,7 +397,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 //Only Estate Managers may use the function 397 //Only Estate Managers may use the function
385 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) 398 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
386 { 399 {
387 return; 400 return String.Empty;
388 } 401 }
389 } 402 }
390 403
@@ -393,25 +406,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
393 { 406 {
394 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID) 407 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
395 { 408 {
396 return; 409 return String.Empty;
397 } 410 }
398 } 411 }
399 412
400 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) 413 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
401 OSSLError( 414 return(
402 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", 415 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
403 function)); 416 function));
404 417
405 if (m_item.CreatorID != ownerID) 418 if (m_item.CreatorID != ownerID)
406 { 419 {
407 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0) 420 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
408 OSSLError( 421 return String.Format("{0} permission denied. Script permissions error.", function);
409 String.Format("{0} permission denied. Script permissions error.",
410 function));
411 422
412 } 423 }
413 } 424 }
414 } 425 }
426 return String.Empty;
415 } 427 }
416 428
417 internal void OSSLDeprecated(string function, string replacement) 429 internal void OSSLDeprecated(string function, string replacement)
@@ -983,7 +995,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
983 if (animID == UUID.Zero) 995 if (animID == UUID.Zero)
984 target.Animator.RemoveAnimation(animation); 996 target.Animator.RemoveAnimation(animation);
985 else 997 else
986 target.Animator.RemoveAnimation(animID); 998 target.Animator.RemoveAnimation(animID, true);
987 } 999 }
988 } 1000 }
989 } 1001 }
@@ -1214,12 +1226,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1214 sunHour += 24.0; 1226 sunHour += 24.0;
1215 1227
1216 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun; 1228 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun;
1217 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30 1229 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30
1218 World.RegionInfo.RegionSettings.FixedSun = sunFixed; 1230 World.RegionInfo.RegionSettings.FixedSun = sunFixed;
1219 World.RegionInfo.RegionSettings.Save(); 1231 World.RegionInfo.RegionSettings.Save();
1220 1232
1221 World.EventManager.TriggerEstateToolsSunUpdate( 1233 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1222 World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour);
1223 } 1234 }
1224 1235
1225 /// <summary> 1236 /// <summary>
@@ -1244,8 +1255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1244 World.RegionInfo.EstateSettings.FixedSun = sunFixed; 1255 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1245 World.RegionInfo.EstateSettings.Save(); 1256 World.RegionInfo.EstateSettings.Save();
1246 1257
1247 World.EventManager.TriggerEstateToolsSunUpdate( 1258 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1248 World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour);
1249 } 1259 }
1250 1260
1251 /// <summary> 1261 /// <summary>
@@ -1569,6 +1579,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1569 } 1579 }
1570 } 1580 }
1571 1581
1582 public string osGetPhysicsEngineType()
1583 {
1584 // High because it can be used to target attacks to known weaknesses
1585 // This would allow a new class of griefer scripts that don't even
1586 // require their user to know what they are doing (see script
1587 // kiddie)
1588 // Because it would be nice if scripts didn't blow up if the information
1589 // about the physics engine, this function returns an empty string if
1590 // the user does not have permission to see it. This as opposed to
1591 // throwing an exception.
1592 m_host.AddScriptLPS(1);
1593 string ret = String.Empty;
1594 if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType")))
1595 {
1596 if (m_ScriptEngine.World.PhysicsScene != null)
1597 {
1598 ret = m_ScriptEngine.World.PhysicsScene.EngineType;
1599 // An old physics engine might have an uninitialized engine type
1600 if (ret == null)
1601 ret = "unknown";
1602 }
1603 }
1604
1605 return ret;
1606 }
1607
1572 public string osGetSimulatorVersion() 1608 public string osGetSimulatorVersion()
1573 { 1609 {
1574 // High because it can be used to target attacks to known weaknesses 1610 // High because it can be used to target attacks to known weaknesses
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 4dd795d..d3ef378 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -42,6 +42,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
42 { 42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 44
45 /// <summary>
46 /// Used by one-off and repeated sensors
47 /// </summary>
48 public class SensorInfo
49 {
50 public uint localID;
51 public UUID itemID;
52 public double interval;
53 public DateTime next;
54
55 public string name;
56 public UUID keyID;
57 public int type;
58 public double range;
59 public double arc;
60 public SceneObjectPart host;
61
62 public SensorInfo Clone()
63 {
64 return (SensorInfo)this.MemberwiseClone();
65 }
66 }
67
45 public AsyncCommandManager m_CmdManager; 68 public AsyncCommandManager m_CmdManager;
46 69
47 /// <summary> 70 /// <summary>
@@ -78,24 +101,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
78 private int maximumToReturn = 16; 101 private int maximumToReturn = 16;
79 102
80 // 103 //
81 // SenseRepeater and Sensors
82 //
83 private class SenseRepeatClass
84 {
85 public uint localID;
86 public UUID itemID;
87 public double interval;
88 public DateTime next;
89
90 public string name;
91 public UUID keyID;
92 public int type;
93 public double range;
94 public double arc;
95 public SceneObjectPart host;
96 }
97
98 //
99 // Sensed entity 104 // Sensed entity
100 // 105 //
101 private class SensedEntity : IComparable 106 private class SensedEntity : IComparable
@@ -127,7 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
127 /// 132 ///
128 /// Always lock SenseRepeatListLock when updating this list. 133 /// Always lock SenseRepeatListLock when updating this list.
129 /// </remarks> 134 /// </remarks>
130 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>(); 135 private List<SensorInfo> SenseRepeaters = new List<SensorInfo>();
131 private object SenseRepeatListLock = new object(); 136 private object SenseRepeatListLock = new object();
132 137
133 public void SetSenseRepeatEvent(uint m_localID, UUID m_itemID, 138 public void SetSenseRepeatEvent(uint m_localID, UUID m_itemID,
@@ -141,7 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
141 return; 146 return;
142 147
143 // Add to timer 148 // Add to timer
144 SenseRepeatClass ts = new SenseRepeatClass(); 149 SensorInfo ts = new SensorInfo();
145 ts.localID = m_localID; 150 ts.localID = m_localID;
146 ts.itemID = m_itemID; 151 ts.itemID = m_itemID;
147 ts.interval = sec; 152 ts.interval = sec;
@@ -160,11 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
160 AddSenseRepeater(ts); 165 AddSenseRepeater(ts);
161 } 166 }
162 167
163 private void AddSenseRepeater(SenseRepeatClass senseRepeater) 168 private void AddSenseRepeater(SensorInfo senseRepeater)
164 { 169 {
165 lock (SenseRepeatListLock) 170 lock (SenseRepeatListLock)
166 { 171 {
167 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(SenseRepeaters); 172 List<SensorInfo> newSenseRepeaters = new List<SensorInfo>(SenseRepeaters);
168 newSenseRepeaters.Add(senseRepeater); 173 newSenseRepeaters.Add(senseRepeater);
169 SenseRepeaters = newSenseRepeaters; 174 SenseRepeaters = newSenseRepeaters;
170 } 175 }
@@ -175,8 +180,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
175 // Remove from timer 180 // Remove from timer
176 lock (SenseRepeatListLock) 181 lock (SenseRepeatListLock)
177 { 182 {
178 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(); 183 List<SensorInfo> newSenseRepeaters = new List<SensorInfo>();
179 foreach (SenseRepeatClass ts in SenseRepeaters) 184 foreach (SensorInfo ts in SenseRepeaters)
180 { 185 {
181 if (ts.localID != m_localID || ts.itemID != m_itemID) 186 if (ts.localID != m_localID || ts.itemID != m_itemID)
182 { 187 {
@@ -191,7 +196,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
191 public void CheckSenseRepeaterEvents() 196 public void CheckSenseRepeaterEvents()
192 { 197 {
193 // Go through all timers 198 // Go through all timers
194 foreach (SenseRepeatClass ts in SenseRepeaters) 199 foreach (SensorInfo ts in SenseRepeaters)
195 { 200 {
196 // Time has passed? 201 // Time has passed?
197 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) 202 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
@@ -208,7 +213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
208 double range, double arc, SceneObjectPart host) 213 double range, double arc, SceneObjectPart host)
209 { 214 {
210 // Add to timer 215 // Add to timer
211 SenseRepeatClass ts = new SenseRepeatClass(); 216 SensorInfo ts = new SensorInfo();
212 ts.localID = m_localID; 217 ts.localID = m_localID;
213 ts.itemID = m_itemID; 218 ts.itemID = m_itemID;
214 ts.interval = 0; 219 ts.interval = 0;
@@ -224,7 +229,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
224 SensorSweep(ts); 229 SensorSweep(ts);
225 } 230 }
226 231
227 private void SensorSweep(SenseRepeatClass ts) 232 private void SensorSweep(SensorInfo ts)
228 { 233 {
229 if (ts.host == null) 234 if (ts.host == null)
230 { 235 {
@@ -300,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
300 } 305 }
301 } 306 }
302 307
303 private List<SensedEntity> doObjectSensor(SenseRepeatClass ts) 308 private List<SensedEntity> doObjectSensor(SensorInfo ts)
304 { 309 {
305 List<EntityBase> Entities; 310 List<EntityBase> Entities;
306 List<SensedEntity> sensedEntities = new List<SensedEntity>(); 311 List<SensedEntity> sensedEntities = new List<SensedEntity>();
@@ -451,7 +456,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
451 return sensedEntities; 456 return sensedEntities;
452 } 457 }
453 458
454 private List<SensedEntity> doAgentSensor(SenseRepeatClass ts) 459 private List<SensedEntity> doAgentSensor(SensorInfo ts)
455 { 460 {
456 List<SensedEntity> sensedEntities = new List<SensedEntity>(); 461 List<SensedEntity> sensedEntities = new List<SensedEntity>();
457 462
@@ -630,7 +635,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
630 { 635 {
631 List<Object> data = new List<Object>(); 636 List<Object> data = new List<Object>();
632 637
633 foreach (SenseRepeatClass ts in SenseRepeaters) 638 foreach (SensorInfo ts in SenseRepeaters)
634 { 639 {
635 if (ts.itemID == itemID) 640 if (ts.itemID == itemID)
636 { 641 {
@@ -660,7 +665,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
660 665
661 while (idx < data.Length) 666 while (idx < data.Length)
662 { 667 {
663 SenseRepeatClass ts = new SenseRepeatClass(); 668 SensorInfo ts = new SensorInfo();
664 669
665 ts.localID = localID; 670 ts.localID = localID;
666 ts.itemID = itemID; 671 ts.itemID = itemID;
@@ -681,5 +686,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
681 idx += 6; 686 idx += 6;
682 } 687 }
683 } 688 }
689
690 public List<SensorInfo> GetSensorInfo()
691 {
692 List<SensorInfo> retList = new List<SensorInfo>();
693
694 lock (SenseRepeatListLock)
695 {
696 foreach (SensorInfo i in SenseRepeaters)
697 retList.Add(i.Clone());
698 }
699
700 return retList;
701 }
684 } 702 }
685} 703} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index 9ee6946..68aacd2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -35,6 +35,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
35{ 35{
36 public class Timer 36 public class Timer
37 { 37 {
38 public class TimerInfo
39 {
40 public uint localID;
41 public UUID itemID;
42 //public double interval;
43 public long interval;
44 //public DateTime next;
45 public long next;
46
47 public TimerInfo Clone()
48 {
49 return (TimerInfo)this.MemberwiseClone();
50 }
51 }
52
38 public AsyncCommandManager m_CmdManager; 53 public AsyncCommandManager m_CmdManager;
39 54
40 public int TimersCount 55 public int TimersCount
@@ -59,17 +74,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
59 return localID.ToString() + itemID.ToString(); 74 return localID.ToString() + itemID.ToString();
60 } 75 }
61 76
62 private class TimerClass 77 private Dictionary<string,TimerInfo> Timers = new Dictionary<string,TimerInfo>();
63 {
64 public uint localID;
65 public UUID itemID;
66 //public double interval;
67 public long interval;
68 //public DateTime next;
69 public long next;
70 }
71
72 private Dictionary<string,TimerClass> Timers = new Dictionary<string,TimerClass>();
73 private object TimerListLock = new object(); 78 private object TimerListLock = new object();
74 79
75 public void SetTimerEvent(uint m_localID, UUID m_itemID, double sec) 80 public void SetTimerEvent(uint m_localID, UUID m_itemID, double sec)
@@ -81,7 +86,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
81 } 86 }
82 87
83 // Add to timer 88 // Add to timer
84 TimerClass ts = new TimerClass(); 89 TimerInfo ts = new TimerInfo();
85 ts.localID = m_localID; 90 ts.localID = m_localID;
86 ts.itemID = m_itemID; 91 ts.itemID = m_itemID;
87 ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait 92 ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait
@@ -118,14 +123,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
118 if (Timers.Count == 0) 123 if (Timers.Count == 0)
119 return; 124 return;
120 125
121 Dictionary<string, TimerClass>.ValueCollection tvals; 126 Dictionary<string, TimerInfo>.ValueCollection tvals;
122 lock (TimerListLock) 127 lock (TimerListLock)
123 { 128 {
124 // Go through all timers 129 // Go through all timers
125 tvals = Timers.Values; 130 tvals = Timers.Values;
126 } 131 }
127 132
128 foreach (TimerClass ts in tvals) 133 foreach (TimerInfo ts in tvals)
129 { 134 {
130 // Time has passed? 135 // Time has passed?
131 if (ts.next < DateTime.Now.Ticks) 136 if (ts.next < DateTime.Now.Ticks)
@@ -149,8 +154,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
149 154
150 lock (TimerListLock) 155 lock (TimerListLock)
151 { 156 {
152 Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values; 157 Dictionary<string, TimerInfo>.ValueCollection tvals = Timers.Values;
153 foreach (TimerClass ts in tvals) 158 foreach (TimerInfo ts in tvals)
154 { 159 {
155 if (ts.itemID == itemID) 160 if (ts.itemID == itemID)
156 { 161 {
@@ -169,7 +174,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
169 174
170 while (idx < data.Length) 175 while (idx < data.Length)
171 { 176 {
172 TimerClass ts = new TimerClass(); 177 TimerInfo ts = new TimerInfo();
173 178
174 ts.localID = localID; 179 ts.localID = localID;
175 ts.itemID = itemID; 180 ts.itemID = itemID;
@@ -183,5 +188,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
183 } 188 }
184 } 189 }
185 } 190 }
191
192 public List<TimerInfo> GetTimersInfo()
193 {
194 List<TimerInfo> retList = new List<TimerInfo>();
195
196 lock (TimerListLock)
197 {
198 foreach (TimerInfo i in Timers.Values)
199 retList.Add(i.Clone());
200 }
201
202 return retList;
203 }
186 } 204 }
187} 205}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index c447d1f..7eb347e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -259,6 +259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
259 259
260 string osGetScriptEngineName(); 260 string osGetScriptEngineName();
261 string osGetSimulatorVersion(); 261 string osGetSimulatorVersion();
262 string osGetPhysicsEngineType();
262 Object osParseJSONNew(string JSON); 263 Object osParseJSONNew(string JSON);
263 Hashtable osParseJSON(string JSON); 264 Hashtable osParseJSON(string JSON);
264 265
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 0dd5a57..da3b31f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -557,6 +557,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
557 public const int OBJECT_SERVER_COST = 14; 557 public const int OBJECT_SERVER_COST = 14;
558 public const int OBJECT_STREAMING_COST = 15; 558 public const int OBJECT_STREAMING_COST = 15;
559 public const int OBJECT_PHYSICS_COST = 16; 559 public const int OBJECT_PHYSICS_COST = 16;
560 public const int OBJECT_CHARACTER_TIME = 17;
561 public const int OBJECT_ROOT = 18;
562 public const int OBJECT_ATTACHED_POINT = 19;
563 public const int OBJECT_PATHFINDING_TYPE = 20;
564 public const int OBJECT_PHYSICS = 21;
565 public const int OBJECT_PHANTOM = 22;
566 public const int OBJECT_TEMP_ON_REZ = 23;
567
568 // Pathfinding types
569 public const int OPT_OTHER = -1;
570 public const int OPT_LEGACY_LINKSET = 0;
571 public const int OPT_AVATAR = 1;
572 public const int OPT_CHARACTER = 2;
573 public const int OPT_WALKABLE = 3;
574 public const int OPT_STATIC_OBSTACLE = 4;
575 public const int OPT_MATERIAL_VOLUME = 5;
576 public const int OPT_EXCLUSION_VOLUME = 6;
560 577
561 // for llGetAgentList 578 // for llGetAgentList
562 public const int AGENT_LIST_PARCEL = 1; 579 public const int AGENT_LIST_PARCEL = 1;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index afa9ae0..c9902e4 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -420,6 +420,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
420 return m_OSSL_Functions.osGetScriptEngineName(); 420 return m_OSSL_Functions.osGetScriptEngineName();
421 } 421 }
422 422
423 public string osGetPhysicsEngineType()
424 {
425 return m_OSSL_Functions.osGetPhysicsEngineType();
426 }
427
423 public string osGetSimulatorVersion() 428 public string osGetSimulatorVersion()
424 { 429 {
425 return m_OSSL_Functions.osGetSimulatorVersion(); 430 return m_OSSL_Functions.osGetSimulatorVersion();
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 97dd0f6..985e598 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -49,6 +49,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
49 private List<string> m_warnings = new List<string>(); 49 private List<string> m_warnings = new List<string>();
50 private IScriptModuleComms m_comms = null; 50 private IScriptModuleComms m_comms = null;
51 51
52 private bool m_insertCoopTerminationChecks;
53 private static string m_coopTerminationCheck = "opensim_reserved_CheckForCoopTermination();";
54
55 /// <summary>
56 /// Keep a record of the previous node when we do the parsing.
57 /// </summary>
58 /// <remarks>
59 /// We do this here because the parser generated by CSTools does not retain a reference to its parent node.
60 /// The previous node is required so we can correctly insert co-op termination checks when required.
61 /// </remarks>
62// private SYMBOL m_previousNode;
63
52 /// <summary> 64 /// <summary>
53 /// Creates an 'empty' CSCodeGenerator instance. 65 /// Creates an 'empty' CSCodeGenerator instance.
54 /// </summary> 66 /// </summary>
@@ -58,9 +70,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
58 ResetCounters(); 70 ResetCounters();
59 } 71 }
60 72
61 public CSCodeGenerator(IScriptModuleComms comms) 73 public CSCodeGenerator(IScriptModuleComms comms, bool insertCoopTerminationChecks)
62 { 74 {
63 m_comms = comms; 75 m_comms = comms;
76 m_insertCoopTerminationChecks = insertCoopTerminationChecks;
64 ResetCounters(); 77 ResetCounters();
65 } 78 }
66 79
@@ -155,7 +168,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
155 // here's the payload 168 // here's the payload
156 retstr += GenerateLine(); 169 retstr += GenerateLine();
157 foreach (SYMBOL s in m_astRoot.kids) 170 foreach (SYMBOL s in m_astRoot.kids)
158 retstr += GenerateNode(s); 171 retstr += GenerateNode(m_astRoot, s);
159 172
160 // close braces! 173 // close braces!
161 m_braceCount--; 174 m_braceCount--;
@@ -165,7 +178,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
165 178
166 // Removes all carriage return characters which may be generated in Windows platform. Is there 179 // Removes all carriage return characters which may be generated in Windows platform. Is there
167 // cleaner way of doing this? 180 // cleaner way of doing this?
168 retstr=retstr.Replace("\r", ""); 181 retstr = retstr.Replace("\r", "");
169 182
170 return retstr; 183 return retstr;
171 } 184 }
@@ -191,9 +204,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
191 /// Recursively called to generate each type of node. Will generate this 204 /// Recursively called to generate each type of node. Will generate this
192 /// node, then all it's children. 205 /// node, then all it's children.
193 /// </summary> 206 /// </summary>
207 /// <param name="previousSymbol">The parent node.</param>
194 /// <param name="s">The current node to generate code for.</param> 208 /// <param name="s">The current node to generate code for.</param>
195 /// <returns>String containing C# code for SYMBOL s.</returns> 209 /// <returns>String containing C# code for SYMBOL s.</returns>
196 private string GenerateNode(SYMBOL s) 210 private string GenerateNode(SYMBOL previousSymbol, SYMBOL s)
197 { 211 {
198 string retstr = String.Empty; 212 string retstr = String.Empty;
199 213
@@ -207,11 +221,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
207 else if (s is State) 221 else if (s is State)
208 retstr += GenerateState((State) s); 222 retstr += GenerateState((State) s);
209 else if (s is CompoundStatement) 223 else if (s is CompoundStatement)
210 retstr += GenerateCompoundStatement((CompoundStatement) s); 224 retstr += GenerateCompoundStatement(previousSymbol, (CompoundStatement) s);
211 else if (s is Declaration) 225 else if (s is Declaration)
212 retstr += GenerateDeclaration((Declaration) s); 226 retstr += GenerateDeclaration((Declaration) s);
213 else if (s is Statement) 227 else if (s is Statement)
214 retstr += GenerateStatement((Statement) s); 228 retstr += GenerateStatement(previousSymbol, (Statement) s);
215 else if (s is ReturnStatement) 229 else if (s is ReturnStatement)
216 retstr += GenerateReturnStatement((ReturnStatement) s); 230 retstr += GenerateReturnStatement((ReturnStatement) s);
217 else if (s is JumpLabel) 231 else if (s is JumpLabel)
@@ -261,7 +275,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
261 else 275 else
262 { 276 {
263 foreach (SYMBOL kid in s.kids) 277 foreach (SYMBOL kid in s.kids)
264 retstr += GenerateNode(kid); 278 retstr += GenerateNode(s, kid);
265 } 279 }
266 280
267 return retstr; 281 return retstr;
@@ -295,7 +309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
295 retstr += GenerateLine(")"); 309 retstr += GenerateLine(")");
296 310
297 foreach (SYMBOL kid in remainingKids) 311 foreach (SYMBOL kid in remainingKids)
298 retstr += GenerateNode(kid); 312 retstr += GenerateNode(gf, kid);
299 313
300 return retstr; 314 return retstr;
301 } 315 }
@@ -312,7 +326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
312 foreach (SYMBOL s in gv.kids) 326 foreach (SYMBOL s in gv.kids)
313 { 327 {
314 retstr += Indent(); 328 retstr += Indent();
315 retstr += GenerateNode(s); 329 retstr += GenerateNode(gv, s);
316 retstr += GenerateLine(";"); 330 retstr += GenerateLine(";");
317 } 331 }
318 332
@@ -365,7 +379,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
365 retstr += GenerateLine(")"); 379 retstr += GenerateLine(")");
366 380
367 foreach (SYMBOL kid in remainingKids) 381 foreach (SYMBOL kid in remainingKids)
368 retstr += GenerateNode(kid); 382 retstr += GenerateNode(se, kid);
369 383
370 return retstr; 384 return retstr;
371 } 385 }
@@ -404,7 +418,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
404 418
405 foreach (SYMBOL s in al.kids) 419 foreach (SYMBOL s in al.kids)
406 { 420 {
407 retstr += GenerateNode(s); 421 retstr += GenerateNode(al, s);
408 if (0 < comma--) 422 if (0 < comma--)
409 retstr += Generate(", "); 423 retstr += Generate(", ");
410 } 424 }
@@ -417,7 +431,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
417 /// </summary> 431 /// </summary>
418 /// <param name="cs">The CompoundStatement node.</param> 432 /// <param name="cs">The CompoundStatement node.</param>
419 /// <returns>String containing C# code for CompoundStatement cs.</returns> 433 /// <returns>String containing C# code for CompoundStatement cs.</returns>
420 private string GenerateCompoundStatement(CompoundStatement cs) 434 private string GenerateCompoundStatement(SYMBOL previousSymbol, CompoundStatement cs)
421 { 435 {
422 string retstr = String.Empty; 436 string retstr = String.Empty;
423 437
@@ -425,8 +439,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
425 retstr += GenerateIndentedLine("{"); 439 retstr += GenerateIndentedLine("{");
426 m_braceCount++; 440 m_braceCount++;
427 441
442 if (m_insertCoopTerminationChecks)
443 {
444 // We have to check in event functions as well because the user can manually call these.
445 if (previousSymbol is GlobalFunctionDefinition
446 || previousSymbol is WhileStatement
447 || previousSymbol is DoWhileStatement
448 || previousSymbol is ForLoop
449 || previousSymbol is StateEvent)
450 retstr += GenerateIndentedLine(m_coopTerminationCheck);
451 }
452
428 foreach (SYMBOL kid in cs.kids) 453 foreach (SYMBOL kid in cs.kids)
429 retstr += GenerateNode(kid); 454 retstr += GenerateNode(cs, kid);
430 455
431 // closing brace 456 // closing brace
432 m_braceCount--; 457 m_braceCount--;
@@ -450,13 +475,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
450 /// </summary> 475 /// </summary>
451 /// <param name="s">The Statement node.</param> 476 /// <param name="s">The Statement node.</param>
452 /// <returns>String containing C# code for Statement s.</returns> 477 /// <returns>String containing C# code for Statement s.</returns>
453 private string GenerateStatement(Statement s) 478 private string GenerateStatement(SYMBOL previousSymbol, Statement s)
454 { 479 {
455 string retstr = String.Empty; 480 string retstr = String.Empty;
456 bool printSemicolon = true; 481 bool printSemicolon = true;
457 482
458 retstr += Indent(); 483 retstr += Indent();
459 484
485 if (m_insertCoopTerminationChecks)
486 {
487 // We have to check in event functions as well because the user can manually call these.
488 if (previousSymbol is GlobalFunctionDefinition
489 || previousSymbol is WhileStatement
490 || previousSymbol is DoWhileStatement
491 || previousSymbol is ForLoop
492 || previousSymbol is StateEvent)
493 retstr += Generate(m_coopTerminationCheck);
494 }
495
460 if (0 < s.kids.Count) 496 if (0 < s.kids.Count)
461 { 497 {
462 // Jump label prints its own colon, we don't need a semicolon. 498 // Jump label prints its own colon, we don't need a semicolon.
@@ -466,7 +502,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
466 // (MONO) error. 502 // (MONO) error.
467 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count)) 503 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count))
468 foreach (SYMBOL kid in s.kids) 504 foreach (SYMBOL kid in s.kids)
469 retstr += GenerateNode(kid); 505 retstr += GenerateNode(s, kid);
470 } 506 }
471 507
472 if (printSemicolon) 508 if (printSemicolon)
@@ -487,10 +523,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
487 List<string> identifiers = new List<string>(); 523 List<string> identifiers = new List<string>();
488 checkForMultipleAssignments(identifiers, a); 524 checkForMultipleAssignments(identifiers, a);
489 525
490 retstr += GenerateNode((SYMBOL) a.kids.Pop()); 526 retstr += GenerateNode(a, (SYMBOL) a.kids.Pop());
491 retstr += Generate(String.Format(" {0} ", a.AssignmentType), a); 527 retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
492 foreach (SYMBOL kid in a.kids) 528 foreach (SYMBOL kid in a.kids)
493 retstr += GenerateNode(kid); 529 retstr += GenerateNode(a, kid);
494 530
495 return retstr; 531 return retstr;
496 } 532 }
@@ -563,7 +599,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
563 retstr += Generate("return ", rs); 599 retstr += Generate("return ", rs);
564 600
565 foreach (SYMBOL kid in rs.kids) 601 foreach (SYMBOL kid in rs.kids)
566 retstr += GenerateNode(kid); 602 retstr += GenerateNode(rs, kid);
567 603
568 return retstr; 604 return retstr;
569 } 605 }
@@ -575,7 +611,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
575 /// <returns>String containing C# code for JumpLabel jl.</returns> 611 /// <returns>String containing C# code for JumpLabel jl.</returns>
576 private string GenerateJumpLabel(JumpLabel jl) 612 private string GenerateJumpLabel(JumpLabel jl)
577 { 613 {
578 return Generate(String.Format("{0}:", CheckName(jl.LabelName)), jl) + " NoOp();\n"; 614 string labelStatement;
615
616 if (m_insertCoopTerminationChecks)
617 labelStatement = m_coopTerminationCheck + "\n";
618 else
619 labelStatement = "NoOp();\n";
620
621 return Generate(String.Format("{0}: ", CheckName(jl.LabelName)), jl) + labelStatement;
579 } 622 }
580 623
581 /// <summary> 624 /// <summary>
@@ -598,14 +641,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
598 string retstr = String.Empty; 641 string retstr = String.Empty;
599 642
600 retstr += GenerateIndented("if (", ifs); 643 retstr += GenerateIndented("if (", ifs);
601 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 644 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
602 retstr += GenerateLine(")"); 645 retstr += GenerateLine(")");
603 646
604 // CompoundStatement handles indentation itself but we need to do it 647 // CompoundStatement handles indentation itself but we need to do it
605 // otherwise. 648 // otherwise.
606 bool indentHere = ifs.kids.Top is Statement; 649 bool indentHere = ifs.kids.Top is Statement;
607 if (indentHere) m_braceCount++; 650 if (indentHere) m_braceCount++;
608 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 651 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
609 if (indentHere) m_braceCount--; 652 if (indentHere) m_braceCount--;
610 653
611 if (0 < ifs.kids.Count) // do it again for an else 654 if (0 < ifs.kids.Count) // do it again for an else
@@ -614,7 +657,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
614 657
615 indentHere = ifs.kids.Top is Statement; 658 indentHere = ifs.kids.Top is Statement;
616 if (indentHere) m_braceCount++; 659 if (indentHere) m_braceCount++;
617 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 660 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
618 if (indentHere) m_braceCount--; 661 if (indentHere) m_braceCount--;
619 } 662 }
620 663
@@ -641,14 +684,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
641 string retstr = String.Empty; 684 string retstr = String.Empty;
642 685
643 retstr += GenerateIndented("while (", ws); 686 retstr += GenerateIndented("while (", ws);
644 retstr += GenerateNode((SYMBOL) ws.kids.Pop()); 687 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
645 retstr += GenerateLine(")"); 688 retstr += GenerateLine(")");
646 689
647 // CompoundStatement handles indentation itself but we need to do it 690 // CompoundStatement handles indentation itself but we need to do it
648 // otherwise. 691 // otherwise.
649 bool indentHere = ws.kids.Top is Statement; 692 bool indentHere = ws.kids.Top is Statement;
650 if (indentHere) m_braceCount++; 693 if (indentHere) m_braceCount++;
651 retstr += GenerateNode((SYMBOL) ws.kids.Pop()); 694 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
652 if (indentHere) m_braceCount--; 695 if (indentHere) m_braceCount--;
653 696
654 return retstr; 697 return retstr;
@@ -669,11 +712,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
669 // otherwise. 712 // otherwise.
670 bool indentHere = dws.kids.Top is Statement; 713 bool indentHere = dws.kids.Top is Statement;
671 if (indentHere) m_braceCount++; 714 if (indentHere) m_braceCount++;
672 retstr += GenerateNode((SYMBOL) dws.kids.Pop()); 715 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
673 if (indentHere) m_braceCount--; 716 if (indentHere) m_braceCount--;
674 717
675 retstr += GenerateIndented("while (", dws); 718 retstr += GenerateIndented("while (", dws);
676 retstr += GenerateNode((SYMBOL) dws.kids.Pop()); 719 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
677 retstr += GenerateLine(");"); 720 retstr += GenerateLine(");");
678 721
679 return retstr; 722 return retstr;
@@ -702,7 +745,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
702 retstr += Generate("; "); 745 retstr += Generate("; ");
703 // for (x = 0; x < 10; x++) 746 // for (x = 0; x < 10; x++)
704 // ^^^^^^ 747 // ^^^^^^
705 retstr += GenerateNode((SYMBOL) fl.kids.Pop()); 748 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
706 retstr += Generate("; "); 749 retstr += Generate("; ");
707 // for (x = 0; x < 10; x++) 750 // for (x = 0; x < 10; x++)
708 // ^^^ 751 // ^^^
@@ -713,7 +756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
713 // otherwise. 756 // otherwise.
714 bool indentHere = fl.kids.Top is Statement; 757 bool indentHere = fl.kids.Top is Statement;
715 if (indentHere) m_braceCount++; 758 if (indentHere) m_braceCount++;
716 retstr += GenerateNode((SYMBOL) fl.kids.Pop()); 759 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
717 if (indentHere) m_braceCount--; 760 if (indentHere) m_braceCount--;
718 761
719 return retstr; 762 return retstr;
@@ -758,7 +801,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
758 while (s is ParenthesisExpression) 801 while (s is ParenthesisExpression)
759 s = (SYMBOL)s.kids.Pop(); 802 s = (SYMBOL)s.kids.Pop();
760 803
761 retstr += GenerateNode(s); 804 retstr += GenerateNode(fls, s);
762 if (0 < comma--) 805 if (0 < comma--)
763 retstr += Generate(", "); 806 retstr += Generate(", ");
764 } 807 }
@@ -779,20 +822,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
779 { 822 {
780 // special case handling for logical and/or, see Mantis 3174 823 // special case handling for logical and/or, see Mantis 3174
781 retstr += "((bool)("; 824 retstr += "((bool)(";
782 retstr += GenerateNode((SYMBOL)be.kids.Pop()); 825 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
783 retstr += "))"; 826 retstr += "))";
784 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be); 827 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be);
785 retstr += "((bool)("; 828 retstr += "((bool)(";
786 foreach (SYMBOL kid in be.kids) 829 foreach (SYMBOL kid in be.kids)
787 retstr += GenerateNode(kid); 830 retstr += GenerateNode(be, kid);
788 retstr += "))"; 831 retstr += "))";
789 } 832 }
790 else 833 else
791 { 834 {
792 retstr += GenerateNode((SYMBOL)be.kids.Pop()); 835 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
793 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be); 836 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
794 foreach (SYMBOL kid in be.kids) 837 foreach (SYMBOL kid in be.kids)
795 retstr += GenerateNode(kid); 838 retstr += GenerateNode(be, kid);
796 } 839 }
797 840
798 return retstr; 841 return retstr;
@@ -808,7 +851,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
808 string retstr = String.Empty; 851 string retstr = String.Empty;
809 852
810 retstr += Generate(ue.UnarySymbol, ue); 853 retstr += Generate(ue.UnarySymbol, ue);
811 retstr += GenerateNode((SYMBOL) ue.kids.Pop()); 854 retstr += GenerateNode(ue, (SYMBOL) ue.kids.Pop());
812 855
813 return retstr; 856 return retstr;
814 } 857 }
@@ -824,7 +867,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
824 867
825 retstr += Generate("("); 868 retstr += Generate("(");
826 foreach (SYMBOL kid in pe.kids) 869 foreach (SYMBOL kid in pe.kids)
827 retstr += GenerateNode(kid); 870 retstr += GenerateNode(pe, kid);
828 retstr += Generate(")"); 871 retstr += Generate(")");
829 872
830 return retstr; 873 return retstr;
@@ -861,7 +904,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
861 904
862 // we wrap all typecasted statements in parentheses 905 // we wrap all typecasted statements in parentheses
863 retstr += Generate(String.Format("({0}) (", te.TypecastType), te); 906 retstr += Generate(String.Format("({0}) (", te.TypecastType), te);
864 retstr += GenerateNode((SYMBOL) te.kids.Pop()); 907 retstr += GenerateNode(te, (SYMBOL) te.kids.Pop());
865 retstr += Generate(")"); 908 retstr += Generate(")");
866 909
867 return retstr; 910 return retstr;
@@ -931,7 +974,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
931 } 974 }
932 975
933 foreach (SYMBOL kid in fc.kids) 976 foreach (SYMBOL kid in fc.kids)
934 retstr += GenerateNode(kid); 977 retstr += GenerateNode(fc, kid);
935 978
936 retstr += Generate(")"); 979 retstr += Generate(")");
937 980
@@ -980,11 +1023,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
980 string retstr = String.Empty; 1023 string retstr = String.Empty;
981 1024
982 retstr += Generate(String.Format("new {0}(", vc.Type), vc); 1025 retstr += Generate(String.Format("new {0}(", vc.Type), vc);
983 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1026 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
984 retstr += Generate(", "); 1027 retstr += Generate(", ");
985 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1028 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
986 retstr += Generate(", "); 1029 retstr += Generate(", ");
987 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1030 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
988 retstr += Generate(")"); 1031 retstr += Generate(")");
989 1032
990 return retstr; 1033 return retstr;
@@ -1000,13 +1043,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
1000 string retstr = String.Empty; 1043 string retstr = String.Empty;
1001 1044
1002 retstr += Generate(String.Format("new {0}(", rc.Type), rc); 1045 retstr += Generate(String.Format("new {0}(", rc.Type), rc);
1003 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1046 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1004 retstr += Generate(", "); 1047 retstr += Generate(", ");
1005 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1048 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1006 retstr += Generate(", "); 1049 retstr += Generate(", ");
1007 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1050 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1008 retstr += Generate(", "); 1051 retstr += Generate(", ");
1009 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1052 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1010 retstr += Generate(")"); 1053 retstr += Generate(")");
1011 1054
1012 return retstr; 1055 return retstr;
@@ -1024,7 +1067,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
1024 retstr += Generate(String.Format("new {0}(", lc.Type), lc); 1067 retstr += Generate(String.Format("new {0}(", lc.Type), lc);
1025 1068
1026 foreach (SYMBOL kid in lc.kids) 1069 foreach (SYMBOL kid in lc.kids)
1027 retstr += GenerateNode(kid); 1070 retstr += GenerateNode(lc, kid);
1028 1071
1029 retstr += Generate(")"); 1072 retstr += Generate(")");
1030 1073
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 03be2ab..9d20c9e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -72,6 +72,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
72 private bool CompileWithDebugInformation; 72 private bool CompileWithDebugInformation;
73 private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase); 73 private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
74 private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase); 74 private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase);
75 private bool m_insertCoopTerminationCalls;
75 76
76 private string FilePrefix; 77 private string FilePrefix;
77 private string ScriptEnginesPath = null; 78 private string ScriptEnginesPath = null;
@@ -95,20 +96,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
95 private Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>> m_lineMaps = 96 private Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>> m_lineMaps =
96 new Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>>(); 97 new Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>>();
97 98
99 public bool in_startup = true;
100
98 public Compiler(IScriptEngine scriptEngine) 101 public Compiler(IScriptEngine scriptEngine)
99 { 102 {
100 m_scriptEngine = scriptEngine;; 103 m_scriptEngine = scriptEngine;
101 ScriptEnginesPath = scriptEngine.ScriptEnginePath; 104 ScriptEnginesPath = scriptEngine.ScriptEnginePath;
102 ReadConfig(); 105 ReadConfig();
103 } 106 }
104 107
105 public bool in_startup = true;
106 public void ReadConfig() 108 public void ReadConfig()
107 { 109 {
108 // Get some config 110 // Get some config
109 WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false); 111 WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false);
110 CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true); 112 CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true);
111 bool DeleteScriptsOnStartup = m_scriptEngine.Config.GetBoolean("DeleteScriptsOnStartup", true); 113 bool DeleteScriptsOnStartup = m_scriptEngine.Config.GetBoolean("DeleteScriptsOnStartup", true);
114 m_insertCoopTerminationCalls = m_scriptEngine.Config.GetString("ScriptStopStrategy", "abort") == "co-op";
112 115
113 // Get file prefix from scriptengine name and make it file system safe: 116 // Get file prefix from scriptengine name and make it file system safe:
114 FilePrefix = "CommonCompiler"; 117 FilePrefix = "CommonCompiler";
@@ -386,7 +389,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
386 if (language == enumCompileType.lsl) 389 if (language == enumCompileType.lsl)
387 { 390 {
388 // Its LSL, convert it to C# 391 // Its LSL, convert it to C#
389 LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms); 392 LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms, m_insertCoopTerminationCalls);
390 compileScript = LSL_Converter.Convert(Script); 393 compileScript = LSL_Converter.Convert(Script);
391 394
392 // copy converter warnings into our warnings. 395 // copy converter warnings into our warnings.
@@ -411,16 +414,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
411 { 414 {
412 case enumCompileType.cs: 415 case enumCompileType.cs:
413 case enumCompileType.lsl: 416 case enumCompileType.lsl:
414 compileScript = CreateCSCompilerScript(compileScript); 417 compileScript = CreateCSCompilerScript(
418 compileScript,
419 m_scriptEngine.ScriptClassName,
420 m_scriptEngine.ScriptBaseClassName,
421 m_scriptEngine.ScriptBaseClassParameters);
415 break; 422 break;
416 case enumCompileType.vb: 423 case enumCompileType.vb:
417 compileScript = CreateVBCompilerScript(compileScript); 424 compileScript = CreateVBCompilerScript(
425 compileScript, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName);
418 break; 426 break;
419// case enumCompileType.js: 427// case enumCompileType.js:
420// compileScript = CreateJSCompilerScript(compileScript); 428// compileScript = CreateJSCompilerScript(compileScript, m_scriptEngine.ScriptBaseClassName);
421// break; 429// break;
422 case enumCompileType.yp: 430 case enumCompileType.yp:
423 compileScript = CreateYPCompilerScript(compileScript); 431 compileScript = CreateYPCompilerScript(
432 compileScript, m_scriptEngine.ScriptClassName,m_scriptEngine.ScriptBaseClassName);
424 break; 433 break;
425 } 434 }
426 435
@@ -451,43 +460,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
451// return compileScript; 460// return compileScript;
452// } 461// }
453 462
454 private static string CreateCSCompilerScript(string compileScript) 463 private static string CreateCSCompilerScript(
464 string compileScript, string className, string baseClassName, ParameterInfo[] constructorParameters)
455 { 465 {
456 compileScript = String.Empty + 466 compileScript = string.Format(
457 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" + 467@"using OpenSim.Region.ScriptEngine.Shared;
458 String.Empty + "namespace SecondLife { " + 468using System.Collections.Generic;
459 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + 469
460 @"public Script() { } " + 470namespace SecondLife
461 compileScript + 471{{
462 "} }\r\n"; 472 public class {0} : {1}
473 {{
474 public {0}({2}) : base({3}) {{}}
475{4}
476 }}
477}}",
478 className,
479 baseClassName,
480 constructorParameters != null
481 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.ToString()))
482 : "",
483 constructorParameters != null
484 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.Name))
485 : "",
486 compileScript);
487
463 return compileScript; 488 return compileScript;
464 } 489 }
465 490
466 private static string CreateYPCompilerScript(string compileScript) 491 private static string CreateYPCompilerScript(string compileScript, string className, string baseClassName)
467 { 492 {
468 compileScript = String.Empty + 493 compileScript = String.Empty +
469 "using OpenSim.Region.ScriptEngine.Shared.YieldProlog; " + 494 "using OpenSim.Region.ScriptEngine.Shared.YieldProlog; " +
470 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" + 495 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
471 String.Empty + "namespace SecondLife { " + 496 String.Empty + "namespace SecondLife { " +
472 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + 497 String.Empty + "public class " + className + " : " + baseClassName + " { \r\n" +
473 //@"public Script() { } " + 498 //@"public Script() { } " +
474 @"static OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP YP=null; " + 499 @"static OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP YP=null; " +
475 @"public Script() { YP= new OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP(); } " + 500 @"public " + className + "() { YP= new OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP(); } " +
476
477 compileScript + 501 compileScript +
478 "} }\r\n"; 502 "} }\r\n";
503
479 return compileScript; 504 return compileScript;
480 } 505 }
481 506
482 private static string CreateVBCompilerScript(string compileScript) 507 private static string CreateVBCompilerScript(string compileScript, string className, string baseClassName)
483 { 508 {
484 compileScript = String.Empty + 509 compileScript = String.Empty +
485 "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " + 510 "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " +
486 String.Empty + "NameSpace SecondLife:" + 511 String.Empty + "NameSpace SecondLife:" +
487 String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass: " + 512 String.Empty + "Public Class " + className + ": Inherits " + baseClassName +
488 "\r\nPublic Sub New()\r\nEnd Sub: " + 513 "\r\nPublic Sub New()\r\nEnd Sub: " +
489 compileScript + 514 compileScript +
490 ":End Class :End Namespace\r\n"; 515 ":End Class :End Namespace\r\n";
516
491 return compileScript; 517 return compileScript;
492 } 518 }
493 519
@@ -549,6 +575,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
549 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 575 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
550 "OpenMetaverseTypes.dll")); 576 "OpenMetaverseTypes.dll"));
551 577
578 if (m_scriptEngine.ScriptReferencedAssemblies != null)
579 Array.ForEach<string>(
580 m_scriptEngine.ScriptReferencedAssemblies,
581 a => parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, a)));
582
552 if (lang == enumCompileType.yp) 583 if (lang == enumCompileType.yp)
553 { 584 {
554 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 585 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
index 7763619..77e087c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
39 /// The generated C# code is compared against the expected C# code. 39 /// The generated C# code is compared against the expected C# code.
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class CSCodeGeneratorTest 42 public class CSCodeGeneratorTest : OpenSimTestCase
43 { 43 {
44 [Test] 44 [Test]
45 public void TestDefaultState() 45 public void TestDefaultState()
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
index 1fa6954..05a8756 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
41 /// the LSL source. 41 /// the LSL source.
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class CompilerTest 44 public class CompilerTest : OpenSimTestCase
45 { 45 {
46 private string m_testDir; 46 private string m_testDir;
47 private CSharpCodeProvider m_CSCodeProvider; 47 private CSharpCodeProvider m_CSCodeProvider;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 22804f5..e44a106 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -82,6 +82,24 @@ namespace OpenSim.Region.ScriptEngine.Shared
82 } 82 }
83 } 83 }
84 84
85 /// <summary>
86 /// Used to signal when the script is stopping in co-operation with the script engine
87 /// (instead of through Thread.Abort()).
88 /// </summary>
89 [Serializable]
90 public class ScriptCoopStopException : Exception
91 {
92 public ScriptCoopStopException()
93 {
94 }
95
96 protected ScriptCoopStopException(
97 SerializationInfo info,
98 StreamingContext context)
99 {
100 }
101 }
102
85 public class DetectParams 103 public class DetectParams
86 { 104 {
87 public const int AGENT = 1; 105 public const int AGENT = 1;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 771db0c..c8ced43 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -94,6 +94,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
94 private UUID m_CurrentStateHash; 94 private UUID m_CurrentStateHash;
95 private UUID m_RegionID; 95 private UUID m_RegionID;
96 96
97 public int DebugLevel { get; set; }
98
97 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } 99 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
98 100
99 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); 101 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
@@ -156,6 +158,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
156 158
157 public UUID AppDomain { get; set; } 159 public UUID AppDomain { get; set; }
158 160
161 public SceneObjectPart Part { get; private set; }
162
159 public string PrimName { get; private set; } 163 public string PrimName { get; private set; }
160 164
161 public string ScriptName { get; private set; } 165 public string ScriptName { get; private set; }
@@ -174,6 +178,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
174 178
175 public Queue EventQueue { get; private set; } 179 public Queue EventQueue { get; private set; }
176 180
181 public long EventsQueued
182 {
183 get
184 {
185 lock (EventQueue)
186 return EventQueue.Count;
187 }
188 }
189
190 public long EventsProcessed { get; private set; }
191
177 public int StartParam { get; set; } 192 public int StartParam { get; set; }
178 193
179 public TaskInventoryItem ScriptTask { get; private set; } 194 public TaskInventoryItem ScriptTask { get; private set; }
@@ -186,66 +201,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
186 201
187 public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute; 202 public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute;
188 203
204 private bool m_coopTermination;
205
206 private EventWaitHandle m_coopSleepHandle;
207
189 public void ClearQueue() 208 public void ClearQueue()
190 { 209 {
191 m_TimerQueued = false; 210 m_TimerQueued = false;
192 EventQueue.Clear(); 211 EventQueue.Clear();
193 } 212 }
194 213
195 public ScriptInstance(IScriptEngine engine, SceneObjectPart part, 214 public ScriptInstance(
196 UUID itemID, UUID assetID, string assembly, 215 IScriptEngine engine, SceneObjectPart part, TaskInventoryItem item,
197 AppDomain dom, string primName, string scriptName, 216 int startParam, bool postOnRez,
198 int startParam, bool postOnRez, StateSource stateSource, 217 int maxScriptQueue)
199 int maxScriptQueue)
200 { 218 {
201 State = "default"; 219 State = "default";
202 EventQueue = new Queue(32); 220 EventQueue = new Queue(32);
203 221
204 Engine = engine; 222 Engine = engine;
205 LocalID = part.LocalId; 223 Part = part;
206 ObjectID = part.UUID; 224 ScriptTask = item;
207 RootLocalID = part.ParentGroup.LocalId; 225
208 RootObjectID = part.ParentGroup.UUID; 226 // This is currently only here to allow regression tests to get away without specifying any inventory
209 ItemID = itemID; 227 // item when they are testing script logic that doesn't require an item.
210 AssetID = assetID; 228 if (ScriptTask != null)
211 PrimName = primName; 229 {
212 ScriptName = scriptName; 230 ScriptName = ScriptTask.Name;
213 m_Assembly = assembly; 231 ItemID = ScriptTask.ItemID;
232 AssetID = ScriptTask.AssetID;
233 }
234
235 PrimName = part.ParentGroup.Name;
214 StartParam = startParam; 236 StartParam = startParam;
215 m_MaxScriptQueue = maxScriptQueue; 237 m_MaxScriptQueue = maxScriptQueue;
216 m_stateSource = stateSource;
217 m_postOnRez = postOnRez; 238 m_postOnRez = postOnRez;
218 m_AttachedAvatar = part.ParentGroup.AttachedAvatar; 239 m_AttachedAvatar = part.ParentGroup.AttachedAvatar;
219 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID; 240 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID;
220 241
221 if (part != null) 242 if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
222 { 243 {
223 part.TaskInventory.LockItemsForRead(true); 244 m_coopTermination = true;
224 if (part.TaskInventory.ContainsKey(ItemID)) 245 m_coopSleepHandle = new AutoResetEvent(false);
225 {
226 ScriptTask = part.TaskInventory[ItemID];
227 }
228 part.TaskInventory.LockItemsForRead(false);
229 } 246 }
247 }
248
249 /// <summary>
250 /// Load the script from an assembly into an AppDomain.
251 /// </summary>
252 /// <param name='dom'></param>
253 /// <param name='assembly'></param>
254 /// <param name='stateSource'></param>
255 /// <returns>false if load failed, true if suceeded</returns>
256 public bool Load(AppDomain dom, string assembly, StateSource stateSource)
257 {
258 m_Assembly = assembly;
259 m_stateSource = stateSource;
230 260
231 ApiManager am = new ApiManager(); 261 ApiManager am = new ApiManager();
232 262
233 foreach (string api in am.GetApis()) 263 foreach (string api in am.GetApis())
234 { 264 {
235 m_Apis[api] = am.CreateApi(api); 265 m_Apis[api] = am.CreateApi(api);
236 m_Apis[api].Initialize(engine, part, ScriptTask); 266 m_Apis[api].Initialize(Engine, Part, ScriptTask, m_coopSleepHandle);
237 } 267 }
238 268
239 try 269 try
240 { 270 {
271 object[] constructorParams;
272
273 Assembly scriptAssembly = dom.Load(Path.GetFileNameWithoutExtension(assembly));
274 Type scriptType = scriptAssembly.GetType("SecondLife.XEngineScript");
275
276 if (scriptType != null)
277 {
278 constructorParams = new object[] { m_coopSleepHandle };
279 }
280 else if (!m_coopTermination)
281 {
282 scriptType = scriptAssembly.GetType("SecondLife.Script");
283 constructorParams = null;
284 }
285 else
286 {
287 m_log.ErrorFormat(
288 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. You must remove all existing {6}* script DLL files before using enabling co-op termination"
289 + ", either by setting DeleteScriptsOnStartup = true in [XEngine] for one run"
290 + " or by deleting these files manually.",
291 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly);
292
293 return false;
294 }
295
296// m_log.DebugFormat(
297// "[SCRIPT INSTANCE]: Looking to load {0} from assembly {1} in {2}",
298// scriptType.FullName, Path.GetFileNameWithoutExtension(assembly), Engine.World.Name);
299
241 if (dom != System.AppDomain.CurrentDomain) 300 if (dom != System.AppDomain.CurrentDomain)
242 m_Script = (IScript)dom.CreateInstanceAndUnwrap( 301 m_Script
302 = (IScript)dom.CreateInstanceAndUnwrap(
243 Path.GetFileNameWithoutExtension(assembly), 303 Path.GetFileNameWithoutExtension(assembly),
244 "SecondLife.Script"); 304 scriptType.FullName,
305 false,
306 BindingFlags.Default,
307 null,
308 constructorParams,
309 null,
310 null,
311 null);
245 else 312 else
246 m_Script = (IScript)Assembly.Load( 313 m_Script
247 Path.GetFileNameWithoutExtension(assembly)).CreateInstance( 314 = (IScript)scriptAssembly.CreateInstance(
248 "SecondLife.Script"); 315 scriptType.FullName,
316 false,
317 BindingFlags.Default,
318 null,
319 constructorParams,
320 null,
321 null);
249 322
250 //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 323 //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
251 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 324 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
@@ -254,8 +327,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
254 catch (Exception e) 327 catch (Exception e)
255 { 328 {
256 m_log.ErrorFormat( 329 m_log.ErrorFormat(
257 "[SCRIPT INSTANCE]: Error loading assembly {0}. Exception {1}{2}", 330 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}",
258 assembly, e.Message, e.StackTrace); 331 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly, e.Message, e.StackTrace);
332
333 return false;
259 } 334 }
260 335
261 try 336 try
@@ -267,16 +342,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
267 342
268// // m_log.Debug("[Script] Script instance created"); 343// // m_log.Debug("[Script] Script instance created");
269 344
270 part.SetScriptEvents(ItemID, 345 Part.SetScriptEvents(ItemID,
271 (int)m_Script.GetStateEventFlags(State)); 346 (int)m_Script.GetStateEventFlags(State));
272 } 347 }
273 catch (Exception e) 348 catch (Exception e)
274 { 349 {
275 m_log.ErrorFormat( 350 m_log.ErrorFormat(
276 "[SCRIPT INSTANCE]: Error loading script instance from assembly {0}. Exception {1}{2}", 351 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error initializing script instance. Exception {6}{7}",
277 assembly, e.Message, e.StackTrace); 352 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, e.Message, e.StackTrace);
278 353
279 return; 354 return false;
280 } 355 }
281 356
282 m_SaveState = true; 357 m_SaveState = true;
@@ -309,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
309 384
310// m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName); 385// m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName);
311 386
312 part.SetScriptEvents(ItemID, 387 Part.SetScriptEvents(ItemID,
313 (int)m_Script.GetStateEventFlags(State)); 388 (int)m_Script.GetStateEventFlags(State));
314 389
315 if (!Running) 390 if (!Running)
@@ -329,15 +404,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
329 else 404 else
330 { 405 {
331 m_log.WarnFormat( 406 m_log.WarnFormat(
332 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). Memory limit exceeded", 407 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.",
333 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly); 408 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
334 } 409 }
335 } 410 }
336 catch (Exception e) 411 catch (Exception e)
337 { 412 {
338 m_log.ErrorFormat( 413 m_log.ErrorFormat(
339 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). XML is {6}. Exception {7}{8}", 414 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. XML is {7}. Exception {8}{9}",
340 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly, xml, e.Message, e.StackTrace); 415 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState, xml, e.Message, e.StackTrace);
341 } 416 }
342 } 417 }
343// else 418// else
@@ -348,6 +423,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
348// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); 423// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
349 424
350// } 425// }
426
427 return true;
351 } 428 }
352 429
353 public void Init() 430 public void Init()
@@ -521,9 +598,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
521 } 598 }
522 599
523 // Wait for the current event to complete. 600 // Wait for the current event to complete.
524 if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000))) 601 if (!m_InSelfDelete)
525 { 602 {
526 return true; 603 if (!m_coopTermination)
604 {
605 // If we're not co-operative terminating then try and wait for the event to complete before stopping
606 if (workItem.Wait(new TimeSpan((long)timeout * 100000)))
607 return true;
608 }
609 else
610 {
611 if (DebugLevel >= 1)
612 m_log.DebugFormat(
613 "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}",
614 ScriptName, ItemID, PrimName, ObjectID);
615
616 // This will terminate the event on next handle check by the script.
617 m_coopSleepHandle.Set();
618
619 // For now, we will wait forever since the event should always cleanly terminate once LSL loop
620 // checking is implemented. May want to allow a shorter timeout option later.
621 if (workItem.Wait(TimeSpan.MaxValue))
622 {
623 if (DebugLevel >= 1)
624 m_log.DebugFormat(
625 "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}",
626 ScriptName, ItemID, PrimName, ObjectID);
627
628 return true;
629 }
630 }
527 } 631 }
528 632
529 lock (EventQueue) 633 lock (EventQueue)
@@ -536,11 +640,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
536 640
537 // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then 641 // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then
538 // forcibly abort the work item (this aborts the underlying thread). 642 // forcibly abort the work item (this aborts the underlying thread).
643 // Co-operative termination should never reach this point.
539 if (!m_InSelfDelete) 644 if (!m_InSelfDelete)
540 { 645 {
541// m_log.ErrorFormat( 646 m_log.DebugFormat(
542// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", 647 "[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms",
543// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); 648 ScriptName, ItemID, PrimName, LocalID, timeout);
544 649
545 workItem.Abort(); 650 workItem.Abort();
546 } 651 }
@@ -696,19 +801,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
696 { 801 {
697 802
698// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); 803// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
804 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
805
806 if (DebugLevel >= 2)
807 m_log.DebugFormat(
808 "[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
809 data.EventName,
810 ScriptName,
811 part.Name,
812 part.LocalId,
813 part.ParentGroup.Name,
814 part.ParentGroup.UUID,
815 part.AbsolutePosition,
816 part.ParentGroup.Scene.Name);
699 817
700 m_DetectParams = data.DetectParams; 818 m_DetectParams = data.DetectParams;
701 819
702 if (data.EventName == "state") // Hardcoded state change 820 if (data.EventName == "state") // Hardcoded state change
703 { 821 {
704 // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
705 // PrimName, ScriptName, data.Params[0].ToString());
706 State = data.Params[0].ToString(); 822 State = data.Params[0].ToString();
823
824 if (DebugLevel >= 1)
825 m_log.DebugFormat(
826 "[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
827 State,
828 ScriptName,
829 part.Name,
830 part.LocalId,
831 part.ParentGroup.Name,
832 part.ParentGroup.UUID,
833 part.AbsolutePosition,
834 part.ParentGroup.Scene.Name);
835
707 AsyncCommandManager.RemoveScript(Engine, 836 AsyncCommandManager.RemoveScript(Engine,
708 LocalID, ItemID); 837 LocalID, ItemID);
709 838
710 SceneObjectPart part = Engine.World.GetSceneObjectPart(
711 LocalID);
712 if (part != null) 839 if (part != null)
713 { 840 {
714 part.SetScriptEvents(ItemID, 841 part.SetScriptEvents(ItemID,
@@ -720,8 +847,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
720 if (Engine.World.PipeEventsForScript(LocalID) || 847 if (Engine.World.PipeEventsForScript(LocalID) ||
721 data.EventName == "control") // Don't freeze avies! 848 data.EventName == "control") // Don't freeze avies!
722 { 849 {
723 SceneObjectPart part = Engine.World.GetSceneObjectPart(
724 LocalID);
725 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", 850 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
726 // PrimName, ScriptName, data.EventName, State); 851 // PrimName, ScriptName, data.EventName, State);
727 852
@@ -763,7 +888,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
763 m_InEvent = false; 888 m_InEvent = false;
764 m_CurrentEvent = String.Empty; 889 m_CurrentEvent = String.Empty;
765 890
766 if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) 891 if ((!(e is TargetInvocationException)
892 || (!(e.InnerException is SelfDeleteException)
893 && !(e.InnerException is ScriptDeleteException)
894 && !(e.InnerException is ScriptCoopStopException)))
895 && !(e is ThreadAbortException))
767 { 896 {
768 try 897 try
769 { 898 {
@@ -776,6 +905,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
776 ChatTypeEnum.DebugChannel, 2147483647, 905 ChatTypeEnum.DebugChannel, 2147483647,
777 part.AbsolutePosition, 906 part.AbsolutePosition,
778 part.Name, part.UUID, false); 907 part.Name, part.UUID, false);
908
909
910 m_log.DebugFormat(
911 "[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}",
912 ScriptName,
913 PrimName,
914 part.UUID,
915 part.AbsolutePosition,
916 part.ParentGroup.Scene.Name,
917 text.Replace("\n", "\\n"),
918 e.InnerException);
779 } 919 }
780 catch (Exception) 920 catch (Exception)
781 { 921 {
@@ -802,6 +942,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
802 if (part != null) 942 if (part != null)
803 part.Inventory.RemoveInventoryItem(ItemID); 943 part.Inventory.RemoveInventoryItem(ItemID);
804 } 944 }
945 else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException))
946 {
947 if (DebugLevel >= 1)
948 m_log.DebugFormat(
949 "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.",
950 PrimName, ScriptName, data.EventName, State);
951 }
805 } 952 }
806 } 953 }
807 } 954 }
@@ -810,6 +957,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
810 // script engine to run the next event. 957 // script engine to run the next event.
811 lock (EventQueue) 958 lock (EventQueue)
812 { 959 {
960 EventsProcessed++;
961
813 if (EventQueue.Count > 0 && Running && !ShuttingDown) 962 if (EventQueue.Count > 0 && Running && !ShuttingDown)
814 { 963 {
815 m_CurrentWorkItem = Engine.QueueEventHandler(this); 964 m_CurrentWorkItem = Engine.QueueEventHandler(this);
@@ -834,7 +983,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
834 return (DateTime.Now - m_EventStart).Seconds; 983 return (DateTime.Now - m_EventStart).Seconds;
835 } 984 }
836 985
837 public void ResetScript() 986 public void ResetScript(int timeout)
838 { 987 {
839 if (m_Script == null) 988 if (m_Script == null)
840 return; 989 return;
@@ -844,7 +993,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
844 RemoveState(); 993 RemoveState();
845 ReleaseControls(); 994 ReleaseControls();
846 995
847 Stop(0); 996 Stop(timeout);
848 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 997 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
849 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 998 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
850 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; 999 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
@@ -1015,7 +1164,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1015 "({0}): {1}", scriptLine - 1, 1164 "({0}): {1}", scriptLine - 1,
1016 e.InnerException.Message); 1165 e.InnerException.Message);
1017 1166
1018 System.Console.WriteLine(e.ToString()+"\n");
1019 return message; 1167 return message;
1020 } 1168 }
1021 } 1169 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
new file mode 100644
index 0000000..3b13386
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
@@ -0,0 +1,377 @@
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.Threading;
31using Nini.Config;
32using NUnit.Framework;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.CoreModules.Scripting.WorldComm;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.ScriptEngine.XEngine;
39using OpenSim.Tests.Common;
40using OpenSim.Tests.Common.Mock;
41
42namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
43{
44 /// <summary>
45 /// Test that co-operative script thread termination is working correctly.
46 /// </summary>
47 [TestFixture]
48 public class CoopTerminationTests : OpenSimTestCase
49 {
50 private TestScene m_scene;
51 private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine;
52
53 private AutoResetEvent m_chatEvent;
54 private AutoResetEvent m_stoppedEvent;
55
56 private OSChatMessage m_osChatMessageReceived;
57
58 [SetUp]
59 public void Init()
60 {
61 m_osChatMessageReceived = null;
62 m_chatEvent = new AutoResetEvent(false);
63 m_stoppedEvent = new AutoResetEvent(false);
64
65 //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin");
66// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
67 m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine();
68
69 IniConfigSource configSource = new IniConfigSource();
70
71 IConfig startupConfig = configSource.AddConfig("Startup");
72 startupConfig.Set("DefaultScriptEngine", "XEngine");
73
74 IConfig xEngineConfig = configSource.AddConfig("XEngine");
75 xEngineConfig.Set("Enabled", "true");
76 xEngineConfig.Set("StartDelay", "0");
77
78 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
79 // to AssemblyResolver.OnAssemblyResolve fails.
80 xEngineConfig.Set("AppDomainLoading", "false");
81
82 xEngineConfig.Set("ScriptStopStrategy", "co-op");
83
84 // Make sure loops aren't actually being terminated by a script delay wait.
85 xEngineConfig.Set("ScriptDelayFactor", 0);
86
87 // This is really just set for debugging the test.
88 xEngineConfig.Set("WriteScriptSourceToDebugFile", true);
89
90 // Set to false if we need to debug test so the old scripts don't get wiped before each separate test
91// xEngineConfig.Set("DeleteScriptsOnStartup", false);
92
93 // This is not currently used at all for co-op termination. Bumping up to demonstrate that co-op termination
94 // has an effect - without it tests will fail due to a 120 second wait for the event to finish.
95 xEngineConfig.Set("WaitForEventCompletionOnScriptStop", 120000);
96
97 m_scene = new SceneHelpers().SetupScene("My Test", TestHelpers.ParseTail(0x9999), 1000, 1000, configSource);
98 SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
99 m_scene.StartScripts();
100 }
101
102 /// <summary>
103 /// Test co-operative termination on derez of an object containing a script with a long-running event.
104 /// </summary>
105 /// <remarks>
106 /// TODO: Actually compiling the script is incidental to this test. Really want a way to compile test scripts
107 /// within the build itself.
108 /// </remarks>
109 [Test]
110 public void TestStopOnLongSleep()
111 {
112 TestHelpers.InMethod();
113// TestHelpers.EnableLogging();
114
115 string script =
116@"default
117{
118 state_entry()
119 {
120 llSay(0, ""Thin Lizzy"");
121 llSleep(60);
122 }
123}";
124
125 TestStop(script);
126 }
127
128 [Test]
129 public void TestStopOnLongSingleStatementForLoop()
130 {
131 TestHelpers.InMethod();
132// TestHelpers.EnableLogging();
133
134 string script =
135@"default
136{
137 state_entry()
138 {
139 integer i = 0;
140 llSay(0, ""Thin Lizzy"");
141
142 for (i = 0; i < 2147483647; i++)
143 llSay(0, ""Iter "" + (string)i);
144 }
145}";
146
147 TestStop(script);
148 }
149
150 [Test]
151 public void TestStopOnLongCompoundStatementForLoop()
152 {
153 TestHelpers.InMethod();
154// TestHelpers.EnableLogging();
155
156 string script =
157@"default
158{
159 state_entry()
160 {
161 integer i = 0;
162 llSay(0, ""Thin Lizzy"");
163
164 for (i = 0; i < 2147483647; i++)
165 {
166 llSay(0, ""Iter "" + (string)i);
167 }
168 }
169}";
170
171 TestStop(script);
172 }
173
174 [Test]
175 public void TestStopOnLongSingleStatementWhileLoop()
176 {
177 TestHelpers.InMethod();
178// TestHelpers.EnableLogging();
179
180 string script =
181@"default
182{
183 state_entry()
184 {
185 integer i = 0;
186 llSay(0, ""Thin Lizzy"");
187
188 while (1 == 1)
189 llSay(0, ""Iter "" + (string)i++);
190 }
191}";
192
193 TestStop(script);
194 }
195
196 [Test]
197 public void TestStopOnLongCompoundStatementWhileLoop()
198 {
199 TestHelpers.InMethod();
200// TestHelpers.EnableLogging();
201
202 string script =
203@"default
204{
205 state_entry()
206 {
207 integer i = 0;
208 llSay(0, ""Thin Lizzy"");
209
210 while (1 == 1)
211 {
212 llSay(0, ""Iter "" + (string)i++);
213 }
214 }
215}";
216
217 TestStop(script);
218 }
219
220 [Test]
221 public void TestStopOnLongDoWhileLoop()
222 {
223 TestHelpers.InMethod();
224// TestHelpers.EnableLogging();
225
226 string script =
227@"default
228{
229 state_entry()
230 {
231 integer i = 0;
232 llSay(0, ""Thin Lizzy"");
233
234 do
235 {
236 llSay(0, ""Iter "" + (string)i++);
237} while (1 == 1);
238 }
239}";
240
241 TestStop(script);
242 }
243
244 [Test]
245 public void TestStopOnInfiniteJumpLoop()
246 {
247 TestHelpers.InMethod();
248 TestHelpers.EnableLogging();
249
250 string script =
251@"default
252{
253 state_entry()
254 {
255 integer i = 0;
256 llSay(0, ""Thin Lizzy"");
257
258 @p1;
259 llSay(0, ""Iter "" + (string)i++);
260 jump p1;
261 }
262}";
263
264 TestStop(script);
265 }
266
267 // Disabling for now as these are not particularly useful tests (since they fail due to stack overflow before
268 // termination can even be tried.
269// [Test]
270 public void TestStopOnInfiniteUserFunctionCallLoop()
271 {
272 TestHelpers.InMethod();
273// TestHelpers.EnableLogging();
274
275 string script =
276@"
277integer i = 0;
278
279ufn1()
280{
281 llSay(0, ""Iter ufn1() "" + (string)i++);
282 ufn1();
283}
284
285default
286{
287 state_entry()
288 {
289 integer i = 0;
290 llSay(0, ""Thin Lizzy"");
291
292 ufn1();
293 }
294}";
295
296 TestStop(script);
297 }
298
299 // Disabling for now as these are not particularly useful tests (since they fail due to stack overflow before
300 // termination can even be tried.
301// [Test]
302 public void TestStopOnInfiniteManualEventCallLoop()
303 {
304 TestHelpers.InMethod();
305// TestHelpers.EnableLogging();
306
307 string script =
308@"default
309{
310 state_entry()
311 {
312 integer i = 0;
313 llSay(0, ""Thin Lizzy"");
314
315 llSay(0, ""Iter"" + (string)i++);
316 default_event_state_entry();
317 }
318}";
319
320 TestStop(script);
321 }
322
323 private void TestStop(string script)
324 {
325 UUID userId = TestHelpers.ParseTail(0x1);
326// UUID objectId = TestHelpers.ParseTail(0x100);
327// UUID itemId = TestHelpers.ParseTail(0x3);
328 string itemName = "TestStop() Item";
329
330 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100);
331 m_scene.AddNewSceneObject(so, true);
332
333 InventoryItemBase itemTemplate = new InventoryItemBase();
334// itemTemplate.ID = itemId;
335 itemTemplate.Name = itemName;
336 itemTemplate.Folder = so.UUID;
337 itemTemplate.InvType = (int)InventoryType.LSL;
338
339 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
340
341 SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script);
342
343 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
344
345 // Wait for the script to start the event before we try stopping it.
346 m_chatEvent.WaitOne(60000);
347
348 Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
349
350 // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
351 // executes llSay() but has not started the next statement before we try to stop it.
352 Thread.Sleep(1000);
353
354 // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually
355 // stopped. This kind of multi-threading is far from ideal in a regression test.
356 new Thread(() => { m_xEngine.StopScript(rezzedItem.ItemID); m_stoppedEvent.Set(); }).Start();
357
358 if (!m_stoppedEvent.WaitOne(30000))
359 Assert.Fail("Script did not co-operatively stop.");
360
361 bool running;
362 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
363 Assert.That(
364 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
365 Assert.That(running, Is.False);
366 }
367
368 private void OnChatFromWorld(object sender, OSChatMessage oscm)
369 {
370 m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
371 Console.WriteLine("Got chat [{0}]", oscm.Message);
372
373 m_osChatMessageReceived = oscm;
374 m_chatEvent.Set();
375 }
376 }
377} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index c9c4753..2e61fb8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -633,19 +633,44 @@ namespace OpenSim.Region.ScriptEngine.Shared
633 633
634 public LSL_Types.Vector3 GetVector3Item(int itemIndex) 634 public LSL_Types.Vector3 GetVector3Item(int itemIndex)
635 { 635 {
636 if(m_data[itemIndex] is LSL_Types.Vector3) 636 if (m_data[itemIndex] is LSL_Types.Vector3)
637 {
637 return (LSL_Types.Vector3)m_data[itemIndex]; 638 return (LSL_Types.Vector3)m_data[itemIndex];
639 }
640 else if(m_data[itemIndex] is OpenMetaverse.Vector3)
641 {
642 return new LSL_Types.Vector3(
643 (OpenMetaverse.Vector3)m_data[itemIndex]);
644 }
638 else 645 else
646 {
639 throw new InvalidCastException(string.Format( 647 throw new InvalidCastException(string.Format(
640 "{0} expected but {1} given", 648 "{0} expected but {1} given",
641 typeof(LSL_Types.Vector3).Name, 649 typeof(LSL_Types.Vector3).Name,
642 m_data[itemIndex] != null ? 650 m_data[itemIndex] != null ?
643 m_data[itemIndex].GetType().Name : "null")); 651 m_data[itemIndex].GetType().Name : "null"));
652 }
644 } 653 }
645 654
646 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) 655 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
647 { 656 {
648 return (LSL_Types.Quaternion)m_data[itemIndex]; 657 if (m_data[itemIndex] is LSL_Types.Quaternion)
658 {
659 return (LSL_Types.Quaternion)m_data[itemIndex];
660 }
661 else if(m_data[itemIndex] is OpenMetaverse.Quaternion)
662 {
663 return new LSL_Types.Quaternion(
664 (OpenMetaverse.Quaternion)m_data[itemIndex]);
665 }
666 else
667 {
668 throw new InvalidCastException(string.Format(
669 "{0} expected but {1} given",
670 typeof(LSL_Types.Quaternion).Name,
671 m_data[itemIndex] != null ?
672 m_data[itemIndex].GetType().Name : "null"));
673 }
649 } 674 }
650 675
651 public LSL_Types.key GetKeyItem(int itemIndex) 676 public LSL_Types.key GetKeyItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index c73e22f..6dd6c17 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
@@ -51,14 +52,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for inventory functions in LSL 52 /// Tests for inventory functions in LSL
52 /// </summary> 53 /// </summary>
53 [TestFixture] 54 [TestFixture]
54 public class LSL_ApiInventoryTests 55 public class LSL_ApiInventoryTests : OpenSimTestCase
55 { 56 {
56 protected Scene m_scene; 57 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 58 protected XEngine.XEngine m_engine;
58 59
59 [SetUp] 60 [SetUp]
60 public void SetUp() 61 public override void SetUp()
61 { 62 {
63 base.SetUp();
64
62 IConfigSource initConfigSource = new IniConfigSource(); 65 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 66 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 67 config.Set("Enabled", "true");
@@ -91,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
91 TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId); 94 TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId);
92 95
93 LSL_Api api = new LSL_Api(); 96 LSL_Api api = new LSL_Api();
94 api.Initialize(m_engine, so1.RootPart, null); 97 api.Initialize(m_engine, so1.RootPart, null, null);
95 98
96 // Create a second object 99 // Create a second object
97 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100); 100 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100);
@@ -124,7 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
124 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10); 127 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10);
125 m_scene.AddSceneObject(so1); 128 m_scene.AddSceneObject(so1);
126 LSL_Api api = new LSL_Api(); 129 LSL_Api api = new LSL_Api();
127 api.Initialize(m_engine, so1.RootPart, null); 130 api.Initialize(m_engine, so1.RootPart, null, null);
128 131
129 // Create an object embedded inside the first 132 // Create an object embedded inside the first
130 UUID itemId = TestHelpers.ParseTail(0x20); 133 UUID itemId = TestHelpers.ParseTail(0x20);
@@ -134,7 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
134 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100); 137 SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100);
135 m_scene.AddSceneObject(so2); 138 m_scene.AddSceneObject(so2);
136 LSL_Api api2 = new LSL_Api(); 139 LSL_Api api2 = new LSL_Api();
137 api2.Initialize(m_engine, so2.RootPart, null); 140 api2.Initialize(m_engine, so2.RootPart, null, null);
138 141
139 // *** Firstly, we test where llAllowInventoryDrop() has not been called. *** 142 // *** Firstly, we test where llAllowInventoryDrop() has not been called. ***
140 api.llGiveInventory(so2.UUID.ToString(), inventoryItemName); 143 api.llGiveInventory(so2.UUID.ToString(), inventoryItemName);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
index 2565ae7..5b57bbe 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 45using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
45using OpenSim.Services.Interfaces; 46using OpenSim.Services.Interfaces;
46using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
@@ -56,14 +57,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests. 57 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests.
57 /// </remarks> 58 /// </remarks>
58 [TestFixture] 59 [TestFixture]
59 public class LSL_ApiLinkingTests 60 public class LSL_ApiLinkingTests : OpenSimTestCase
60 { 61 {
61 protected Scene m_scene; 62 protected Scene m_scene;
62 protected XEngine.XEngine m_engine; 63 protected XEngine.XEngine m_engine;
63 64
64 [SetUp] 65 [SetUp]
65 public void SetUp() 66 public override void SetUp()
66 { 67 {
68 base.SetUp();
69
67 IConfigSource initConfigSource = new IniConfigSource(); 70 IConfigSource initConfigSource = new IniConfigSource();
68 IConfig config = initConfigSource.AddConfig("XEngine"); 71 IConfig config = initConfigSource.AddConfig("XEngine");
69 config.Set("Enabled", "true"); 72 config.Set("Enabled", "true");
@@ -102,7 +105,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
102 m_scene.AddSceneObject(grp2); 105 m_scene.AddSceneObject(grp2);
103 106
104 LSL_Api apiGrp1 = new LSL_Api(); 107 LSL_Api apiGrp1 = new LSL_Api();
105 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item); 108 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null);
106 109
107 apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE); 110 apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE);
108 111
@@ -129,7 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
129 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 132 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
130 133
131 LSL_Api apiGrp1 = new LSL_Api(); 134 LSL_Api apiGrp1 = new LSL_Api();
132 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item); 135 apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null);
133 136
134 apiGrp1.llBreakLink(2); 137 apiGrp1.llBreakLink(2);
135 138
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
index dd23be8..60de5cb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -34,6 +34,7 @@ using OpenSim.Region.ScriptEngine.Shared;
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using Nini.Config; 35using Nini.Config;
36using OpenSim.Region.ScriptEngine.Shared.Api; 36using OpenSim.Region.ScriptEngine.Shared.Api;
37using OpenSim.Region.ScriptEngine.Shared.Instance;
37using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 38using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenSim.Tests.Common.Mock; 40using OpenSim.Tests.Common.Mock;
@@ -46,13 +47,15 @@ using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
46namespace OpenSim.Region.ScriptEngine.Shared.Tests 47namespace OpenSim.Region.ScriptEngine.Shared.Tests
47{ 48{
48 [TestFixture] 49 [TestFixture]
49 public class LSL_ApiListTests 50 public class LSL_ApiListTests : OpenSimTestCase
50 { 51 {
51 private LSL_Api m_lslApi; 52 private LSL_Api m_lslApi;
52 53
53 [SetUp] 54 [SetUp]
54 public void SetUp() 55 public override void SetUp()
55 { 56 {
57 base.SetUp();
58
56 IConfigSource initConfigSource = new IniConfigSource(); 59 IConfigSource initConfigSource = new IniConfigSource();
57 IConfig config = initConfigSource.AddConfig("XEngine"); 60 IConfig config = initConfigSource.AddConfig("XEngine");
58 config.Set("Enabled", "true"); 61 config.Set("Enabled", "true");
@@ -65,7 +68,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
65 engine.AddRegion(scene); 68 engine.AddRegion(scene);
66 69
67 m_lslApi = new LSL_Api(); 70 m_lslApi = new LSL_Api();
68 m_lslApi.Initialize(engine, part, null); 71 m_lslApi.Initialize(engine, part, null, null);
69 } 72 }
70 73
71 [Test] 74 [Test]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index c41d1e7..e97ae06 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -33,6 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using Nini.Config; 34using Nini.Config;
35using OpenSim.Region.ScriptEngine.Shared.Api; 35using OpenSim.Region.ScriptEngine.Shared.Api;
36using OpenSim.Region.ScriptEngine.Shared.Instance;
36using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 37using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
37using OpenMetaverse; 38using OpenMetaverse;
38using System; 39using System;
@@ -66,7 +67,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
66 engine.AddRegion(scene); 67 engine.AddRegion(scene);
67 68
68 m_lslApi = new LSL_Api(); 69 m_lslApi = new LSL_Api();
69 m_lslApi.Initialize(engine, part, null); 70 m_lslApi.Initialize(engine, part, null, null);
70 } 71 }
71 72
72 [Test] 73 [Test]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
index 3ed2562..c8c7f82 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLFloat 36 public class LSL_TypesTestLSLFloat : OpenSimTestCase
37 { 37 {
38 // Used for testing equality of two floats. 38 // Used for testing equality of two floats.
39 private double _lowPrecisionTolerance = 0.000001; 39 private double _lowPrecisionTolerance = 0.000001;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
index 8d1169a..c664108 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLInteger 36 public class LSL_TypesTestLSLInteger : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, int> m_doubleIntSet; 38 private Dictionary<double, int> m_doubleIntSet;
39 private Dictionary<string, int> m_stringIntSet; 39 private Dictionary<string, int> m_stringIntSet;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
index c4ca1a8..8550f2d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLString 36 public class LSL_TypesTestLSLString : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, string> m_doubleStringSet; 38 private Dictionary<double, string> m_doubleStringSet;
39 39
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
index b81225f..71b88bc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests the LSL_Types.list class. 36 /// Tests the LSL_Types.list class.
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestList 39 public class LSL_TypesTestList : OpenSimTestCase
40 { 40 {
41 /// <summary> 41 /// <summary>
42 /// Tests concatenating a string to a list. 42 /// Tests concatenating a string to a list.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
index ebf8001..0c838af 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests for Vector3 36 /// Tests for Vector3
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestVector3 39 public class LSL_TypesTestVector3 : OpenSimTestCase
40 { 40 {
41 [Test] 41 [Test]
42 public void TestDotProduct() 42 public void TestDotProduct()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index c401794..c88bad5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
@@ -51,14 +52,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for OSSL_Api 52 /// Tests for OSSL_Api
52 /// </summary> 53 /// </summary>
53 [TestFixture] 54 [TestFixture]
54 public class OSSL_ApiAppearanceTest 55 public class OSSL_ApiAppearanceTest : OpenSimTestCase
55 { 56 {
56 protected Scene m_scene; 57 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 58 protected XEngine.XEngine m_engine;
58 59
59 [SetUp] 60 [SetUp]
60 public void SetUp() 61 public override void SetUp()
61 { 62 {
63 base.SetUp();
64
62 IConfigSource initConfigSource = new IniConfigSource(); 65 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 66 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 67 config.Set("Enabled", "true");
@@ -91,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
91 m_scene.AddSceneObject(so); 94 m_scene.AddSceneObject(so);
92 95
93 OSSL_Api osslApi = new OSSL_Api(); 96 OSSL_Api osslApi = new OSSL_Api();
94 osslApi.Initialize(m_engine, part, null); 97 osslApi.Initialize(m_engine, part, null, null);
95 98
96 string notecardName = "appearanceNc"; 99 string notecardName = "appearanceNc";
97 100
@@ -132,7 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
132 m_scene.AddSceneObject(so); 135 m_scene.AddSceneObject(so);
133 136
134 OSSL_Api osslApi = new OSSL_Api(); 137 OSSL_Api osslApi = new OSSL_Api();
135 osslApi.Initialize(m_engine, part, null); 138 osslApi.Initialize(m_engine, part, null, null);
136 139
137 string notecardName = "appearanceNc"; 140 string notecardName = "appearanceNc";
138 141
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
index 5ed1f3d..b2803a1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.CoreModules.Framework.InventoryAccess;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
44using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
@@ -98,9 +99,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
98 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); 99 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
99 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); 100 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
100 101
101 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); 102 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
102 OSSL_Api osslApi = new OSSL_Api(); 103 OSSL_Api osslApi = new OSSL_Api();
103 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); 104 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
104 105
105// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID); 106// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID);
106 107
@@ -144,9 +145,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
144 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); 145 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
145 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); 146 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
146 147
147 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); 148 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
148 OSSL_Api osslApi = new OSSL_Api(); 149 OSSL_Api osslApi = new OSSL_Api();
149 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); 150 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
150 151
151 // Create an object embedded inside the first 152 // Create an object embedded inside the first
152 TaskInventoryHelpers.AddNotecard( 153 TaskInventoryHelpers.AddNotecard(
@@ -192,12 +193,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
192 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); 193 SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
193 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart); 194 TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
194 195
195 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); 196 new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
196 OSSL_Api osslApi = new OSSL_Api(); 197 OSSL_Api osslApi = new OSSL_Api();
197 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); 198 osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
198 199
199 // Create an object embedded inside the first 200 // Create an object embedded inside the first
200 TaskInventoryHelpers.AddSceneObject(m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID); 201 TaskInventoryHelpers.AddSceneObject(
202 m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID);
201 203
202 ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2); 204 ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2);
203 205
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index b49bcc2..1f8a6e5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -42,6 +42,7 @@ using OpenSim.Region.OptionalModules.World.NPC;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.ScriptEngine.Shared; 43using OpenSim.Region.ScriptEngine.Shared;
44using OpenSim.Region.ScriptEngine.Shared.Api; 44using OpenSim.Region.ScriptEngine.Shared.Api;
45using OpenSim.Region.ScriptEngine.Shared.Instance;
45using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 46using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
46using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
47using OpenSim.Tests.Common; 48using OpenSim.Tests.Common;
@@ -99,7 +100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
99 m_scene.AddSceneObject(so); 100 m_scene.AddSceneObject(so);
100 101
101 OSSL_Api osslApi = new OSSL_Api(); 102 OSSL_Api osslApi = new OSSL_Api();
102 osslApi.Initialize(m_engine, part, null); 103 osslApi.Initialize(m_engine, part, null, null);
103 104
104 string notecardName = "appearanceNc"; 105 string notecardName = "appearanceNc";
105 osslApi.osOwnerSaveAppearance(notecardName); 106 osslApi.osOwnerSaveAppearance(notecardName);
@@ -125,14 +126,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
125 m_scene.AddSceneObject(so); 126 m_scene.AddSceneObject(so);
126 127
127 OSSL_Api osslApi = new OSSL_Api(); 128 OSSL_Api osslApi = new OSSL_Api();
128 osslApi.Initialize(m_engine, so.RootPart, null); 129 osslApi.Initialize(m_engine, so.RootPart, null, null);
129 130
130 string npcRaw;
131 bool gotExpectedException = false; 131 bool gotExpectedException = false;
132 try 132 try
133 { 133 {
134 npcRaw 134 osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
135 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
136 } 135 }
137 catch (ScriptException) 136 catch (ScriptException)
138 { 137 {
@@ -162,7 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
162 m_scene.AddSceneObject(so); 161 m_scene.AddSceneObject(so);
163 162
164 OSSL_Api osslApi = new OSSL_Api(); 163 OSSL_Api osslApi = new OSSL_Api();
165 osslApi.Initialize(m_engine, part, null); 164 osslApi.Initialize(m_engine, part, null, null);
166 165
167 string notecardName = "appearanceNc"; 166 string notecardName = "appearanceNc";
168 osslApi.osOwnerSaveAppearance(notecardName); 167 osslApi.osOwnerSaveAppearance(notecardName);
@@ -196,7 +195,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
196 m_scene.AddSceneObject(so); 195 m_scene.AddSceneObject(so);
197 196
198 OSSL_Api osslApi = new OSSL_Api(); 197 OSSL_Api osslApi = new OSSL_Api();
199 osslApi.Initialize(m_engine, part, null); 198 osslApi.Initialize(m_engine, part, null, null);
200 199
201 osslApi.osOwnerSaveAppearance(firstAppearanceNcName); 200 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
202 201
@@ -234,7 +233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
234 m_scene.AddSceneObject(so); 233 m_scene.AddSceneObject(so);
235 234
236 OSSL_Api osslApi = new OSSL_Api(); 235 OSSL_Api osslApi = new OSSL_Api();
237 osslApi.Initialize(m_engine, part, null); 236 osslApi.Initialize(m_engine, part, null, null);
238 237
239 osslApi.osOwnerSaveAppearance(firstAppearanceNcName); 238 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
240 239
@@ -286,10 +285,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
286 m_scene.AddSceneObject(otherSo); 285 m_scene.AddSceneObject(otherSo);
287 286
288 OSSL_Api osslApi = new OSSL_Api(); 287 OSSL_Api osslApi = new OSSL_Api();
289 osslApi.Initialize(m_engine, part, null); 288 osslApi.Initialize(m_engine, part, null, null);
290 289
291 OSSL_Api otherOsslApi = new OSSL_Api(); 290 OSSL_Api otherOsslApi = new OSSL_Api();
292 otherOsslApi.Initialize(m_engine, otherPart, null); 291 otherOsslApi.Initialize(m_engine, otherPart, null, null);
293 292
294 string notecardName = "appearanceNc"; 293 string notecardName = "appearanceNc";
295 osslApi.osOwnerSaveAppearance(notecardName); 294 osslApi.osOwnerSaveAppearance(notecardName);
@@ -333,7 +332,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
333 m_scene.AddSceneObject(so); 332 m_scene.AddSceneObject(so);
334 333
335 OSSL_Api osslApi = new OSSL_Api(); 334 OSSL_Api osslApi = new OSSL_Api();
336 osslApi.Initialize(m_engine, part, null); 335 osslApi.Initialize(m_engine, part, null, null);
337 336
338 string notecardName = "appearanceNc"; 337 string notecardName = "appearanceNc";
339 osslApi.osOwnerSaveAppearance(notecardName); 338 osslApi.osOwnerSaveAppearance(notecardName);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs
new file mode 100644
index 0000000..f4211c8
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs
@@ -0,0 +1,61 @@
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.Runtime.Remoting;
30using System.Runtime.Remoting.Lifetime;
31using System.Security.Permissions;
32using System.Threading;
33using System.Reflection;
34using System.Collections;
35using System.Collections.Generic;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
39
40namespace OpenSim.Region.ScriptEngine.XEngine.ScriptBase
41{
42 public class XEngineScriptBase : ScriptBaseClass
43 {
44 /// <summary>
45 /// Used for script sleeps when we are using co-operative script termination.
46 /// </summary>
47 /// <remarks>null if co-operative script termination is not active</remarks>
48 WaitHandle m_coopSleepHandle;
49
50 public XEngineScriptBase(WaitHandle coopSleepHandle) : base()
51 {
52 m_coopSleepHandle = coopSleepHandle;
53 }
54
55 public void opensim_reserved_CheckForCoopTermination()
56 {
57 if (m_coopSleepHandle != null && m_coopSleepHandle.WaitOne(0))
58 throw new ScriptCoopStopException();
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 9405075..0ff2da3 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
52 { 52 {
53 myScriptEngine = _ScriptEngine; 53 myScriptEngine = _ScriptEngine;
54 54
55 m_log.Info("[XEngine] Hooking up to server events"); 55// m_log.Info("[XEngine] Hooking up to server events");
56 myScriptEngine.World.EventManager.OnAttach += attach; 56 myScriptEngine.World.EventManager.OnAttach += attach;
57 myScriptEngine.World.EventManager.OnObjectGrab += touch_start; 57 myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
58 myScriptEngine.World.EventManager.OnObjectGrabbing += touch; 58 myScriptEngine.World.EventManager.OnObjectGrabbing += touch;
@@ -62,6 +62,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
62 myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target; 62 myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target;
63 myScriptEngine.World.EventManager.OnScriptAtRotTargetEvent += at_rot_target; 63 myScriptEngine.World.EventManager.OnScriptAtRotTargetEvent += at_rot_target;
64 myScriptEngine.World.EventManager.OnScriptNotAtRotTargetEvent += not_at_rot_target; 64 myScriptEngine.World.EventManager.OnScriptNotAtRotTargetEvent += not_at_rot_target;
65 myScriptEngine.World.EventManager.OnScriptMovingStartEvent += moving_start;
66 myScriptEngine.World.EventManager.OnScriptMovingEndEvent += moving_end;
65 myScriptEngine.World.EventManager.OnScriptControlEvent += control; 67 myScriptEngine.World.EventManager.OnScriptControlEvent += control;
66 myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start; 68 myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start;
67 myScriptEngine.World.EventManager.OnScriptColliding += collision; 69 myScriptEngine.World.EventManager.OnScriptColliding += collision;
@@ -69,7 +71,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
69 myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start; 71 myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start;
70 myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision; 72 myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision;
71 myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end; 73 myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end;
72 IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>(); 74 IMoneyModule money = myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
73 if (money != null) 75 if (money != null)
74 { 76 {
75 money.OnObjectPaid+=HandleObjectPaid; 77 money.OnObjectPaid+=HandleObjectPaid;
@@ -419,14 +421,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
419 // dataserver: not handled here 421 // dataserver: not handled here
420 // link_message: not handled here 422 // link_message: not handled here
421 423
422 public void moving_start(uint localID, UUID itemID) 424 public void moving_start(uint localID)
423 { 425 {
424 myScriptEngine.PostObjectEvent(localID, new EventParams( 426 myScriptEngine.PostObjectEvent(localID, new EventParams(
425 "moving_start",new object[0], 427 "moving_start",new object[0],
426 new DetectParams[0])); 428 new DetectParams[0]));
427 } 429 }
428 430
429 public void moving_end(uint localID, UUID itemID) 431 public void moving_end(uint localID)
430 { 432 {
431 myScriptEngine.PostObjectEvent(localID, new EventParams( 433 myScriptEngine.PostObjectEvent(localID, new EventParams(
432 "moving_end",new object[0], 434 "moving_end",new object[0],
diff --git a/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs
new file mode 100644
index 0000000..efb854d
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs
@@ -0,0 +1,126 @@
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 OpenSim.Framework;
31using OpenSim.Framework.Console;
32using OpenSim.Region.ScriptEngine.Interfaces;
33using OpenSim.Region.ScriptEngine.Shared.Api;
34using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
35
36namespace OpenSim.Region.ScriptEngine.XEngine
37{
38 public class ScriptEngineConsoleCommands
39 {
40 IScriptEngine m_engine;
41
42 public ScriptEngineConsoleCommands(IScriptEngine engine)
43 {
44 m_engine = engine;
45 }
46
47 public void RegisterCommands()
48 {
49 MainConsole.Instance.Commands.AddCommand(
50 "Scripts", false, "show script sensors", "show script sensors", "Show script sensors information",
51 HandleShowSensors);
52
53 MainConsole.Instance.Commands.AddCommand(
54 "Scripts", false, "show script timers", "show script timers", "Show script sensors information",
55 HandleShowTimers);
56 }
57
58 private bool IsSceneSelected()
59 {
60 return MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_engine.World;
61 }
62
63 private void HandleShowSensors(string module, string[] cmdparams)
64 {
65 if (!IsSceneSelected())
66 return;
67
68 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(m_engine);
69
70 if (sr == null)
71 {
72 MainConsole.Instance.Output("Plugin not yet initialized");
73 return;
74 }
75
76 List<SensorRepeat.SensorInfo> sensorInfo = sr.GetSensorInfo();
77
78 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
79 cdt.AddColumn("Part name", 40);
80 cdt.AddColumn("Script item ID", 36);
81 cdt.AddColumn("Type", 4);
82 cdt.AddColumn("Interval", 8);
83 cdt.AddColumn("Range", 8);
84 cdt.AddColumn("Arc", 8);
85
86 foreach (SensorRepeat.SensorInfo s in sensorInfo)
87 {
88 cdt.AddRow(s.host.Name, s.itemID, s.type, s.interval, s.range, s.arc);
89 }
90
91 MainConsole.Instance.Output(cdt.ToString());
92 MainConsole.Instance.OutputFormat("Total: {0}", sensorInfo.Count);
93 }
94
95 private void HandleShowTimers(string module, string[] cmdparams)
96 {
97 if (!IsSceneSelected())
98 return;
99
100 Timer timerPlugin = AsyncCommandManager.GetTimerPlugin(m_engine);
101
102 if (timerPlugin == null)
103 {
104 MainConsole.Instance.Output("Plugin not yet initialized");
105 return;
106 }
107
108 List<Timer.TimerInfo> timersInfo = timerPlugin.GetTimersInfo();
109
110 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
111 cdt.AddColumn("Part local ID", 13);
112 cdt.AddColumn("Script item ID", 36);
113 cdt.AddColumn("Interval", 10);
114 cdt.AddColumn("Next", 8);
115
116 foreach (Timer.TimerInfo t in timersInfo)
117 {
118 // Convert from 100 ns ticks back to seconds
119 cdt.AddRow(t.localID, t.itemID, (double)t.interval / 10000000, t.next);
120 }
121
122 MainConsole.Instance.Output(cdt.ToString());
123 MainConsole.Instance.OutputFormat("Total: {0}", timersInfo.Count);
124 }
125 }
126} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
index f331658..5abfe9a 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
44 /// XEngine tests. 44 /// XEngine tests.
45 /// </summary> 45 /// </summary>
46 [TestFixture] 46 [TestFixture]
47 public class XEngineTest 47 public class XEngineTest : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 private XEngine m_xEngine; 50 private XEngine m_xEngine;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9f05666..6e04e79 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode] 31using System.Diagnostics; //for [DebuggerNonUserCode]
32using System.Globalization; 32using System.Globalization;
33using System.IO; 33using System.IO;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Security; 36using System.Security;
36using System.Security.Policy; 37using System.Security.Policy;
@@ -46,13 +47,15 @@ using OpenSim.Framework;
46using OpenSim.Framework.Console; 47using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Interfaces; 49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.ScriptEngine.Interfaces;
49using OpenSim.Region.ScriptEngine.Shared; 51using OpenSim.Region.ScriptEngine.Shared;
50using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 52using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
51using OpenSim.Region.ScriptEngine.Shared.CodeTools; 53using OpenSim.Region.ScriptEngine.Shared.CodeTools;
52using OpenSim.Region.ScriptEngine.Shared.Instance; 54using OpenSim.Region.ScriptEngine.Shared.Instance;
53using OpenSim.Region.ScriptEngine.Shared.Api; 55using OpenSim.Region.ScriptEngine.Shared.Api;
54using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 56using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
55using OpenSim.Region.ScriptEngine.Interfaces; 57using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
58using OpenSim.Region.ScriptEngine.XEngine.ScriptBase;
56using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; 59using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
57 60
58using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; 61using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
@@ -107,6 +110,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
107 private IXmlRpcRouter m_XmlRpcRouter; 110 private IXmlRpcRouter m_XmlRpcRouter;
108 private int m_EventLimit; 111 private int m_EventLimit;
109 private bool m_KillTimedOutScripts; 112 private bool m_KillTimedOutScripts;
113
114 /// <summary>
115 /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
116 /// its thread.
117 /// </summary>
118 /// <remarks>
119 /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write
120 /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly
121 /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing
122 /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed
123 /// actually hold.
124 ///
125 /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads
126 /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately
127 /// shutting down.
128 /// </remarks>
129 private int m_WaitForEventCompletionOnScriptStop = 1000;
130
110 private string m_ScriptEnginesPath = null; 131 private string m_ScriptEnginesPath = null;
111 132
112 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); 133 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
@@ -218,11 +239,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
218 } 239 }
219 } 240 }
220 241
242 private ScriptEngineConsoleCommands m_consoleCommands;
243
221 public string ScriptEngineName 244 public string ScriptEngineName
222 { 245 {
223 get { return "XEngine"; } 246 get { return "XEngine"; }
224 } 247 }
225 248
249 public string ScriptClassName { get; private set; }
250
251 public string ScriptBaseClassName { get; private set; }
252
253 public ParameterInfo[] ScriptBaseClassParameters { get; private set; }
254
255 public string[] ScriptReferencedAssemblies { get; private set; }
256
226 public Scene World 257 public Scene World
227 { 258 {
228 get { return m_Scene; } 259 get { return m_Scene; }
@@ -277,21 +308,35 @@ namespace OpenSim.Region.ScriptEngine.XEngine
277 308
278 m_ScriptConfig = configSource.Configs["XEngine"]; 309 m_ScriptConfig = configSource.Configs["XEngine"];
279 m_ConfigSource = configSource; 310 m_ConfigSource = configSource;
311
312 string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "abort");
313
314 m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy);
315
316 if (rawScriptStopStrategy == "co-op")
317 {
318 ScriptClassName = "XEngineScript";
319 ScriptBaseClassName = typeof(XEngineScriptBase).FullName;
320 ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters();
321 ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) };
322 }
323 else
324 {
325 ScriptClassName = "Script";
326 ScriptBaseClassName = typeof(ScriptBaseClass).FullName;
327 }
328
329// Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]);
280 } 330 }
281 331
282 public void AddRegion(Scene scene) 332 public void AddRegion(Scene scene)
283 { 333 {
284 if (m_ScriptConfig == null) 334 if (m_ScriptConfig == null)
285 return; 335 return;
336
286 m_ScriptFailCount = 0; 337 m_ScriptFailCount = 0;
287 m_ScriptErrorMessage = String.Empty; 338 m_ScriptErrorMessage = String.Empty;
288 339
289 if (m_ScriptConfig == null)
290 {
291// m_log.ErrorFormat("[XEngine] No script configuration found. Scripts disabled");
292 return;
293 }
294
295 m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true); 340 m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true);
296 341
297 if (!m_Enabled) 342 if (!m_Enabled)
@@ -316,6 +361,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
316 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); 361 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
317 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); 362 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
318 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; 363 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
364 m_WaitForEventCompletionOnScriptStop
365 = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
366
319 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); 367 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
320 368
321 m_Prio = ThreadPriority.BelowNormal; 369 m_Prio = ThreadPriority.BelowNormal;
@@ -364,48 +412,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
364 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved; 412 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved;
365 } 413 }
366 414
415 m_consoleCommands = new ScriptEngineConsoleCommands(this);
416 m_consoleCommands.RegisterCommands();
417
367 MainConsole.Instance.Commands.AddCommand( 418 MainConsole.Instance.Commands.AddCommand(
368 "Scripts", false, "xengine status", "xengine status", "Show status information", 419 "Scripts", false, "xengine status", "xengine status", "Show status information",
369 "Show status information on the script engine.", 420 "Show status information on the script engine.",
370 HandleShowStatus); 421 HandleShowStatus);
371 422
372 MainConsole.Instance.Commands.AddCommand( 423 MainConsole.Instance.Commands.AddCommand(
373 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", 424 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>+]", "Show script information",
374 "Show information on all scripts known to the script engine." 425 "Show information on all scripts known to the script engine.\n"
375 + "If a <script-item-uuid> is given then only information on that script will be shown.", 426 + "If one or more <script-item-uuid>s are given then only information on that script will be shown.",
376 HandleShowScripts); 427 HandleShowScripts);
377 428
378 MainConsole.Instance.Commands.AddCommand( 429 MainConsole.Instance.Commands.AddCommand(
379 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>]", "Show script information", 430 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>+]", "Show script information",
380 "Synonym for scripts show command", HandleShowScripts); 431 "Synonym for scripts show command", HandleShowScripts);
381 432
382 MainConsole.Instance.Commands.AddCommand( 433 MainConsole.Instance.Commands.AddCommand(
383 "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>]", "Suspends all running scripts", 434 "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>+]", "Suspends all running scripts",
384 "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a" 435 "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a"
385 + " script that is currently processing an event.\n" 436 + " script that is currently processing an event.\n"
386 + "Suspended scripts will continue to accumulate events but won't process them.\n" 437 + "Suspended scripts will continue to accumulate events but won't process them.\n"
387 + "If a <script-item-uuid> is given then only that script will be suspended. Otherwise, all suitable scripts are suspended.", 438 + "If one or more <script-item-uuid>s are given then only that script will be suspended. Otherwise, all suitable scripts are suspended.",
388 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript)); 439 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript));
389 440
390 MainConsole.Instance.Commands.AddCommand( 441 MainConsole.Instance.Commands.AddCommand(
391 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", 442 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>+]", "Resumes all suspended scripts",
392 "Resumes all currently suspended scripts.\n" 443 "Resumes all currently suspended scripts.\n"
393 + "Resumed scripts will process all events accumulated whilst suspended." 444 + "Resumed scripts will process all events accumulated whilst suspended.\n"
394 + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", 445 + "If one or more <script-item-uuid>s are given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
395 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); 446 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
396 447
397 MainConsole.Instance.Commands.AddCommand( 448 MainConsole.Instance.Commands.AddCommand(
398 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", 449 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>+]", "Stops all running scripts",
399 "Stops all running scripts." 450 "Stops all running scripts.\n"
400 + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", 451 + "If one or more <script-item-uuid>s are given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
401 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); 452 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
402 453
403 MainConsole.Instance.Commands.AddCommand( 454 MainConsole.Instance.Commands.AddCommand(
404 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", 455 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>+]", "Starts all stopped scripts",
405 "Starts all stopped scripts." 456 "Starts all stopped scripts.\n"
406 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", 457 + "If one or more <script-item-uuid>s are given then only that script will be started. Otherwise, all suitable scripts are started.",
407 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); 458 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
408 459
460 MainConsole.Instance.Commands.AddCommand(
461 "Scripts", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
462 "Activates or deactivates extra debug logging for the given script.\n"
463 + "Level == 0, deactivate extra debug logging.\n"
464 + "Level >= 1, log state changes.\n"
465 + "Level >= 2, log event invocations.\n",
466 HandleDebugScriptLogCommand);
467
409// MainConsole.Instance.Commands.AddCommand( 468// MainConsole.Instance.Commands.AddCommand(
410// "Debug", false, "debug xengine", "debug xengine [<level>]", 469// "Debug", false, "debug xengine", "debug xengine [<level>]",
411// "Turn on detailed xengine debugging.", 470// "Turn on detailed xengine debugging.",
@@ -414,6 +473,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
414// HandleDebugLevelCommand); 473// HandleDebugLevelCommand);
415 } 474 }
416 475
476 private void HandleDebugScriptLogCommand(string module, string[] args)
477 {
478 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
479 return;
480
481 if (args.Length != 5)
482 {
483 MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
484 return;
485 }
486
487 UUID itemId;
488
489 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
490 return;
491
492 int newLevel;
493
494 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
495 return;
496
497 IScriptInstance si;
498
499 lock (m_Scripts)
500 {
501 // XXX: We can't give the user feedback on a bad item id because this may apply to a different script
502 // engine
503 if (!m_Scripts.TryGetValue(itemId, out si))
504 return;
505 }
506
507 si.DebugLevel = newLevel;
508 MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
509 }
510
417 /// <summary> 511 /// <summary>
418 /// Change debug level 512 /// Change debug level
419 /// </summary> 513 /// </summary>
@@ -445,9 +539,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
445 /// </summary> 539 /// </summary>
446 /// <param name="cmdparams"></param> 540 /// <param name="cmdparams"></param>
447 /// <param name="instance"></param> 541 /// <param name="instance"></param>
448 /// <returns>true if we're okay to proceed, false if not.</returns> 542 /// <param name="comparer">Basis on which to sort output. Can be null if no sort needs to take place</param>
449 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action) 543 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action)
450 { 544 {
545 HandleScriptsAction<object>(cmdparams, action, null);
546 }
547
548 /// <summary>
549 /// Parse the raw item id into a script instance from the command params if it's present.
550 /// </summary>
551 /// <param name="cmdparams"></param>
552 /// <param name="instance"></param>
553 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
554 private void HandleScriptsAction<TKey>(
555 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
556 {
451 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 557 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
452 return; 558 return;
453 559
@@ -458,35 +564,42 @@ namespace OpenSim.Region.ScriptEngine.XEngine
458 564
459 if (cmdparams.Length == 2) 565 if (cmdparams.Length == 2)
460 { 566 {
461 foreach (IScriptInstance instance in m_Scripts.Values) 567 IEnumerable<IScriptInstance> scripts = m_Scripts.Values;
568
569 if (keySelector != null)
570 scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector);
571
572 foreach (IScriptInstance instance in scripts)
462 action(instance); 573 action(instance);
463 574
464 return; 575 return;
465 } 576 }
466 577
467 rawItemId = cmdparams[2]; 578 for (int i = 2; i < cmdparams.Length; i++)
468
469 if (!UUID.TryParse(rawItemId, out itemId))
470 {
471 MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId);
472 return;
473 }
474
475 if (itemId != UUID.Zero)
476 { 579 {
477 IScriptInstance instance = GetInstance(itemId); 580 rawItemId = cmdparams[i];
478 if (instance == null) 581
582 if (!UUID.TryParse(rawItemId, out itemId))
479 { 583 {
480 // Commented out for now since this will cause false reports on simulators with more than 584 MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
481 // one scene where the current command line set region is 'root' (which causes commands to 585 continue;
482 // go to both regions... (sigh)
483// MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
484 return;
485 } 586 }
486 else 587
588 if (itemId != UUID.Zero)
487 { 589 {
488 action(instance); 590 IScriptInstance instance = GetInstance(itemId);
489 return; 591 if (instance == null)
592 {
593 // Commented out for now since this will cause false reports on simulators with more than
594 // one scene where the current command line set region is 'root' (which causes commands to
595 // go to both regions... (sigh)
596 // MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
597 continue;
598 }
599 else
600 {
601 action(instance);
602 }
490 } 603 }
491 } 604 }
492 } 605 }
@@ -505,9 +618,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
505 StringBuilder sb = new StringBuilder(); 618 StringBuilder sb = new StringBuilder();
506 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); 619 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName);
507 620
621 long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0;
622
508 lock (m_Scripts) 623 lock (m_Scripts)
509 sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); 624 {
625 scriptsLoaded = m_Scripts.Count;
510 626
627 foreach (IScriptInstance si in m_Scripts.Values)
628 {
629 eventsQueued += si.EventsQueued;
630 eventsProcessed += si.EventsProcessed;
631 }
632 }
633
634 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
511 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); 635 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
512 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 636 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
513 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 637 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
@@ -516,6 +640,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
516 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); 640 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads);
517 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); 641 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks);
518// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); 642// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count);
643 sb.AppendFormat("Events queued : {0}\n", eventsQueued);
644 sb.AppendFormat("Events processed : {0}\n", eventsProcessed);
519 645
520 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); 646 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this);
521 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); 647 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0);
@@ -546,7 +672,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
546 } 672 }
547 } 673 }
548 674
549 HandleScriptsAction(cmdparams, HandleShowScript); 675 HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed);
550 } 676 }
551 677
552 private void HandleShowScript(IScriptInstance instance) 678 private void HandleShowScript(IScriptInstance instance)
@@ -576,11 +702,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
576 702
577 sb.AppendFormat("Script name : {0}\n", instance.ScriptName); 703 sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
578 sb.AppendFormat("Status : {0}\n", status); 704 sb.AppendFormat("Status : {0}\n", status);
579 705 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
580 lock (eq) 706 sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
581 sb.AppendFormat("Queued events : {0}\n", eq.Count);
582
583 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); 707 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
708 sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
584 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); 709 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
585 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); 710 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
586 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); 711 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
@@ -1079,7 +1204,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1079 } 1204 }
1080 1205
1081 m_log.DebugFormat( 1206 m_log.DebugFormat(
1082 "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1207 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1083 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1208 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1084 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1209 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1085 1210
@@ -1089,8 +1214,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 1214
1090 string assembly = ""; 1215 string assembly = "";
1091 1216
1092 CultureInfo USCulture = new CultureInfo("en-US"); 1217 Culture.SetCurrentCulture();
1093 Thread.CurrentThread.CurrentCulture = USCulture;
1094 1218
1095 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 1219 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
1096 1220
@@ -1101,6 +1225,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1101 lock (m_AddingAssemblies) 1225 lock (m_AddingAssemblies)
1102 { 1226 {
1103 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); 1227 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap);
1228
1104 if (!m_AddingAssemblies.ContainsKey(assembly)) { 1229 if (!m_AddingAssemblies.ContainsKey(assembly)) {
1105 m_AddingAssemblies[assembly] = 1; 1230 m_AddingAssemblies[assembly] = 1;
1106 } else { 1231 } else {
@@ -1150,7 +1275,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1150 } 1275 }
1151 catch (Exception e) 1276 catch (Exception e)
1152 { 1277 {
1153// m_log.ErrorFormat("[XEngine]: Exception when rezzing script {0}{1}", e.Message, e.StackTrace); 1278// m_log.ErrorFormat(
1279// "[XEngine]: Exception when rezzing script with item ID {0}, {1}{2}",
1280// itemID, e.Message, e.StackTrace);
1154 1281
1155 // try 1282 // try
1156 // { 1283 // {
@@ -1229,13 +1356,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1229 sandbox = AppDomain.CurrentDomain; 1356 sandbox = AppDomain.CurrentDomain;
1230 } 1357 }
1231 1358
1232 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1359 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
1233 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1360 return false;
1234 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1235 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1236 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1237 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1238 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1239 1361
1240 m_AppDomains[appDomain] = sandbox; 1362 m_AppDomains[appDomain] = sandbox;
1241 1363
@@ -1256,12 +1378,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1256 m_DomainScripts[appDomain].Add(itemID); 1378 m_DomainScripts[appDomain].Add(itemID);
1257 1379
1258 instance = new ScriptInstance(this, part, 1380 instance = new ScriptInstance(this, part,
1259 itemID, assetID, assembly, 1381 item,
1260 m_AppDomains[appDomain], 1382 startParam, postOnRez,
1261 part.ParentGroup.RootPart.Name, 1383 m_MaxScriptQueue);
1262 item.Name, startParam, postOnRez,
1263 stateSource, m_MaxScriptQueue);
1264 1384
1385 instance.Load(m_AppDomains[appDomain], assembly, stateSource);
1265// m_log.DebugFormat( 1386// m_log.DebugFormat(
1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1387// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1388// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
@@ -1347,9 +1468,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1347 lockScriptsForWrite(false); 1468 lockScriptsForWrite(false);
1348 instance.ClearQueue(); 1469 instance.ClearQueue();
1349 1470
1350 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1471 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1351 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1352 instance.Stop(1000);
1353 1472
1354// bool objectRemoved = false; 1473// bool objectRemoved = false;
1355 1474
@@ -1477,7 +1596,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1477 m_MaxScriptQueue = maxScriptQueue; 1596 m_MaxScriptQueue = maxScriptQueue;
1478 1597
1479 STPStartInfo startInfo = new STPStartInfo(); 1598 STPStartInfo startInfo = new STPStartInfo();
1480 startInfo.IdleTimeout = idleTimeout*1000; // convert to seconds as stated in .ini 1599 startInfo.ThreadPoolName = "XEngine";
1600 startInfo.IdleTimeout = idleTimeout * 1000; // convert to seconds as stated in .ini
1481 startInfo.MaxWorkerThreads = maxThreads; 1601 startInfo.MaxWorkerThreads = maxThreads;
1482 startInfo.MinWorkerThreads = minThreads; 1602 startInfo.MinWorkerThreads = minThreads;
1483 startInfo.ThreadPriority = threadPriority;; 1603 startInfo.ThreadPriority = threadPriority;;
@@ -1504,8 +1624,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 /// <returns></returns> 1624 /// <returns></returns>
1505 private object ProcessEventHandler(object parms) 1625 private object ProcessEventHandler(object parms)
1506 { 1626 {
1507 CultureInfo USCulture = new CultureInfo("en-US"); 1627 Culture.SetCurrentCulture();
1508 Thread.CurrentThread.CurrentCulture = USCulture;
1509 1628
1510 IScriptInstance instance = (ScriptInstance) parms; 1629 IScriptInstance instance = (ScriptInstance) parms;
1511 1630
@@ -1693,7 +1812,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1693 { 1812 {
1694 IScriptInstance instance = GetInstance(itemID); 1813 IScriptInstance instance = GetInstance(itemID);
1695 if (instance != null) 1814 if (instance != null)
1696 instance.ResetScript(); 1815 instance.ResetScript(m_WaitForEventCompletionOnScriptStop);
1697 } 1816 }
1698 1817
1699 public void StartScript(UUID itemID) 1818 public void StartScript(UUID itemID)
@@ -1708,14 +1827,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1708 public void StopScript(UUID itemID) 1827 public void StopScript(UUID itemID)
1709 { 1828 {
1710 IScriptInstance instance = GetInstance(itemID); 1829 IScriptInstance instance = GetInstance(itemID);
1830
1711 if (instance != null) 1831 if (instance != null)
1712 { 1832 {
1713 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1833 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1714 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1715 instance.Stop(1000);
1716 } 1834 }
1717 else 1835 else
1718 { 1836 {
1837// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name);
1719 m_runFlags.AddOrUpdate(itemID, false, 240); 1838 m_runFlags.AddOrUpdate(itemID, false, 240);
1720 } 1839 }
1721 } 1840 }