aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs694
1 files changed, 347 insertions, 347 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
index e98ff81..8f74620 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs
@@ -1,348 +1,348 @@
1/* 1/*
2* Copyright (c) Contributors, http://opensimulator.org/ 2* Copyright (c) Contributors, http://opensimulator.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4*
5* Redistribution and use in source and binary forms, with or without 5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14* derived from this software without specific prior written permission.
15* 15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY 16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26*
27*/ 27*/
28 28
29 29
30using System; 30using System;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.IO; 32using System.IO;
33using System.Reflection; 33using System.Reflection;
34using System.Runtime.Serialization.Formatters.Binary; 34using System.Runtime.Serialization.Formatters.Binary;
35using System.Threading; 35using System.Threading;
36using libsecondlife; 36using libsecondlife;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Region.Environment.Scenes; 38using OpenSim.Region.Environment.Scenes;
39using OpenSim.Region.ScriptEngine.Common; 39using OpenSim.Region.ScriptEngine.Common;
40 40
41namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase 41namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
42{ 42{
43 /// <summary> 43 /// <summary>
44 /// Loads scripts 44 /// Loads scripts
45 /// Compiles them if necessary 45 /// Compiles them if necessary
46 /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution) 46 /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
47 /// </summary> 47 /// </summary>
48 /// 48 ///
49 49
50 // 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. 50 // 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.
51 // * Keeps track of running scripts 51 // * Keeps track of running scripts
52 // * Compiles script if necessary (through "Compiler") 52 // * Compiles script if necessary (through "Compiler")
53 // * Loads script (through "AppDomainManager" called from for example "EventQueueManager") 53 // * Loads script (through "AppDomainManager" called from for example "EventQueueManager")
54 // * Executes functions inside script (called from for example "EventQueueManager" class) 54 // * Executes functions inside script (called from for example "EventQueueManager" class)
55 // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager") 55 // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager")
56 // * Dedicated load/unload thread, and queues loading/unloading. 56 // * Dedicated load/unload thread, and queues loading/unloading.
57 // This so that scripts starting or stopping will not slow down other theads or whole system. 57 // This so that scripts starting or stopping will not slow down other theads or whole system.
58 // 58 //
59 [Serializable] 59 [Serializable]
60 public abstract class ScriptManager 60 public abstract class ScriptManager
61 { 61 {
62 #region Declares 62 #region Declares
63 63
64 private Thread scriptLoadUnloadThread; 64 private Thread scriptLoadUnloadThread;
65 private int scriptLoadUnloadThread_IdleSleepms = 100; 65 private int scriptLoadUnloadThread_IdleSleepms = 100;
66 private Queue<LUStruct> LUQueue = new Queue<LUStruct>(); 66 private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
67 67
68 68
69 // Load/Unload structure 69 // Load/Unload structure
70 private struct LUStruct 70 private struct LUStruct
71 { 71 {
72 public uint localID; 72 public uint localID;
73 public LLUUID itemID; 73 public LLUUID itemID;
74 public string script; 74 public string script;
75 public LUType Action; 75 public LUType Action;
76 } 76 }
77 77
78 private enum LUType 78 private enum LUType
79 { 79 {
80 Unknown = 0, 80 Unknown = 0,
81 Load = 1, 81 Load = 1,
82 Unload = 2 82 Unload = 2
83 } 83 }
84 84
85 // Object<string, Script<string, script>> 85 // Object<string, Script<string, script>>
86 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. 86 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
87 // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! 87 // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
88 public Dictionary<uint, Dictionary<LLUUID, IScript>> Scripts = 88 public Dictionary<uint, Dictionary<LLUUID, IScript>> Scripts =
89 new Dictionary<uint, Dictionary<LLUUID, IScript>>(); 89 new Dictionary<uint, Dictionary<LLUUID, IScript>>();
90 90
91 public Scene World 91 public Scene World
92 { 92 {
93 get { return m_scriptEngine.World; } 93 get { return m_scriptEngine.World; }
94 } 94 }
95 95
96 #endregion 96 #endregion
97 97
98 #region Object init/shutdown 98 #region Object init/shutdown
99 99
100 public ScriptEngineBase.ScriptEngine m_scriptEngine; 100 public ScriptEngineBase.ScriptEngine m_scriptEngine;
101 101
102 public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine) 102 public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine)
103 { 103 {
104 m_scriptEngine = scriptEngine; 104 m_scriptEngine = scriptEngine;
105 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 105 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
106 scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop); 106 scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop);
107 scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread"; 107 scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread";
108 scriptLoadUnloadThread.IsBackground = true; 108 scriptLoadUnloadThread.IsBackground = true;
109 scriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal; 109 scriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal;
110 scriptLoadUnloadThread.Start(); 110 scriptLoadUnloadThread.Start();
111 } 111 }
112 112
113 ~ScriptManager() 113 ~ScriptManager()
114 { 114 {
115 // Abort load/unload thread 115 // Abort load/unload thread
116 try 116 try
117 { 117 {
118 if (scriptLoadUnloadThread != null) 118 if (scriptLoadUnloadThread != null)
119 { 119 {
120 if (scriptLoadUnloadThread.IsAlive == true) 120 if (scriptLoadUnloadThread.IsAlive == true)
121 { 121 {
122 scriptLoadUnloadThread.Abort(); 122 scriptLoadUnloadThread.Abort();
123 scriptLoadUnloadThread.Join(); 123 scriptLoadUnloadThread.Join();
124 } 124 }
125 } 125 }
126 } 126 }
127 catch 127 catch
128 { 128 {
129 } 129 }
130 } 130 }
131 131
132 #endregion 132 #endregion
133 133
134 #region Load / Unload scripts (Thread loop) 134 #region Load / Unload scripts (Thread loop)
135 135
136 private void ScriptLoadUnloadThreadLoop() 136 private void ScriptLoadUnloadThreadLoop()
137 { 137 {
138 try 138 try
139 { 139 {
140 while (true) 140 while (true)
141 { 141 {
142 if (LUQueue.Count == 0) 142 if (LUQueue.Count == 0)
143 Thread.Sleep(scriptLoadUnloadThread_IdleSleepms); 143 Thread.Sleep(scriptLoadUnloadThread_IdleSleepms);
144 if (LUQueue.Count > 0) 144 if (LUQueue.Count > 0)
145 { 145 {
146 LUStruct item = LUQueue.Dequeue(); 146 LUStruct item = LUQueue.Dequeue();
147 lock (startStopLock) // Lock so we have only 1 thread working on loading/unloading of scripts 147 lock (startStopLock) // Lock so we have only 1 thread working on loading/unloading of scripts
148 { 148 {
149 if (item.Action == LUType.Unload) 149 if (item.Action == LUType.Unload)
150 { 150 {
151 _StopScript(item.localID, item.itemID); 151 _StopScript(item.localID, item.itemID);
152 } 152 }
153 if (item.Action == LUType.Load) 153 if (item.Action == LUType.Load)
154 { 154 {
155 _StartScript(item.localID, item.itemID, item.script); 155 _StartScript(item.localID, item.itemID, item.script);
156 } 156 }
157 } 157 }
158 } 158 }
159 } 159 }
160 } 160 }
161 catch (ThreadAbortException tae) 161 catch (ThreadAbortException tae)
162 { 162 {
163 string a = tae.ToString(); 163 string a = tae.ToString();
164 a = ""; 164 a = "";
165 // Expected 165 // Expected
166 } 166 }
167 } 167 }
168 168
169 #endregion 169 #endregion
170 170
171 #region Helper functions 171 #region Helper functions
172 172
173 private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 173 private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
174 { 174 {
175 //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name); 175 //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name);
176 return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null; 176 return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
177 } 177 }
178 178
179 #endregion 179 #endregion
180 180
181 181
182 182
183 #region Start/Stop/Reset script 183 #region Start/Stop/Reset script
184 184
185 private readonly Object startStopLock = new Object(); 185 private readonly Object startStopLock = new Object();
186 186
187 /// <summary> 187 /// <summary>
188 /// Fetches, loads and hooks up a script to an objects events 188 /// Fetches, loads and hooks up a script to an objects events
189 /// </summary> 189 /// </summary>
190 /// <param name="itemID"></param> 190 /// <param name="itemID"></param>
191 /// <param name="localID"></param> 191 /// <param name="localID"></param>
192 public void StartScript(uint localID, LLUUID itemID, string Script) 192 public void StartScript(uint localID, LLUUID itemID, string Script)
193 { 193 {
194 LUStruct ls = new LUStruct(); 194 LUStruct ls = new LUStruct();
195 ls.localID = localID; 195 ls.localID = localID;
196 ls.itemID = itemID; 196 ls.itemID = itemID;
197 ls.script = Script; 197 ls.script = Script;
198 ls.Action = LUType.Load; 198 ls.Action = LUType.Load;
199 LUQueue.Enqueue(ls); 199 LUQueue.Enqueue(ls);
200 } 200 }
201 201
202 /// <summary> 202 /// <summary>
203 /// Disables and unloads a script 203 /// Disables and unloads a script
204 /// </summary> 204 /// </summary>
205 /// <param name="localID"></param> 205 /// <param name="localID"></param>
206 /// <param name="itemID"></param> 206 /// <param name="itemID"></param>
207 public void StopScript(uint localID, LLUUID itemID) 207 public void StopScript(uint localID, LLUUID itemID)
208 { 208 {
209 LUStruct ls = new LUStruct(); 209 LUStruct ls = new LUStruct();
210 ls.localID = localID; 210 ls.localID = localID;
211 ls.itemID = itemID; 211 ls.itemID = itemID;
212 ls.Action = LUType.Unload; 212 ls.Action = LUType.Unload;
213 LUQueue.Enqueue(ls); 213 LUQueue.Enqueue(ls);
214 } 214 }
215 215
216 // Create a new instance of the compiler (reuse) 216 // Create a new instance of the compiler (reuse)
217 //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler(); 217 //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
218 218
219 public abstract void _StartScript(uint localID, LLUUID itemID, string Script); 219 public abstract void _StartScript(uint localID, LLUUID itemID, string Script);
220 220
221 public abstract void _StopScript(uint localID, LLUUID itemID); 221 public abstract void _StopScript(uint localID, LLUUID itemID);
222 222
223 223
224 #endregion 224 #endregion
225 225
226 #region Perform event execution in script 226 #region Perform event execution in script
227 227
228 /// <summary> 228 /// <summary>
229 /// Execute a LL-event-function in Script 229 /// Execute a LL-event-function in Script
230 /// </summary> 230 /// </summary>
231 /// <param name="localID">Object the script is located in</param> 231 /// <param name="localID">Object the script is located in</param>
232 /// <param name="itemID">Script ID</param> 232 /// <param name="itemID">Script ID</param>
233 /// <param name="FunctionName">Name of function</param> 233 /// <param name="FunctionName">Name of function</param>
234 /// <param name="args">Arguments to pass to function</param> 234 /// <param name="args">Arguments to pass to function</param>
235 internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args) 235 internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args)
236 { 236 {
237#if DEBUG 237#if DEBUG
238 Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName); 238 Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
239#endif 239#endif
240 // Execute a function in the script 240 // Execute a function in the script
241 //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); 241 //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
242 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID); 242 //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
243 IScript Script = GetScript(localID, itemID); 243 IScript Script = GetScript(localID, itemID);
244 if (Script == null) 244 if (Script == null)
245 return; 245 return;
246#if DEBUG 246#if DEBUG
247 Console.WriteLine("ScriptEngine: Executing event: " + FunctionName); 247 Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
248#endif 248#endif
249 // Must be done in correct AppDomain, so leaving it up to the script itself 249 // Must be done in correct AppDomain, so leaving it up to the script itself
250 Script.Exec.ExecuteEvent(FunctionName, args); 250 Script.Exec.ExecuteEvent(FunctionName, args);
251 } 251 }
252 252
253 #endregion 253 #endregion
254 254
255 #region Internal functions to keep track of script 255 #region Internal functions to keep track of script
256 256
257 public Dictionary<LLUUID, IScript>.KeyCollection GetScriptKeys(uint localID) 257 public Dictionary<LLUUID, IScript>.KeyCollection GetScriptKeys(uint localID)
258 { 258 {
259 if (Scripts.ContainsKey(localID) == false) 259 if (Scripts.ContainsKey(localID) == false)
260 return null; 260 return null;
261 261
262 Dictionary<LLUUID, IScript> Obj; 262 Dictionary<LLUUID, IScript> Obj;
263 Scripts.TryGetValue(localID, out Obj); 263 Scripts.TryGetValue(localID, out Obj);
264 264
265 return Obj.Keys; 265 return Obj.Keys;
266 } 266 }
267 267
268 public IScript GetScript(uint localID, LLUUID itemID) 268 public IScript GetScript(uint localID, LLUUID itemID)
269 { 269 {
270 if (Scripts.ContainsKey(localID) == false) 270 if (Scripts.ContainsKey(localID) == false)
271 return null; 271 return null;
272 272
273 Dictionary<LLUUID, IScript> Obj; 273 Dictionary<LLUUID, IScript> Obj;
274 Scripts.TryGetValue(localID, out Obj); 274 Scripts.TryGetValue(localID, out Obj);
275 if (Obj.ContainsKey(itemID) == false) 275 if (Obj.ContainsKey(itemID) == false)
276 return null; 276 return null;
277 277
278 // Get script 278 // Get script
279 IScript Script; 279 IScript Script;
280 Obj.TryGetValue(itemID, out Script); 280 Obj.TryGetValue(itemID, out Script);
281 281
282 return Script; 282 return Script;
283 } 283 }
284 284
285 public void SetScript(uint localID, LLUUID itemID, IScript Script) 285 public void SetScript(uint localID, LLUUID itemID, IScript Script)
286 { 286 {
287 // Create object if it doesn't exist 287 // Create object if it doesn't exist
288 if (Scripts.ContainsKey(localID) == false) 288 if (Scripts.ContainsKey(localID) == false)
289 { 289 {
290 Scripts.Add(localID, new Dictionary<LLUUID, IScript>()); 290 Scripts.Add(localID, new Dictionary<LLUUID, IScript>());
291 } 291 }
292 292
293 // Delete script if it exists 293 // Delete script if it exists
294 Dictionary<LLUUID, IScript> Obj; 294 Dictionary<LLUUID, IScript> Obj;
295 Scripts.TryGetValue(localID, out Obj); 295 Scripts.TryGetValue(localID, out Obj);
296 if (Obj.ContainsKey(itemID) == true) 296 if (Obj.ContainsKey(itemID) == true)
297 Obj.Remove(itemID); 297 Obj.Remove(itemID);
298 298
299 // Add to object 299 // Add to object
300 Obj.Add(itemID, Script); 300 Obj.Add(itemID, Script);
301 } 301 }
302 302
303 public void RemoveScript(uint localID, LLUUID itemID) 303 public void RemoveScript(uint localID, LLUUID itemID)
304 { 304 {
305 // Don't have that object? 305 // Don't have that object?
306 if (Scripts.ContainsKey(localID) == false) 306 if (Scripts.ContainsKey(localID) == false)
307 return; 307 return;
308 308
309 // Delete script if it exists 309 // Delete script if it exists
310 Dictionary<LLUUID, IScript> Obj; 310 Dictionary<LLUUID, IScript> Obj;
311 Scripts.TryGetValue(localID, out Obj); 311 Scripts.TryGetValue(localID, out Obj);
312 if (Obj.ContainsKey(itemID) == true) 312 if (Obj.ContainsKey(itemID) == true)
313 Obj.Remove(itemID); 313 Obj.Remove(itemID);
314 } 314 }
315 315
316 #endregion 316 #endregion
317 317
318 318
319 public void ResetScript(uint localID, LLUUID itemID) 319 public void ResetScript(uint localID, LLUUID itemID)
320 { 320 {
321 string script = GetScript(localID, itemID).Source; 321 string script = GetScript(localID, itemID).Source;
322 StopScript(localID, itemID); 322 StopScript(localID, itemID);
323 StartScript(localID, itemID, script); 323 StartScript(localID, itemID, script);
324 } 324 }
325 325
326 326
327 #region Script serialization/deserialization 327 #region Script serialization/deserialization
328 328
329 public void GetSerializedScript(uint localID, LLUUID itemID) 329 public void GetSerializedScript(uint localID, LLUUID itemID)
330 { 330 {
331 // Serialize the script and return it 331 // Serialize the script and return it
332 // Should not be a problem 332 // Should not be a problem
333 FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID); 333 FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID);
334 BinaryFormatter b = new BinaryFormatter(); 334 BinaryFormatter b = new BinaryFormatter();
335 b.Serialize(fs, GetScript(localID, itemID)); 335 b.Serialize(fs, GetScript(localID, itemID));
336 fs.Close(); 336 fs.Close();
337 } 337 }
338 338
339 public void PutSerializedScript(uint localID, LLUUID itemID) 339 public void PutSerializedScript(uint localID, LLUUID itemID)
340 { 340 {
341 // Deserialize the script and inject it into an AppDomain 341 // Deserialize the script and inject it into an AppDomain
342 342
343 // How to inject into an AppDomain? 343 // How to inject into an AppDomain?
344 } 344 }
345 345
346 #endregion 346 #endregion
347 } 347 }
348} \ No newline at end of file 348} \ No newline at end of file