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.cs73
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs478
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs69
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs90
-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/Implementation/Properties/AssemblyInfo.cs4
-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/Api/Runtime/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs147
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs73
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs4
-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/Properties/AssemblyInfo.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs256
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs513
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs29
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs250
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs270
-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.cs18
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs23
-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/Properties/AssemblyInfo.cs4
-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.cs271
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs6
48 files changed, 2535 insertions, 566 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..35ae44c 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
@@ -50,7 +52,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
50 { 52 {
51 bool Cancel(); 53 bool Cancel();
52 void Abort(); 54 void Abort();
53 bool Wait(TimeSpan t); 55
56 /// <summary>
57 /// Wait for the work item to complete.
58 /// </summary>
59 /// <param name='t'>The number of milliseconds to wait. Must be >= -1 (Timeout.Infinite).</param>
60 bool Wait(int t);
54 } 61 }
55 62
56 /// <summary> 63 /// <summary>
@@ -59,6 +66,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
59 public interface IScriptInstance 66 public interface IScriptInstance
60 { 67 {
61 /// <summary> 68 /// <summary>
69 /// Debug level for this script instance.
70 /// </summary>
71 /// <remarks>
72 /// Level == 0, no extra data is logged.
73 /// Level >= 1, state changes are logged.
74 /// Level >= 2, event firing is logged.
75 /// <value>
76 /// The debug level.
77 /// </value>
78 int DebugLevel { get; set; }
79
80 /// <summary>
62 /// Is the script currently running? 81 /// Is the script currently running?
63 /// </summary> 82 /// </summary>
64 bool Running { get; set; } 83 bool Running { get; set; }
@@ -93,6 +112,11 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
93 /// </summary> 112 /// </summary>
94 long MeasurementPeriodExecutionTime { get; } 113 long MeasurementPeriodExecutionTime { get; }
95 114
115 /// <summary>
116 /// Scene part in which this script instance is contained.
117 /// </summary>
118 SceneObjectPart Part { get; }
119
96 IScriptEngine Engine { get; } 120 IScriptEngine Engine { get; }
97 UUID AppDomain { get; set; } 121 UUID AppDomain { get; set; }
98 string PrimName { get; } 122 string PrimName { get; }
@@ -112,8 +136,24 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
112 136
113 uint LocalID { get; } 137 uint LocalID { get; }
114 UUID AssetID { get; } 138 UUID AssetID { get; }
139
140 /// <summary>
141 /// Inventory item containing the script used.
142 /// </summary>
143 TaskInventoryItem ScriptTask { get; }
144
115 Queue EventQueue { get; } 145 Queue EventQueue { get; }
116 146
147 /// <summary>
148 /// Number of events queued for processing.
149 /// </summary>
150 long EventsQueued { get; }
151
152 /// <summary>
153 /// Number of events processed by this script instance.
154 /// </summary>
155 long EventsProcessed { get; }
156
117 void ClearQueue(); 157 void ClearQueue();
118 int StartParam { get; set; } 158 int StartParam { get; set; }
119 159
@@ -125,7 +165,13 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
125 /// <summary> 165 /// <summary>
126 /// Stop the script instance. 166 /// Stop the script instance.
127 /// </summary> 167 /// </summary>
168 /// <remarks>
169 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
170 /// there is a danger that it will self-abort and not complete the reset.
171 /// </remarks>
128 /// <param name="timeout"></param> 172 /// <param name="timeout"></param>
173 /// How many milliseconds we will wait for an existing script event to finish before
174 /// forcibly aborting that event.
129 /// <returns>true if the script was successfully stopped, false otherwise</returns> 175 /// <returns>true if the script was successfully stopped, false otherwise</returns>
130 bool Stop(int timeout); 176 bool Stop(int timeout);
131 177
@@ -147,8 +193,31 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
147 object EventProcessor(); 193 object EventProcessor();
148 194
149 int EventTime(); 195 int EventTime();
150 void ResetScript(); 196
197 /// <summary>
198 /// Reset the script.
199 /// </summary>
200 /// <remarks>
201 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
202 /// there is a danger that it will self-abort and not complete the reset. Such a thread must call
203 /// ApiResetScript() instead.
204 /// </remarks>
205 /// <param name='timeout'>
206 /// How many milliseconds we will wait for an existing script event to finish before
207 /// forcibly aborting that event prior to script reset.
208 /// </param>
209 void ResetScript(int timeout);
210
211 /// <summary>
212 /// Reset the script.
213 /// </summary>
214 /// <remarks>
215 /// This must not be called by any thread other than the one executing the scripts current event. This is
216 /// because there is no wait or abort logic if another thread is in the middle of processing a script event.
217 /// Such an external thread should use ResetScript() instead.
218 /// </remarks>
151 void ApiResetScript(); 219 void ApiResetScript();
220
152 Dictionary<string, object> GetVars(); 221 Dictionary<string, object> GetVars();
153 void SetVars(Dictionary<string, object> vars); 222 void SetVars(Dictionary<string, object> vars);
154 DetectParams GetDetectParams(int idx); 223 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 7be64eb..4a24d22 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -48,6 +48,7 @@ using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Scenes.Serialization; 49using OpenSim.Region.Framework.Scenes.Serialization;
50using OpenSim.Region.Framework.Scenes.Animation; 50using OpenSim.Region.Framework.Scenes.Animation;
51using OpenSim.Region.Framework.Scenes.Scripting;
51using OpenSim.Region.Physics.Manager; 52using OpenSim.Region.Physics.Manager;
52using OpenSim.Region.ScriptEngine.Shared; 53using OpenSim.Region.ScriptEngine.Shared;
53using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 54using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
@@ -87,10 +88,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
87 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 88 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
88 { 89 {
89 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 90 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
91
90 protected IScriptEngine m_ScriptEngine; 92 protected IScriptEngine m_ScriptEngine;
91 protected SceneObjectPart m_host; 93 protected SceneObjectPart m_host;
92 94
93 /// <summary> 95 /// <summary>
96 /// Used for script sleeps when we are using co-operative script termination.
97 /// </summary>
98 /// <remarks>null if co-operative script termination is not active</remarks>
99 WaitHandle m_coopSleepHandle;
100
101 /// <summary>
94 /// The item that hosts this script 102 /// The item that hosts this script
95 /// </summary> 103 /// </summary>
96 protected TaskInventoryItem m_item; 104 protected TaskInventoryItem m_item;
@@ -100,6 +108,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
100 protected float m_ScriptDelayFactor = 1.0f; 108 protected float m_ScriptDelayFactor = 1.0f;
101 protected float m_ScriptDistanceFactor = 1.0f; 109 protected float m_ScriptDistanceFactor = 1.0f;
102 protected float m_MinTimerInterval = 0.5f; 110 protected float m_MinTimerInterval = 0.5f;
111 protected float m_recoilScaleFactor = 0.0f;
103 112
104 protected DateTime m_timer = DateTime.Now; 113 protected DateTime m_timer = DateTime.Now;
105 protected bool m_waitingForScriptAnswer = false; 114 protected bool m_waitingForScriptAnswer = false;
@@ -141,33 +150,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 {"TURNRIGHT", "Turning Right"} 150 {"TURNRIGHT", "Turning Right"}
142 }; 151 };
143 152
144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 153 public void Initialize(
154 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
145 { 155 {
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; 156 m_lastSayShoutCheck = DateTime.UtcNow;
153 157
154 m_ScriptEngine = ScriptEngine; 158 m_ScriptEngine = scriptEngine;
155 m_host = host; 159 m_host = host;
156 m_item = item; 160 m_item = item;
157 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 161 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
162 m_coopSleepHandle = coopSleepHandle;
158 163
159 LoadLimits(); // read script limits from config. 164 LoadConfig();
160 165
161 m_TransferModule = 166 m_TransferModule =
162 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 167 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
163 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 168 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
164 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); 169 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
165 170
166 AsyncCommands = new AsyncCommandManager(ScriptEngine); 171 AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
167 } 172 }
168 173
169 /* load configuration items that affect script, object and run-time behavior. */ 174 /// <summary>
170 private void LoadLimits() 175 /// Load configuration items that affect script, object and run-time behavior. */
176 /// </summary>
177 private void LoadConfig()
171 { 178 {
172 m_ScriptDelayFactor = 179 m_ScriptDelayFactor =
173 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 180 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -181,12 +188,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
181 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255); 188 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
182 if (m_notecardLineReadCharsMax > 65535) 189 if (m_notecardLineReadCharsMax > 65535)
183 m_notecardLineReadCharsMax = 65535; 190 m_notecardLineReadCharsMax = 65535;
191
184 // load limits for particular subsystems. 192 // load limits for particular subsystems.
185 IConfig SMTPConfig; 193 IConfig SMTPConfig;
186 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) { 194 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) {
187 // there's an smtp config, so load in the snooze time. 195 // there's an smtp config, so load in the snooze time.
188 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); 196 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
189 } 197 }
198
199 // Rezzing an object with a velocity can create recoil. This feature seems to have been
200 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
201 // it by this factor. May be zero to turn off recoil all together.
202 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
190 } 203 }
191 204
192 public override Object InitializeLifetimeService() 205 public override Object InitializeLifetimeService()
@@ -207,7 +220,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
207 delay = (int)((float)delay * m_ScriptDelayFactor); 220 delay = (int)((float)delay * m_ScriptDelayFactor);
208 if (delay == 0) 221 if (delay == 0)
209 return; 222 return;
210 System.Threading.Thread.Sleep(delay); 223
224 Sleep(delay);
225 }
226
227 protected virtual void Sleep(int delay)
228 {
229 if (m_coopSleepHandle == null)
230 System.Threading.Thread.Sleep(delay);
231 else
232 CheckForCoopTermination(delay);
233 }
234
235 /// <summary>
236 /// Check for co-operative termination.
237 /// </summary>
238 /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param>
239 protected virtual void CheckForCoopTermination(int delay)
240 {
241 if (m_coopSleepHandle.WaitOne(delay))
242 throw new ScriptCoopStopException();
211 } 243 }
212 244
213 public Scene World 245 public Scene World
@@ -392,79 +424,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
392 } 424 }
393 } 425 }
394 426
395 protected UUID InventoryKey(string name, int type)
396 {
397 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
398
399 if (item != null && item.Type == type)
400 return item.AssetID;
401 else
402 return UUID.Zero;
403 }
404
405 /// <summary>
406 /// accepts a valid UUID, -or- a name of an inventory item.
407 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
408 /// in prim inventory.
409 /// </summary>
410 /// <param name="k"></param>
411 /// <returns></returns>
412 protected UUID KeyOrName(string k)
413 {
414 UUID key;
415
416 // if we can parse the string as a key, use it.
417 // else try to locate the name in inventory of object. found returns key,
418 // not found returns UUID.Zero
419 if (!UUID.TryParse(k, out key))
420 {
421 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
422
423 if (item != null)
424 key = item.AssetID;
425 else
426 key = UUID.Zero;
427 }
428
429 return key;
430 }
431
432 /// <summary>
433 /// Return the UUID of the asset matching the specified key or name
434 /// and asset type.
435 /// </summary>
436 /// <param name="k"></param>
437 /// <param name="type"></param>
438 /// <returns></returns>
439 protected UUID KeyOrName(string k, AssetType type)
440 {
441 UUID key;
442
443 if (!UUID.TryParse(k, out key))
444 {
445 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
446 if (item != null && item.Type == (int)type)
447 key = item.AssetID;
448 }
449 else
450 {
451 lock (m_host.TaskInventory)
452 {
453 foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory)
454 {
455 if (item.Value.Type == (int)type && item.Value.Name == k)
456 {
457 key = item.Value.ItemID;
458 break;
459 }
460 }
461 }
462 }
463
464
465 return key;
466 }
467
468 //These are the implementations of the various ll-functions used by the LSL scripts. 427 //These are the implementations of the various ll-functions used by the LSL scripts.
469 public LSL_Float llSin(double f) 428 public LSL_Float llSin(double f)
470 { 429 {
@@ -1483,19 +1442,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1483 return 0; 1442 return 0;
1484 1443
1485 case ScriptBaseClass.STATUS_ROTATE_X: 1444 case ScriptBaseClass.STATUS_ROTATE_X:
1486 if (m_host.GetAxisRotation(2) == 2) 1445 // if (m_host.GetAxisRotation(2) != 0)
1446 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
1487 return 1; 1447 return 1;
1488 else 1448 else
1489 return 0; 1449 return 0;
1490 1450
1491 case ScriptBaseClass.STATUS_ROTATE_Y: 1451 case ScriptBaseClass.STATUS_ROTATE_Y:
1492 if (m_host.GetAxisRotation(4) == 4) 1452 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
1493 return 1; 1453 return 1;
1494 else 1454 else
1495 return 0; 1455 return 0;
1496 1456
1497 case ScriptBaseClass.STATUS_ROTATE_Z: 1457 case ScriptBaseClass.STATUS_ROTATE_Z:
1498 if (m_host.GetAxisRotation(8) == 8) 1458 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
1499 return 1; 1459 return 1;
1500 else 1460 else
1501 return 0; 1461 return 0;
@@ -1875,10 +1835,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1875 part.Shape.FlexiForceX = (float)Force.x; 1835 part.Shape.FlexiForceX = (float)Force.x;
1876 part.Shape.FlexiForceY = (float)Force.y; 1836 part.Shape.FlexiForceY = (float)Force.y;
1877 part.Shape.FlexiForceZ = (float)Force.z; 1837 part.Shape.FlexiForceZ = (float)Force.z;
1878 part.Shape.PathCurve = 0x80; 1838 part.Shape.PathCurve = (byte)Extrusion.Flexible;
1879 part.ParentGroup.HasGroupChanged = true; 1839 }
1880 part.ScheduleFullUpdate(); 1840 else
1841 {
1842 // Other values not set, they do not seem to be sent to the viewer
1843 // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off
1844 part.Shape.PathCurve = (byte)Extrusion.Straight;
1845 part.Shape.FlexiEntry = false;
1881 } 1846 }
1847 part.ParentGroup.HasGroupChanged = true;
1848 part.ScheduleFullUpdate();
1882 } 1849 }
1883 1850
1884 /// <summary> 1851 /// <summary>
@@ -1996,7 +1963,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1996 1963
1997 UUID textureID = new UUID(); 1964 UUID textureID = new UUID();
1998 1965
1999 textureID = InventoryKey(texture, (int)AssetType.Texture); 1966 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
2000 if (textureID == UUID.Zero) 1967 if (textureID == UUID.Zero)
2001 { 1968 {
2002 if (!UUID.TryParse(texture, out textureID)) 1969 if (!UUID.TryParse(texture, out textureID))
@@ -2712,7 +2679,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2712 if (m_SoundModule != null) 2679 if (m_SoundModule != null)
2713 { 2680 {
2714 m_SoundModule.SendSound(m_host.UUID, 2681 m_SoundModule.SendSound(m_host.UUID,
2715 KeyOrName(sound, AssetType.Sound), volume, false, 0, 2682 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
2716 0, false, false); 2683 0, false, false);
2717 } 2684 }
2718 } 2685 }
@@ -2722,7 +2689,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2722 m_host.AddScriptLPS(1); 2689 m_host.AddScriptLPS(1);
2723 if (m_SoundModule != null) 2690 if (m_SoundModule != null)
2724 { 2691 {
2725 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2692 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2726 volume, 20, false); 2693 volume, 20, false);
2727 } 2694 }
2728 } 2695 }
@@ -2732,7 +2699,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2732 m_host.AddScriptLPS(1); 2699 m_host.AddScriptLPS(1);
2733 if (m_SoundModule != null) 2700 if (m_SoundModule != null)
2734 { 2701 {
2735 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2702 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2736 volume, 20, true); 2703 volume, 20, true);
2737 } 2704 }
2738 } 2705 }
@@ -2754,7 +2721,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2754 if (m_SoundModule != null) 2721 if (m_SoundModule != null)
2755 { 2722 {
2756 m_SoundModule.SendSound(m_host.UUID, 2723 m_SoundModule.SendSound(m_host.UUID,
2757 KeyOrName(sound, AssetType.Sound), volume, false, 0, 2724 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
2758 0, true, false); 2725 0, true, false);
2759 } 2726 }
2760 } 2727 }
@@ -2766,7 +2733,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2766 if (m_SoundModule != null) 2733 if (m_SoundModule != null)
2767 { 2734 {
2768 m_SoundModule.SendSound(m_host.UUID, 2735 m_SoundModule.SendSound(m_host.UUID,
2769 KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, 2736 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0,
2770 false, false); 2737 false, false);
2771 } 2738 }
2772 } 2739 }
@@ -2783,7 +2750,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2783 { 2750 {
2784 m_host.AddScriptLPS(1); 2751 m_host.AddScriptLPS(1);
2785 if (m_SoundModule != null) 2752 if (m_SoundModule != null)
2786 m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); 2753 m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
2787 ScriptSleep(1000); 2754 ScriptSleep(1000);
2788 } 2755 }
2789 2756
@@ -3141,11 +3108,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3141 3108
3142 PhysicsActor pa = new_group.RootPart.PhysActor; 3109 PhysicsActor pa = new_group.RootPart.PhysActor;
3143 3110
3111 //Recoil.
3144 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3112 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3145 { 3113 {
3146 float groupmass = new_group.GetMass(); 3114 float groupmass = new_group.GetMass();
3147 vel *= -groupmass; 3115 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3148 llApplyImpulse(vel, 0); 3116 if (recoil != Vector3.Zero)
3117 {
3118 llApplyImpulse(recoil, 0);
3119 }
3149 } 3120 }
3150 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3121 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3151 return; 3122 return;
@@ -3220,7 +3191,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3220 { 3191 {
3221// m_log.Info("llSleep snoozing " + sec + "s."); 3192// m_log.Info("llSleep snoozing " + sec + "s.");
3222 m_host.AddScriptLPS(1); 3193 m_host.AddScriptLPS(1);
3223 Thread.Sleep((int)(sec * 1000)); 3194
3195 Sleep((int)(sec * 1000));
3224 } 3196 }
3225 3197
3226 public LSL_Float llGetMass() 3198 public LSL_Float llGetMass()
@@ -3322,7 +3294,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3322 /// <summary> 3294 /// <summary>
3323 /// Attach the object containing this script to the avatar that owns it. 3295 /// Attach the object containing this script to the avatar that owns it.
3324 /// </summary> 3296 /// </summary>
3325 /// <param name='attachment'>The attachment point (e.g. ATTACH_CHEST)</param> 3297 /// <param name='attachmentPoint'>
3298 /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>)
3299 /// </param>
3326 /// <returns>true if the attach suceeded, false if it did not</returns> 3300 /// <returns>true if the attach suceeded, false if it did not</returns>
3327 public bool AttachToAvatar(int attachmentPoint) 3301 public bool AttachToAvatar(int attachmentPoint)
3328 { 3302 {
@@ -3653,7 +3627,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3653 if (presence != null) 3627 if (presence != null)
3654 { 3628 {
3655 // Do NOT try to parse UUID, animations cannot be triggered by ID 3629 // Do NOT try to parse UUID, animations cannot be triggered by ID
3656 UUID animID = InventoryKey(anim, (int)AssetType.Animation); 3630 UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
3657 if (animID == UUID.Zero) 3631 if (animID == UUID.Zero)
3658 presence.Animator.AddAnimation(anim, m_host.UUID); 3632 presence.Animator.AddAnimation(anim, m_host.UUID);
3659 else 3633 else
@@ -3675,12 +3649,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3675 3649
3676 if (presence != null) 3650 if (presence != null)
3677 { 3651 {
3678 UUID animID = KeyOrName(anim); 3652 UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim);
3679 3653
3680 if (animID == UUID.Zero) 3654 if (animID == UUID.Zero)
3681 presence.Animator.RemoveAnimation(anim); 3655 presence.Animator.RemoveAnimation(anim);
3682 else 3656 else
3683 presence.Animator.RemoveAnimation(animID); 3657 presence.Animator.RemoveAnimation(animID, true);
3684 } 3658 }
3685 } 3659 }
3686 } 3660 }
@@ -3753,21 +3727,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3753 } 3727 }
3754 else 3728 else
3755 { 3729 {
3756 bool sitting = false; 3730 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 { 3731 {
3772 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3732 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3773 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3733 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
@@ -3809,7 +3769,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3809 INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); 3769 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
3810 if (npcModule != null && npcModule.IsNPC(agentID, World)) 3770 if (npcModule != null && npcModule.IsNPC(agentID, World))
3811 { 3771 {
3812 if (agentID == m_host.ParentGroup.OwnerID || npcModule.GetOwner(agentID) == m_host.ParentGroup.OwnerID) 3772 if (npcModule.CheckPermissions(agentID, m_host.OwnerID))
3813 { 3773 {
3814 lock (m_host.TaskInventory) 3774 lock (m_host.TaskInventory)
3815 { 3775 {
@@ -4184,62 +4144,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4184 public LSL_String llGetLinkName(int linknum) 4144 public LSL_String llGetLinkName(int linknum)
4185 { 4145 {
4186 m_host.AddScriptLPS(1); 4146 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 4147
4191 // parse for sitting avatare-names 4148 if (linknum < 0)
4192 List<String> nametable = new List<String>();
4193 World.ForEachRootScenePresence(delegate(ScenePresence presence)
4194 { 4149 {
4195 SceneObjectPart sitPart = presence.ParentPart; 4150 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; 4151 return m_host.Name;
4209 // LinkNumber > of Real PrimSet = AvatarName 4152 else
4210 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims) 4153 return ScriptBaseClass.NULL_KEY;
4211 return nametable[totalprims - linknum];
4212 } 4154 }
4213 4155
4214 // Single prim 4156 int actualPrimCount = m_host.ParentGroup.PrimCount;
4215 if (m_host.LinkNum == 0) 4157 List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars();
4158 int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count;
4159
4160 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
4161 // prim that has any avatars sat upon it (in which case the root prim is link 1).
4162 if (linknum == 0)
4216 { 4163 {
4217 if (linknum == 0 || linknum == ScriptBaseClass.LINK_ROOT) 4164 if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
4218 return m_host.Name; 4165 return m_host.Name;
4219 else
4220 return UUID.Zero.ToString();
4221 }
4222 4166
4223 // Link set 4167 return ScriptBaseClass.NULL_KEY;
4224 SceneObjectPart part = null; 4168 }
4225 if (m_host.LinkNum == 1) // this is the Root prim 4169 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
4170 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
4171 else if (linknum == 1 && actualPrimCount == 1)
4226 { 4172 {
4227 if (linknum < 0) 4173 if (sittingAvatarIds.Count > 0)
4228 part = m_host.ParentGroup.GetLinkNumPart(2); 4174 return m_host.ParentGroup.RootPart.Name;
4229 else 4175 else
4230 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4176 return ScriptBaseClass.NULL_KEY;
4231 } 4177 }
4232 else // this is a child prim 4178 else if (linknum <= adjustedPrimCount)
4233 { 4179 {
4234 if (linknum < 2) 4180 if (linknum <= actualPrimCount)
4235 part = m_host.ParentGroup.GetLinkNumPart(1); 4181 {
4182 return m_host.ParentGroup.GetLinkNumPart(linknum).Name;
4183 }
4236 else 4184 else
4237 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4185 {
4186 ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]);
4187 if (sp != null)
4188 return sp.Name;
4189 else
4190 return ScriptBaseClass.NULL_KEY;
4191 }
4238 } 4192 }
4239 if (part != null)
4240 return part.Name;
4241 else 4193 else
4242 return UUID.Zero.ToString(); 4194 {
4195 return ScriptBaseClass.NULL_KEY;
4196 }
4243 } 4197 }
4244 4198
4245 public LSL_Integer llGetInventoryNumber(int type) 4199 public LSL_Integer llGetInventoryNumber(int type)
@@ -4691,7 +4645,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4691 4645
4692 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) 4646 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt)
4693 { 4647 {
4694 UUID assetID = KeyOrName(destination); 4648 UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination);
4695 4649
4696 // The destinaion is not an asset ID and also doesn't name a landmark. 4650 // The destinaion is not an asset ID and also doesn't name a landmark.
4697 // Use it as a sim name 4651 // Use it as a sim name
@@ -4764,7 +4718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4764 return; 4718 return;
4765 } 4719 }
4766 // TODO: Parameter check logic required. 4720 // TODO: Parameter check logic required.
4767 m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); 4721 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4768 m_host.CollisionSoundVolume = (float)impact_volume; 4722 m_host.CollisionSoundVolume = (float)impact_volume;
4769 m_host.CollisionSoundType = 1; 4723 m_host.CollisionSoundType = 1;
4770 } 4724 }
@@ -4934,6 +4888,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4934 } 4888 }
4935 } 4889 }
4936 } 4890 }
4891
4937 if (pushAllowed) 4892 if (pushAllowed)
4938 { 4893 {
4939 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4894 float distance = (PusheePos - m_host.AbsolutePosition).Length();
@@ -4963,17 +4918,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4963 applied_linear_impulse *= scaling_factor; 4918 applied_linear_impulse *= scaling_factor;
4964 4919
4965 } 4920 }
4921
4966 if (pusheeIsAvatar) 4922 if (pusheeIsAvatar)
4967 { 4923 {
4968 if (pusheeav != null) 4924 if (pusheeav != null)
4969 { 4925 {
4970 if (pusheeav.PhysicsActor != null) 4926 PhysicsActor pa = pusheeav.PhysicsActor;
4927
4928 if (pa != null)
4971 { 4929 {
4972 if (local != 0) 4930 if (local != 0)
4973 { 4931 {
4974 applied_linear_impulse *= m_host.GetWorldRotation(); 4932 applied_linear_impulse *= m_host.GetWorldRotation();
4975 } 4933 }
4976 pusheeav.PhysicsActor.AddForce(applied_linear_impulse, true); 4934
4935 pa.AddForce(applied_linear_impulse, true);
4977 } 4936 }
4978 } 4937 }
4979 } 4938 }
@@ -5851,9 +5810,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5851 } 5810 }
5852 5811
5853 /// <summary> 5812 /// <summary>
5854 /// Insert the list identified by <src> into the 5813 /// Insert the list identified by <paramref name="src"/> into the
5855 /// list designated by <dest> such that the first 5814 /// list designated by <paramref name="dest"/> such that the first
5856 /// new element has the index specified by <index> 5815 /// new element has the index specified by <paramref name="index"/>
5857 /// </summary> 5816 /// </summary>
5858 5817
5859 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) 5818 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
@@ -6219,13 +6178,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6219 if (parcelOwned && land.LandData.OwnerID == id || 6178 if (parcelOwned && land.LandData.OwnerID == id ||
6220 parcel && land.LandData.GlobalID == id) 6179 parcel && land.LandData.GlobalID == id)
6221 { 6180 {
6222 result.Add(ssp.UUID.ToString()); 6181 result.Add(new LSL_Key(ssp.UUID.ToString()));
6223 } 6182 }
6224 } 6183 }
6225 } 6184 }
6226 else 6185 else
6227 { 6186 {
6228 result.Add(ssp.UUID.ToString()); 6187 result.Add(new LSL_Key(ssp.UUID.ToString()));
6229 } 6188 }
6230 } 6189 }
6231 // Maximum of 100 results 6190 // Maximum of 100 results
@@ -6329,7 +6288,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6329 if (m_SoundModule != null) 6288 if (m_SoundModule != null)
6330 { 6289 {
6331 m_SoundModule.TriggerSoundLimited(m_host.UUID, 6290 m_SoundModule.TriggerSoundLimited(m_host.UUID,
6332 KeyOrName(sound, AssetType.Sound), volume, 6291 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume,
6333 bottom_south_west, top_north_east); 6292 bottom_south_west, top_north_east);
6334 } 6293 }
6335 } 6294 }
@@ -6686,6 +6645,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6686 ps.BurstSpeedMax = 1.0f; 6645 ps.BurstSpeedMax = 1.0f;
6687 ps.BurstRate = 0.1f; 6646 ps.BurstRate = 0.1f;
6688 ps.PartMaxAge = 10.0f; 6647 ps.PartMaxAge = 10.0f;
6648 ps.BurstPartCount = 1;
6689 return ps; 6649 return ps;
6690 } 6650 }
6691 6651
@@ -6707,10 +6667,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6707 SetParticleSystem(m_host, rules); 6667 SetParticleSystem(m_host, rules);
6708 } 6668 }
6709 6669
6710 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) 6670 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6711 { 6671 {
6712
6713
6714 if (rules.Length == 0) 6672 if (rules.Length == 0)
6715 { 6673 {
6716 part.RemoveParticleSystem(); 6674 part.RemoveParticleSystem();
@@ -6801,7 +6759,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6801 break; 6759 break;
6802 6760
6803 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: 6761 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
6804 prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1)); 6762 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
6805 break; 6763 break;
6806 6764
6807 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: 6765 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
@@ -7373,6 +7331,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7373 public void llCloseRemoteDataChannel(string channel) 7331 public void llCloseRemoteDataChannel(string channel)
7374 { 7332 {
7375 m_host.AddScriptLPS(1); 7333 m_host.AddScriptLPS(1);
7334
7335 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
7336 if (xmlRpcRouter != null)
7337 {
7338 xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID);
7339 }
7340
7376 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7341 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7377 if (xmlrpcMod != null) 7342 if (xmlrpcMod != null)
7378 xmlrpcMod.CloseXMLRPCChannel((UUID)channel); 7343 xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
@@ -7746,9 +7711,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7746 UUID sculptId; 7711 UUID sculptId;
7747 7712
7748 if (!UUID.TryParse(map, out sculptId)) 7713 if (!UUID.TryParse(map, out sculptId))
7749 { 7714 sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture);
7750 sculptId = InventoryKey(map, (int)AssetType.Texture);
7751 }
7752 7715
7753 if (sculptId == UUID.Zero) 7716 if (sculptId == UUID.Zero)
7754 return; 7717 return;
@@ -10238,6 +10201,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10238 return UUID.Zero.ToString(); 10201 return UUID.Zero.ToString();
10239 } 10202 }
10240 } 10203 }
10204
10241 public LSL_String llRequestURL() 10205 public LSL_String llRequestURL()
10242 { 10206 {
10243 m_host.AddScriptLPS(1); 10207 m_host.AddScriptLPS(1);
@@ -11519,6 +11483,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11519 case ScriptBaseClass.OBJECT_PHYSICS_COST: 11483 case ScriptBaseClass.OBJECT_PHYSICS_COST:
11520 ret.Add(new LSL_Float(0)); 11484 ret.Add(new LSL_Float(0));
11521 break; 11485 break;
11486 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
11487 ret.Add(new LSL_Float(0));
11488 break;
11489 case ScriptBaseClass.OBJECT_ROOT:
11490 SceneObjectPart p = av.ParentPart;
11491 if (p != null)
11492 {
11493 ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString()));
11494 }
11495 else
11496 {
11497 ret.Add(new LSL_String(id));
11498 }
11499 break;
11500 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
11501 ret.Add(new LSL_Integer(0));
11502 break;
11503 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding
11504 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR));
11505 break;
11506 case ScriptBaseClass.OBJECT_PHYSICS:
11507 ret.Add(new LSL_Integer(0));
11508 break;
11509 case ScriptBaseClass.OBJECT_PHANTOM:
11510 ret.Add(new LSL_Integer(0));
11511 break;
11512 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
11513 ret.Add(new LSL_Integer(0));
11514 break;
11522 default: 11515 default:
11523 // Invalid or unhandled constant. 11516 // Invalid or unhandled constant.
11524 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 11517 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -11610,6 +11603,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11610 // The value returned in SL for normal prims is prim count 11603 // The value returned in SL for normal prims is prim count
11611 ret.Add(new LSL_Float(obj.PhysicsCost)); 11604 ret.Add(new LSL_Float(obj.PhysicsCost));
11612 break; 11605 break;
11606 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
11607 ret.Add(new LSL_Float(0));
11608 break;
11609 case ScriptBaseClass.OBJECT_ROOT:
11610 ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString()));
11611 break;
11612 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
11613 ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint));
11614 break;
11615 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE:
11616 byte pcode = obj.Shape.PCode;
11617 if (obj.ParentGroup.AttachmentPoint != 0
11618 || pcode == (byte)PCode.Grass
11619 || pcode == (byte)PCode.Tree
11620 || pcode == (byte)PCode.NewTree)
11621 {
11622 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER));
11623 }
11624 else
11625 {
11626 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET));
11627 }
11628 break;
11629 case ScriptBaseClass.OBJECT_PHYSICS:
11630 if (obj.ParentGroup.AttachmentPoint != 0)
11631 {
11632 ret.Add(new LSL_Integer(0)); // Always false if attached
11633 }
11634 else
11635 {
11636 ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0));
11637 }
11638 break;
11639 case ScriptBaseClass.OBJECT_PHANTOM:
11640 if (obj.ParentGroup.AttachmentPoint != 0)
11641 {
11642 ret.Add(new LSL_Integer(0)); // Always false if attached
11643 }
11644 else
11645 {
11646 ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0));
11647 }
11648 break;
11649 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
11650 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0));
11651 break;
11613 default: 11652 default:
11614 // Invalid or unhandled constant. 11653 // Invalid or unhandled constant.
11615 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 11654 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -11689,14 +11728,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11689 return UUID.Zero.ToString(); 11728 return UUID.Zero.ToString();
11690 } 11729 }
11691 11730
11731 string reqIdentifier = UUID.Random().ToString();
11732
11692 // was: UUID tid = tid = AsyncCommands. 11733 // was: UUID tid = tid = AsyncCommands.
11693 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString()); 11734 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
11694 11735
11695 if (NotecardCache.IsCached(assetID)) 11736 if (NotecardCache.IsCached(assetID))
11696 { 11737 {
11697 AsyncCommands. 11738 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString());
11698 DataserverPlugin.DataserverReply(assetID.ToString(), 11739
11699 NotecardCache.GetLines(assetID).ToString());
11700 ScriptSleep(100); 11740 ScriptSleep(100);
11701 return tid.ToString(); 11741 return tid.ToString();
11702 } 11742 }
@@ -11712,9 +11752,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11712 string data = Encoding.UTF8.GetString(a.Data); 11752 string data = Encoding.UTF8.GetString(a.Data);
11713 //m_log.Debug(data); 11753 //m_log.Debug(data);
11714 NotecardCache.Cache(id, data); 11754 NotecardCache.Cache(id, data);
11715 AsyncCommands. 11755 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString());
11716 DataserverPlugin.DataserverReply(id.ToString(),
11717 NotecardCache.GetLines(id).ToString());
11718 }); 11756 });
11719 11757
11720 ScriptSleep(100); 11758 ScriptSleep(100);
@@ -11743,13 +11781,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11743 return UUID.Zero.ToString(); 11781 return UUID.Zero.ToString();
11744 } 11782 }
11745 11783
11784 string reqIdentifier = UUID.Random().ToString();
11785
11746 // was: UUID tid = tid = AsyncCommands. 11786 // was: UUID tid = tid = AsyncCommands.
11747 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString()); 11787 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
11748 11788
11749 if (NotecardCache.IsCached(assetID)) 11789 if (NotecardCache.IsCached(assetID))
11750 { 11790 {
11751 AsyncCommands.DataserverPlugin.DataserverReply(assetID.ToString(), 11791 AsyncCommands.DataserverPlugin.DataserverReply(
11752 NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); 11792 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
11793
11753 ScriptSleep(100); 11794 ScriptSleep(100);
11754 return tid.ToString(); 11795 return tid.ToString();
11755 } 11796 }
@@ -11765,8 +11806,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11765 string data = Encoding.UTF8.GetString(a.Data); 11806 string data = Encoding.UTF8.GetString(a.Data);
11766 //m_log.Debug(data); 11807 //m_log.Debug(data);
11767 NotecardCache.Cache(id, data); 11808 NotecardCache.Cache(id, data);
11768 AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), 11809 AsyncCommands.DataserverPlugin.DataserverReply(
11769 NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); 11810 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
11770 }); 11811 });
11771 11812
11772 ScriptSleep(100); 11813 ScriptSleep(100);
@@ -11993,12 +12034,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11993 radius = Math.Abs(maxY); 12034 radius = Math.Abs(maxY);
11994 if (Math.Abs(maxZ) > radius) 12035 if (Math.Abs(maxZ) > radius)
11995 radius = Math.Abs(maxZ); 12036 radius = Math.Abs(maxZ);
11996 12037 radius = radius*1.413f;
11997 Vector3 ac = group.AbsolutePosition - rayStart; 12038 Vector3 ac = group.AbsolutePosition - rayStart;
11998 Vector3 bc = group.AbsolutePosition - rayEnd; 12039 Vector3 bc = group.AbsolutePosition - rayEnd;
11999 12040
12000 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 12041 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
12001 12042
12002 // Too far off ray, don't bother 12043 // Too far off ray, don't bother
12003 if (d > radius) 12044 if (d > radius)
12004 return; 12045 return;
@@ -12008,11 +12049,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12008 if (d2 > 0) 12049 if (d2 > 0)
12009 return; 12050 return;
12010 12051
12052 ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
12011 EntityIntersection intersection = group.TestIntersection(ray, true, false); 12053 EntityIntersection intersection = group.TestIntersection(ray, true, false);
12012 // Miss. 12054 // Miss.
12013 if (!intersection.HitTF) 12055 if (!intersection.HitTF)
12014 return; 12056 return;
12015 12057
12058 Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ);
12059 Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ);
12060 //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);
12061 if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
12062 intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
12063 intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
12064 return;
12065
12016 ContactResult result = new ContactResult (); 12066 ContactResult result = new ContactResult ();
12017 result.ConsumerID = group.LocalId; 12067 result.ConsumerID = group.LocalId;
12018// result.Depth = intersection.distance; 12068// result.Depth = intersection.distance;
@@ -12228,7 +12278,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12228 if (checkNonPhysical) 12278 if (checkNonPhysical)
12229 rayfilter |= RayFilterFlags.nonphysical; 12279 rayfilter |= RayFilterFlags.nonphysical;
12230 if (detectPhantom) 12280 if (detectPhantom)
12231 rayfilter |= RayFilterFlags.LSLPhanton; 12281 rayfilter |= RayFilterFlags.LSLPhantom;
12232 12282
12233 Vector3 direction = dir * ( 1/dist); 12283 Vector3 direction = dir * ( 1/dist);
12234 12284
@@ -12286,8 +12336,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12286 if (checkPhysical || checkNonPhysical || detectPhantom) 12336 if (checkPhysical || checkNonPhysical || detectPhantom)
12287 { 12337 {
12288 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 12338 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
12289 foreach (ContactResult r in objectHits) 12339 for (int iter = 0; iter < objectHits.Length; iter++)
12290 results.Add(r); 12340 {
12341 // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
12342 objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
12343 results.Add(objectHits[iter]);
12344 }
12291 } 12345 }
12292 } 12346 }
12293 12347
@@ -13235,7 +13289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13235 13289
13236 public static void Cache(UUID assetID, string text) 13290 public static void Cache(UUID assetID, string text)
13237 { 13291 {
13238 CacheCheck(); 13292 CheckCache();
13239 13293
13240 lock (m_Notecards) 13294 lock (m_Notecards)
13241 { 13295 {
@@ -13273,7 +13327,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13273 /// Get a notecard line. 13327 /// Get a notecard line.
13274 /// </summary> 13328 /// </summary>
13275 /// <param name="assetID"></param> 13329 /// <param name="assetID"></param>
13276 /// <param name="line">Lines start at index 0</param> 13330 /// <param name="lineNumber">Lines start at index 0</param>
13277 /// <returns></returns> 13331 /// <returns></returns>
13278 public static string GetLine(UUID assetID, int lineNumber) 13332 public static string GetLine(UUID assetID, int lineNumber)
13279 { 13333 {
@@ -13302,9 +13356,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13302 /// Get a notecard line. 13356 /// Get a notecard line.
13303 /// </summary> 13357 /// </summary>
13304 /// <param name="assetID"></param> 13358 /// <param name="assetID"></param>
13305 /// <param name="line">Lines start at index 0</param> 13359 /// <param name="lineNumber">Lines start at index 0</param>
13306 /// <param name="maxLength">Maximum length of the returned line. Longer lines will be truncated</para> 13360 /// <param name="maxLength">
13307 /// <returns></returns> 13361 /// Maximum length of the returned line.
13362 /// </param>
13363 /// <returns>
13364 /// If the line length is longer than <paramref name="maxLength"/>,
13365 /// the return string will be truncated.
13366 /// </returns>
13308 public static string GetLine(UUID assetID, int lineNumber, int maxLength) 13367 public static string GetLine(UUID assetID, int lineNumber, int maxLength)
13309 { 13368 {
13310 string line = GetLine(assetID, lineNumber); 13369 string line = GetLine(assetID, lineNumber);
@@ -13315,14 +13374,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13315 return line; 13374 return line;
13316 } 13375 }
13317 13376
13318 public static void CacheCheck() 13377 public static void CheckCache()
13319 { 13378 {
13320 foreach (UUID key in new List<UUID>(m_Notecards.Keys)) 13379 lock (m_Notecards)
13321 { 13380 {
13322 Notecard nc = m_Notecards[key]; 13381 foreach (UUID key in new List<UUID>(m_Notecards.Keys))
13323 if (nc.lastRef.AddSeconds(30) < DateTime.Now) 13382 {
13324 m_Notecards.Remove(key); 13383 Notecard nc = m_Notecards[key];
13384 if (nc.lastRef.AddSeconds(30) < DateTime.Now)
13385 m_Notecards.Remove(key);
13386 }
13325 } 13387 }
13326 } 13388 }
13327 } 13389 }
13328} 13390} \ No newline at end of file
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 ee89f9d..542222e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -30,6 +30,8 @@ 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;
34using log4net;
33using OpenMetaverse; 35using OpenMetaverse;
34using Nini.Config; 36using Nini.Config;
35using OpenSim; 37using OpenSim;
@@ -55,15 +57,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
55 [Serializable] 57 [Serializable]
56 public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi 58 public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi
57 { 59 {
60// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
58 internal IScriptEngine m_ScriptEngine; 62 internal IScriptEngine m_ScriptEngine;
59 internal SceneObjectPart m_host; 63 internal SceneObjectPart m_host;
60 internal TaskInventoryItem m_item; 64 internal TaskInventoryItem m_item;
61 internal bool m_MODFunctionsEnabled = false; 65 internal bool m_MODFunctionsEnabled = false;
62 internal IScriptModuleComms m_comms = null; 66 internal IScriptModuleComms m_comms = null;
63 67
64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 68 public void Initialize(
69 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
65 { 70 {
66 m_ScriptEngine = ScriptEngine; 71 m_ScriptEngine = scriptEngine;
67 m_host = host; 72 m_host = host;
68 m_item = item; 73 m_item = item;
69 74
@@ -107,8 +112,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
107 if (message.Length > 1023) 112 if (message.Length > 1023)
108 message = message.Substring(0, 1023); 113 message = message.Substring(0, 1023);
109 114
110 World.SimChat(Utils.StringToBytes(message), 115 World.SimChat(
111 ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); 116 Utils.StringToBytes(message),
117 ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL,
118 m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
112 119
113 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 120 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
114 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); 121 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
@@ -122,6 +129,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
122 /// <returns>string result of the invocation</returns> 129 /// <returns>string result of the invocation</returns>
123 public void modInvokeN(string fname, params object[] parms) 130 public void modInvokeN(string fname, params object[] parms)
124 { 131 {
132// m_log.DebugFormat(
133// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
134// fname,
135// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
136// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
137
125 Type returntype = m_comms.LookupReturnType(fname); 138 Type returntype = m_comms.LookupReturnType(fname);
126 if (returntype != typeof(void)) 139 if (returntype != typeof(void))
127 MODError(String.Format("return type mismatch for {0}",fname)); 140 MODError(String.Format("return type mismatch for {0}",fname));
@@ -131,6 +144,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
131 144
132 public LSL_String modInvokeS(string fname, params object[] parms) 145 public LSL_String modInvokeS(string fname, params object[] parms)
133 { 146 {
147// m_log.DebugFormat(
148// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
149// fname,
150// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
151// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
152
134 Type returntype = m_comms.LookupReturnType(fname); 153 Type returntype = m_comms.LookupReturnType(fname);
135 if (returntype != typeof(string)) 154 if (returntype != typeof(string))
136 MODError(String.Format("return type mismatch for {0}",fname)); 155 MODError(String.Format("return type mismatch for {0}",fname));
@@ -141,6 +160,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 160
142 public LSL_Integer modInvokeI(string fname, params object[] parms) 161 public LSL_Integer modInvokeI(string fname, params object[] parms)
143 { 162 {
163// m_log.DebugFormat(
164// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
165// fname,
166// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
167// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
168
144 Type returntype = m_comms.LookupReturnType(fname); 169 Type returntype = m_comms.LookupReturnType(fname);
145 if (returntype != typeof(int)) 170 if (returntype != typeof(int))
146 MODError(String.Format("return type mismatch for {0}",fname)); 171 MODError(String.Format("return type mismatch for {0}",fname));
@@ -151,6 +176,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
151 176
152 public LSL_Float modInvokeF(string fname, params object[] parms) 177 public LSL_Float modInvokeF(string fname, params object[] parms)
153 { 178 {
179// m_log.DebugFormat(
180// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
181// fname,
182// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
183// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
184
154 Type returntype = m_comms.LookupReturnType(fname); 185 Type returntype = m_comms.LookupReturnType(fname);
155 if (returntype != typeof(float)) 186 if (returntype != typeof(float))
156 MODError(String.Format("return type mismatch for {0}",fname)); 187 MODError(String.Format("return type mismatch for {0}",fname));
@@ -161,6 +192,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 192
162 public LSL_Key modInvokeK(string fname, params object[] parms) 193 public LSL_Key modInvokeK(string fname, params object[] parms)
163 { 194 {
195// m_log.DebugFormat(
196// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
197// fname,
198// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
199// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
200
164 Type returntype = m_comms.LookupReturnType(fname); 201 Type returntype = m_comms.LookupReturnType(fname);
165 if (returntype != typeof(UUID)) 202 if (returntype != typeof(UUID))
166 MODError(String.Format("return type mismatch for {0}",fname)); 203 MODError(String.Format("return type mismatch for {0}",fname));
@@ -171,6 +208,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 208
172 public LSL_Vector modInvokeV(string fname, params object[] parms) 209 public LSL_Vector modInvokeV(string fname, params object[] parms)
173 { 210 {
211// m_log.DebugFormat(
212// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
213// fname,
214// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
215// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
216
174 Type returntype = m_comms.LookupReturnType(fname); 217 Type returntype = m_comms.LookupReturnType(fname);
175 if (returntype != typeof(OpenMetaverse.Vector3)) 218 if (returntype != typeof(OpenMetaverse.Vector3))
176 MODError(String.Format("return type mismatch for {0}",fname)); 219 MODError(String.Format("return type mismatch for {0}",fname));
@@ -181,6 +224,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
181 224
182 public LSL_Rotation modInvokeR(string fname, params object[] parms) 225 public LSL_Rotation modInvokeR(string fname, params object[] parms)
183 { 226 {
227// m_log.DebugFormat(
228// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
229// fname,
230// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
231// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
232
184 Type returntype = m_comms.LookupReturnType(fname); 233 Type returntype = m_comms.LookupReturnType(fname);
185 if (returntype != typeof(OpenMetaverse.Quaternion)) 234 if (returntype != typeof(OpenMetaverse.Quaternion))
186 MODError(String.Format("return type mismatch for {0}",fname)); 235 MODError(String.Format("return type mismatch for {0}",fname));
@@ -191,6 +240,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
191 240
192 public LSL_List modInvokeL(string fname, params object[] parms) 241 public LSL_List modInvokeL(string fname, params object[] parms)
193 { 242 {
243// m_log.DebugFormat(
244// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
245// fname,
246// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
247// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
248
194 Type returntype = m_comms.LookupReturnType(fname); 249 Type returntype = m_comms.LookupReturnType(fname);
195 if (returntype != typeof(object[])) 250 if (returntype != typeof(object[]))
196 MODError(String.Format("return type mismatch for {0}",fname)); 251 MODError(String.Format("return type mismatch for {0}",fname));
@@ -248,6 +303,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
248 return ""; 303 return "";
249 } 304 }
250 305
306// m_log.DebugFormat(
307// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
308// fname,
309// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
310// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
311
251 Type[] signature = m_comms.LookupTypeSignature(fname); 312 Type[] signature = m_comms.LookupTypeSignature(fname);
252 if (signature.Length != parms.Length) 313 if (signature.Length != parms.Length)
253 MODError(String.Format("wrong number of parameters to function {0}",fname)); 314 MODError(String.Format("wrong number of parameters to function {0}",fname));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 8aac33f..e87bb04 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
@@ -2136,9 +2172,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2136 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI"); 2172 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI");
2137 m_host.AddScriptLPS(1); 2173 m_host.AddScriptLPS(1);
2138 2174
2139 string HomeURI = String.Empty;
2140 IConfigSource config = m_ScriptEngine.ConfigSource; 2175 IConfigSource config = m_ScriptEngine.ConfigSource;
2176 string HomeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",
2177 new string[] { "Startup", "Hypergrid" }, String.Empty);
2178
2179 if (!string.IsNullOrEmpty(HomeURI))
2180 return HomeURI;
2141 2181
2182 // Legacy. Remove soon!
2142 if (config.Configs["LoginService"] != null) 2183 if (config.Configs["LoginService"] != null)
2143 HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI); 2184 HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI);
2144 2185
@@ -2153,9 +2194,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2153 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI"); 2194 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI");
2154 m_host.AddScriptLPS(1); 2195 m_host.AddScriptLPS(1);
2155 2196
2156 string gatekeeperURI = String.Empty;
2157 IConfigSource config = m_ScriptEngine.ConfigSource; 2197 IConfigSource config = m_ScriptEngine.ConfigSource;
2198 string gatekeeperURI = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
2199 new string[] { "Startup", "Hypergrid" }, String.Empty);
2200
2201 if (!string.IsNullOrEmpty(gatekeeperURI))
2202 return gatekeeperURI;
2158 2203
2204 // Legacy. Remove soon!
2159 if (config.Configs["GridService"] != null) 2205 if (config.Configs["GridService"] != null)
2160 gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI); 2206 gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI);
2161 2207
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/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
index d173db0..6d218a6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 8aa1249..a652cb8 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 Hashtable osParseJSON(string JSON); 263 Hashtable osParseJSON(string JSON);
263 264
264 void osMessageObject(key objectUUID,string message); 265 void osMessageObject(key objectUUID,string message);
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 95dff18..b63773b 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/Api/Runtime/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
index 573a803..b1825ac 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
index f6d5d41..342dbff 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 97dd0f6..9e32f40 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using Tools; 33using Tools;
34
35using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
36 35
37namespace OpenSim.Region.ScriptEngine.Shared.CodeTools 36namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
@@ -49,6 +48,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
49 private List<string> m_warnings = new List<string>(); 48 private List<string> m_warnings = new List<string>();
50 private IScriptModuleComms m_comms = null; 49 private IScriptModuleComms m_comms = null;
51 50
51 private bool m_insertCoopTerminationChecks;
52 private static string m_coopTerminationCheck = "opensim_reserved_CheckForCoopTermination();";
53
54 /// <summary>
55 /// Keep a record of the previous node when we do the parsing.
56 /// </summary>
57 /// <remarks>
58 /// We do this here because the parser generated by CSTools does not retain a reference to its parent node.
59 /// The previous node is required so we can correctly insert co-op termination checks when required.
60 /// </remarks>
61// private SYMBOL m_previousNode;
62
52 /// <summary> 63 /// <summary>
53 /// Creates an 'empty' CSCodeGenerator instance. 64 /// Creates an 'empty' CSCodeGenerator instance.
54 /// </summary> 65 /// </summary>
@@ -58,9 +69,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
58 ResetCounters(); 69 ResetCounters();
59 } 70 }
60 71
61 public CSCodeGenerator(IScriptModuleComms comms) 72 public CSCodeGenerator(IScriptModuleComms comms, bool insertCoopTerminationChecks)
62 { 73 {
63 m_comms = comms; 74 m_comms = comms;
75 m_insertCoopTerminationChecks = insertCoopTerminationChecks;
64 ResetCounters(); 76 ResetCounters();
65 } 77 }
66 78
@@ -155,7 +167,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
155 // here's the payload 167 // here's the payload
156 retstr += GenerateLine(); 168 retstr += GenerateLine();
157 foreach (SYMBOL s in m_astRoot.kids) 169 foreach (SYMBOL s in m_astRoot.kids)
158 retstr += GenerateNode(s); 170 retstr += GenerateNode(m_astRoot, s);
159 171
160 // close braces! 172 // close braces!
161 m_braceCount--; 173 m_braceCount--;
@@ -165,7 +177,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
165 177
166 // Removes all carriage return characters which may be generated in Windows platform. Is there 178 // Removes all carriage return characters which may be generated in Windows platform. Is there
167 // cleaner way of doing this? 179 // cleaner way of doing this?
168 retstr=retstr.Replace("\r", ""); 180 retstr = retstr.Replace("\r", "");
169 181
170 return retstr; 182 return retstr;
171 } 183 }
@@ -191,9 +203,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
191 /// Recursively called to generate each type of node. Will generate this 203 /// Recursively called to generate each type of node. Will generate this
192 /// node, then all it's children. 204 /// node, then all it's children.
193 /// </summary> 205 /// </summary>
206 /// <param name="previousSymbol">The parent node.</param>
194 /// <param name="s">The current node to generate code for.</param> 207 /// <param name="s">The current node to generate code for.</param>
195 /// <returns>String containing C# code for SYMBOL s.</returns> 208 /// <returns>String containing C# code for SYMBOL s.</returns>
196 private string GenerateNode(SYMBOL s) 209 private string GenerateNode(SYMBOL previousSymbol, SYMBOL s)
197 { 210 {
198 string retstr = String.Empty; 211 string retstr = String.Empty;
199 212
@@ -207,11 +220,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
207 else if (s is State) 220 else if (s is State)
208 retstr += GenerateState((State) s); 221 retstr += GenerateState((State) s);
209 else if (s is CompoundStatement) 222 else if (s is CompoundStatement)
210 retstr += GenerateCompoundStatement((CompoundStatement) s); 223 retstr += GenerateCompoundStatement(previousSymbol, (CompoundStatement) s);
211 else if (s is Declaration) 224 else if (s is Declaration)
212 retstr += GenerateDeclaration((Declaration) s); 225 retstr += GenerateDeclaration((Declaration) s);
213 else if (s is Statement) 226 else if (s is Statement)
214 retstr += GenerateStatement((Statement) s); 227 retstr += GenerateStatement(previousSymbol, (Statement) s);
215 else if (s is ReturnStatement) 228 else if (s is ReturnStatement)
216 retstr += GenerateReturnStatement((ReturnStatement) s); 229 retstr += GenerateReturnStatement((ReturnStatement) s);
217 else if (s is JumpLabel) 230 else if (s is JumpLabel)
@@ -261,7 +274,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
261 else 274 else
262 { 275 {
263 foreach (SYMBOL kid in s.kids) 276 foreach (SYMBOL kid in s.kids)
264 retstr += GenerateNode(kid); 277 retstr += GenerateNode(s, kid);
265 } 278 }
266 279
267 return retstr; 280 return retstr;
@@ -295,7 +308,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
295 retstr += GenerateLine(")"); 308 retstr += GenerateLine(")");
296 309
297 foreach (SYMBOL kid in remainingKids) 310 foreach (SYMBOL kid in remainingKids)
298 retstr += GenerateNode(kid); 311 retstr += GenerateNode(gf, kid);
299 312
300 return retstr; 313 return retstr;
301 } 314 }
@@ -312,7 +325,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
312 foreach (SYMBOL s in gv.kids) 325 foreach (SYMBOL s in gv.kids)
313 { 326 {
314 retstr += Indent(); 327 retstr += Indent();
315 retstr += GenerateNode(s); 328 retstr += GenerateNode(gv, s);
316 retstr += GenerateLine(";"); 329 retstr += GenerateLine(";");
317 } 330 }
318 331
@@ -365,7 +378,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
365 retstr += GenerateLine(")"); 378 retstr += GenerateLine(")");
366 379
367 foreach (SYMBOL kid in remainingKids) 380 foreach (SYMBOL kid in remainingKids)
368 retstr += GenerateNode(kid); 381 retstr += GenerateNode(se, kid);
369 382
370 return retstr; 383 return retstr;
371 } 384 }
@@ -404,7 +417,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
404 417
405 foreach (SYMBOL s in al.kids) 418 foreach (SYMBOL s in al.kids)
406 { 419 {
407 retstr += GenerateNode(s); 420 retstr += GenerateNode(al, s);
408 if (0 < comma--) 421 if (0 < comma--)
409 retstr += Generate(", "); 422 retstr += Generate(", ");
410 } 423 }
@@ -417,7 +430,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
417 /// </summary> 430 /// </summary>
418 /// <param name="cs">The CompoundStatement node.</param> 431 /// <param name="cs">The CompoundStatement node.</param>
419 /// <returns>String containing C# code for CompoundStatement cs.</returns> 432 /// <returns>String containing C# code for CompoundStatement cs.</returns>
420 private string GenerateCompoundStatement(CompoundStatement cs) 433 private string GenerateCompoundStatement(SYMBOL previousSymbol, CompoundStatement cs)
421 { 434 {
422 string retstr = String.Empty; 435 string retstr = String.Empty;
423 436
@@ -425,8 +438,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
425 retstr += GenerateIndentedLine("{"); 438 retstr += GenerateIndentedLine("{");
426 m_braceCount++; 439 m_braceCount++;
427 440
441 if (m_insertCoopTerminationChecks)
442 {
443 // We have to check in event functions as well because the user can manually call these.
444 if (previousSymbol is GlobalFunctionDefinition
445 || previousSymbol is WhileStatement
446 || previousSymbol is DoWhileStatement
447 || previousSymbol is ForLoop
448 || previousSymbol is StateEvent)
449 retstr += GenerateIndentedLine(m_coopTerminationCheck);
450 }
451
428 foreach (SYMBOL kid in cs.kids) 452 foreach (SYMBOL kid in cs.kids)
429 retstr += GenerateNode(kid); 453 retstr += GenerateNode(cs, kid);
430 454
431 // closing brace 455 // closing brace
432 m_braceCount--; 456 m_braceCount--;
@@ -450,10 +474,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
450 /// </summary> 474 /// </summary>
451 /// <param name="s">The Statement node.</param> 475 /// <param name="s">The Statement node.</param>
452 /// <returns>String containing C# code for Statement s.</returns> 476 /// <returns>String containing C# code for Statement s.</returns>
453 private string GenerateStatement(Statement s) 477 private string GenerateStatement(SYMBOL previousSymbol, Statement s)
454 { 478 {
455 string retstr = String.Empty; 479 string retstr = String.Empty;
456 bool printSemicolon = true; 480 bool printSemicolon = true;
481 bool transformToBlock = false;
482
483 if (m_insertCoopTerminationChecks)
484 {
485 // A non-braced single line do while structure cannot contain multiple statements.
486 // So to insert the termination check we change this to a braced control structure instead.
487 if (previousSymbol is WhileStatement
488 || previousSymbol is DoWhileStatement
489 || previousSymbol is ForLoop)
490 {
491 transformToBlock = true;
492
493 // FIXME: This will be wrongly indented because the previous for/while/dowhile will have already indented.
494 retstr += GenerateIndentedLine("{");
495
496 retstr += GenerateIndentedLine(m_coopTerminationCheck);
497 }
498 }
457 499
458 retstr += Indent(); 500 retstr += Indent();
459 501
@@ -466,12 +508,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
466 // (MONO) error. 508 // (MONO) error.
467 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count)) 509 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count))
468 foreach (SYMBOL kid in s.kids) 510 foreach (SYMBOL kid in s.kids)
469 retstr += GenerateNode(kid); 511 retstr += GenerateNode(s, kid);
470 } 512 }
471 513
472 if (printSemicolon) 514 if (printSemicolon)
473 retstr += GenerateLine(";"); 515 retstr += GenerateLine(";");
474 516
517 if (transformToBlock)
518 {
519 // FIXME: This will be wrongly indented because the for/while/dowhile is currently handling the unindent
520 retstr += GenerateIndentedLine("}");
521 }
522
475 return retstr; 523 return retstr;
476 } 524 }
477 525
@@ -487,10 +535,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
487 List<string> identifiers = new List<string>(); 535 List<string> identifiers = new List<string>();
488 checkForMultipleAssignments(identifiers, a); 536 checkForMultipleAssignments(identifiers, a);
489 537
490 retstr += GenerateNode((SYMBOL) a.kids.Pop()); 538 retstr += GenerateNode(a, (SYMBOL) a.kids.Pop());
491 retstr += Generate(String.Format(" {0} ", a.AssignmentType), a); 539 retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
492 foreach (SYMBOL kid in a.kids) 540 foreach (SYMBOL kid in a.kids)
493 retstr += GenerateNode(kid); 541 retstr += GenerateNode(a, kid);
494 542
495 return retstr; 543 return retstr;
496 } 544 }
@@ -563,7 +611,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
563 retstr += Generate("return ", rs); 611 retstr += Generate("return ", rs);
564 612
565 foreach (SYMBOL kid in rs.kids) 613 foreach (SYMBOL kid in rs.kids)
566 retstr += GenerateNode(kid); 614 retstr += GenerateNode(rs, kid);
567 615
568 return retstr; 616 return retstr;
569 } 617 }
@@ -575,7 +623,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
575 /// <returns>String containing C# code for JumpLabel jl.</returns> 623 /// <returns>String containing C# code for JumpLabel jl.</returns>
576 private string GenerateJumpLabel(JumpLabel jl) 624 private string GenerateJumpLabel(JumpLabel jl)
577 { 625 {
578 return Generate(String.Format("{0}:", CheckName(jl.LabelName)), jl) + " NoOp();\n"; 626 string labelStatement;
627
628 if (m_insertCoopTerminationChecks)
629 labelStatement = m_coopTerminationCheck + "\n";
630 else
631 labelStatement = "NoOp();\n";
632
633 return Generate(String.Format("{0}: ", CheckName(jl.LabelName)), jl) + labelStatement;
579 } 634 }
580 635
581 /// <summary> 636 /// <summary>
@@ -598,14 +653,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
598 string retstr = String.Empty; 653 string retstr = String.Empty;
599 654
600 retstr += GenerateIndented("if (", ifs); 655 retstr += GenerateIndented("if (", ifs);
601 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 656 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
602 retstr += GenerateLine(")"); 657 retstr += GenerateLine(")");
603 658
604 // CompoundStatement handles indentation itself but we need to do it 659 // CompoundStatement handles indentation itself but we need to do it
605 // otherwise. 660 // otherwise.
606 bool indentHere = ifs.kids.Top is Statement; 661 bool indentHere = ifs.kids.Top is Statement;
607 if (indentHere) m_braceCount++; 662 if (indentHere) m_braceCount++;
608 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 663 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
609 if (indentHere) m_braceCount--; 664 if (indentHere) m_braceCount--;
610 665
611 if (0 < ifs.kids.Count) // do it again for an else 666 if (0 < ifs.kids.Count) // do it again for an else
@@ -614,7 +669,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
614 669
615 indentHere = ifs.kids.Top is Statement; 670 indentHere = ifs.kids.Top is Statement;
616 if (indentHere) m_braceCount++; 671 if (indentHere) m_braceCount++;
617 retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); 672 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
618 if (indentHere) m_braceCount--; 673 if (indentHere) m_braceCount--;
619 } 674 }
620 675
@@ -641,14 +696,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
641 string retstr = String.Empty; 696 string retstr = String.Empty;
642 697
643 retstr += GenerateIndented("while (", ws); 698 retstr += GenerateIndented("while (", ws);
644 retstr += GenerateNode((SYMBOL) ws.kids.Pop()); 699 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
645 retstr += GenerateLine(")"); 700 retstr += GenerateLine(")");
646 701
647 // CompoundStatement handles indentation itself but we need to do it 702 // CompoundStatement handles indentation itself but we need to do it
648 // otherwise. 703 // otherwise.
649 bool indentHere = ws.kids.Top is Statement; 704 bool indentHere = ws.kids.Top is Statement;
650 if (indentHere) m_braceCount++; 705 if (indentHere) m_braceCount++;
651 retstr += GenerateNode((SYMBOL) ws.kids.Pop()); 706 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
652 if (indentHere) m_braceCount--; 707 if (indentHere) m_braceCount--;
653 708
654 return retstr; 709 return retstr;
@@ -669,11 +724,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
669 // otherwise. 724 // otherwise.
670 bool indentHere = dws.kids.Top is Statement; 725 bool indentHere = dws.kids.Top is Statement;
671 if (indentHere) m_braceCount++; 726 if (indentHere) m_braceCount++;
672 retstr += GenerateNode((SYMBOL) dws.kids.Pop()); 727 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
673 if (indentHere) m_braceCount--; 728 if (indentHere) m_braceCount--;
674 729
675 retstr += GenerateIndented("while (", dws); 730 retstr += GenerateIndented("while (", dws);
676 retstr += GenerateNode((SYMBOL) dws.kids.Pop()); 731 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
677 retstr += GenerateLine(");"); 732 retstr += GenerateLine(");");
678 733
679 return retstr; 734 return retstr;
@@ -702,7 +757,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
702 retstr += Generate("; "); 757 retstr += Generate("; ");
703 // for (x = 0; x < 10; x++) 758 // for (x = 0; x < 10; x++)
704 // ^^^^^^ 759 // ^^^^^^
705 retstr += GenerateNode((SYMBOL) fl.kids.Pop()); 760 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
706 retstr += Generate("; "); 761 retstr += Generate("; ");
707 // for (x = 0; x < 10; x++) 762 // for (x = 0; x < 10; x++)
708 // ^^^ 763 // ^^^
@@ -713,7 +768,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
713 // otherwise. 768 // otherwise.
714 bool indentHere = fl.kids.Top is Statement; 769 bool indentHere = fl.kids.Top is Statement;
715 if (indentHere) m_braceCount++; 770 if (indentHere) m_braceCount++;
716 retstr += GenerateNode((SYMBOL) fl.kids.Pop()); 771 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
717 if (indentHere) m_braceCount--; 772 if (indentHere) m_braceCount--;
718 773
719 return retstr; 774 return retstr;
@@ -758,7 +813,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
758 while (s is ParenthesisExpression) 813 while (s is ParenthesisExpression)
759 s = (SYMBOL)s.kids.Pop(); 814 s = (SYMBOL)s.kids.Pop();
760 815
761 retstr += GenerateNode(s); 816 retstr += GenerateNode(fls, s);
762 if (0 < comma--) 817 if (0 < comma--)
763 retstr += Generate(", "); 818 retstr += Generate(", ");
764 } 819 }
@@ -779,20 +834,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
779 { 834 {
780 // special case handling for logical and/or, see Mantis 3174 835 // special case handling for logical and/or, see Mantis 3174
781 retstr += "((bool)("; 836 retstr += "((bool)(";
782 retstr += GenerateNode((SYMBOL)be.kids.Pop()); 837 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
783 retstr += "))"; 838 retstr += "))";
784 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be); 839 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be);
785 retstr += "((bool)("; 840 retstr += "((bool)(";
786 foreach (SYMBOL kid in be.kids) 841 foreach (SYMBOL kid in be.kids)
787 retstr += GenerateNode(kid); 842 retstr += GenerateNode(be, kid);
788 retstr += "))"; 843 retstr += "))";
789 } 844 }
790 else 845 else
791 { 846 {
792 retstr += GenerateNode((SYMBOL)be.kids.Pop()); 847 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
793 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be); 848 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
794 foreach (SYMBOL kid in be.kids) 849 foreach (SYMBOL kid in be.kids)
795 retstr += GenerateNode(kid); 850 retstr += GenerateNode(be, kid);
796 } 851 }
797 852
798 return retstr; 853 return retstr;
@@ -808,7 +863,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
808 string retstr = String.Empty; 863 string retstr = String.Empty;
809 864
810 retstr += Generate(ue.UnarySymbol, ue); 865 retstr += Generate(ue.UnarySymbol, ue);
811 retstr += GenerateNode((SYMBOL) ue.kids.Pop()); 866 retstr += GenerateNode(ue, (SYMBOL) ue.kids.Pop());
812 867
813 return retstr; 868 return retstr;
814 } 869 }
@@ -824,7 +879,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
824 879
825 retstr += Generate("("); 880 retstr += Generate("(");
826 foreach (SYMBOL kid in pe.kids) 881 foreach (SYMBOL kid in pe.kids)
827 retstr += GenerateNode(kid); 882 retstr += GenerateNode(pe, kid);
828 retstr += Generate(")"); 883 retstr += Generate(")");
829 884
830 return retstr; 885 return retstr;
@@ -861,7 +916,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
861 916
862 // we wrap all typecasted statements in parentheses 917 // we wrap all typecasted statements in parentheses
863 retstr += Generate(String.Format("({0}) (", te.TypecastType), te); 918 retstr += Generate(String.Format("({0}) (", te.TypecastType), te);
864 retstr += GenerateNode((SYMBOL) te.kids.Pop()); 919 retstr += GenerateNode(te, (SYMBOL) te.kids.Pop());
865 retstr += Generate(")"); 920 retstr += Generate(")");
866 921
867 return retstr; 922 return retstr;
@@ -931,7 +986,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
931 } 986 }
932 987
933 foreach (SYMBOL kid in fc.kids) 988 foreach (SYMBOL kid in fc.kids)
934 retstr += GenerateNode(kid); 989 retstr += GenerateNode(fc, kid);
935 990
936 retstr += Generate(")"); 991 retstr += Generate(")");
937 992
@@ -980,11 +1035,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
980 string retstr = String.Empty; 1035 string retstr = String.Empty;
981 1036
982 retstr += Generate(String.Format("new {0}(", vc.Type), vc); 1037 retstr += Generate(String.Format("new {0}(", vc.Type), vc);
983 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1038 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
984 retstr += Generate(", "); 1039 retstr += Generate(", ");
985 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1040 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
986 retstr += Generate(", "); 1041 retstr += Generate(", ");
987 retstr += GenerateNode((SYMBOL) vc.kids.Pop()); 1042 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
988 retstr += Generate(")"); 1043 retstr += Generate(")");
989 1044
990 return retstr; 1045 return retstr;
@@ -1000,13 +1055,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
1000 string retstr = String.Empty; 1055 string retstr = String.Empty;
1001 1056
1002 retstr += Generate(String.Format("new {0}(", rc.Type), rc); 1057 retstr += Generate(String.Format("new {0}(", rc.Type), rc);
1003 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1058 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1004 retstr += Generate(", "); 1059 retstr += Generate(", ");
1005 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1060 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1006 retstr += Generate(", "); 1061 retstr += Generate(", ");
1007 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1062 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1008 retstr += Generate(", "); 1063 retstr += Generate(", ");
1009 retstr += GenerateNode((SYMBOL) rc.kids.Pop()); 1064 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1010 retstr += Generate(")"); 1065 retstr += Generate(")");
1011 1066
1012 return retstr; 1067 return retstr;
@@ -1024,7 +1079,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
1024 retstr += Generate(String.Format("new {0}(", lc.Type), lc); 1079 retstr += Generate(String.Format("new {0}(", lc.Type), lc);
1025 1080
1026 foreach (SYMBOL kid in lc.kids) 1081 foreach (SYMBOL kid in lc.kids)
1027 retstr += GenerateNode(kid); 1082 retstr += GenerateNode(lc, kid);
1028 1083
1029 retstr += Generate(")"); 1084 retstr += Generate(")");
1030 1085
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/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
index c65caa8..5b5c4fd 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
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/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
index 470e1a1..48964b6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 771db0c..26850c4 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(timeout))
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(Timeout.Infinite))
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..ac822c6
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
@@ -0,0 +1,513 @@
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 /// <summary>
59 /// Number of chat messages received so far. Reset before each test.
60 /// </summary>
61 private int m_chatMessagesReceived;
62
63 /// <summary>
64 /// Number of chat messages expected. m_chatEvent is not fired until this number is reached or exceeded.
65 /// </summary>
66 private int m_chatMessagesThreshold;
67
68 [SetUp]
69 public void Init()
70 {
71 m_osChatMessageReceived = null;
72 m_chatMessagesReceived = 0;
73 m_chatMessagesThreshold = 0;
74 m_chatEvent = new AutoResetEvent(false);
75 m_stoppedEvent = new AutoResetEvent(false);
76
77 //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin");
78// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
79 m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine();
80
81 IniConfigSource configSource = new IniConfigSource();
82
83 IConfig startupConfig = configSource.AddConfig("Startup");
84 startupConfig.Set("DefaultScriptEngine", "XEngine");
85
86 IConfig xEngineConfig = configSource.AddConfig("XEngine");
87 xEngineConfig.Set("Enabled", "true");
88 xEngineConfig.Set("StartDelay", "0");
89
90 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
91 // to AssemblyResolver.OnAssemblyResolve fails.
92 xEngineConfig.Set("AppDomainLoading", "false");
93
94 xEngineConfig.Set("ScriptStopStrategy", "co-op");
95
96 // Make sure loops aren't actually being terminated by a script delay wait.
97 xEngineConfig.Set("ScriptDelayFactor", 0);
98
99 // This is really just set for debugging the test.
100 xEngineConfig.Set("WriteScriptSourceToDebugFile", true);
101
102 // Set to false if we need to debug test so the old scripts don't get wiped before each separate test
103// xEngineConfig.Set("DeleteScriptsOnStartup", false);
104
105 // This is not currently used at all for co-op termination. Bumping up to demonstrate that co-op termination
106 // has an effect - without it tests will fail due to a 120 second wait for the event to finish.
107 xEngineConfig.Set("WaitForEventCompletionOnScriptStop", 120000);
108
109 m_scene = new SceneHelpers().SetupScene("My Test", TestHelpers.ParseTail(0x9999), 1000, 1000, configSource);
110 SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
111 m_scene.StartScripts();
112 }
113
114 /// <summary>
115 /// Test co-operative termination on derez of an object containing a script with a long-running event.
116 /// </summary>
117 /// <remarks>
118 /// TODO: Actually compiling the script is incidental to this test. Really want a way to compile test scripts
119 /// within the build itself.
120 /// </remarks>
121 [Test]
122 public void TestStopOnLongSleep()
123 {
124 TestHelpers.InMethod();
125// TestHelpers.EnableLogging();
126
127 string script =
128@"default
129{
130 state_entry()
131 {
132 llSay(0, ""Thin Lizzy"");
133 llSleep(60);
134 }
135}";
136
137 TestStop(script);
138 }
139
140 [Test]
141 public void TestNoStopOnSingleStatementForLoop()
142 {
143 TestHelpers.InMethod();
144// TestHelpers.EnableLogging();
145
146 string script =
147@"default
148{
149 state_entry()
150 {
151 integer i = 0;
152 for (i = 0; i <= 1; i++) llSay(0, ""Iter "" + (string)i);
153 }
154}";
155
156 TestSingleStatementNoStop(script);
157 }
158
159 [Test]
160 public void TestStopOnLongSingleStatementForLoop()
161 {
162 TestHelpers.InMethod();
163// TestHelpers.EnableLogging();
164
165 string script =
166@"default
167{
168 state_entry()
169 {
170 integer i = 0;
171 llSay(0, ""Thin Lizzy"");
172
173 for (i = 0; i < 2147483647; i++) llSay(0, ""Iter "" + (string)i);
174 }
175}";
176
177 TestStop(script);
178 }
179
180 [Test]
181 public void TestStopOnLongCompoundStatementForLoop()
182 {
183 TestHelpers.InMethod();
184// TestHelpers.EnableLogging();
185
186 string script =
187@"default
188{
189 state_entry()
190 {
191 integer i = 0;
192 llSay(0, ""Thin Lizzy"");
193
194 for (i = 0; i < 2147483647; i++)
195 {
196 llSay(0, ""Iter "" + (string)i);
197 }
198 }
199}";
200
201 TestStop(script);
202 }
203
204 [Test]
205 public void TestNoStopOnSingleStatementWhileLoop()
206 {
207 TestHelpers.InMethod();
208// TestHelpers.EnableLogging();
209
210 string script =
211@"default
212{
213 state_entry()
214 {
215 integer i = 0;
216 while (i < 2) llSay(0, ""Iter "" + (string)i++);
217 }
218}";
219
220 TestSingleStatementNoStop(script);
221 }
222
223 [Test]
224 public void TestStopOnLongSingleStatementWhileLoop()
225 {
226 TestHelpers.InMethod();
227// TestHelpers.EnableLogging();
228
229 string script =
230@"default
231{
232 state_entry()
233 {
234 integer i = 0;
235 llSay(0, ""Thin Lizzy"");
236
237 while (1 == 1)
238 llSay(0, ""Iter "" + (string)i++);
239 }
240}";
241
242 TestStop(script);
243 }
244
245 [Test]
246 public void TestStopOnLongCompoundStatementWhileLoop()
247 {
248 TestHelpers.InMethod();
249// TestHelpers.EnableLogging();
250
251 string script =
252@"default
253{
254 state_entry()
255 {
256 integer i = 0;
257 llSay(0, ""Thin Lizzy"");
258
259 while (1 == 1)
260 {
261 llSay(0, ""Iter "" + (string)i++);
262 }
263 }
264}";
265
266 TestStop(script);
267 }
268
269 [Test]
270 public void TestNoStopOnSingleStatementDoWhileLoop()
271 {
272 TestHelpers.InMethod();
273// TestHelpers.EnableLogging();
274
275 string script =
276@"default
277{
278 state_entry()
279 {
280 integer i = 0;
281
282 do llSay(0, ""Iter "" + (string)i++);
283 while (i < 2);
284 }
285}";
286
287 TestSingleStatementNoStop(script);
288 }
289
290 [Test]
291 public void TestStopOnLongSingleStatementDoWhileLoop()
292 {
293 TestHelpers.InMethod();
294// TestHelpers.EnableLogging();
295
296 string script =
297@"default
298{
299 state_entry()
300 {
301 integer i = 0;
302 llSay(0, ""Thin Lizzy"");
303
304 do llSay(0, ""Iter "" + (string)i++);
305 while (1 == 1);
306 }
307}";
308
309 TestStop(script);
310 }
311
312 [Test]
313 public void TestStopOnLongCompoundStatementDoWhileLoop()
314 {
315 TestHelpers.InMethod();
316// TestHelpers.EnableLogging();
317
318 string script =
319@"default
320{
321 state_entry()
322 {
323 integer i = 0;
324 llSay(0, ""Thin Lizzy"");
325
326 do
327 {
328 llSay(0, ""Iter "" + (string)i++);
329 } while (1 == 1);
330 }
331}";
332
333 TestStop(script);
334 }
335
336 [Test]
337 public void TestStopOnInfiniteJumpLoop()
338 {
339 TestHelpers.InMethod();
340// TestHelpers.EnableLogging();
341
342 string script =
343@"default
344{
345 state_entry()
346 {
347 integer i = 0;
348 llSay(0, ""Thin Lizzy"");
349
350 @p1;
351 llSay(0, ""Iter "" + (string)i++);
352 jump p1;
353 }
354}";
355
356 TestStop(script);
357 }
358
359 // Disabling for now as these are not particularly useful tests (since they fail due to stack overflow before
360 // termination can even be tried.
361// [Test]
362 public void TestStopOnInfiniteUserFunctionCallLoop()
363 {
364 TestHelpers.InMethod();
365// TestHelpers.EnableLogging();
366
367 string script =
368@"
369integer i = 0;
370
371ufn1()
372{
373 llSay(0, ""Iter ufn1() "" + (string)i++);
374 ufn1();
375}
376
377default
378{
379 state_entry()
380 {
381 integer i = 0;
382 llSay(0, ""Thin Lizzy"");
383
384 ufn1();
385 }
386}";
387
388 TestStop(script);
389 }
390
391 // Disabling for now as these are not particularly useful tests (since they fail due to stack overflow before
392 // termination can even be tried.
393// [Test]
394 public void TestStopOnInfiniteManualEventCallLoop()
395 {
396 TestHelpers.InMethod();
397// TestHelpers.EnableLogging();
398
399 string script =
400@"default
401{
402 state_entry()
403 {
404 integer i = 0;
405 llSay(0, ""Thin Lizzy"");
406
407 llSay(0, ""Iter"" + (string)i++);
408 default_event_state_entry();
409 }
410}";
411
412 TestStop(script);
413 }
414
415 private SceneObjectPart CreateScript(string script, string itemName, UUID userId)
416 {
417// UUID objectId = TestHelpers.ParseTail(0x100);
418// UUID itemId = TestHelpers.ParseTail(0x3);
419
420 SceneObjectGroup so
421 = SceneHelpers.CreateSceneObject(1, userId, string.Format("Object for {0}", itemName), 0x100);
422 m_scene.AddNewSceneObject(so, true);
423
424 InventoryItemBase itemTemplate = new InventoryItemBase();
425// itemTemplate.ID = itemId;
426 itemTemplate.Name = itemName;
427 itemTemplate.Folder = so.UUID;
428 itemTemplate.InvType = (int)InventoryType.LSL;
429
430 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
431
432 return m_scene.RezNewScript(userId, itemTemplate, script);
433 }
434
435 private void TestSingleStatementNoStop(string script)
436 {
437 // In these tests we expect to see at least 2 chat messages to confirm that the loop is working properly.
438 m_chatMessagesThreshold = 2;
439
440 UUID userId = TestHelpers.ParseTail(0x1);
441// UUID objectId = TestHelpers.ParseTail(0x100);
442// UUID itemId = TestHelpers.ParseTail(0x3);
443 string itemName = "TestNoStop";
444
445 SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
446
447 // Wait for the script to start the event before we try stopping it.
448 m_chatEvent.WaitOne(60000);
449
450 if (m_osChatMessageReceived == null)
451 Assert.Fail("Script did not start");
452 else
453 Assert.That(m_chatMessagesReceived, Is.EqualTo(2));
454
455 bool running;
456 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
457 Assert.That(
458 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
459 Assert.That(running, Is.True);
460 }
461
462 private void TestStop(string script)
463 {
464 // In these tests we're only interested in the first message to confirm that the script has started.
465 m_chatMessagesThreshold = 1;
466
467 UUID userId = TestHelpers.ParseTail(0x1);
468// UUID objectId = TestHelpers.ParseTail(0x100);
469// UUID itemId = TestHelpers.ParseTail(0x3);
470 string itemName = "TestStop";
471
472 SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
473 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
474
475 // Wait for the script to start the event before we try stopping it.
476 m_chatEvent.WaitOne(60000);
477
478 if (m_osChatMessageReceived != null)
479 Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
480 else
481 Assert.Fail("Script did not start");
482
483 // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
484 // executes llSay() but has not started the next statement before we try to stop it.
485 Thread.Sleep(1000);
486
487 // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually
488 // stopped. This kind of multi-threading is far from ideal in a regression test.
489 new Thread(() => { m_xEngine.StopScript(rezzedItem.ItemID); m_stoppedEvent.Set(); }).Start();
490
491 if (!m_stoppedEvent.WaitOne(30000))
492 Assert.Fail("Script did not co-operatively stop.");
493
494 bool running;
495 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
496 Assert.That(
497 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
498 Assert.That(running, Is.False);
499 }
500
501 private void OnChatFromWorld(object sender, OSChatMessage oscm)
502 {
503 Console.WriteLine("Got chat [{0}]", oscm.Message);
504 m_osChatMessageReceived = oscm;
505
506 if (++m_chatMessagesReceived >= m_chatMessagesThreshold)
507 {
508 m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
509 m_chatEvent.Set();
510 }
511 }
512 }
513} \ 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/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
index e6e8777..d08b0a6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs
new file mode 100644
index 0000000..b0baa1c
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs
@@ -0,0 +1,250 @@
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.IO;
31using System.Net;
32using System.Reflection;
33using System.Text;
34using log4net;
35using Nini.Config;
36using NUnit.Framework;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.CoreModules.Scripting.LSLHttp;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.ScriptEngine.Shared;
44using OpenSim.Region.ScriptEngine.Shared.Api;
45using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
46using OpenSim.Services.Interfaces;
47using OpenSim.Tests.Common;
48using OpenSim.Tests.Common.Mock;
49
50namespace OpenSim.Region.ScriptEngine.Shared.Tests
51{
52 /// <summary>
53 /// Tests for HTTP related functions in LSL
54 /// </summary>
55 [TestFixture]
56 public class LSL_ApiHttpTests : OpenSimTestCase
57 {
58 private Scene m_scene;
59 private MockScriptEngine m_engine;
60 private UrlModule m_urlModule;
61
62 private TaskInventoryItem m_scriptItem;
63 private LSL_Api m_lslApi;
64
65 [TestFixtureSetUp]
66 public void TestFixtureSetUp()
67 {
68 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
69 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
70 }
71
72 [TestFixtureTearDown]
73 public void TestFixureTearDown()
74 {
75 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
76 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
77 // tests really shouldn't).
78 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
79 }
80
81 [SetUp]
82 public override void SetUp()
83 {
84 base.SetUp();
85
86 // This is an unfortunate bit of clean up we have to do because MainServer manages things through static
87 // variables and the VM is not restarted between tests.
88 uint port = 9999;
89 MainServer.RemoveHttpServer(port);
90
91 BaseHttpServer server = new BaseHttpServer(port, false, 0, "");
92 MainServer.AddHttpServer(server);
93 MainServer.Instance = server;
94
95 server.Start();
96
97 m_engine = new MockScriptEngine();
98 m_urlModule = new UrlModule();
99
100 m_scene = new SceneHelpers().SetupScene();
101 SceneHelpers.SetupSceneModules(m_scene, new IniConfigSource(), m_engine, m_urlModule);
102
103 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
104 m_scriptItem = TaskInventoryHelpers.AddScript(m_scene, so.RootPart);
105
106 // This is disconnected from the actual script - the mock engine does not set up any LSL_Api atm.
107 // Possibly this could be done and we could obtain it directly from the MockScriptEngine.
108 m_lslApi = new LSL_Api();
109 m_lslApi.Initialize(m_engine, so.RootPart, m_scriptItem, null);
110 }
111
112 [TearDown]
113 public void TearDown()
114 {
115 MainServer.Instance.Stop();
116 }
117
118 [Test]
119 public void TestLlReleaseUrl()
120 {
121 TestHelpers.InMethod();
122
123 m_lslApi.llRequestURL();
124 string returnedUri = m_engine.PostedEvents[m_scriptItem.ItemID][0].Params[2].ToString();
125
126 {
127 // Check that the initial number of URLs is correct
128 Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
129 }
130
131 {
132 // Check releasing a non-url
133 m_lslApi.llReleaseURL("GARBAGE");
134 Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
135 }
136
137 {
138 // Check releasing a non-existing url
139 m_lslApi.llReleaseURL("http://example.com");
140 Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
141 }
142
143 {
144 // Check URL release
145 m_lslApi.llReleaseURL(returnedUri);
146 Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls));
147
148 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri);
149
150 bool gotExpectedException = false;
151
152 try
153 {
154 using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
155 {}
156 }
157 catch (WebException e)
158 {
159 using (HttpWebResponse response = (HttpWebResponse)e.Response)
160 gotExpectedException = response.StatusCode == HttpStatusCode.NotFound;
161 }
162
163 Assert.That(gotExpectedException, Is.True);
164 }
165
166 {
167 // Check releasing the same URL again
168 m_lslApi.llReleaseURL(returnedUri);
169 Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls));
170 }
171 }
172
173 [Test]
174 public void TestLlRequestUrl()
175 {
176 TestHelpers.InMethod();
177
178 string requestId = m_lslApi.llRequestURL();
179 Assert.That(requestId, Is.Not.EqualTo(UUID.Zero.ToString()));
180 string returnedUri;
181
182 {
183 // Check that URL is correctly set up
184 Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
185
186 Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID));
187
188 List<EventParams> events = m_engine.PostedEvents[m_scriptItem.ItemID];
189 Assert.That(events.Count, Is.EqualTo(1));
190 EventParams eventParams = events[0];
191 Assert.That(eventParams.EventName, Is.EqualTo("http_request"));
192
193 UUID returnKey;
194 string rawReturnKey = eventParams.Params[0].ToString();
195 string method = eventParams.Params[1].ToString();
196 returnedUri = eventParams.Params[2].ToString();
197
198 Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True);
199 Assert.That(method, Is.EqualTo(ScriptBaseClass.URL_REQUEST_GRANTED));
200 Assert.That(Uri.IsWellFormedUriString(returnedUri, UriKind.Absolute), Is.True);
201 }
202
203 {
204 // Check that request to URL works.
205 string testResponse = "Hello World";
206
207 m_engine.ClearPostedEvents();
208 m_engine.PostEventHook
209 += (itemId, evp) => m_lslApi.llHTTPResponse(evp.Params[0].ToString(), 200, testResponse);
210
211// Console.WriteLine("Trying {0}", returnedUri);
212 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri);
213
214 AssertHttpResponse(returnedUri, testResponse);
215
216 Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID));
217
218 List<EventParams> events = m_engine.PostedEvents[m_scriptItem.ItemID];
219 Assert.That(events.Count, Is.EqualTo(1));
220 EventParams eventParams = events[0];
221 Assert.That(eventParams.EventName, Is.EqualTo("http_request"));
222
223 UUID returnKey;
224 string rawReturnKey = eventParams.Params[0].ToString();
225 string method = eventParams.Params[1].ToString();
226 string body = eventParams.Params[2].ToString();
227
228 Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True);
229 Assert.That(method, Is.EqualTo("GET"));
230 Assert.That(body, Is.EqualTo(""));
231 }
232 }
233
234 private void AssertHttpResponse(string uri, string expectedResponse)
235 {
236 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
237
238 using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
239 {
240 using (Stream stream = webResponse.GetResponseStream())
241 {
242 using (StreamReader reader = new StreamReader(stream))
243 {
244 Assert.That(reader.ReadToEnd(), Is.EqualTo(expectedResponse));
245 }
246 }
247 }
248 }
249 }
250} \ No newline at end of file
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..ac9f93b 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");
@@ -90,7 +93,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
90 // FIXME: This should really be a script item (with accompanying script) 93 // FIXME: This should really be a script item (with accompanying script)
91 TaskInventoryItem grp1Item 94 TaskInventoryItem grp1Item
92 = TaskInventoryHelpers.AddNotecard( 95 = TaskInventoryHelpers.AddNotecard(
93 m_scene, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900)); 96 m_scene, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!");
94 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 97 grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
95 98
96 SceneObjectGroup grp2 = SceneHelpers.CreateSceneObject(2, ownerId, "grp2-", 0x20); 99 SceneObjectGroup grp2 = SceneHelpers.CreateSceneObject(2, ownerId, "grp2-", 0x20);
@@ -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
@@ -124,12 +127,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
124 // FIXME: This should really be a script item (with accompanying script) 127 // FIXME: This should really be a script item (with accompanying script)
125 TaskInventoryItem grp1Item 128 TaskInventoryItem grp1Item
126 = TaskInventoryHelpers.AddNotecard( 129 = TaskInventoryHelpers.AddNotecard(
127 m_scene, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900)); 130 m_scene, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!");
128 131
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_ApiNotecardTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
new file mode 100644
index 0000000..c92bcdb
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
@@ -0,0 +1,270 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Net;
5using System.Reflection;
6using System.Text;
7using log4net;
8using Nini.Config;
9using NUnit.Framework;
10using OpenMetaverse;
11using OpenSim.Framework;
12using OpenSim.Framework.Servers;
13using OpenSim.Framework.Servers.HttpServer;
14using OpenSim.Region.CoreModules.Scripting.LSLHttp;
15using OpenSim.Region.Framework.Scenes;
16using OpenSim.Region.ScriptEngine.Shared;
17using OpenSim.Region.ScriptEngine.Shared.Api;
18using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
19using OpenSim.Services.Interfaces;
20using OpenSim.Tests.Common;
21using OpenSim.Tests.Common.Mock;
22
23namespace OpenSim.Region.ScriptEngine.Shared.Tests
24{
25 /// <summary>
26 /// Tests for notecard related functions in LSL
27 /// </summary>
28 [TestFixture]
29 public class LSL_ApiNotecardTests : OpenSimTestCase
30 {
31 private Scene m_scene;
32 private MockScriptEngine m_engine;
33
34 private SceneObjectGroup m_so;
35 private TaskInventoryItem m_scriptItem;
36 private LSL_Api m_lslApi;
37
38 [TestFixtureSetUp]
39 public void TestFixtureSetUp()
40 {
41 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
42 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
43 }
44
45 [TestFixtureTearDown]
46 public void TestFixureTearDown()
47 {
48 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
49 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
50 // tests really shouldn't).
51 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
52 }
53
54 [SetUp]
55 public override void SetUp()
56 {
57 base.SetUp();
58
59 m_engine = new MockScriptEngine();
60
61 m_scene = new SceneHelpers().SetupScene();
62 SceneHelpers.SetupSceneModules(m_scene, new IniConfigSource(), m_engine);
63
64 m_so = SceneHelpers.AddSceneObject(m_scene);
65 m_scriptItem = TaskInventoryHelpers.AddScript(m_scene, m_so.RootPart);
66
67 // This is disconnected from the actual script - the mock engine does not set up any LSL_Api atm.
68 // Possibly this could be done and we could obtain it directly from the MockScriptEngine.
69 m_lslApi = new LSL_Api();
70 m_lslApi.Initialize(m_engine, m_so.RootPart, m_scriptItem, null);
71 }
72
73 [Test]
74 public void TestLlGetNotecardLine()
75 {
76 TestHelpers.InMethod();
77
78 string[] ncLines = { "One", "Two", "Three" };
79
80 TaskInventoryItem ncItem
81 = TaskInventoryHelpers.AddNotecard(m_scene, m_so.RootPart, "nc", "1", "10", string.Join("\n", ncLines));
82
83 AssertValidNotecardLine(ncItem.Name, 0, ncLines[0]);
84 AssertValidNotecardLine(ncItem.Name, 2, ncLines[2]);
85 AssertValidNotecardLine(ncItem.Name, 3, ScriptBaseClass.EOF);
86 AssertValidNotecardLine(ncItem.Name, 4, ScriptBaseClass.EOF);
87
88 // XXX: Is this correct or do we really expect no dataserver event to fire at all?
89 AssertValidNotecardLine(ncItem.Name, -1, "");
90 AssertValidNotecardLine(ncItem.Name, -2, "");
91 }
92
93 [Test]
94 public void TestLlGetNotecardLine_NoNotecard()
95 {
96 TestHelpers.InMethod();
97
98 AssertInValidNotecardLine("nc", 0);
99 }
100
101 [Test]
102 public void TestLlGetNotecardLine_NotANotecard()
103 {
104 TestHelpers.InMethod();
105
106 TaskInventoryItem ncItem = TaskInventoryHelpers.AddScript(m_scene, m_so.RootPart, "nc1", "Not important");
107
108 AssertInValidNotecardLine(ncItem.Name, 0);
109 }
110
111 private void AssertValidNotecardLine(string ncName, int lineNumber, string assertLine)
112 {
113 string key = m_lslApi.llGetNotecardLine(ncName, lineNumber);
114 Assert.That(key, Is.Not.EqualTo(UUID.Zero.ToString()));
115
116 Assert.That(m_engine.PostedEvents.Count, Is.EqualTo(1));
117 Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID));
118
119 List<EventParams> events = m_engine.PostedEvents[m_scriptItem.ItemID];
120 Assert.That(events.Count, Is.EqualTo(1));
121 EventParams eventParams = events[0];
122
123 Assert.That(eventParams.EventName, Is.EqualTo("dataserver"));
124 Assert.That(eventParams.Params[0].ToString(), Is.EqualTo(key));
125 Assert.That(eventParams.Params[1].ToString(), Is.EqualTo(assertLine));
126
127 m_engine.ClearPostedEvents();
128 }
129
130 private void AssertInValidNotecardLine(string ncName, int lineNumber)
131 {
132 string key = m_lslApi.llGetNotecardLine(ncName, lineNumber);
133 Assert.That(key, Is.EqualTo(UUID.Zero.ToString()));
134
135 Assert.That(m_engine.PostedEvents.Count, Is.EqualTo(0));
136 }
137
138// [Test]
139// public void TestLlReleaseUrl()
140// {
141// TestHelpers.InMethod();
142//
143// m_lslApi.llRequestURL();
144// string returnedUri = m_engine.PostedEvents[m_scriptItem.ItemID][0].Params[2].ToString();
145//
146// {
147// // Check that the initial number of URLs is correct
148// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
149// }
150//
151// {
152// // Check releasing a non-url
153// m_lslApi.llReleaseURL("GARBAGE");
154// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
155// }
156//
157// {
158// // Check releasing a non-existing url
159// m_lslApi.llReleaseURL("http://example.com");
160// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
161// }
162//
163// {
164// // Check URL release
165// m_lslApi.llReleaseURL(returnedUri);
166// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls));
167//
168// HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri);
169//
170// bool gotExpectedException = false;
171//
172// try
173// {
174// using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
175// {}
176// }
177// catch (WebException e)
178// {
179// using (HttpWebResponse response = (HttpWebResponse)e.Response)
180// gotExpectedException = response.StatusCode == HttpStatusCode.NotFound;
181// }
182//
183// Assert.That(gotExpectedException, Is.True);
184// }
185//
186// {
187// // Check releasing the same URL again
188// m_lslApi.llReleaseURL(returnedUri);
189// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls));
190// }
191// }
192//
193// [Test]
194// public void TestLlRequestUrl()
195// {
196// TestHelpers.InMethod();
197//
198// string requestId = m_lslApi.llRequestURL();
199// Assert.That(requestId, Is.Not.EqualTo(UUID.Zero.ToString()));
200// string returnedUri;
201//
202// {
203// // Check that URL is correctly set up
204// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1));
205//
206// Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID));
207//
208// List<EventParams> events = m_engine.PostedEvents[m_scriptItem.ItemID];
209// Assert.That(events.Count, Is.EqualTo(1));
210// EventParams eventParams = events[0];
211// Assert.That(eventParams.EventName, Is.EqualTo("http_request"));
212//
213// UUID returnKey;
214// string rawReturnKey = eventParams.Params[0].ToString();
215// string method = eventParams.Params[1].ToString();
216// returnedUri = eventParams.Params[2].ToString();
217//
218// Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True);
219// Assert.That(method, Is.EqualTo(ScriptBaseClass.URL_REQUEST_GRANTED));
220// Assert.That(Uri.IsWellFormedUriString(returnedUri, UriKind.Absolute), Is.True);
221// }
222//
223// {
224// // Check that request to URL works.
225// string testResponse = "Hello World";
226//
227// m_engine.ClearPostedEvents();
228// m_engine.PostEventHook
229// += (itemId, evp) => m_lslApi.llHTTPResponse(evp.Params[0].ToString(), 200, testResponse);
230//
231//// Console.WriteLine("Trying {0}", returnedUri);
232// HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri);
233//
234// AssertHttpResponse(returnedUri, testResponse);
235//
236// Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID));
237//
238// List<EventParams> events = m_engine.PostedEvents[m_scriptItem.ItemID];
239// Assert.That(events.Count, Is.EqualTo(1));
240// EventParams eventParams = events[0];
241// Assert.That(eventParams.EventName, Is.EqualTo("http_request"));
242//
243// UUID returnKey;
244// string rawReturnKey = eventParams.Params[0].ToString();
245// string method = eventParams.Params[1].ToString();
246// string body = eventParams.Params[2].ToString();
247//
248// Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True);
249// Assert.That(method, Is.EqualTo("GET"));
250// Assert.That(body, Is.EqualTo(""));
251// }
252// }
253//
254// private void AssertHttpResponse(string uri, string expectedResponse)
255// {
256// HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
257//
258// using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
259// {
260// using (Stream stream = webResponse.GetResponseStream())
261// {
262// using (StreamReader reader = new StreamReader(stream))
263// {
264// Assert.That(reader.ReadToEnd(), Is.EqualTo(expectedResponse));
265// }
266// }
267// }
268// }
269 }
270} \ No newline at end of file
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..e422f5b 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,13 +145,13 @@ 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(
153 m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, TestHelpers.ParseTail(0x900)); 154 m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, TestHelpers.ParseTail(0x900), "Hello World!");
154 155
155 bool exceptionCaught = false; 156 bool exceptionCaught = false;
156 157
@@ -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..74f010e 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
@@ -223,7 +222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
223 // Store an avatar with a different height from default in a notecard. 222 // Store an avatar with a different height from default in a notecard.
224 UUID userId = TestHelpers.ParseTail(0x1); 223 UUID userId = TestHelpers.ParseTail(0x1);
225 float firstHeight = 1.9f; 224 float firstHeight = 1.9f;
226 float secondHeight = 2.1f; 225// float secondHeight = 2.1f;
227 string firstAppearanceNcName = "appearanceNc1"; 226 string firstAppearanceNcName = "appearanceNc1";
228 string secondAppearanceNcName = "appearanceNc2"; 227 string secondAppearanceNcName = "appearanceNc2";
229 228
@@ -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/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
index bd26a8b..f0640da 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
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..17243ab 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,14 @@ 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;
51using OpenSim.Region.ScriptEngine.Shared.CodeTools; 52using OpenSim.Region.ScriptEngine.Shared.CodeTools;
52using OpenSim.Region.ScriptEngine.Shared.Instance; 53using OpenSim.Region.ScriptEngine.Shared.Instance;
53using OpenSim.Region.ScriptEngine.Shared.Api; 54using OpenSim.Region.ScriptEngine.Shared.Api;
54using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 55using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
55using OpenSim.Region.ScriptEngine.Interfaces; 56using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
57using OpenSim.Region.ScriptEngine.XEngine.ScriptBase;
56using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; 58using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
57 59
58using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; 60using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
@@ -107,6 +109,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
107 private IXmlRpcRouter m_XmlRpcRouter; 109 private IXmlRpcRouter m_XmlRpcRouter;
108 private int m_EventLimit; 110 private int m_EventLimit;
109 private bool m_KillTimedOutScripts; 111 private bool m_KillTimedOutScripts;
112
113 /// <summary>
114 /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
115 /// its thread.
116 /// </summary>
117 /// <remarks>
118 /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write
119 /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly
120 /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing
121 /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed
122 /// actually hold.
123 ///
124 /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads
125 /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately
126 /// shutting down.
127 /// </remarks>
128 private int m_WaitForEventCompletionOnScriptStop = 1000;
129
110 private string m_ScriptEnginesPath = null; 130 private string m_ScriptEnginesPath = null;
111 131
112 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); 132 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
@@ -218,11 +238,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
218 } 238 }
219 } 239 }
220 240
241 private ScriptEngineConsoleCommands m_consoleCommands;
242
221 public string ScriptEngineName 243 public string ScriptEngineName
222 { 244 {
223 get { return "XEngine"; } 245 get { return "XEngine"; }
224 } 246 }
225 247
248 public string ScriptClassName { get; private set; }
249
250 public string ScriptBaseClassName { get; private set; }
251
252 public ParameterInfo[] ScriptBaseClassParameters { get; private set; }
253
254 public string[] ScriptReferencedAssemblies { get; private set; }
255
226 public Scene World 256 public Scene World
227 { 257 {
228 get { return m_Scene; } 258 get { return m_Scene; }
@@ -277,21 +307,35 @@ namespace OpenSim.Region.ScriptEngine.XEngine
277 307
278 m_ScriptConfig = configSource.Configs["XEngine"]; 308 m_ScriptConfig = configSource.Configs["XEngine"];
279 m_ConfigSource = configSource; 309 m_ConfigSource = configSource;
310
311 string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "abort");
312
313 m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy);
314
315 if (rawScriptStopStrategy == "co-op")
316 {
317 ScriptClassName = "XEngineScript";
318 ScriptBaseClassName = typeof(XEngineScriptBase).FullName;
319 ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters();
320 ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) };
321 }
322 else
323 {
324 ScriptClassName = "Script";
325 ScriptBaseClassName = typeof(ScriptBaseClass).FullName;
326 }
327
328// Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]);
280 } 329 }
281 330
282 public void AddRegion(Scene scene) 331 public void AddRegion(Scene scene)
283 { 332 {
284 if (m_ScriptConfig == null) 333 if (m_ScriptConfig == null)
285 return; 334 return;
335
286 m_ScriptFailCount = 0; 336 m_ScriptFailCount = 0;
287 m_ScriptErrorMessage = String.Empty; 337 m_ScriptErrorMessage = String.Empty;
288 338
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); 339 m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true);
296 340
297 if (!m_Enabled) 341 if (!m_Enabled)
@@ -316,6 +360,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
316 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); 360 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
317 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); 361 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
318 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; 362 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
363 m_WaitForEventCompletionOnScriptStop
364 = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
365
319 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); 366 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
320 367
321 m_Prio = ThreadPriority.BelowNormal; 368 m_Prio = ThreadPriority.BelowNormal;
@@ -364,48 +411,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
364 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved; 411 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved;
365 } 412 }
366 413
414 m_consoleCommands = new ScriptEngineConsoleCommands(this);
415 m_consoleCommands.RegisterCommands();
416
367 MainConsole.Instance.Commands.AddCommand( 417 MainConsole.Instance.Commands.AddCommand(
368 "Scripts", false, "xengine status", "xengine status", "Show status information", 418 "Scripts", false, "xengine status", "xengine status", "Show status information",
369 "Show status information on the script engine.", 419 "Show status information on the script engine.",
370 HandleShowStatus); 420 HandleShowStatus);
371 421
372 MainConsole.Instance.Commands.AddCommand( 422 MainConsole.Instance.Commands.AddCommand(
373 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", 423 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>+]", "Show script information",
374 "Show information on all scripts known to the script engine." 424 "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.", 425 + "If one or more <script-item-uuid>s are given then only information on that script will be shown.",
376 HandleShowScripts); 426 HandleShowScripts);
377 427
378 MainConsole.Instance.Commands.AddCommand( 428 MainConsole.Instance.Commands.AddCommand(
379 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>]", "Show script information", 429 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>+]", "Show script information",
380 "Synonym for scripts show command", HandleShowScripts); 430 "Synonym for scripts show command", HandleShowScripts);
381 431
382 MainConsole.Instance.Commands.AddCommand( 432 MainConsole.Instance.Commands.AddCommand(
383 "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>]", "Suspends all running scripts", 433 "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" 434 "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a"
385 + " script that is currently processing an event.\n" 435 + " script that is currently processing an event.\n"
386 + "Suspended scripts will continue to accumulate events but won't process them.\n" 436 + "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.", 437 + "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)); 438 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript));
389 439
390 MainConsole.Instance.Commands.AddCommand( 440 MainConsole.Instance.Commands.AddCommand(
391 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", 441 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>+]", "Resumes all suspended scripts",
392 "Resumes all currently suspended scripts.\n" 442 "Resumes all currently suspended scripts.\n"
393 + "Resumed scripts will process all events accumulated whilst suspended." 443 + "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.", 444 + "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)); 445 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
396 446
397 MainConsole.Instance.Commands.AddCommand( 447 MainConsole.Instance.Commands.AddCommand(
398 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", 448 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>+]", "Stops all running scripts",
399 "Stops all running scripts." 449 "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.", 450 + "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)); 451 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
402 452
403 MainConsole.Instance.Commands.AddCommand( 453 MainConsole.Instance.Commands.AddCommand(
404 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", 454 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>+]", "Starts all stopped scripts",
405 "Starts all stopped scripts." 455 "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.", 456 + "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)); 457 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
408 458
459 MainConsole.Instance.Commands.AddCommand(
460 "Scripts", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
461 "Activates or deactivates extra debug logging for the given script.\n"
462 + "Level == 0, deactivate extra debug logging.\n"
463 + "Level >= 1, log state changes.\n"
464 + "Level >= 2, log event invocations.\n",
465 HandleDebugScriptLogCommand);
466
409// MainConsole.Instance.Commands.AddCommand( 467// MainConsole.Instance.Commands.AddCommand(
410// "Debug", false, "debug xengine", "debug xengine [<level>]", 468// "Debug", false, "debug xengine", "debug xengine [<level>]",
411// "Turn on detailed xengine debugging.", 469// "Turn on detailed xengine debugging.",
@@ -414,6 +472,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
414// HandleDebugLevelCommand); 472// HandleDebugLevelCommand);
415 } 473 }
416 474
475 private void HandleDebugScriptLogCommand(string module, string[] args)
476 {
477 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
478 return;
479
480 if (args.Length != 5)
481 {
482 MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
483 return;
484 }
485
486 UUID itemId;
487
488 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
489 return;
490
491 int newLevel;
492
493 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
494 return;
495
496 IScriptInstance si;
497
498 lock (m_Scripts)
499 {
500 // XXX: We can't give the user feedback on a bad item id because this may apply to a different script
501 // engine
502 if (!m_Scripts.TryGetValue(itemId, out si))
503 return;
504 }
505
506 si.DebugLevel = newLevel;
507 MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
508 }
509
417 /// <summary> 510 /// <summary>
418 /// Change debug level 511 /// Change debug level
419 /// </summary> 512 /// </summary>
@@ -445,9 +538,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
445 /// </summary> 538 /// </summary>
446 /// <param name="cmdparams"></param> 539 /// <param name="cmdparams"></param>
447 /// <param name="instance"></param> 540 /// <param name="instance"></param>
448 /// <returns>true if we're okay to proceed, false if not.</returns> 541 /// <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) 542 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action)
450 { 543 {
544 HandleScriptsAction<object>(cmdparams, action, null);
545 }
546
547 /// <summary>
548 /// Parse the raw item id into a script instance from the command params if it's present.
549 /// </summary>
550 /// <param name="cmdparams"></param>
551 /// <param name="instance"></param>
552 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
553 private void HandleScriptsAction<TKey>(
554 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
555 {
451 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 556 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
452 return; 557 return;
453 558
@@ -458,35 +563,42 @@ namespace OpenSim.Region.ScriptEngine.XEngine
458 563
459 if (cmdparams.Length == 2) 564 if (cmdparams.Length == 2)
460 { 565 {
461 foreach (IScriptInstance instance in m_Scripts.Values) 566 IEnumerable<IScriptInstance> scripts = m_Scripts.Values;
567
568 if (keySelector != null)
569 scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector);
570
571 foreach (IScriptInstance instance in scripts)
462 action(instance); 572 action(instance);
463 573
464 return; 574 return;
465 } 575 }
466 576
467 rawItemId = cmdparams[2]; 577 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 { 578 {
477 IScriptInstance instance = GetInstance(itemId); 579 rawItemId = cmdparams[i];
478 if (instance == null) 580
581 if (!UUID.TryParse(rawItemId, out itemId))
479 { 582 {
480 // Commented out for now since this will cause false reports on simulators with more than 583 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 584 continue;
482 // go to both regions... (sigh)
483// MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
484 return;
485 } 585 }
486 else 586
587 if (itemId != UUID.Zero)
487 { 588 {
488 action(instance); 589 IScriptInstance instance = GetInstance(itemId);
489 return; 590 if (instance == null)
591 {
592 // Commented out for now since this will cause false reports on simulators with more than
593 // one scene where the current command line set region is 'root' (which causes commands to
594 // go to both regions... (sigh)
595 // MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
596 continue;
597 }
598 else
599 {
600 action(instance);
601 }
490 } 602 }
491 } 603 }
492 } 604 }
@@ -505,9 +617,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
505 StringBuilder sb = new StringBuilder(); 617 StringBuilder sb = new StringBuilder();
506 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); 618 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName);
507 619
620 long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0;
621
508 lock (m_Scripts) 622 lock (m_Scripts)
509 sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); 623 {
624 scriptsLoaded = m_Scripts.Count;
510 625
626 foreach (IScriptInstance si in m_Scripts.Values)
627 {
628 eventsQueued += si.EventsQueued;
629 eventsProcessed += si.EventsProcessed;
630 }
631 }
632
633 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
511 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); 634 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
512 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 635 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
513 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 636 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
@@ -516,6 +639,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
516 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); 639 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads);
517 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); 640 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks);
518// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); 641// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count);
642 sb.AppendFormat("Events queued : {0}\n", eventsQueued);
643 sb.AppendFormat("Events processed : {0}\n", eventsProcessed);
519 644
520 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); 645 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this);
521 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); 646 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0);
@@ -546,7 +671,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
546 } 671 }
547 } 672 }
548 673
549 HandleScriptsAction(cmdparams, HandleShowScript); 674 HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed);
550 } 675 }
551 676
552 private void HandleShowScript(IScriptInstance instance) 677 private void HandleShowScript(IScriptInstance instance)
@@ -572,15 +697,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
572 } 697 }
573 698
574 StringBuilder sb = new StringBuilder(); 699 StringBuilder sb = new StringBuilder();
575 Queue eq = instance.EventQueue;
576 700
577 sb.AppendFormat("Script name : {0}\n", instance.ScriptName); 701 sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
578 sb.AppendFormat("Status : {0}\n", status); 702 sb.AppendFormat("Status : {0}\n", status);
579 703 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
580 lock (eq) 704 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); 705 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
706 sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
584 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); 707 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
585 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); 708 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
586 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); 709 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
@@ -1079,7 +1202,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1079 } 1202 }
1080 1203
1081 m_log.DebugFormat( 1204 m_log.DebugFormat(
1082 "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1205 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1083 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1206 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1084 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1207 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1085 1208
@@ -1089,8 +1212,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 1212
1090 string assembly = ""; 1213 string assembly = "";
1091 1214
1092 CultureInfo USCulture = new CultureInfo("en-US"); 1215 Culture.SetCurrentCulture();
1093 Thread.CurrentThread.CurrentCulture = USCulture;
1094 1216
1095 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 1217 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
1096 1218
@@ -1101,6 +1223,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1101 lock (m_AddingAssemblies) 1223 lock (m_AddingAssemblies)
1102 { 1224 {
1103 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); 1225 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap);
1226
1104 if (!m_AddingAssemblies.ContainsKey(assembly)) { 1227 if (!m_AddingAssemblies.ContainsKey(assembly)) {
1105 m_AddingAssemblies[assembly] = 1; 1228 m_AddingAssemblies[assembly] = 1;
1106 } else { 1229 } else {
@@ -1150,7 +1273,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1150 } 1273 }
1151 catch (Exception e) 1274 catch (Exception e)
1152 { 1275 {
1153// m_log.ErrorFormat("[XEngine]: Exception when rezzing script {0}{1}", e.Message, e.StackTrace); 1276// m_log.ErrorFormat(
1277// "[XEngine]: Exception when rezzing script with item ID {0}, {1}{2}",
1278// itemID, e.Message, e.StackTrace);
1154 1279
1155 // try 1280 // try
1156 // { 1281 // {
@@ -1229,13 +1354,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1229 sandbox = AppDomain.CurrentDomain; 1354 sandbox = AppDomain.CurrentDomain;
1230 } 1355 }
1231 1356
1232 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1357 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
1233 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1358 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 1359
1240 m_AppDomains[appDomain] = sandbox; 1360 m_AppDomains[appDomain] = sandbox;
1241 1361
@@ -1256,12 +1376,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1256 m_DomainScripts[appDomain].Add(itemID); 1376 m_DomainScripts[appDomain].Add(itemID);
1257 1377
1258 instance = new ScriptInstance(this, part, 1378 instance = new ScriptInstance(this, part,
1259 itemID, assetID, assembly, 1379 item,
1260 m_AppDomains[appDomain], 1380 startParam, postOnRez,
1261 part.ParentGroup.RootPart.Name, 1381 m_MaxScriptQueue);
1262 item.Name, startParam, postOnRez,
1263 stateSource, m_MaxScriptQueue);
1264 1382
1383 instance.Load(m_AppDomains[appDomain], assembly, stateSource);
1265// m_log.DebugFormat( 1384// m_log.DebugFormat(
1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1385// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1386// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
@@ -1347,9 +1466,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1347 lockScriptsForWrite(false); 1466 lockScriptsForWrite(false);
1348 instance.ClearQueue(); 1467 instance.ClearQueue();
1349 1468
1350 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1469 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 1470
1354// bool objectRemoved = false; 1471// bool objectRemoved = false;
1355 1472
@@ -1477,7 +1594,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1477 m_MaxScriptQueue = maxScriptQueue; 1594 m_MaxScriptQueue = maxScriptQueue;
1478 1595
1479 STPStartInfo startInfo = new STPStartInfo(); 1596 STPStartInfo startInfo = new STPStartInfo();
1480 startInfo.IdleTimeout = idleTimeout*1000; // convert to seconds as stated in .ini 1597 startInfo.ThreadPoolName = "XEngine";
1598 startInfo.IdleTimeout = idleTimeout * 1000; // convert to seconds as stated in .ini
1481 startInfo.MaxWorkerThreads = maxThreads; 1599 startInfo.MaxWorkerThreads = maxThreads;
1482 startInfo.MinWorkerThreads = minThreads; 1600 startInfo.MinWorkerThreads = minThreads;
1483 startInfo.ThreadPriority = threadPriority;; 1601 startInfo.ThreadPriority = threadPriority;;
@@ -1504,8 +1622,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 /// <returns></returns> 1622 /// <returns></returns>
1505 private object ProcessEventHandler(object parms) 1623 private object ProcessEventHandler(object parms)
1506 { 1624 {
1507 CultureInfo USCulture = new CultureInfo("en-US"); 1625 Culture.SetCurrentCulture();
1508 Thread.CurrentThread.CurrentCulture = USCulture;
1509 1626
1510 IScriptInstance instance = (ScriptInstance) parms; 1627 IScriptInstance instance = (ScriptInstance) parms;
1511 1628
@@ -1693,7 +1810,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1693 { 1810 {
1694 IScriptInstance instance = GetInstance(itemID); 1811 IScriptInstance instance = GetInstance(itemID);
1695 if (instance != null) 1812 if (instance != null)
1696 instance.ResetScript(); 1813 instance.ResetScript(m_WaitForEventCompletionOnScriptStop);
1697 } 1814 }
1698 1815
1699 public void StartScript(UUID itemID) 1816 public void StartScript(UUID itemID)
@@ -1708,14 +1825,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1708 public void StopScript(UUID itemID) 1825 public void StopScript(UUID itemID)
1709 { 1826 {
1710 IScriptInstance instance = GetInstance(itemID); 1827 IScriptInstance instance = GetInstance(itemID);
1828
1711 if (instance != null) 1829 if (instance != null)
1712 { 1830 {
1713 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1831 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 } 1832 }
1717 else 1833 else
1718 { 1834 {
1835// 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); 1836 m_runFlags.AddOrUpdate(itemID, false, 240);
1720 } 1837 }
1721 } 1838 }
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
index 2ac5c31..8dd7677 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
@@ -57,8 +57,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
57 wr.Abort(); 57 wr.Abort();
58 } 58 }
59 59
60 public bool Wait(TimeSpan t) 60 public bool Wait(int t)
61 { 61 {
62 // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
63 // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
64 // int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8
65 // (or very likely other versions of Mono at least up until 3.0.3).
62 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); 66 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
63 } 67 }
64 } 68 }