aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/IScript.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs479
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs317
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs510
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs35
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs (renamed from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs)3
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs (renamed from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs)2
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs (renamed from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs)2
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs (renamed from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs)4
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs (renamed from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs)2
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs268
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs460
14 files changed, 721 insertions, 1367 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/IScript.cs b/OpenSim/Region/ScriptEngine/Common/IScript.cs
index 8d91071..d38dc7b 100644
--- a/OpenSim/Region/ScriptEngine/Common/IScript.cs
+++ b/OpenSim/Region/ScriptEngine/Common/IScript.cs
@@ -25,7 +25,6 @@
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 OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
29using OpenSim.Region.ScriptEngine.Shared; 28using OpenSim.Region.ScriptEngine.Shared;
30using OpenSim.Region.ScriptEngine.Interfaces; 29using OpenSim.Region.ScriptEngine.Interfaces;
31 30
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs
index 927ab2c..dc3ae05 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs
@@ -29,7 +29,6 @@ using System;
29using System.Runtime.Remoting.Lifetime; 29using System.Runtime.Remoting.Lifetime;
30using System.Threading; 30using System.Threading;
31using OpenSim.Region.Environment.Interfaces; 31using OpenSim.Region.Environment.Interfaces;
32using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
33using OpenSim.Region.ScriptEngine.Shared; 32using OpenSim.Region.ScriptEngine.Shared;
34using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; 33using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
35using OpenSim.Region.ScriptEngine.Interfaces; 34using OpenSim.Region.ScriptEngine.Interfaces;
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
deleted file mode 100644
index 8293fae..0000000
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs
+++ /dev/null
@@ -1,479 +0,0 @@
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 OpenSim 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 OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney;
33using OpenSim.Region.Environment;
34using OpenSim.Region.Interfaces;
35using OpenSim.Region;
36using OpenSim.Region.Environment.Scenes;
37using OpenSim.Region.Environment.Interfaces;
38using OpenSim.Region.ScriptEngine.Shared;
39
40namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
41{
42 /// <summary>
43 /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
44 /// </summary>
45 [Serializable]
46 public class EventManager : iScriptEngineFunctionModule
47 {
48 //
49 // Class is instanced in "ScriptEngine" and Uses "EventQueueManager" that is also instanced in "ScriptEngine".
50 // This class needs a bit of explaining:
51 //
52 // This class it the link between an event inside OpenSim and the corresponding event in a user script being executed.
53 //
54 // For example when an user touches an object then the "myScriptEngine.World.EventManager.OnObjectGrab" event is fired inside OpenSim.
55 // We hook up to this event and queue a touch_start in EventQueueManager with the proper LSL parameters.
56 // It will then be delivered to the script by EventQueueManager.
57 //
58 // You can check debug C# dump of an LSL script if you need to verify what exact parameters are needed.
59 //
60
61
62 private ScriptEngine myScriptEngine;
63 //public IScriptHost TEMP_OBJECT_ID;
64 public EventManager(ScriptEngine _ScriptEngine, bool performHookUp)
65 {
66 myScriptEngine = _ScriptEngine;
67 ReadConfig();
68
69 if (performHookUp)
70 {
71 myScriptEngine.World.EventManager.OnRezScript += OnRezScript;
72 }
73 }
74
75 public void HookUpEvents()
76 {
77 // Hook up to events from OpenSim
78 // We may not want to do it because someone is controlling us and will deliver events to us
79
80 myScriptEngine.Log.Info("[" + myScriptEngine.ScriptEngineName + "]: Hooking up to server events");
81 myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
82 myScriptEngine.World.EventManager.OnObjectDeGrab += touch_end;
83 myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript;
84 myScriptEngine.World.EventManager.OnScriptChangedEvent += changed;
85 myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target;
86 myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target;
87 myScriptEngine.World.EventManager.OnScriptControlEvent += control;
88 myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start;
89 myScriptEngine.World.EventManager.OnScriptColliding += collision;
90 myScriptEngine.World.EventManager.OnScriptCollidingEnd += collision_end;
91
92 // TODO: HOOK ALL EVENTS UP TO SERVER!
93 IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
94 if (money != null)
95 {
96 money.OnObjectPaid+=HandleObjectPaid;
97 }
98
99 }
100
101 public void ReadConfig()
102 {
103 }
104
105 private void HandleObjectPaid(UUID objectID, UUID agentID, int amount)
106 {
107 SceneObjectPart part=myScriptEngine.World.GetSceneObjectPart(objectID);
108 if (part != null)
109 {
110 money(part.LocalId, agentID, amount);
111 }
112 }
113
114 public void changed(uint localID, uint change)
115 {
116 // Add to queue for all scripts in localID, Object pass change.
117 myScriptEngine.PostObjectEvent(localID, new EventParams(
118 "changed",new object[] { new LSL_Types.LSLInteger(change) },
119 new DetectParams[0]));
120 }
121
122 public void state_entry(uint localID)
123 {
124 // Add to queue for all scripts in ObjectID object
125 myScriptEngine.PostObjectEvent(localID, new EventParams(
126 "state_entry",new object[] { },
127 new DetectParams[0]));
128 }
129
130 public void touch_start(uint localID, uint originalID, Vector3 offsetPos,
131 IClientAPI remoteClient)
132 {
133 // Add to queue for all scripts in ObjectID object
134 DetectParams[] det = new DetectParams[1];
135 det[0] = new DetectParams();
136 det[0].Key = remoteClient.AgentId;
137 det[0].Populate(myScriptEngine.World);
138
139 if (originalID == 0)
140 {
141 SceneObjectPart part = myScriptEngine.World.GetSceneObjectPart(localID);
142 if (part == null)
143 return;
144
145 det[0].LinkNum = part.LinkNum;
146 }
147 else
148 {
149 SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID);
150 det[0].LinkNum = originalPart.LinkNum;
151 }
152
153 myScriptEngine.PostObjectEvent(localID, new EventParams(
154 "touch_start", new Object[] { new LSL_Types.LSLInteger(1) },
155 det));
156 }
157
158 public void touch(uint localID, uint originalID, Vector3 offsetPos,
159 IClientAPI remoteClient)
160 {
161 // Add to queue for all scripts in ObjectID object
162 DetectParams[] det = new DetectParams[1];
163 det[0] = new DetectParams();
164 det[0].Key = remoteClient.AgentId;
165 det[0].Populate(myScriptEngine.World);
166 det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X,
167 offsetPos.Y,
168 offsetPos.Z);
169
170 if (originalID == 0)
171 {
172 SceneObjectPart part = myScriptEngine.World.GetSceneObjectPart(localID);
173 if (part == null)
174 return;
175
176 det[0].LinkNum = part.LinkNum;
177 }
178 else
179 {
180 SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID);
181 det[0].LinkNum = originalPart.LinkNum;
182 }
183
184 myScriptEngine.PostObjectEvent(localID, new EventParams(
185 "touch", new Object[] { new LSL_Types.LSLInteger(1) },
186 det));
187 }
188
189 public void touch_end(uint localID, uint originalID, IClientAPI remoteClient)
190 {
191 // Add to queue for all scripts in ObjectID object
192 DetectParams[] det = new DetectParams[1];
193 det[0] = new DetectParams();
194 det[0].Key = remoteClient.AgentId;
195 det[0].Populate(myScriptEngine.World);
196
197 if (originalID == 0)
198 {
199 SceneObjectPart part = myScriptEngine.World.GetSceneObjectPart(localID);
200 if (part == null)
201 return;
202
203 det[0].LinkNum = part.LinkNum;
204 }
205 else
206 {
207 SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID);
208 det[0].LinkNum = originalPart.LinkNum;
209 }
210
211 myScriptEngine.PostObjectEvent(localID, new EventParams(
212 "touch_end", new Object[] { new LSL_Types.LSLInteger(1) },
213 det));
214 }
215
216 public void OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine)
217 {
218 List<IScriptModule> engines = new List<IScriptModule>(myScriptEngine.World.RequestModuleInterfaces<IScriptModule>());
219
220 List<string> names = new List<string>();
221 foreach (IScriptModule m in engines)
222 names.Add(m.ScriptEngineName);
223
224 int lineEnd = script.IndexOf('\n');
225
226 if (lineEnd != 1)
227 {
228 string firstline = script.Substring(0, lineEnd).Trim();
229
230 int colon = firstline.IndexOf(':');
231 if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1)
232 {
233 string engineName = firstline.Substring(2, colon-2);
234
235 if (names.Contains(engineName))
236 {
237 engine = engineName;
238 script = "//" + script.Substring(script.IndexOf(':')+1);
239 }
240 }
241 }
242
243 if (engine != myScriptEngine.ScriptEngineName)
244 return;
245
246 myScriptEngine.Log.Debug("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " +
247 script.Length);
248 myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script, startParam, postOnRez);
249 }
250
251 public void OnRemoveScript(uint localID, UUID itemID)
252 {
253 myScriptEngine.Log.Debug("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString());
254 myScriptEngine.m_ScriptManager.StopScript(
255 localID,
256 itemID
257 );
258 }
259
260 public void money(uint localID, UUID agentID, int amount)
261 {
262 myScriptEngine.PostObjectEvent(localID, new EventParams(
263 "money", new object[] {
264 new LSL_Types.LSLString(agentID.ToString()),
265 new LSL_Types.LSLInteger(amount) },
266 new DetectParams[0]));
267 }
268
269 // TODO: Replace placeholders below
270 // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT!
271 // These needs to be hooked up to OpenSim during init of this class
272 // then queued in EventQueueManager.
273 // When queued in EventQueueManager they need to be LSL compatible (name and params)
274
275 public void state_exit(uint localID)
276 {
277 myScriptEngine.PostObjectEvent(localID, new EventParams(
278 "state_exit", new object[] { },
279 new DetectParams[0]));
280 }
281
282 public void collision_start(uint localID, ColliderArgs col)
283 {
284 // Add to queue for all scripts in ObjectID object
285 List<DetectParams> det = new List<DetectParams>();
286
287 foreach (DetectedObject detobj in col.Colliders)
288 {
289 DetectParams d = new DetectParams();
290 d.Key =detobj.keyUUID;
291 d.Populate(myScriptEngine.World);
292 det.Add(d);
293 }
294
295 if (det.Count > 0)
296 myScriptEngine.PostObjectEvent(localID, new EventParams(
297 "collision_start",
298 new Object[] { new LSL_Types.LSLInteger(det.Count) },
299 det.ToArray()));
300 }
301
302 public void collision(uint localID, ColliderArgs col)
303 {
304 // Add to queue for all scripts in ObjectID object
305 List<DetectParams> det = new List<DetectParams>();
306
307 foreach (DetectedObject detobj in col.Colliders)
308 {
309 DetectParams d = new DetectParams();
310 d.Key =detobj.keyUUID;
311 d.Populate(myScriptEngine.World);
312 det.Add(d);
313 }
314
315 if (det.Count > 0)
316 myScriptEngine.PostObjectEvent(localID, new EventParams(
317 "collision", new Object[] { new LSL_Types.LSLInteger(det.Count) },
318 det.ToArray()));
319 }
320
321 public void collision_end(uint localID, ColliderArgs col)
322 {
323 // Add to queue for all scripts in ObjectID object
324 List<DetectParams> det = new List<DetectParams>();
325
326 foreach (DetectedObject detobj in col.Colliders)
327 {
328 DetectParams d = new DetectParams();
329 d.Key =detobj.keyUUID;
330 d.Populate(myScriptEngine.World);
331 det.Add(d);
332 }
333
334 if (det.Count > 0)
335 myScriptEngine.PostObjectEvent(localID, new EventParams(
336 "collision_end",
337 new Object[] { new LSL_Types.LSLInteger(det.Count) },
338 det.ToArray()));
339 }
340
341 public void land_collision_start(uint localID, UUID itemID)
342 {
343 myScriptEngine.PostObjectEvent(localID, new EventParams(
344 "land_collision_start",
345 new object[0],
346 new DetectParams[0]));
347 }
348
349 public void land_collision(uint localID, UUID itemID)
350 {
351 myScriptEngine.PostObjectEvent(localID, new EventParams(
352 "land_collision",
353 new object[0],
354 new DetectParams[0]));
355 }
356
357 public void land_collision_end(uint localID, UUID itemID)
358 {
359 myScriptEngine.PostObjectEvent(localID, new EventParams(
360 "land_collision_end",
361 new object[0],
362 new DetectParams[0]));
363 }
364
365 // Handled by long commands
366 public void timer(uint localID, UUID itemID)
367 {
368 }
369
370 public void listen(uint localID, UUID itemID)
371 {
372 }
373
374 public void control(uint localID, UUID itemID, UUID agentID, uint held, uint change)
375 {
376 if ((change == 0) && (myScriptEngine.m_EventQueueManager.CheckEeventQueueForEvent(localID,"control"))) return;
377 myScriptEngine.PostObjectEvent(localID, new EventParams(
378 "control",new object[] {
379 new LSL_Types.LSLString(agentID.ToString()),
380 new LSL_Types.LSLInteger(held),
381 new LSL_Types.LSLInteger(change)},
382 new DetectParams[0]));
383 }
384
385 public void email(uint localID, UUID itemID, string timeSent,
386 string address, string subject, string message, int numLeft)
387 {
388 myScriptEngine.PostObjectEvent(localID, new EventParams(
389 "email",new object[] {
390 new LSL_Types.LSLString(timeSent),
391 new LSL_Types.LSLString(address),
392 new LSL_Types.LSLString(subject),
393 new LSL_Types.LSLString(message),
394 new LSL_Types.LSLInteger(numLeft)},
395 new DetectParams[0]));
396 }
397
398 public void at_target(uint localID, uint handle, Vector3 targetpos,
399 Vector3 atpos)
400 {
401 myScriptEngine.PostObjectEvent(localID, new EventParams(
402 "at_target", new object[] {
403 new LSL_Types.LSLInteger(handle),
404 new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z),
405 new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) },
406 new DetectParams[0]));
407 }
408
409 public void not_at_target(uint localID)
410 {
411 myScriptEngine.PostObjectEvent(localID, new EventParams(
412 "not_at_target",new object[0],
413 new DetectParams[0]));
414 }
415
416 public void at_rot_target(uint localID, UUID itemID)
417 {
418 myScriptEngine.PostObjectEvent(localID, new EventParams(
419 "at_rot_target",new object[0],
420 new DetectParams[0]));
421 }
422
423 public void not_at_rot_target(uint localID, UUID itemID)
424 {
425 myScriptEngine.PostObjectEvent(localID, new EventParams(
426 "not_at_rot_target",new object[0],
427 new DetectParams[0]));
428 }
429
430 public void attach(uint localID, UUID itemID)
431 {
432 }
433
434 public void dataserver(uint localID, UUID itemID)
435 {
436 }
437
438 public void link_message(uint localID, UUID itemID)
439 {
440 }
441
442 public void moving_start(uint localID, UUID itemID)
443 {
444 myScriptEngine.PostObjectEvent(localID, new EventParams(
445 "moving_start",new object[0],
446 new DetectParams[0]));
447 }
448
449 public void moving_end(uint localID, UUID itemID)
450 {
451 myScriptEngine.PostObjectEvent(localID, new EventParams(
452 "moving_end",new object[0],
453 new DetectParams[0]));
454 }
455
456 public void object_rez(uint localID, UUID itemID)
457 {
458 }
459
460 public void remote_data(uint localID, UUID itemID)
461 {
462 }
463
464 // Handled by long commands
465 public void http_response(uint localID, UUID itemID)
466 {
467 }
468
469 /// <summary>
470 /// If set to true then threads and stuff should try to make a graceful exit
471 /// </summary>
472 public bool PleaseShutdown
473 {
474 get { return _PleaseShutdown; }
475 set { _PleaseShutdown = value; }
476 }
477 private bool _PleaseShutdown = false;
478 }
479}
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
deleted file mode 100644
index f259ec1..0000000
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
+++ /dev/null
@@ -1,317 +0,0 @@
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 OpenSim 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.Reflection;
31using log4net;
32using Nini.Config;
33using OpenSim.Region.Interfaces;
34using OpenSim.Region.Environment.Interfaces;
35using OpenSim.Region.Environment.Scenes;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenMetaverse;
38using OpenSim.Region.ScriptEngine.Shared;
39
40namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
41{
42 /// <summary>
43 /// This is the root object for ScriptEngine. Objects access each other trough this class.
44 /// </summary>
45 ///
46 [Serializable]
47 public abstract class ScriptEngine : IRegionModule, IScriptModule, iScriptEngineFunctionModule, IEventReceiver
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 public static List<ScriptEngine> ScriptEngines = new List<ScriptEngine>();
52 private Scene m_Scene;
53 public Scene World
54 {
55 get { return m_Scene; }
56 }
57 public EventManager m_EventManager; // Handles and queues incoming events from OpenSim
58 public EventQueueManager m_EventQueueManager; // Executes events, handles script threads
59 public ScriptManager m_ScriptManager; // Load, unload and execute scripts
60 public AppDomainManager m_AppDomainManager; // Handles loading/unloading of scripts into AppDomains
61 public static MaintenanceThread m_MaintenanceThread; // Thread that does different kinds of maintenance, for example refreshing config and killing scripts that has been running too long
62
63 public IConfigSource ConfigSource;
64 public IConfig ScriptConfigSource;
65 public abstract string ScriptEngineName { get; }
66 private bool m_enabled = false;
67 private bool m_hookUpToServer = false;
68
69 public IConfig Config
70 {
71 get { return ScriptConfigSource; }
72 }
73
74 /// <summary>
75 /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes.
76 /// </summary>
77 public int RefreshConfigFileSeconds {
78 get { return (int)(RefreshConfigFilens / 10000000); }
79 set { RefreshConfigFilens = value * 10000000; }
80 }
81 public long RefreshConfigFilens;
82
83 public ScriptManager GetScriptManager()
84 {
85 return _GetScriptManager();
86 }
87
88 public abstract ScriptManager _GetScriptManager();
89
90 public ILog Log
91 {
92 get { return m_log; }
93 }
94
95 public ScriptEngine()
96 {
97 Common.mySE = this; // For logging, just need any instance, doesn't matter
98 lock (ScriptEngines)
99 {
100 ScriptEngines.Add(this); // Keep a list of ScriptEngines for shared threads to process all instances
101 }
102 }
103
104 public void InitializeEngine(Scene Sceneworld, IConfigSource config, bool HookUpToServer, ScriptManager newScriptManager)
105 {
106 m_Scene = Sceneworld;
107 ConfigSource = config;
108 m_hookUpToServer = HookUpToServer;
109
110 m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing");
111
112 // Make sure we have config
113 if (ConfigSource.Configs[ScriptEngineName] == null)
114 ConfigSource.AddConfig(ScriptEngineName);
115 ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
116
117 m_enabled = ScriptConfigSource.GetBoolean("Enabled", true);
118 if (!m_enabled)
119 return;
120
121 //m_log.Info("[" + ScriptEngineName + "]: InitializeEngine");
122
123 // Create all objects we'll be using
124 m_EventQueueManager = new EventQueueManager(this);
125 m_EventManager = new EventManager(this, HookUpToServer);
126 // We need to start it
127 m_ScriptManager = newScriptManager;
128 m_ScriptManager.Setup();
129 m_AppDomainManager = new AppDomainManager(this);
130 if (m_MaintenanceThread == null)
131 m_MaintenanceThread = new MaintenanceThread();
132
133 m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\"");
134 ReadConfig();
135
136 m_Scene.StackModuleInterface<IScriptModule>(this);
137 }
138
139 public void PostInitialise()
140 {
141 if (!m_enabled)
142 return;
143
144 if (m_hookUpToServer)
145 m_EventManager.HookUpEvents();
146
147 m_ScriptManager.Start();
148 }
149
150 public void Shutdown()
151 {
152 // We are shutting down
153 lock (ScriptEngines)
154 {
155 ScriptEngines.Remove(this);
156 }
157 }
158
159 public void ReadConfig()
160 {
161#if DEBUG
162 //m_log.Debug("[" + ScriptEngineName + "]: Refreshing configuration for all modules");
163#endif
164 RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30);
165
166
167 // Create a new object (probably not necessary?)
168// ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
169
170 if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig();
171 if (m_EventManager != null) m_EventManager.ReadConfig();
172 if (m_ScriptManager != null) m_ScriptManager.ReadConfig();
173 if (m_AppDomainManager != null) m_AppDomainManager.ReadConfig();
174 if (m_MaintenanceThread != null) m_MaintenanceThread.ReadConfig();
175 }
176
177 #region IRegionModule
178
179 public abstract void Initialise(Scene scene, IConfigSource config);
180
181 public void Close()
182 {
183 }
184
185 public string Name
186 {
187 get { return "Common." + ScriptEngineName; }
188 }
189
190 public bool IsSharedModule
191 {
192 get { return false; }
193 }
194
195 public bool PostObjectEvent(uint localID, EventParams p)
196 {
197 return m_EventQueueManager.AddToObjectQueue(localID, p.EventName, p.DetectParams, p.Params);
198 }
199
200 public bool PostScriptEvent(UUID itemID, EventParams p)
201 {
202 uint localID = m_ScriptManager.GetLocalID(itemID);
203 return m_EventQueueManager.AddToScriptQueue(localID, itemID, p.EventName, p.DetectParams, p.Params);
204 }
205
206 public DetectParams GetDetectParams(UUID itemID, int number)
207 {
208 uint localID = m_ScriptManager.GetLocalID(itemID);
209 if (localID == 0)
210 return null;
211
212 IScript Script = m_ScriptManager.GetScript(localID, itemID);
213
214 if (Script == null)
215 return null;
216
217 DetectParams[] det = m_ScriptManager.GetDetectParams(Script);
218
219 if (number < 0 || number >= det.Length)
220 return null;
221
222 return det[number];
223 }
224
225 public int GetStartParameter(UUID itemID)
226 {
227 return 0;
228 }
229 #endregion
230
231 public void SetState(UUID itemID, string state)
232 {
233 uint localID = m_ScriptManager.GetLocalID(itemID);
234 if (localID == 0)
235 return;
236
237 IScript Script = m_ScriptManager.GetScript(localID, itemID);
238
239 if (Script == null)
240 return;
241
242 string currentState = Script.State;
243
244 if (currentState != state)
245 {
246 try
247 {
248 m_EventManager.state_exit(localID);
249
250 }
251 catch (AppDomainUnloadedException)
252 {
253 Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance");
254 }
255
256 Script.State = state;
257
258 try
259 {
260 int eventFlags = m_ScriptManager.GetStateEventFlags(localID, itemID);
261 SceneObjectPart part = m_Scene.GetSceneObjectPart(itemID);
262 if (part != null)
263 part.SetScriptEvents(itemID, eventFlags);
264 m_EventManager.state_entry(localID);
265 }
266 catch (AppDomainUnloadedException)
267 {
268 Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance");
269 }
270 }
271 }
272
273 public bool GetScriptState(UUID itemID)
274 {
275 uint localID = m_ScriptManager.GetLocalID(itemID);
276 if (localID == 0)
277 return false;
278
279 IScript script = m_ScriptManager.GetScript(localID, itemID);
280 if (script == null)
281 return false;
282
283 return script.Exec.Running?true:false;
284 }
285
286 public void SetScriptState(UUID itemID, bool state)
287 {
288 uint localID = m_ScriptManager.GetLocalID(itemID);
289 if (localID == 0)
290 return;
291
292 IScript script = m_ScriptManager.GetScript(localID, itemID);
293 if (script == null)
294 return;
295
296 script.Exec.Running = state;
297 }
298
299 public void ApiResetScript(UUID itemID)
300 {
301 uint localID = m_ScriptManager.GetLocalID(itemID);
302 if (localID == 0)
303 return;
304
305 m_ScriptManager.ResetScript(localID, itemID);
306 }
307
308 public void ResetScript(UUID itemID)
309 {
310 uint localID = m_ScriptManager.GetLocalID(itemID);
311 if (localID == 0)
312 return;
313
314 m_ScriptManager.ResetScript(localID, itemID);
315 }
316 }
317}
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
deleted file mode 100644
index 987a0a0..0000000
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
+++ /dev/null
@@ -1,510 +0,0 @@
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 OpenSim 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.Reflection;
32using System.Runtime.Serialization.Formatters.Binary;
33using System.Threading;
34using OpenMetaverse;
35using OpenSim.Region.Environment.Scenes;
36using OpenSim.Region.ScriptEngine.Shared;
37
38namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
39{
40 /// <summary>
41 /// Loads scripts
42 /// Compiles them if necessary
43 /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
44 /// </summary>
45 ///
46
47 // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes.
48 // * Keeps track of running scripts
49 // * Compiles script if necessary (through "Compiler")
50 // * Loads script (through "AppDomainManager" called from for example "EventQueueManager")
51 // * Executes functions inside script (called from for example "EventQueueManager" class)
52 // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager")
53 // * Dedicated load/unload thread, and queues loading/unloading.
54 // This so that scripts starting or stopping will not slow down other theads or whole system.
55 //
56 [Serializable]
57 public abstract class ScriptManager : iScriptEngineFunctionModule
58 {
59 #region Declares
60
61 private Thread scriptLoadUnloadThread;
62 private static Thread staticScriptLoadUnloadThread;
63 // private int scriptLoadUnloadThread_IdleSleepms;
64 private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
65 private static bool PrivateThread;
66 private int LoadUnloadMaxQueueSize;
67 private Object scriptLock = new Object();
68 private bool m_started = false;
69 private Dictionary<IScript, DetectParams[]> detparms = new Dictionary<IScript, DetectParams[]>();
70
71 // Load/Unload structure
72 private struct LUStruct
73 {
74 public uint localID;
75 public UUID itemID;
76 public string script;
77 public LUType Action;
78 public int startParam;
79 public bool postOnRez;
80 }
81
82 private enum LUType
83 {
84 Unknown = 0,
85 Load = 1,
86 Unload = 2
87 }
88
89 // Xantor 20080525: Keep a list of compiled scripts this session for reuse
90 public Dictionary<UUID, String> scriptList = new Dictionary<UUID, string>();
91
92 // Object<string, Script<string, script>>
93 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
94 // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
95 public Dictionary<uint, Dictionary<UUID, IScript>> Scripts =
96 new Dictionary<uint, Dictionary<UUID, IScript>>();
97
98
99 public Scene World
100 {
101 get { return m_scriptEngine.World; }
102 }
103
104 #endregion
105
106 public void ReadConfig()
107 {
108 // scriptLoadUnloadThread_IdleSleepms = m_scriptEngine.ScriptConfigSource.GetInt("ScriptLoadUnloadLoopms", 30);
109 // TODO: Requires sharing of all ScriptManagers to single thread
110 PrivateThread = true; // m_scriptEngine.ScriptConfigSource.GetBoolean("PrivateScriptLoadUnloadThread", false);
111 LoadUnloadMaxQueueSize = m_scriptEngine.ScriptConfigSource.GetInt("LoadUnloadMaxQueueSize", 100);
112 }
113
114 #region Object init/shutdown
115
116 public ScriptEngine m_scriptEngine;
117
118 public ScriptManager(ScriptEngine scriptEngine)
119 {
120 m_scriptEngine = scriptEngine;
121 }
122 public abstract void Initialize();
123 public void Setup()
124 {
125 ReadConfig();
126 Initialize();
127 }
128 public void Start()
129 {
130 m_started = true;
131
132
133 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
134
135 //
136 // CREATE THREAD
137 // Private or shared
138 //
139 if (PrivateThread)
140 {
141 // Assign one thread per region
142 //scriptLoadUnloadThread = StartScriptLoadUnloadThread();
143 }
144 else
145 {
146 // Shared thread - make sure one exist, then assign it to the private
147 if (staticScriptLoadUnloadThread == null)
148 {
149 //staticScriptLoadUnloadThread = StartScriptLoadUnloadThread();
150 }
151 scriptLoadUnloadThread = staticScriptLoadUnloadThread;
152 }
153 }
154
155// TODO: unused
156// private static int privateThreadCount = 0;
157// private Thread StartScriptLoadUnloadThread()
158// {
159// Thread t = new Thread(ScriptLoadUnloadThreadLoop);
160// string name = "ScriptLoadUnloadThread:";
161// if (PrivateThread)
162// {
163// name += "Private:" + privateThreadCount;
164// privateThreadCount++;
165// }
166// else
167// {
168// name += "Shared";
169// }
170// t.Name = name;
171// t.IsBackground = true;
172// t.Priority = ThreadPriority.Normal;
173// t.Start();
174// OpenSim.Framework.ThreadTracker.Add(t);
175// return t;
176// }
177
178 ~ScriptManager()
179 {
180 // Abort load/unload thread
181 try
182 {
183 //PleaseShutdown = true;
184 //Thread.Sleep(100);
185 if (scriptLoadUnloadThread != null && scriptLoadUnloadThread.IsAlive == true)
186 {
187 scriptLoadUnloadThread.Abort();
188 //scriptLoadUnloadThread.Join();
189 }
190 }
191 catch
192 {
193 }
194 }
195
196 #endregion
197
198 #region Load / Unload scripts (Thread loop)
199
200// TODO: unused
201// private void ScriptLoadUnloadThreadLoop()
202// {
203// try
204// {
205// while (true)
206// {
207// if (LUQueue.Count == 0)
208// Thread.Sleep(scriptLoadUnloadThread_IdleSleepms);
209// //if (PleaseShutdown)
210// // return;
211// DoScriptLoadUnload();
212// }
213// }
214// catch (ThreadAbortException tae)
215// {
216// string a = tae.ToString();
217// a = String.Empty;
218// // Expected
219// }
220// }
221
222 public void DoScriptLoadUnload()
223 {
224 if (!m_started)
225 return;
226
227 lock (LUQueue)
228 {
229 if (LUQueue.Count > 0)
230 {
231m_scriptEngine.Log.InfoFormat("[{0}]: Loading script", m_scriptEngine.ScriptEngineName);
232 LUStruct item = LUQueue.Dequeue();
233
234 if (item.Action == LUType.Unload)
235 {
236 _StopScript(item.localID, item.itemID);
237 RemoveScript(item.localID, item.itemID);
238 }
239 else if (item.Action == LUType.Load)
240 {
241 _StartScript(item.localID, item.itemID, item.script, item.startParam, item.postOnRez);
242 }
243 }
244 }
245 }
246
247 #endregion
248
249 #region Helper functions
250
251 private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
252 {
253 //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name);
254 return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
255 }
256
257 #endregion
258
259
260
261 #region Start/Stop/Reset script
262
263 // private readonly Object startStopLock = new Object();
264
265 /// <summary>
266 /// Fetches, loads and hooks up a script to an objects events
267 /// </summary>
268 /// <param name="itemID"></param>
269 /// <param name="localID"></param>
270 public void StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez)
271 {
272 lock (LUQueue)
273 {
274 if ((LUQueue.Count >= LoadUnloadMaxQueueSize) && m_started)
275 {
276 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: ERROR: Load/unload queue item count is at " + LUQueue.Count + ". Config variable \"LoadUnloadMaxQueueSize\" is set to " + LoadUnloadMaxQueueSize + ", so ignoring new script.");
277 return;
278 }
279
280 LUStruct ls = new LUStruct();
281 ls.localID = localID;
282 ls.itemID = itemID;
283 ls.script = Script;
284 ls.Action = LUType.Load;
285 ls.startParam = startParam;
286 ls.postOnRez = postOnRez;
287 LUQueue.Enqueue(ls);
288m_scriptEngine.Log.InfoFormat("[{0}]: Queued script for load", m_scriptEngine.ScriptEngineName);
289 }
290 }
291
292 /// <summary>
293 /// Disables and unloads a script
294 /// </summary>
295 /// <param name="localID"></param>
296 /// <param name="itemID"></param>
297 public void StopScript(uint localID, UUID itemID)
298 {
299 LUStruct ls = new LUStruct();
300 ls.localID = localID;
301 ls.itemID = itemID;
302 ls.Action = LUType.Unload;
303 ls.startParam = 0;
304 ls.postOnRez = false;
305 lock (LUQueue)
306 {
307 LUQueue.Enqueue(ls);
308 }
309 }
310
311 // Create a new instance of the compiler (reuse)
312 //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
313
314 public abstract void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez);
315 public abstract void _StopScript(uint localID, UUID itemID);
316
317
318 #endregion
319
320 #region Perform event execution in script
321
322 /// <summary>
323 /// Execute a LL-event-function in Script
324 /// </summary>
325 /// <param name="localID">Object the script is located in</param>
326 /// <param name="itemID">Script ID</param>
327 /// <param name="FunctionName">Name of function</param>
328 /// <param name="args">Arguments to pass to function</param>
329 internal void ExecuteEvent(uint localID, UUID itemID, string FunctionName, DetectParams[] qParams, object[] args)
330 {
331 //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
332 ///#if DEBUG
333 /// Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
334 ///#endif
335 // Execute a function in the script
336 //m_scriptEngine.Log.Info("[" + ScriptEngineName + "]: Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
337 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
338 IScript Script = GetScript(localID, itemID);
339 if (Script == null)
340 {
341 return;
342 }
343 //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
344 ///#if DEBUG
345 /// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
346 ///#endif
347 // Must be done in correct AppDomain, so leaving it up to the script itself
348 detparms[Script] = qParams;
349 Script.Exec.ExecuteEvent(FunctionName, args);
350 detparms.Remove(Script);
351 }
352
353 public uint GetLocalID(UUID itemID)
354 {
355 foreach (KeyValuePair<uint, Dictionary<UUID, IScript> > k in Scripts)
356 {
357 if (k.Value.ContainsKey(itemID))
358 return k.Key;
359 }
360 return 0;
361 }
362
363 public int GetStateEventFlags(uint localID, UUID itemID)
364 {
365 // Console.WriteLine("GetStateEventFlags for <" + localID + "," + itemID + ">");
366 try
367 {
368 IScript Script = GetScript(localID, itemID);
369 if (Script == null)
370 {
371 return 0;
372 }
373 ExecutorBase.scriptEvents evflags = Script.Exec.GetStateEventFlags();
374 return (int)evflags;
375 }
376 catch (Exception)
377 {
378 }
379
380 return 0;
381 }
382
383
384 #endregion
385
386 #region Internal functions to keep track of script
387
388 public List<UUID> GetScriptKeys(uint localID)
389 {
390 if (Scripts.ContainsKey(localID) == false)
391 return new List<UUID>();
392
393 Dictionary<UUID, IScript> Obj;
394 Scripts.TryGetValue(localID, out Obj);
395
396 return new List<UUID>(Obj.Keys);
397 }
398
399 public IScript GetScript(uint localID, UUID itemID)
400 {
401 lock (scriptLock)
402 {
403 IScript Script = null;
404
405 if (Scripts.ContainsKey(localID) == false)
406 return null;
407
408 Dictionary<UUID, IScript> Obj;
409 Scripts.TryGetValue(localID, out Obj);
410 if (Obj.ContainsKey(itemID) == false)
411 return null;
412
413 // Get script
414 Obj.TryGetValue(itemID, out Script);
415 return Script;
416 }
417 }
418
419 public void SetScript(uint localID, UUID itemID, IScript Script)
420 {
421 lock (scriptLock)
422 {
423 // Create object if it doesn't exist
424 if (Scripts.ContainsKey(localID) == false)
425 {
426 Scripts.Add(localID, new Dictionary<UUID, IScript>());
427 }
428
429 // Delete script if it exists
430 Dictionary<UUID, IScript> Obj;
431 Scripts.TryGetValue(localID, out Obj);
432 if (Obj.ContainsKey(itemID) == true)
433 Obj.Remove(itemID);
434
435 // Add to object
436 Obj.Add(itemID, Script);
437 }
438 }
439
440 public void RemoveScript(uint localID, UUID itemID)
441 {
442 if (localID == 0)
443 localID = GetLocalID(itemID);
444
445 // Don't have that object?
446 if (Scripts.ContainsKey(localID) == false)
447 return;
448
449 // Delete script if it exists
450 Dictionary<UUID, IScript> Obj;
451 Scripts.TryGetValue(localID, out Obj);
452 if (Obj.ContainsKey(itemID) == true)
453 Obj.Remove(itemID);
454 }
455
456 #endregion
457
458
459 public void ResetScript(uint localID, UUID itemID)
460 {
461 IScript s = GetScript(localID, itemID);
462 string script = s.Source;
463 StopScript(localID, itemID);
464 SceneObjectPart part = World.GetSceneObjectPart(localID);
465 part.GetInventoryItem(itemID).PermsMask = 0;
466 part.GetInventoryItem(itemID).PermsGranter = UUID.Zero;
467 StartScript(localID, itemID, script, s.StartParam, false);
468 }
469
470
471 #region Script serialization/deserialization
472
473 public void GetSerializedScript(uint localID, UUID itemID)
474 {
475 // Serialize the script and return it
476 // Should not be a problem
477 FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID);
478 BinaryFormatter b = new BinaryFormatter();
479 b.Serialize(fs, GetScript(localID, itemID));
480 fs.Close();
481 }
482
483 public void PutSerializedScript(uint localID, UUID itemID)
484 {
485 // Deserialize the script and inject it into an AppDomain
486
487 // How to inject into an AppDomain?
488 }
489
490 #endregion
491
492 ///// <summary>
493 ///// If set to true then threads and stuff should try to make a graceful exit
494 ///// </summary>
495 //public bool PleaseShutdown
496 //{
497 // get { return _PleaseShutdown; }
498 // set { _PleaseShutdown = value; }
499 //}
500 //private bool _PleaseShutdown = false;
501
502 public DetectParams[] GetDetectParams(IScript script)
503 {
504 if (detparms.ContainsKey(script))
505 return detparms[script];
506
507 return null;
508 }
509 }
510}
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs
deleted file mode 100644
index 768ba6d..0000000
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs
+++ /dev/null
@@ -1,35 +0,0 @@
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 OpenSim 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
28namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
29{
30 public interface iScriptEngineFunctionModule
31 {
32 void ReadConfig();
33// bool PleaseShutdown { get; set; }
34 }
35}
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
index 262d75f..969a05e 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs
@@ -29,8 +29,9 @@ using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using OpenSim.Region.ScriptEngine.Common;
32 33
33namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 34namespace OpenSim.Region.ScriptEngine.DotNetEngine
34{ 35{
35 public class AppDomainManager : iScriptEngineFunctionModule 36 public class AppDomainManager : iScriptEngineFunctionModule
36 { 37 {
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs
index d5ec9b4..3d9e19b 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs
@@ -25,7 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 28namespace OpenSim.Region.ScriptEngine.DotNetEngine
29{ 29{
30 public static class Common 30 public static class Common
31 { 31 {
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs
index b50e823..4cb74fa 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs
@@ -83,8 +83,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
83 private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files 83 private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files
84 private static UInt64 scriptCompileCounter = 0; // And a counter 84 private static UInt64 scriptCompileCounter = 0; // And a counter
85 85
86 public Common.ScriptEngineBase.ScriptEngine m_scriptEngine; 86 public ScriptEngine m_scriptEngine;
87 public Compiler(Common.ScriptEngineBase.ScriptEngine scriptEngine) 87 public Compiler(ScriptEngine scriptEngine)
88 { 88 {
89 m_scriptEngine = scriptEngine; 89 m_scriptEngine = scriptEngine;
90 ReadConfig(); 90 ReadConfig();
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
index b13ab21..7805d67 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
@@ -31,7 +31,7 @@ using System.Collections.Generic;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.ScriptEngine.Shared; 32using OpenSim.Region.ScriptEngine.Shared;
33 33
34namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 34namespace OpenSim.Region.ScriptEngine.DotNetEngine
35{ 35{
36 /// <summary> 36 /// <summary>
37 /// EventQueueManager handles event queues 37 /// EventQueueManager handles event queues
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
index 7f52793..db3f89f 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
@@ -36,7 +36,7 @@ using log4net;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Region.Environment.Scenes.Scripting; 37using OpenSim.Region.Environment.Scenes.Scripting;
38 38
39namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 39namespace OpenSim.Region.ScriptEngine.DotNetEngine
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class 42 /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
@@ -103,7 +103,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
103 break; 103 break;
104 default: 104 default:
105 MyThreadPriority = ThreadPriority.BelowNormal; // Default 105 MyThreadPriority = ThreadPriority.BelowNormal; // Default
106 m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri + 106 m_ScriptEngine.Log.Error("[ScriptEngine.DotNetEngine]: Unknown priority type \"" + pri +
107 "\" in config file. Defaulting to \"BelowNormal\"."); 107 "\" in config file. Defaulting to \"BelowNormal\".");
108 break; 108 break;
109 } 109 }
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
index ef87b2f..6c1528f 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
@@ -32,7 +32,7 @@ using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework; 33using OpenSim.Framework;
34 34
35namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 35namespace OpenSim.Region.ScriptEngine.DotNetEngine
36{ 36{
37 /// <summary> 37 /// <summary>
38 /// This class does maintenance on script engine. 38 /// This class does maintenance on script engine.
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
index e785cc0..7ec71c2 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
@@ -26,29 +26,281 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
29using Nini.Config; 32using Nini.Config;
33using OpenSim.Region.Interfaces;
34using OpenSim.Region.Environment.Interfaces;
30using OpenSim.Region.Environment.Scenes; 35using OpenSim.Region.Environment.Scenes;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenMetaverse;
38using OpenSim.Region.ScriptEngine.Shared;
39using OpenSim.Region.ScriptEngine.Common;
31 40
32namespace OpenSim.Region.ScriptEngine.DotNetEngine 41namespace OpenSim.Region.ScriptEngine.DotNetEngine
33{ 42{
34 [Serializable] 43 [Serializable]
35 public class ScriptEngine : Common.ScriptEngineBase.ScriptEngine 44 public class ScriptEngine : IRegionModule, IEventReceiver, IScriptModule
36 { 45 {
37 // We need to override a few things for our DotNetEngine 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
38 public override void Initialise(Scene scene, IConfigSource config) 47
48 public static List<ScriptEngine> ScriptEngines = new List<ScriptEngine>();
49 private Scene m_Scene;
50 public Scene World
39 { 51 {
40 ConfigSource = config; 52 get { return m_Scene; }
41 InitializeEngine(scene, config, true, GetScriptManager());
42 } 53 }
54 public EventManager m_EventManager; // Handles and queues incoming events from OpenSim
55 public EventQueueManager m_EventQueueManager; // Executes events, handles script threads
56 public ScriptManager m_ScriptManager; // Load, unload and execute scripts
57 public AppDomainManager m_AppDomainManager; // Handles loading/unloading of scripts into AppDomains
58 public static MaintenanceThread m_MaintenanceThread; // Thread that does different kinds of maintenance, for example refreshing config and killing scripts that has been running too long
59
60 public IConfigSource ConfigSource;
61 public IConfig ScriptConfigSource;
62 private bool m_enabled = false;
43 63
44 public override Common.ScriptEngineBase.ScriptManager _GetScriptManager() 64 public IConfig Config
45 { 65 {
46 return new ScriptManager(this); 66 get { return ScriptConfigSource; }
47 } 67 }
48 68
49 public override string ScriptEngineName 69 /// <summary>
70 /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes.
71 /// </summary>
72 public int RefreshConfigFileSeconds {
73 get { return (int)(RefreshConfigFilens / 10000000); }
74 set { RefreshConfigFilens = value * 10000000; }
75 }
76 public long RefreshConfigFilens;
77
78 public string ScriptEngineName
50 { 79 {
51 get { return "ScriptEngine.DotNetEngine"; } 80 get { return "ScriptEngine.DotNetEngine"; }
52 } 81 }
82
83 public ILog Log
84 {
85 get { return m_log; }
86 }
87
88 public ScriptEngine()
89 {
90 Common.mySE = this; // For logging, just need any instance, doesn't matter
91 lock (ScriptEngines)
92 {
93 ScriptEngines.Add(this); // Keep a list of ScriptEngines for shared threads to process all instances
94 }
95 }
96
97 public void Initialise(Scene Sceneworld, IConfigSource config)
98 {
99 m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing");
100
101 ConfigSource = config;
102 m_Scene = Sceneworld;
103
104 // Make sure we have config
105 if (ConfigSource.Configs[ScriptEngineName] == null)
106 ConfigSource.AddConfig(ScriptEngineName);
107 ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
108
109 m_enabled = ScriptConfigSource.GetBoolean("Enabled", true);
110 if (!m_enabled)
111 return;
112
113 //m_log.Info("[" + ScriptEngineName + "]: InitializeEngine");
114
115 // Create all objects we'll be using
116 m_EventQueueManager = new EventQueueManager(this);
117 m_EventManager = new EventManager(this, true);
118 // We need to start it
119 m_ScriptManager = new ScriptManager(this);
120 m_ScriptManager.Setup();
121 m_AppDomainManager = new AppDomainManager(this);
122 if (m_MaintenanceThread == null)
123 m_MaintenanceThread = new MaintenanceThread();
124
125 m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\"");
126 ReadConfig();
127
128 m_Scene.StackModuleInterface<IScriptModule>(this);
129 }
130
131 public void PostInitialise()
132 {
133 if (!m_enabled)
134 return;
135
136 m_EventManager.HookUpEvents();
137
138 m_ScriptManager.Start();
139 }
140
141 public void Shutdown()
142 {
143 // We are shutting down
144 lock (ScriptEngines)
145 {
146 ScriptEngines.Remove(this);
147 }
148 }
149
150 public void ReadConfig()
151 {
152#if DEBUG
153 //m_log.Debug("[" + ScriptEngineName + "]: Refreshing configuration for all modules");
154#endif
155 RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30);
156
157
158 // Create a new object (probably not necessary?)
159// ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
160
161 if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig();
162 if (m_EventManager != null) m_EventManager.ReadConfig();
163 if (m_ScriptManager != null) m_ScriptManager.ReadConfig();
164 if (m_AppDomainManager != null) m_AppDomainManager.ReadConfig();
165 if (m_MaintenanceThread != null) m_MaintenanceThread.ReadConfig();
166 }
167
168 #region IRegionModule
169
170 public void Close()
171 {
172 }
173
174 public string Name
175 {
176 get { return "Common." + ScriptEngineName; }
177 }
178
179 public bool IsSharedModule
180 {
181 get { return false; }
182 }
183
184 public bool PostObjectEvent(uint localID, EventParams p)
185 {
186 return m_EventQueueManager.AddToObjectQueue(localID, p.EventName, p.DetectParams, p.Params);
187 }
188
189 public bool PostScriptEvent(UUID itemID, EventParams p)
190 {
191 uint localID = m_ScriptManager.GetLocalID(itemID);
192 return m_EventQueueManager.AddToScriptQueue(localID, itemID, p.EventName, p.DetectParams, p.Params);
193 }
194
195 public DetectParams GetDetectParams(UUID itemID, int number)
196 {
197 uint localID = m_ScriptManager.GetLocalID(itemID);
198 if (localID == 0)
199 return null;
200
201 IScript Script = m_ScriptManager.GetScript(localID, itemID);
202
203 if (Script == null)
204 return null;
205
206 DetectParams[] det = m_ScriptManager.GetDetectParams(Script);
207
208 if (number < 0 || number >= det.Length)
209 return null;
210
211 return det[number];
212 }
213
214 public int GetStartParameter(UUID itemID)
215 {
216 return 0;
217 }
218 #endregion
219
220 public void SetState(UUID itemID, string state)
221 {
222 uint localID = m_ScriptManager.GetLocalID(itemID);
223 if (localID == 0)
224 return;
225
226 IScript Script = m_ScriptManager.GetScript(localID, itemID);
227
228 if (Script == null)
229 return;
230
231 string currentState = Script.State;
232
233 if (currentState != state)
234 {
235 try
236 {
237 m_EventManager.state_exit(localID);
238
239 }
240 catch (AppDomainUnloadedException)
241 {
242 Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance");
243 }
244
245 Script.State = state;
246
247 try
248 {
249 int eventFlags = m_ScriptManager.GetStateEventFlags(localID, itemID);
250 SceneObjectPart part = m_Scene.GetSceneObjectPart(itemID);
251 if (part != null)
252 part.SetScriptEvents(itemID, eventFlags);
253 m_EventManager.state_entry(localID);
254 }
255 catch (AppDomainUnloadedException)
256 {
257 Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance");
258 }
259 }
260 }
261
262 public bool GetScriptState(UUID itemID)
263 {
264 uint localID = m_ScriptManager.GetLocalID(itemID);
265 if (localID == 0)
266 return false;
267
268 IScript script = m_ScriptManager.GetScript(localID, itemID);
269 if (script == null)
270 return false;
271
272 return script.Exec.Running?true:false;
273 }
274
275 public void SetScriptState(UUID itemID, bool state)
276 {
277 uint localID = m_ScriptManager.GetLocalID(itemID);
278 if (localID == 0)
279 return;
280
281 IScript script = m_ScriptManager.GetScript(localID, itemID);
282 if (script == null)
283 return;
284
285 script.Exec.Running = state;
286 }
287
288 public void ApiResetScript(UUID itemID)
289 {
290 uint localID = m_ScriptManager.GetLocalID(itemID);
291 if (localID == 0)
292 return;
293
294 m_ScriptManager.ResetScript(localID, itemID);
295 }
296
297 public void ResetScript(UUID itemID)
298 {
299 uint localID = m_ScriptManager.GetLocalID(itemID);
300 if (localID == 0)
301 return;
302
303 m_ScriptManager.ResetScript(localID, itemID);
304 }
53 } 305 }
54} 306}
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
index 8ff3bfd..12a8fe4 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
@@ -34,22 +34,66 @@ using OpenSim.Region.Environment.Scenes;
34using OpenSim.Region.ScriptEngine.Common; 34using OpenSim.Region.ScriptEngine.Common;
35using OpenSim.Region.ScriptEngine.Shared; 35using OpenSim.Region.ScriptEngine.Shared;
36using OpenSim.Region.ScriptEngine.Shared.Api; 36using OpenSim.Region.ScriptEngine.Shared.Api;
37using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; 37using System.Collections.Generic;
38using System.IO;
39using System.Runtime.Serialization.Formatters.Binary;
40using System.Threading;
38 41
39namespace OpenSim.Region.ScriptEngine.DotNetEngine 42namespace OpenSim.Region.ScriptEngine.DotNetEngine
40{ 43{
41 public class ScriptManager : Common.ScriptEngineBase.ScriptManager 44 public class ScriptManager
42 { 45 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 47
45 public ScriptManager(Common.ScriptEngineBase.ScriptEngine scriptEngine) 48 #region Declares
46 : base(scriptEngine) 49
50 private Thread scriptLoadUnloadThread;
51 private static Thread staticScriptLoadUnloadThread;
52 // private int scriptLoadUnloadThread_IdleSleepms;
53 private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
54 private static bool PrivateThread;
55 private int LoadUnloadMaxQueueSize;
56 private Object scriptLock = new Object();
57 private bool m_started = false;
58 private Dictionary<IScript, DetectParams[]> detparms = new Dictionary<IScript, DetectParams[]>();
59
60 // Load/Unload structure
61 private struct LUStruct
62 {
63 public uint localID;
64 public UUID itemID;
65 public string script;
66 public LUType Action;
67 public int startParam;
68 public bool postOnRez;
69 }
70
71 private enum LUType
72 {
73 Unknown = 0,
74 Load = 1,
75 Unload = 2
76 }
77
78 // Xantor 20080525: Keep a list of compiled scripts this session for reuse
79 public Dictionary<UUID, String> scriptList = new Dictionary<UUID, string>();
80
81 // Object<string, Script<string, script>>
82 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
83 // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
84 public Dictionary<uint, Dictionary<UUID, IScript>> Scripts =
85 new Dictionary<uint, Dictionary<UUID, IScript>>();
86
87
88 public Scene World
47 { 89 {
48 base.m_scriptEngine = scriptEngine; 90 get { return m_scriptEngine.World; }
49 } 91 }
92
93 #endregion
50 private Compiler.LSL.Compiler LSLCompiler; 94 private Compiler.LSL.Compiler LSLCompiler;
51 95
52 public override void Initialize() 96 public void Initialize()
53 { 97 {
54 // Create our compiler 98 // Create our compiler
55 LSLCompiler = new Compiler.LSL.Compiler(m_scriptEngine); 99 LSLCompiler = new Compiler.LSL.Compiler(m_scriptEngine);
@@ -62,7 +106,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
62 // PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim 106 // PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim
63 107
64 108
65 public override void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez) 109 public void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez)
66 { 110 {
67 m_log.DebugFormat( 111 m_log.DebugFormat(
68 "[{0}]: ScriptManager StartScript: localID: {1}, itemID: {2}", 112 "[{0}]: ScriptManager StartScript: localID: {1}, itemID: {2}",
@@ -173,7 +217,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
173 } 217 }
174 } 218 }
175 219
176 public override void _StopScript(uint localID, UUID itemID) 220 public void _StopScript(uint localID, UUID itemID)
177 { 221 {
178 IScript LSLBC = GetScript(localID, itemID); 222 IScript LSLBC = GetScript(localID, itemID);
179 if (LSLBC == null) 223 if (LSLBC == null)
@@ -202,5 +246,405 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
202 ": " + e.ToString()); 246 ": " + e.ToString());
203 } 247 }
204 } 248 }
249
250 public void ReadConfig()
251 {
252 // scriptLoadUnloadThread_IdleSleepms = m_scriptEngine.ScriptConfigSource.GetInt("ScriptLoadUnloadLoopms", 30);
253 // TODO: Requires sharing of all ScriptManagers to single thread
254 PrivateThread = true; // m_scriptEngine.ScriptConfigSource.GetBoolean("PrivateScriptLoadUnloadThread", false);
255 LoadUnloadMaxQueueSize = m_scriptEngine.ScriptConfigSource.GetInt("LoadUnloadMaxQueueSize", 100);
256 }
257
258 #region Object init/shutdown
259
260 public ScriptEngine m_scriptEngine;
261
262 public ScriptManager(ScriptEngine scriptEngine)
263 {
264 m_scriptEngine = scriptEngine;
265 }
266 public void Setup()
267 {
268 ReadConfig();
269 Initialize();
270 }
271 public void Start()
272 {
273 m_started = true;
274
275
276 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
277
278 //
279 // CREATE THREAD
280 // Private or shared
281 //
282 if (PrivateThread)
283 {
284 // Assign one thread per region
285 //scriptLoadUnloadThread = StartScriptLoadUnloadThread();
286 }
287 else
288 {
289 // Shared thread - make sure one exist, then assign it to the private
290 if (staticScriptLoadUnloadThread == null)
291 {
292 //staticScriptLoadUnloadThread = StartScriptLoadUnloadThread();
293 }
294 scriptLoadUnloadThread = staticScriptLoadUnloadThread;
295 }
296 }
297
298// TODO: unused
299// private static int privateThreadCount = 0;
300// private Thread StartScriptLoadUnloadThread()
301// {
302// Thread t = new Thread(ScriptLoadUnloadThreadLoop);
303// string name = "ScriptLoadUnloadThread:";
304// if (PrivateThread)
305// {
306// name += "Private:" + privateThreadCount;
307// privateThreadCount++;
308// }
309// else
310// {
311// name += "Shared";
312// }
313// t.Name = name;
314// t.IsBackground = true;
315// t.Priority = ThreadPriority.Normal;
316// t.Start();
317// OpenSim.Framework.ThreadTracker.Add(t);
318// return t;
319// }
320
321 ~ScriptManager()
322 {
323 // Abort load/unload thread
324 try
325 {
326 //PleaseShutdown = true;
327 //Thread.Sleep(100);
328 if (scriptLoadUnloadThread != null && scriptLoadUnloadThread.IsAlive == true)
329 {
330 scriptLoadUnloadThread.Abort();
331 //scriptLoadUnloadThread.Join();
332 }
333 }
334 catch
335 {
336 }
337 }
338
339 #endregion
340
341 #region Load / Unload scripts (Thread loop)
342
343// TODO: unused
344// private void ScriptLoadUnloadThreadLoop()
345// {
346// try
347// {
348// while (true)
349// {
350// if (LUQueue.Count == 0)
351// Thread.Sleep(scriptLoadUnloadThread_IdleSleepms);
352// //if (PleaseShutdown)
353// // return;
354// DoScriptLoadUnload();
355// }
356// }
357// catch (ThreadAbortException tae)
358// {
359// string a = tae.ToString();
360// a = String.Empty;
361// // Expected
362// }
363// }
364
365 public void DoScriptLoadUnload()
366 {
367 if (!m_started)
368 return;
369
370 lock (LUQueue)
371 {
372 if (LUQueue.Count > 0)
373 {
374m_scriptEngine.Log.InfoFormat("[{0}]: Loading script", m_scriptEngine.ScriptEngineName);
375 LUStruct item = LUQueue.Dequeue();
376
377 if (item.Action == LUType.Unload)
378 {
379 _StopScript(item.localID, item.itemID);
380 RemoveScript(item.localID, item.itemID);
381 }
382 else if (item.Action == LUType.Load)
383 {
384 _StartScript(item.localID, item.itemID, item.script, item.startParam, item.postOnRez);
385 }
386 }
387 }
388 }
389
390 #endregion
391
392 #region Helper functions
393
394 private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
395 {
396 //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name);
397 return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
398 }
399
400 #endregion
401
402
403
404 #region Start/Stop/Reset script
405
406 // private readonly Object startStopLock = new Object();
407
408 /// <summary>
409 /// Fetches, loads and hooks up a script to an objects events
410 /// </summary>
411 /// <param name="itemID"></param>
412 /// <param name="localID"></param>
413 public void StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez)
414 {
415 lock (LUQueue)
416 {
417 if ((LUQueue.Count >= LoadUnloadMaxQueueSize) && m_started)
418 {
419 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: ERROR: Load/unload queue item count is at " + LUQueue.Count + ". Config variable \"LoadUnloadMaxQueueSize\" is set to " + LoadUnloadMaxQueueSize + ", so ignoring new script.");
420 return;
421 }
422
423 LUStruct ls = new LUStruct();
424 ls.localID = localID;
425 ls.itemID = itemID;
426 ls.script = Script;
427 ls.Action = LUType.Load;
428 ls.startParam = startParam;
429 ls.postOnRez = postOnRez;
430 LUQueue.Enqueue(ls);
431m_scriptEngine.Log.InfoFormat("[{0}]: Queued script for load", m_scriptEngine.ScriptEngineName);
432 }
433 }
434
435 /// <summary>
436 /// Disables and unloads a script
437 /// </summary>
438 /// <param name="localID"></param>
439 /// <param name="itemID"></param>
440 public void StopScript(uint localID, UUID itemID)
441 {
442 LUStruct ls = new LUStruct();
443 ls.localID = localID;
444 ls.itemID = itemID;
445 ls.Action = LUType.Unload;
446 ls.startParam = 0;
447 ls.postOnRez = false;
448 lock (LUQueue)
449 {
450 LUQueue.Enqueue(ls);
451 }
452 }
453
454 // Create a new instance of the compiler (reuse)
455 //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
456
457
458 #endregion
459
460 #region Perform event execution in script
461
462 /// <summary>
463 /// Execute a LL-event-function in Script
464 /// </summary>
465 /// <param name="localID">Object the script is located in</param>
466 /// <param name="itemID">Script ID</param>
467 /// <param name="FunctionName">Name of function</param>
468 /// <param name="args">Arguments to pass to function</param>
469 internal void ExecuteEvent(uint localID, UUID itemID, string FunctionName, DetectParams[] qParams, object[] args)
470 {
471 //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
472 ///#if DEBUG
473 /// Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
474 ///#endif
475 // Execute a function in the script
476 //m_scriptEngine.Log.Info("[" + ScriptEngineName + "]: Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
477 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
478 IScript Script = GetScript(localID, itemID);
479 if (Script == null)
480 {
481 return;
482 }
483 //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
484 ///#if DEBUG
485 /// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
486 ///#endif
487 // Must be done in correct AppDomain, so leaving it up to the script itself
488 detparms[Script] = qParams;
489 Script.Exec.ExecuteEvent(FunctionName, args);
490 detparms.Remove(Script);
491 }
492
493 public uint GetLocalID(UUID itemID)
494 {
495 foreach (KeyValuePair<uint, Dictionary<UUID, IScript> > k in Scripts)
496 {
497 if (k.Value.ContainsKey(itemID))
498 return k.Key;
499 }
500 return 0;
501 }
502
503 public int GetStateEventFlags(uint localID, UUID itemID)
504 {
505 // Console.WriteLine("GetStateEventFlags for <" + localID + "," + itemID + ">");
506 try
507 {
508 IScript Script = GetScript(localID, itemID);
509 if (Script == null)
510 {
511 return 0;
512 }
513 ExecutorBase.scriptEvents evflags = Script.Exec.GetStateEventFlags();
514 return (int)evflags;
515 }
516 catch (Exception)
517 {
518 }
519
520 return 0;
521 }
522
523
524 #endregion
525
526 #region Internal functions to keep track of script
527
528 public List<UUID> GetScriptKeys(uint localID)
529 {
530 if (Scripts.ContainsKey(localID) == false)
531 return new List<UUID>();
532
533 Dictionary<UUID, IScript> Obj;
534 Scripts.TryGetValue(localID, out Obj);
535
536 return new List<UUID>(Obj.Keys);
537 }
538
539 public IScript GetScript(uint localID, UUID itemID)
540 {
541 lock (scriptLock)
542 {
543 IScript Script = null;
544
545 if (Scripts.ContainsKey(localID) == false)
546 return null;
547
548 Dictionary<UUID, IScript> Obj;
549 Scripts.TryGetValue(localID, out Obj);
550 if (Obj.ContainsKey(itemID) == false)
551 return null;
552
553 // Get script
554 Obj.TryGetValue(itemID, out Script);
555 return Script;
556 }
557 }
558
559 public void SetScript(uint localID, UUID itemID, IScript Script)
560 {
561 lock (scriptLock)
562 {
563 // Create object if it doesn't exist
564 if (Scripts.ContainsKey(localID) == false)
565 {
566 Scripts.Add(localID, new Dictionary<UUID, IScript>());
567 }
568
569 // Delete script if it exists
570 Dictionary<UUID, IScript> Obj;
571 Scripts.TryGetValue(localID, out Obj);
572 if (Obj.ContainsKey(itemID) == true)
573 Obj.Remove(itemID);
574
575 // Add to object
576 Obj.Add(itemID, Script);
577 }
578 }
579
580 public void RemoveScript(uint localID, UUID itemID)
581 {
582 if (localID == 0)
583 localID = GetLocalID(itemID);
584
585 // Don't have that object?
586 if (Scripts.ContainsKey(localID) == false)
587 return;
588
589 // Delete script if it exists
590 Dictionary<UUID, IScript> Obj;
591 Scripts.TryGetValue(localID, out Obj);
592 if (Obj.ContainsKey(itemID) == true)
593 Obj.Remove(itemID);
594 }
595
596 #endregion
597
598
599 public void ResetScript(uint localID, UUID itemID)
600 {
601 IScript s = GetScript(localID, itemID);
602 string script = s.Source;
603 StopScript(localID, itemID);
604 SceneObjectPart part = World.GetSceneObjectPart(localID);
605 part.GetInventoryItem(itemID).PermsMask = 0;
606 part.GetInventoryItem(itemID).PermsGranter = UUID.Zero;
607 StartScript(localID, itemID, script, s.StartParam, false);
608 }
609
610
611 #region Script serialization/deserialization
612
613 public void GetSerializedScript(uint localID, UUID itemID)
614 {
615 // Serialize the script and return it
616 // Should not be a problem
617 FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID);
618 BinaryFormatter b = new BinaryFormatter();
619 b.Serialize(fs, GetScript(localID, itemID));
620 fs.Close();
621 }
622
623 public void PutSerializedScript(uint localID, UUID itemID)
624 {
625 // Deserialize the script and inject it into an AppDomain
626
627 // How to inject into an AppDomain?
628 }
629
630 #endregion
631
632 ///// <summary>
633 ///// If set to true then threads and stuff should try to make a graceful exit
634 ///// </summary>
635 //public bool PleaseShutdown
636 //{
637 // get { return _PleaseShutdown; }
638 // set { _PleaseShutdown = value; }
639 //}
640 //private bool _PleaseShutdown = false;
641
642 public DetectParams[] GetDetectParams(IScript script)
643 {
644 if (detparms.ContainsKey(script))
645 return detparms[script];
646
647 return null;
648 }
205 } 649 }
206} 650}