aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
authorMelanie Thielker2008-09-26 13:16:11 +0000
committerMelanie Thielker2008-09-26 13:16:11 +0000
commit824283ca3c2ab54868ed61fdb0a329221d69e5fa (patch)
tree9013892fa2afa579bffe8bdcd6a46e2242ed085c /OpenSim/Region/ScriptEngine
parent* Wind updates. Still random.. but in 4 directions instead of two! (diff)
downloadopensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.zip
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.gz
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.bz2
opensim-SC_OLD-824283ca3c2ab54868ed61fdb0a329221d69e5fa.tar.xz
Remove all the subclassing complexity and script server interfaces from
DNE and move all of DNE into the DotNetEngine directory. Remove references that would cause the script runtime to load the entire engine + scene into each script appdomain. This might help DNE memory consumption.
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}