aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/DotNetEngine
diff options
context:
space:
mode:
Diffstat (limited to '')
-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
8 files changed, 721 insertions, 24 deletions
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}