aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
authorMelanie Thielker2008-08-27 22:38:36 +0000
committerMelanie Thielker2008-08-27 22:38:36 +0000
commit6e3367d68ca6e0e632078dc02f52b03bd034afce (patch)
tree787b31ac8ce1d29b40869aafa1bebd476e86979a /OpenSim/Region/ScriptEngine
parentRefactor Executor into the script app domain and IScript. This changes (diff)
downloadopensim-SC-6e3367d68ca6e0e632078dc02f52b03bd034afce.zip
opensim-SC-6e3367d68ca6e0e632078dc02f52b03bd034afce.tar.gz
opensim-SC-6e3367d68ca6e0e632078dc02f52b03bd034afce.tar.bz2
opensim-SC-6e3367d68ca6e0e632078dc02f52b03bd034afce.tar.xz
Refactor XScriptInstance to IScriptInstance and move into Shared/. Now
engines that want to use the XEngine's instance handling and state persistence can do so. IScriptInstance is optional, but it does require the SmartThreadPool if it is used.
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs81
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs660
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs461
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs1076
5 files changed, 1233 insertions, 1048 deletions
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
index 0dab318..292858c 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
@@ -32,6 +32,7 @@ using OpenSim.Region.Environment.Scenes;
32using libsecondlife; 32using libsecondlife;
33using Nini.Config; 33using Nini.Config;
34using OpenSim.Region.ScriptEngine.Interfaces; 34using OpenSim.Region.ScriptEngine.Interfaces;
35using Amib.Threading;
35 36
36namespace OpenSim.Region.ScriptEngine.Interfaces 37namespace OpenSim.Region.ScriptEngine.Interfaces
37{ 38{
@@ -47,6 +48,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
47 Object AsyncCommands { get; } 48 Object AsyncCommands { get; }
48 ILog Log { get; } 49 ILog Log { get; }
49 string ScriptEngineName { get; } 50 string ScriptEngineName { get; }
51 int MaxScriptQueue { get; }
50 52
51 bool PostScriptEvent(LLUUID itemID, EventParams parms); 53 bool PostScriptEvent(LLUUID itemID, EventParams parms);
52 bool PostObjectEvent(uint localID, EventParams parms); 54 bool PostObjectEvent(uint localID, EventParams parms);
@@ -56,6 +58,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
56 bool GetScriptState(LLUUID itemID); 58 bool GetScriptState(LLUUID itemID);
57 void SetState(LLUUID itemID, string newState); 59 void SetState(LLUUID itemID, string newState);
58 int GetStartParameter(LLUUID itemID); 60 int GetStartParameter(LLUUID itemID);
61 IWorkItemResult QueueEventHandler(object parms);
59 62
60 DetectParams GetDetectParams(LLUUID item, int number); 63 DetectParams GetDetectParams(LLUUID item, int number);
61 } 64 }
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
new file mode 100644
index 0000000..03a3802
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -0,0 +1,81 @@
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;
30using System.Collections.Generic;
31using libsecondlife;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Region.ScriptEngine.Shared;
35using OpenSim.Region.ScriptEngine.Interfaces;
36
37namespace OpenSim.Region.ScriptEngine.Interfaces
38{
39 public enum StateSource
40 {
41 NewRez = 0,
42 PrimCrossing = 1,
43 AttachmentCrossing = 2
44 }
45
46 public interface IScriptInstance
47 {
48 bool Running { get; set; }
49 string State { get; set; }
50 IScriptEngine Engine { get; }
51 LLUUID AppDomain { get; set; }
52 string PrimName { get; }
53 string ScriptName { get; }
54 LLUUID ItemID { get; }
55 LLUUID ObjectID { get; }
56 uint LocalID { get; }
57 LLUUID AssetID { get; }
58 Queue EventQueue { get; }
59
60 void ClearQueue();
61 int StartParam { get; set; }
62
63 void RemoveState();
64
65 void Start();
66 bool Stop(int timeout);
67 void SetState(string state);
68
69 void PostEvent(EventParams data);
70 object EventProcessor();
71
72 int EventTime();
73 void ResetScript();
74 void ApiResetScript();
75 Dictionary<string, object> GetVars();
76 void SetVars(Dictionary<string, object> vars);
77 DetectParams GetDetectParams(int idx);
78 LLUUID GetDetectID(int idx);
79 void SaveState(string assembly);
80 }
81}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
new file mode 100644
index 0000000..30c0274
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -0,0 +1,660 @@
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.IO;
30using System.Threading;
31using System.Collections;
32using System.Collections.Generic;
33using System.Security.Policy;
34using System.Reflection;
35using System.Globalization;
36using System.Xml;
37using libsecondlife;
38using log4net;
39using Nini.Config;
40using Amib.Threading;
41using OpenSim.Framework;
42using OpenSim.Region.Environment;
43using OpenSim.Region.Environment.Scenes;
44using OpenSim.Region.Environment.Interfaces;
45using OpenSim.Region.ScriptEngine.Shared;
46using OpenSim.Region.ScriptEngine.Shared.Api;
47using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
48using OpenSim.Region.ScriptEngine.Shared.CodeTools;
49using OpenSim.Region.ScriptEngine.Interfaces;
50
51namespace OpenSim.Region.ScriptEngine.Shared.Instance
52{
53 public class ScriptInstance : IScriptInstance
54 {
55 private IScriptEngine m_Engine;
56 private IWorkItemResult m_CurrentResult=null;
57 private Queue m_EventQueue = new Queue(32);
58 private bool m_RunEvents = false;
59 private LLUUID m_ItemID;
60 private uint m_LocalID;
61 private LLUUID m_ObjectID;
62 private LLUUID m_AssetID;
63 private IScript m_Script;
64 private LLUUID m_AppDomain;
65 private DetectParams[] m_DetectParams;
66 private bool m_TimerQueued;
67 private DateTime m_EventStart;
68 private bool m_InEvent;
69 private string m_PrimName;
70 private string m_ScriptName;
71 private string m_Assembly;
72 private int m_StartParam = 0;
73 private string m_CurrentEvent = String.Empty;
74 private bool m_InSelfDelete = false;
75
76 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
77
78 // Script state
79 private string m_State="default";
80
81 public Object[] PluginData = new Object[0];
82
83 public bool Running
84 {
85 get { return m_RunEvents; }
86 set { m_RunEvents = value; }
87 }
88
89 public string State
90 {
91 get { return m_State; }
92 set { m_State = value; }
93 }
94
95 public IScriptEngine Engine
96 {
97 get { return m_Engine; }
98 }
99
100 public LLUUID AppDomain
101 {
102 get { return m_AppDomain; }
103 set { m_AppDomain = value; }
104 }
105
106 public string PrimName
107 {
108 get { return m_PrimName; }
109 }
110
111 public string ScriptName
112 {
113 get { return m_ScriptName; }
114 }
115
116 public LLUUID ItemID
117 {
118 get { return m_ItemID; }
119 }
120
121 public LLUUID ObjectID
122 {
123 get { return m_ObjectID; }
124 }
125
126 public uint LocalID
127 {
128 get { return m_LocalID; }
129 }
130
131 public LLUUID AssetID
132 {
133 get { return m_AssetID; }
134 }
135
136 public Queue EventQueue
137 {
138 get { return m_EventQueue; }
139 }
140
141 public void ClearQueue()
142 {
143 m_TimerQueued = false;
144 m_EventQueue.Clear();
145 }
146
147 public int StartParam
148 {
149 get { return m_StartParam; }
150 set { m_StartParam = value; }
151 }
152
153 public ScriptInstance(IScriptEngine engine, uint localID,
154 LLUUID objectID, LLUUID itemID, LLUUID assetID, string assembly,
155 AppDomain dom, string primName, string scriptName,
156 int startParam, bool postOnRez, StateSource stateSource)
157 {
158 m_Engine = engine;
159
160 m_LocalID = localID;
161 m_ObjectID = objectID;
162 m_ItemID = itemID;
163 m_AssetID = assetID;
164 m_PrimName = primName;
165 m_ScriptName = scriptName;
166 m_Assembly = assembly;
167 m_StartParam = startParam;
168
169 ApiManager am = new ApiManager();
170
171 SceneObjectPart part=engine.World.GetSceneObjectPart(localID);
172 if (part == null)
173 {
174 engine.Log.Error("[Script] SceneObjectPart unavailable. Script NOT started.");
175 return;
176 }
177
178 foreach (string api in am.GetApis())
179 {
180 m_Apis[api] = am.CreateApi(api);
181 m_Apis[api].Initialize(engine, part, localID, itemID);
182 }
183
184 try
185 {
186 m_Script = (IScript)dom.CreateInstanceAndUnwrap(
187 Path.GetFileNameWithoutExtension(assembly),
188 "SecondLife.Script");
189 }
190 catch (Exception e)
191 {
192 m_Engine.Log.ErrorFormat("[Script] Error loading assembly {0}\n"+e.ToString(), assembly);
193 }
194
195 try
196 {
197 foreach (KeyValuePair<string,IScriptApi> kv in m_Apis)
198 {
199 m_Script.InitApi(kv.Key, kv.Value);
200 }
201
202// m_Engine.Log.Debug("[Script] Script instance created");
203
204 part.SetScriptEvents(m_ItemID,
205 (int)m_Script.GetStateEventFlags(State));
206 }
207 catch (Exception e)
208 {
209 m_Engine.Log.Error("[Script] Error loading script instance\n"+e.ToString());
210 return;
211 }
212
213 string savedState = Path.Combine(Path.GetDirectoryName(assembly),
214 m_ItemID.ToString() + ".state");
215 if (File.Exists(savedState))
216 {
217 string xml = String.Empty;
218
219 try
220 {
221 FileInfo fi = new FileInfo(savedState);
222 int size=(int)fi.Length;
223 if (size < 512000)
224 {
225 using (FileStream fs = File.Open(savedState,
226 FileMode.Open, FileAccess.Read, FileShare.None))
227 {
228 System.Text.ASCIIEncoding enc =
229 new System.Text.ASCIIEncoding();
230
231 Byte[] data = new Byte[size];
232 fs.Read(data, 0, size);
233
234 xml = enc.GetString(data);
235
236 ScriptSerializer.Deserialize(xml, this);
237
238 AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands;
239 async.CreateFromData(
240 m_LocalID, m_ItemID, m_ObjectID,
241 PluginData);
242
243 m_Engine.Log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", m_PrimName, m_ScriptName);
244
245 if (m_RunEvents)
246 {
247 m_RunEvents = false;
248 Start();
249 if (postOnRez)
250 PostEvent(new EventParams("on_rez",
251 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
252 }
253
254 // we get new rez events on sim restart, too
255 // but if there is state, then we fire the change
256 // event
257 if (stateSource == StateSource.NewRez)
258 {
259// m_Engine.Log.Debug("[Script] Posted changed(CHANGED_REGION_RESTART) to script");
260 PostEvent(new EventParams("changed",
261 new Object[] {new LSL_Types.LSLInteger(256)}, new DetectParams[0]));
262 }
263 }
264 }
265 else
266 {
267 m_Engine.Log.Error("[Script] Unable to load script state: Memory limit exceeded");
268 Start();
269 PostEvent(new EventParams("state_entry",
270 new Object[0], new DetectParams[0]));
271 if (postOnRez)
272 PostEvent(new EventParams("on_rez",
273 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
274
275 }
276 }
277 catch (Exception e)
278 {
279 m_Engine.Log.ErrorFormat("[Script] Unable to load script state from xml: {0}\n"+e.ToString(), xml);
280 Start();
281 PostEvent(new EventParams("state_entry",
282 new Object[0], new DetectParams[0]));
283 if (postOnRez)
284 PostEvent(new EventParams("on_rez",
285 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
286 }
287 }
288 else
289 {
290// m_Engine.Log.ErrorFormat("[Script] Unable to load script state, file not found");
291 Start();
292 PostEvent(new EventParams("state_entry",
293 new Object[0], new DetectParams[0]));
294
295 if (postOnRez)
296 PostEvent(new EventParams("on_rez",
297 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
298 }
299 }
300
301 public void RemoveState()
302 {
303 string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly),
304 m_ItemID.ToString() + ".state");
305
306 try
307 {
308 File.Delete(savedState);
309 }
310 catch(Exception)
311 {
312 }
313 }
314
315 public void VarDump(Dictionary<string, object> vars)
316 {
317 Console.WriteLine("Variable dump for script {0}", m_ItemID.ToString());
318 foreach (KeyValuePair<string, object> v in vars)
319 {
320 Console.WriteLine("Variable: {0} = '{1}'", v. Key,
321 v.Value.ToString());
322 }
323 }
324
325 public void Start()
326 {
327 lock (m_EventQueue)
328 {
329 if (Running)
330 return;
331
332 m_RunEvents = true;
333
334 if (m_EventQueue.Count > 0)
335 {
336 if (m_CurrentResult == null)
337 m_CurrentResult = m_Engine.QueueEventHandler(this);
338 else
339 m_Engine.Log.Error("[Script] Tried to start a script that was already queued");
340 }
341 }
342 }
343
344 public bool Stop(int timeout)
345 {
346 IWorkItemResult result;
347
348 lock (m_EventQueue)
349 {
350 if (!Running)
351 return true;
352
353 if (m_CurrentResult == null)
354 {
355 m_RunEvents = false;
356 return true;
357 }
358
359 if (m_CurrentResult.Cancel())
360 {
361 m_CurrentResult = null;
362 m_RunEvents = false;
363 return true;
364 }
365
366 result = m_CurrentResult;
367 m_RunEvents = false;
368 }
369
370 if (SmartThreadPool.WaitAll(new IWorkItemResult[] {result}, new TimeSpan((long)timeout * 100000), false))
371 {
372 return true;
373 }
374
375 lock (m_EventQueue)
376 {
377 result = m_CurrentResult;
378 }
379
380 if (result == null)
381 return true;
382
383 if (!m_InSelfDelete)
384 result.Abort();
385
386 lock (m_EventQueue)
387 {
388 m_CurrentResult = null;
389 }
390
391 return true;
392 }
393
394 public void SetState(string state)
395 {
396 PostEvent(new EventParams("state_exit", new Object[0],
397 new DetectParams[0]));
398 PostEvent(new EventParams("state", new Object[] { state },
399 new DetectParams[0]));
400 PostEvent(new EventParams("state_entry", new Object[0],
401 new DetectParams[0]));
402 }
403
404 public void PostEvent(EventParams data)
405 {
406// m_Engine.Log.DebugFormat("[Script] Posted event {2} in state {3} to {0}.{1}",
407// m_PrimName, m_ScriptName, data.EventName, m_State);
408
409 if (!Running)
410 return;
411
412 lock (m_EventQueue)
413 {
414 if (m_EventQueue.Count >= m_Engine.MaxScriptQueue)
415 return;
416
417 m_EventQueue.Enqueue(data);
418 if (data.EventName == "timer")
419 {
420 if (m_TimerQueued)
421 return;
422 m_TimerQueued = true;
423 }
424
425 if (!m_RunEvents)
426 return;
427
428 if (m_CurrentResult == null)
429 {
430 m_CurrentResult = m_Engine.QueueEventHandler(this);
431 }
432 }
433 }
434
435 public object EventProcessor()
436 {
437 EventParams data = null;
438
439 lock (m_EventQueue)
440 {
441 data = (EventParams) m_EventQueue.Dequeue();
442 if (data == null) // Shouldn't happen
443 {
444 m_CurrentResult = null;
445 return 0;
446 }
447 if (data.EventName == "timer")
448 m_TimerQueued = false;
449 }
450
451 m_DetectParams = data.DetectParams;
452
453 if (data.EventName == "state") // Hardcoded state change
454 {
455// m_Engine.Log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
456// m_PrimName, m_ScriptName, data.Params[0].ToString());
457 m_State=data.Params[0].ToString();
458 AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands;
459 async.RemoveScript(
460 m_LocalID, m_ItemID);
461
462 SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
463 m_LocalID);
464 if (part != null)
465 {
466 part.SetScriptEvents(m_ItemID,
467 (int)m_Script.GetStateEventFlags(State));
468 }
469 }
470 else
471 {
472 SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
473 m_LocalID);
474// m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
475// m_PrimName, m_ScriptName, data.EventName, m_State);
476
477 try
478 {
479 m_CurrentEvent = data.EventName;
480 m_EventStart = DateTime.Now;
481 m_InEvent = true;
482
483 m_Script.ExecuteEvent(State, data.EventName, data.Params);
484
485 m_InEvent = false;
486 m_CurrentEvent = String.Empty;
487 }
488 catch (Exception e)
489 {
490 m_InEvent = false;
491 m_CurrentEvent = String.Empty;
492
493 if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException))))
494 {
495 if (e is System.Threading.ThreadAbortException)
496 {
497 lock (m_EventQueue)
498 {
499 if ((m_EventQueue.Count > 0) && m_RunEvents)
500 {
501 m_CurrentResult=m_Engine.QueueEventHandler(this);
502 }
503 else
504 {
505 m_CurrentResult = null;
506 }
507 }
508
509 m_DetectParams = null;
510
511 return 0;
512 }
513
514 try
515 {
516 // DISPLAY ERROR INWORLD
517 string text = "Runtime error:\n" + e.ToString();
518 if (text.Length > 1400)
519 text = text.Substring(0, 1400);
520 m_Engine.World.SimChat(Helpers.StringToField(text),
521 ChatTypeEnum.DebugChannel, 2147483647,
522 part.AbsolutePosition,
523 part.Name, part.UUID, false);
524 }
525 catch (Exception e2) // LEGIT: User Scripting
526 {
527 m_Engine.Log.Error("[Script]: "+
528 "Error displaying error in-world: " +
529 e2.ToString());
530 m_Engine.Log.Error("[Script]: " +
531 "Errormessage: Error compiling script:\r\n" +
532 e.ToString());
533 }
534 }
535 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
536 {
537 m_InSelfDelete = true;
538 if (part != null && part.ParentGroup != null)
539 m_Engine.World.DeleteSceneObject(part.ParentGroup);
540 }
541 }
542 }
543
544 lock (m_EventQueue)
545 {
546 if ((m_EventQueue.Count > 0) && m_RunEvents)
547 {
548 m_CurrentResult = m_Engine.QueueEventHandler(this);
549 }
550 else
551 {
552 m_CurrentResult = null;
553 }
554 }
555
556 m_DetectParams = null;
557
558 return 0;
559 }
560
561 public int EventTime()
562 {
563 if (!m_InEvent)
564 return 0;
565
566 return (DateTime.Now - m_EventStart).Seconds;
567 }
568
569 public void ResetScript()
570 {
571 bool running = Running;
572
573 RemoveState();
574
575 Stop(0);
576 SceneObjectPart part=m_Engine.World.GetSceneObjectPart(m_LocalID);
577 part.GetInventoryItem(m_ItemID).PermsMask = 0;
578 part.GetInventoryItem(m_ItemID).PermsGranter = LLUUID.Zero;
579 AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands;
580 async.RemoveScript(m_LocalID, m_ItemID);
581 m_EventQueue.Clear();
582 m_Script.ResetVars();
583 m_State = "default";
584 if (running)
585 Start();
586 PostEvent(new EventParams("state_entry",
587 new Object[0], new DetectParams[0]));
588 }
589
590 public void ApiResetScript()
591 {
592 // bool running = Running;
593
594 RemoveState();
595
596 m_Script.ResetVars();
597 SceneObjectPart part=m_Engine.World.GetSceneObjectPart(m_LocalID);
598 part.GetInventoryItem(m_ItemID).PermsMask = 0;
599 part.GetInventoryItem(m_ItemID).PermsGranter = LLUUID.Zero;
600 AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands;
601 async.RemoveScript(m_LocalID, m_ItemID);
602 if (m_CurrentEvent != "state_entry")
603 {
604 PostEvent(new EventParams("state_entry",
605 new Object[0], new DetectParams[0]));
606 }
607 }
608
609 public Dictionary<string, object> GetVars()
610 {
611 return m_Script.GetVars();
612 }
613
614 public void SetVars(Dictionary<string, object> vars)
615 {
616 m_Script.SetVars(vars);
617 }
618
619 public DetectParams GetDetectParams(int idx)
620 {
621 if (idx < 0 || idx >= m_DetectParams.Length)
622 return null;
623
624 return m_DetectParams[idx];
625 }
626
627 public LLUUID GetDetectID(int idx)
628 {
629 if (idx < 0 || idx >= m_DetectParams.Length)
630 return LLUUID.Zero;
631
632 return m_DetectParams[idx].Key;
633 }
634
635 public void SaveState(string assembly)
636 {
637 AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands;
638 PluginData = async.GetSerializationData(m_ItemID);
639
640 string xml = ScriptSerializer.Serialize(this);
641
642 try
643 {
644 FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state"));
645 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
646 Byte[] buf = enc.GetBytes(xml);
647 fs.Write(buf, 0, buf.Length);
648 fs.Close();
649 }
650 catch(Exception e)
651 {
652 Console.WriteLine("Unable to save xml\n"+e.ToString());
653 }
654 if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state")))
655 {
656 throw new Exception("Completed persistence save, but no file was created");
657 }
658 }
659 }
660}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs
new file mode 100644
index 0000000..ba003c5
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs
@@ -0,0 +1,461 @@
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.IO;
30using System.Threading;
31using System.Collections;
32using System.Collections.Generic;
33using System.Security.Policy;
34using System.Reflection;
35using System.Globalization;
36using System.Xml;
37using libsecondlife;
38using log4net;
39using Nini.Config;
40using Amib.Threading;
41using OpenSim.Framework;
42using OpenSim.Region.Environment;
43using OpenSim.Region.Environment.Scenes;
44using OpenSim.Region.Environment.Interfaces;
45using OpenSim.Region.ScriptEngine.Shared;
46using OpenSim.Region.ScriptEngine.Shared.Api;
47using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
48using OpenSim.Region.ScriptEngine.Shared.CodeTools;
49using OpenSim.Region.ScriptEngine.Interfaces;
50
51namespace OpenSim.Region.ScriptEngine.Shared.Instance
52{
53 public class ScriptSerializer
54 {
55 public static string Serialize(ScriptInstance instance)
56 {
57 bool running = instance.Running;
58
59 if (running)
60 instance.Stop(50);
61
62 XmlDocument xmldoc = new XmlDocument();
63
64 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
65 "", "");
66 xmldoc.AppendChild(xmlnode);
67
68 XmlElement rootElement = xmldoc.CreateElement("", "ScriptState",
69 "");
70 xmldoc.AppendChild(rootElement);
71
72 XmlElement state = xmldoc.CreateElement("", "State", "");
73 state.AppendChild(xmldoc.CreateTextNode(instance.State));
74
75 rootElement.AppendChild(state);
76
77 XmlElement run = xmldoc.CreateElement("", "Running", "");
78 run.AppendChild(xmldoc.CreateTextNode(
79 running.ToString()));
80
81 rootElement.AppendChild(run);
82
83 Dictionary<string, Object> vars = instance.GetVars();
84
85 XmlElement variables = xmldoc.CreateElement("", "Variables", "");
86
87 foreach (KeyValuePair<string, Object> var in vars)
88 WriteTypedValue(xmldoc, variables, "Variable", var.Key,
89 var.Value);
90
91 rootElement.AppendChild(variables);
92
93 XmlElement queue = xmldoc.CreateElement("", "Queue", "");
94
95 int count = instance.EventQueue.Count;
96
97 while (count > 0)
98 {
99 EventParams ep = (EventParams)instance.EventQueue.Dequeue();
100 instance.EventQueue.Enqueue(ep);
101 count--;
102
103 XmlElement item = xmldoc.CreateElement("", "Item", "");
104 XmlAttribute itemEvent = xmldoc.CreateAttribute("", "event",
105 "");
106 itemEvent.Value = ep.EventName;
107 item.Attributes.Append(itemEvent);
108
109 XmlElement parms = xmldoc.CreateElement("", "Params", "");
110
111 foreach (Object o in ep.Params)
112 WriteTypedValue(xmldoc, parms, "Param", String.Empty, o);
113
114 item.AppendChild(parms);
115
116 XmlElement detect = xmldoc.CreateElement("", "Detected", "");
117
118 foreach (DetectParams det in ep.DetectParams)
119 {
120 XmlElement objectElem = xmldoc.CreateElement("", "Object",
121 "");
122 XmlAttribute pos = xmldoc.CreateAttribute("", "pos", "");
123 pos.Value = det.OffsetPos.ToString();
124 objectElem.Attributes.Append(pos);
125
126 XmlAttribute d_linkNum = xmldoc.CreateAttribute("",
127 "linkNum", "");
128 d_linkNum.Value = det.LinkNum.ToString();
129 objectElem.Attributes.Append(d_linkNum);
130
131 XmlAttribute d_group = xmldoc.CreateAttribute("",
132 "group", "");
133 d_group.Value = det.Group.ToString();
134 objectElem.Attributes.Append(d_group);
135
136 XmlAttribute d_name = xmldoc.CreateAttribute("",
137 "name", "");
138 d_name.Value = det.Name.ToString();
139 objectElem.Attributes.Append(d_name);
140
141 XmlAttribute d_owner = xmldoc.CreateAttribute("",
142 "owner", "");
143 d_owner.Value = det.Owner.ToString();
144 objectElem.Attributes.Append(d_owner);
145
146 XmlAttribute d_position = xmldoc.CreateAttribute("",
147 "position", "");
148 d_position.Value = det.Position.ToString();
149 objectElem.Attributes.Append(d_position);
150
151 XmlAttribute d_rotation = xmldoc.CreateAttribute("",
152 "rotation", "");
153 d_rotation.Value = det.Rotation.ToString();
154 objectElem.Attributes.Append(d_rotation);
155
156 XmlAttribute d_type = xmldoc.CreateAttribute("",
157 "type", "");
158 d_type.Value = det.Type.ToString();
159 objectElem.Attributes.Append(d_type);
160
161 XmlAttribute d_velocity = xmldoc.CreateAttribute("",
162 "velocity", "");
163 d_velocity.Value = det.Velocity.ToString();
164 objectElem.Attributes.Append(d_velocity);
165
166 objectElem.AppendChild(
167 xmldoc.CreateTextNode(det.Key.ToString()));
168
169 detect.AppendChild(objectElem);
170 }
171
172 item.AppendChild(detect);
173
174 queue.AppendChild(item);
175 }
176
177 rootElement.AppendChild(queue);
178
179 XmlNode plugins = xmldoc.CreateElement("", "Plugins", "");
180 DumpList(xmldoc, plugins,
181 new LSL_Types.list(instance.PluginData));
182
183 rootElement.AppendChild(plugins);
184
185 if (running)
186 instance.Start();
187
188 return xmldoc.InnerXml;
189 }
190
191 public static void Deserialize(string xml, ScriptInstance instance)
192 {
193 XmlDocument doc = new XmlDocument();
194
195 Dictionary<string, object> vars = instance.GetVars();
196
197 instance.PluginData = new Object[0];
198
199 doc.LoadXml(xml);
200
201 XmlNodeList rootL = doc.GetElementsByTagName("ScriptState");
202 if (rootL.Count != 1)
203 {
204 return;
205 }
206 XmlNode rootNode = rootL[0];
207
208 if (rootNode != null)
209 {
210 object varValue;
211 XmlNodeList partL = rootNode.ChildNodes;
212
213 foreach (XmlNode part in partL)
214 {
215 switch (part.Name)
216 {
217 case "State":
218 instance.State=part.InnerText;
219 break;
220 case "Running":
221 instance.Running=bool.Parse(part.InnerText);
222 break;
223 case "Variables":
224 XmlNodeList varL = part.ChildNodes;
225 foreach (XmlNode var in varL)
226 {
227 string varName;
228 varValue=ReadTypedValue(var, out varName);
229
230 if (vars.ContainsKey(varName))
231 vars[varName] = varValue;
232 }
233 instance.SetVars(vars);
234 break;
235 case "Queue":
236 XmlNodeList itemL = part.ChildNodes;
237 foreach (XmlNode item in itemL)
238 {
239 List<Object> parms = new List<Object>();
240 List<DetectParams> detected =
241 new List<DetectParams>();
242
243 string eventName =
244 item.Attributes.GetNamedItem("event").Value;
245 XmlNodeList eventL = item.ChildNodes;
246 foreach (XmlNode evt in eventL)
247 {
248 switch (evt.Name)
249 {
250 case "Params":
251 XmlNodeList prms = evt.ChildNodes;
252 foreach (XmlNode pm in prms)
253 parms.Add(ReadTypedValue(pm));
254
255 break;
256 case "Detected":
257 XmlNodeList detL = evt.ChildNodes;
258 foreach (XmlNode det in detL)
259 {
260 string vect =
261 det.Attributes.GetNamedItem(
262 "pos").Value;
263 LSL_Types.Vector3 v =
264 new LSL_Types.Vector3(vect);
265
266 int d_linkNum=0;
267 LLUUID d_group = LLUUID.Zero;
268 string d_name = String.Empty;
269 LLUUID d_owner = LLUUID.Zero;
270 LSL_Types.Vector3 d_position =
271 new LSL_Types.Vector3();
272 LSL_Types.Quaternion d_rotation =
273 new LSL_Types.Quaternion();
274 int d_type = 0;
275 LSL_Types.Vector3 d_velocity =
276 new LSL_Types.Vector3();
277
278 try
279 {
280 string tmp;
281
282 tmp = det.Attributes.GetNamedItem(
283 "linkNum").Value;
284 int.TryParse(tmp, out d_linkNum);
285
286 tmp = det.Attributes.GetNamedItem(
287 "group").Value;
288 LLUUID.TryParse(tmp, out d_group);
289
290 d_name = det.Attributes.GetNamedItem(
291 "name").Value;
292
293 tmp = det.Attributes.GetNamedItem(
294 "owner").Value;
295 LLUUID.TryParse(tmp, out d_owner);
296
297 tmp = det.Attributes.GetNamedItem(
298 "position").Value;
299 d_position =
300 new LSL_Types.Vector3(tmp);
301
302 tmp = det.Attributes.GetNamedItem(
303 "rotation").Value;
304 d_rotation =
305 new LSL_Types.Quaternion(tmp);
306
307 tmp = det.Attributes.GetNamedItem(
308 "type").Value;
309 int.TryParse(tmp, out d_type);
310
311 tmp = det.Attributes.GetNamedItem(
312 "velocity").Value;
313 d_velocity =
314 new LSL_Types.Vector3(tmp);
315
316 }
317 catch (Exception) // Old version XML
318 {
319 }
320
321 LLUUID uuid = new LLUUID();
322 LLUUID.TryParse(det.InnerText,
323 out uuid);
324
325 DetectParams d = new DetectParams();
326 d.Key = uuid;
327 d.OffsetPos = v;
328 d.LinkNum = d_linkNum;
329 d.Group = d_group;
330 d.Name = d_name;
331 d.Owner = d_owner;
332 d.Position = d_position;
333 d.Rotation = d_rotation;
334 d.Type = d_type;
335 d.Velocity = d_velocity;
336
337 detected.Add(d);
338 }
339 break;
340 }
341 }
342 EventParams ep = new EventParams(
343 eventName, parms.ToArray(),
344 detected.ToArray());
345 instance.EventQueue.Enqueue(ep);
346 }
347 break;
348 case "Plugins":
349 instance.PluginData = ReadList(part).Data;
350 break;
351 }
352 }
353 }
354 }
355
356 private static void DumpList(XmlDocument doc, XmlNode parent,
357 LSL_Types.list l)
358 {
359 foreach (Object o in l.Data)
360 WriteTypedValue(doc, parent, "ListItem", "", o);
361 }
362
363 private static LSL_Types.list ReadList(XmlNode parent)
364 {
365 List<Object> olist = new List<Object>();
366
367 XmlNodeList itemL = parent.ChildNodes;
368 foreach (XmlNode item in itemL)
369 olist.Add(ReadTypedValue(item));
370
371 return new LSL_Types.list(olist.ToArray());
372 }
373
374 private static void WriteTypedValue(XmlDocument doc, XmlNode parent,
375 string tag, string name, object value)
376 {
377 Type t=value.GetType();
378 XmlAttribute typ = doc.CreateAttribute("", "type", "");
379 XmlNode n = doc.CreateElement("", tag, "");
380
381 if (value is LSL_Types.list)
382 {
383 typ.Value = "list";
384 n.Attributes.Append(typ);
385
386 DumpList(doc, n, (LSL_Types.list) value);
387
388 if (name != String.Empty)
389 {
390 XmlAttribute nam = doc.CreateAttribute("", "name", "");
391 nam.Value = name;
392 n.Attributes.Append(nam);
393 }
394
395 parent.AppendChild(n);
396 return;
397 }
398
399 n.AppendChild(doc.CreateTextNode(value.ToString()));
400
401 typ.Value = t.ToString();
402 n.Attributes.Append(typ);
403 if (name != String.Empty)
404 {
405 XmlAttribute nam = doc.CreateAttribute("", "name", "");
406 nam.Value = name;
407 n.Attributes.Append(nam);
408 }
409
410 parent.AppendChild(n);
411 }
412
413 private static object ReadTypedValue(XmlNode tag, out string name)
414 {
415 name = tag.Attributes.GetNamedItem("name").Value;
416
417 return ReadTypedValue(tag);
418 }
419
420 private static object ReadTypedValue(XmlNode tag)
421 {
422 Object varValue;
423 string assembly;
424
425 string itemType = tag.Attributes.GetNamedItem("type").Value;
426
427 if (itemType == "list")
428 return ReadList(tag);
429
430 if (itemType == "libsecondlife.LLUUID")
431 {
432 LLUUID val = new LLUUID();
433 LLUUID.TryParse(tag.InnerText, out val);
434
435 return val;
436 }
437
438 Type itemT = Type.GetType(itemType);
439 if (itemT == null)
440 {
441 Object[] args =
442 new Object[] { tag.InnerText };
443
444 assembly = itemType+", OpenSim.Region.ScriptEngine.Shared";
445 itemT = Type.GetType(assembly);
446 if (itemT == null)
447 return null;
448
449 varValue = Activator.CreateInstance(itemT, args);
450
451 if (varValue == null)
452 return null;
453 }
454 else
455 {
456 varValue = Convert.ChangeType(tag.InnerText, itemT);
457 }
458 return varValue;
459 }
460 }
461}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index cfe0599..c5bcfd5 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -46,6 +46,7 @@ using OpenSim.Region.ScriptEngine.Shared;
46using OpenSim.Region.ScriptEngine.Shared.Api; 46using OpenSim.Region.ScriptEngine.Shared.Api;
47using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 47using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
48using OpenSim.Region.ScriptEngine.Shared.CodeTools; 48using OpenSim.Region.ScriptEngine.Shared.CodeTools;
49using OpenSim.Region.ScriptEngine.Shared.Instance;
49using OpenSim.Region.ScriptEngine.Interfaces; 50using OpenSim.Region.ScriptEngine.Interfaces;
50 51
51namespace OpenSim.Region.ScriptEngine.XEngine 52namespace OpenSim.Region.ScriptEngine.XEngine
@@ -67,7 +68,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
67#pragma warning restore 414 68#pragma warning restore 414
68 private int m_EventLimit; 69 private int m_EventLimit;
69 private bool m_KillTimedOutScripts; 70 private bool m_KillTimedOutScripts;
70 public AsyncCommandManager m_AsyncCommands; 71 private AsyncCommandManager m_AsyncCommands;
71 bool m_firstStart = true; 72 bool m_firstStart = true;
72 73
73 private static List<XEngine> m_ScriptEngines = 74 private static List<XEngine> m_ScriptEngines =
@@ -80,8 +81,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
80 81
81 // Maps the LLUUID above to the script instance 82 // Maps the LLUUID above to the script instance
82 83
83 private Dictionary<LLUUID, XScriptInstance> m_Scripts = 84 private Dictionary<LLUUID, IScriptInstance> m_Scripts =
84 new Dictionary<LLUUID, XScriptInstance>(); 85 new Dictionary<LLUUID, IScriptInstance>();
85 86
86 // Maps the asset ID to the assembly 87 // Maps the asset ID to the assembly
87 88
@@ -254,15 +255,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
254 255
255// m_log.Debug("[XEngine] Backing up script states"); 256// m_log.Debug("[XEngine] Backing up script states");
256 257
257 List<XScriptInstance> instances = new List<XScriptInstance>(); 258 List<IScriptInstance> instances = new List<IScriptInstance>();
258 259
259 lock (m_Scripts) 260 lock (m_Scripts)
260 { 261 {
261 foreach (XScriptInstance instance in m_Scripts.Values) 262 foreach (IScriptInstance instance in m_Scripts.Values)
262 instances.Add(instance); 263 instances.Add(instance);
263 } 264 }
264 265
265 foreach (XScriptInstance i in instances) 266 foreach (IScriptInstance i in instances)
266 { 267 {
267 string assembly = String.Empty; 268 string assembly = String.Empty;
268 269
@@ -289,7 +290,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
289 object[] parms = (object[])p; 290 object[] parms = (object[])p;
290 int sleepTime = (int)parms[0]; 291 int sleepTime = (int)parms[0];
291 292
292 foreach (XScriptInstance inst in m_Scripts.Values) 293 foreach (IScriptInstance inst in m_Scripts.Values)
293 { 294 {
294 if (inst.EventTime() > m_EventLimit) 295 if (inst.EventTime() > m_EventLimit)
295 { 296 {
@@ -502,12 +503,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
502 } 503 }
503 m_DomainScripts[appDomain].Add(itemID); 504 m_DomainScripts[appDomain].Add(itemID);
504 505
505 XScriptInstance instance = new XScriptInstance(this,localID, 506 ScriptInstance instance = new ScriptInstance(this,localID,
506 part.UUID, itemID, assetID, assembly, 507 part.UUID, itemID, assetID, assembly,
507 m_AppDomains[appDomain], 508 m_AppDomains[appDomain],
508 part.ParentGroup.RootPart.Name, 509 part.ParentGroup.RootPart.Name,
509 item.Name, startParam, postOnRez, 510 item.Name, startParam, postOnRez,
510 XScriptInstance.StateSource.NewRez); 511 StateSource.NewRez);
511 512
512 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}", 513 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}",
513 part.ParentGroup.RootPart.Name, item.Name); 514 part.ParentGroup.RootPart.Name, item.Name);
@@ -539,7 +540,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
539 540
540 m_AsyncCommands.RemoveScript(localID, itemID); 541 m_AsyncCommands.RemoveScript(localID, itemID);
541 542
542 XScriptInstance instance=m_Scripts[itemID]; 543 IScriptInstance instance=m_Scripts[itemID];
543 m_Scripts.Remove(itemID); 544 m_Scripts.Remove(itemID);
544 545
545 instance.ClearQueue(); 546 instance.ClearQueue();
@@ -599,7 +600,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
599 { 600 {
600 List<LLUUID> assetIDList = new List<LLUUID>(m_Assemblies.Keys); 601 List<LLUUID> assetIDList = new List<LLUUID>(m_Assemblies.Keys);
601 602
602 foreach (XScriptInstance i in m_Scripts.Values) 603 foreach (IScriptInstance i in m_Scripts.Values)
603 { 604 {
604 if (assetIDList.Contains(i.AssetID)) 605 if (assetIDList.Contains(i.AssetID))
605 assetIDList.Remove(i.AssetID); 606 assetIDList.Remove(i.AssetID);
@@ -676,7 +677,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
676 CultureInfo USCulture = new CultureInfo("en-US"); 677 CultureInfo USCulture = new CultureInfo("en-US");
677 Thread.CurrentThread.CurrentCulture = USCulture; 678 Thread.CurrentThread.CurrentCulture = USCulture;
678 679
679 XScriptInstance instance = (XScriptInstance) parms; 680 IScriptInstance instance = (ScriptInstance) parms;
680 681
681 return instance.EventProcessor(); 682 return instance.EventProcessor();
682 } 683 }
@@ -695,7 +696,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
695 { 696 {
696 if (m_Scripts.ContainsKey(itemID)) 697 if (m_Scripts.ContainsKey(itemID))
697 { 698 {
698 XScriptInstance instance = m_Scripts[itemID]; 699 IScriptInstance instance = m_Scripts[itemID];
699 if (instance != null) 700 if (instance != null)
700 { 701 {
701 instance.PostEvent(p); 702 instance.PostEvent(p);
@@ -713,7 +714,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
713 { 714 {
714 if (m_Scripts.ContainsKey(itemID)) 715 if (m_Scripts.ContainsKey(itemID))
715 { 716 {
716 XScriptInstance instance = m_Scripts[itemID]; 717 IScriptInstance instance = m_Scripts[itemID];
717 if (instance != null) 718 if (instance != null)
718 instance.PostEvent(p); 719 instance.PostEvent(p);
719 return true; 720 return true;
@@ -747,9 +748,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
747 return null; 748 return null;
748 } 749 }
749 750
750 private XScriptInstance GetInstance(LLUUID itemID) 751 private IScriptInstance GetInstance(LLUUID itemID)
751 { 752 {
752 XScriptInstance instance; 753 IScriptInstance instance;
753 lock (m_Scripts) 754 lock (m_Scripts)
754 { 755 {
755 if (!m_Scripts.ContainsKey(itemID)) 756 if (!m_Scripts.ContainsKey(itemID))
@@ -761,7 +762,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
761 762
762 public void SetScriptState(LLUUID itemID, bool running) 763 public void SetScriptState(LLUUID itemID, bool running)
763 { 764 {
764 XScriptInstance instance = GetInstance(itemID); 765 IScriptInstance instance = GetInstance(itemID);
765 if (instance != null) 766 if (instance != null)
766 { 767 {
767 if (running) 768 if (running)
@@ -773,7 +774,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
773 774
774 public bool GetScriptState(LLUUID itemID) 775 public bool GetScriptState(LLUUID itemID)
775 { 776 {
776 XScriptInstance instance = GetInstance(itemID); 777 IScriptInstance instance = GetInstance(itemID);
777 if (instance != null) 778 if (instance != null)
778 return instance.Running; 779 return instance.Running;
779 return false; 780 return false;
@@ -781,35 +782,35 @@ namespace OpenSim.Region.ScriptEngine.XEngine
781 782
782 public void ApiResetScript(LLUUID itemID) 783 public void ApiResetScript(LLUUID itemID)
783 { 784 {
784 XScriptInstance instance = GetInstance(itemID); 785 IScriptInstance instance = GetInstance(itemID);
785 if (instance != null) 786 if (instance != null)
786 instance.ApiResetScript(); 787 instance.ApiResetScript();
787 } 788 }
788 789
789 public void ResetScript(LLUUID itemID) 790 public void ResetScript(LLUUID itemID)
790 { 791 {
791 XScriptInstance instance = GetInstance(itemID); 792 IScriptInstance instance = GetInstance(itemID);
792 if (instance != null) 793 if (instance != null)
793 instance.ResetScript(); 794 instance.ResetScript();
794 } 795 }
795 796
796 public void StartScript(LLUUID itemID) 797 public void StartScript(LLUUID itemID)
797 { 798 {
798 XScriptInstance instance = GetInstance(itemID); 799 IScriptInstance instance = GetInstance(itemID);
799 if (instance != null) 800 if (instance != null)
800 instance.Start(); 801 instance.Start();
801 } 802 }
802 803
803 public void StopScript(LLUUID itemID) 804 public void StopScript(LLUUID itemID)
804 { 805 {
805 XScriptInstance instance = GetInstance(itemID); 806 IScriptInstance instance = GetInstance(itemID);
806 if (instance != null) 807 if (instance != null)
807 instance.Stop(0); 808 instance.Stop(0);
808 } 809 }
809 810
810 public DetectParams GetDetectParams(LLUUID itemID, int idx) 811 public DetectParams GetDetectParams(LLUUID itemID, int idx)
811 { 812 {
812 XScriptInstance instance = GetInstance(itemID); 813 IScriptInstance instance = GetInstance(itemID);
813 if (instance != null) 814 if (instance != null)
814 return instance.GetDetectParams(idx); 815 return instance.GetDetectParams(idx);
815 return null; 816 return null;
@@ -817,7 +818,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
817 818
818 public LLUUID GetDetectID(LLUUID itemID, int idx) 819 public LLUUID GetDetectID(LLUUID itemID, int idx)
819 { 820 {
820 XScriptInstance instance = GetInstance(itemID); 821 IScriptInstance instance = GetInstance(itemID);
821 if (instance != null) 822 if (instance != null)
822 return instance.GetDetectID(idx); 823 return instance.GetDetectID(idx);
823 return LLUUID.Zero; 824 return LLUUID.Zero;
@@ -825,14 +826,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
825 826
826 public void SetState(LLUUID itemID, string newState) 827 public void SetState(LLUUID itemID, string newState)
827 { 828 {
828 XScriptInstance instance = GetInstance(itemID); 829 IScriptInstance instance = GetInstance(itemID);
829 if (instance == null) 830 if (instance == null)
830 return; 831 return;
831 instance.SetState(newState); 832 instance.SetState(newState);
832 } 833 }
833 public string GetState(LLUUID itemID) 834 public string GetState(LLUUID itemID)
834 { 835 {
835 XScriptInstance instance = GetInstance(itemID); 836 IScriptInstance instance = GetInstance(itemID);
836 if (instance == null) 837 if (instance == null)
837 return "default"; 838 return "default";
838 return instance.State; 839 return instance.State;
@@ -840,7 +841,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
840 841
841 public int GetStartParameter(LLUUID itemID) 842 public int GetStartParameter(LLUUID itemID)
842 { 843 {
843 XScriptInstance instance = GetInstance(itemID); 844 IScriptInstance instance = GetInstance(itemID);
844 if (instance == null) 845 if (instance == null)
845 return 0; 846 return 0;
846 return instance.StartParam; 847 return instance.StartParam;
@@ -851,1025 +852,4 @@ namespace OpenSim.Region.ScriptEngine.XEngine
851 return GetScriptState(itemID); 852 return GetScriptState(itemID);
852 } 853 }
853 } 854 }
854
855 public class XScriptInstance
856 {
857 private XEngine m_Engine;
858 private IWorkItemResult m_CurrentResult=null;
859 private Queue m_EventQueue = new Queue(32);
860 private bool m_RunEvents = false;
861 private LLUUID m_ItemID;
862 private uint m_LocalID;
863 private LLUUID m_ObjectID;
864 private LLUUID m_AssetID;
865 private IScript m_Script;
866 private LLUUID m_AppDomain;
867 private DetectParams[] m_DetectParams;
868 private bool m_TimerQueued;
869 private DateTime m_EventStart;
870 private bool m_InEvent;
871 private string m_PrimName;
872 private string m_ScriptName;
873 private string m_Assembly;
874 private int m_StartParam = 0;
875 private string m_CurrentEvent = String.Empty;
876 private bool m_InSelfDelete = false;
877
878 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
879
880 public enum StateSource
881 {
882 NewRez = 0,
883 PrimCrossing = 1,
884 AttachmentCrossing = 2
885 }
886
887 // Script state
888 private string m_State="default";
889
890 public Object[] PluginData = new Object[0];
891
892 public bool Running
893 {
894 get { return m_RunEvents; }
895 set { m_RunEvents = value; }
896 }
897
898 public string State
899 {
900 get { return m_State; }
901 set { m_State = value; }
902 }
903
904 public XEngine Engine
905 {
906 get { return m_Engine; }
907 }
908
909 public LLUUID AppDomain
910 {
911 get { return m_AppDomain; }
912 set { m_AppDomain = value; }
913 }
914
915 public string PrimName
916 {
917 get { return m_PrimName; }
918 }
919
920 public string ScriptName
921 {
922 get { return m_ScriptName; }
923 }
924
925 public LLUUID ItemID
926 {
927 get { return m_ItemID; }
928 }
929
930 public LLUUID ObjectID
931 {
932 get { return m_ObjectID; }
933 }
934
935 public uint LocalID
936 {
937 get { return m_LocalID; }
938 }
939
940 public LLUUID AssetID
941 {
942 get { return m_AssetID; }
943 }
944
945 public Queue EventQueue
946 {
947 get { return m_EventQueue; }
948 }
949
950 public void ClearQueue()
951 {
952 m_TimerQueued = false;
953 m_EventQueue.Clear();
954 }
955
956 public int StartParam
957 {
958 get { return m_StartParam; }
959 set { m_StartParam = value; }
960 }
961
962 public XScriptInstance(XEngine engine, uint localID, LLUUID objectID,
963 LLUUID itemID, LLUUID assetID, string assembly, AppDomain dom,
964 string primName, string scriptName, int startParam,
965 bool postOnRez, StateSource stateSource)
966 {
967 m_Engine = engine;
968
969 m_LocalID = localID;
970 m_ObjectID = objectID;
971 m_ItemID = itemID;
972 m_AssetID = assetID;
973 m_PrimName = primName;
974 m_ScriptName = scriptName;
975 m_Assembly = assembly;
976 m_StartParam = startParam;
977
978 ApiManager am = new ApiManager();
979
980 SceneObjectPart part=engine.World.GetSceneObjectPart(localID);
981 if (part == null)
982 {
983 engine.Log.Error("[XEngine] SceneObjectPart unavailable. Script NOT started.");
984 return;
985 }
986
987 foreach (string api in am.GetApis())
988 {
989 m_Apis[api] = am.CreateApi(api);
990 m_Apis[api].Initialize(engine, part, localID, itemID);
991 }
992
993 try
994 {
995 m_Script = (IScript)dom.CreateInstanceAndUnwrap(
996 Path.GetFileNameWithoutExtension(assembly),
997 "SecondLife.Script");
998 }
999 catch (Exception e)
1000 {
1001 m_Engine.Log.ErrorFormat("[XEngine] Error loading assembly {0}\n"+e.ToString(), assembly);
1002 }
1003
1004 try
1005 {
1006 foreach (KeyValuePair<string,IScriptApi> kv in m_Apis)
1007 {
1008 m_Script.InitApi(kv.Key, kv.Value);
1009 }
1010
1011// m_Engine.Log.Debug("[XEngine] Script instance created");
1012
1013 part.SetScriptEvents(m_ItemID,
1014 (int)m_Script.GetStateEventFlags(State));
1015 }
1016 catch (Exception e)
1017 {
1018 m_Engine.Log.Error("[XEngine] Error loading script instance\n"+e.ToString());
1019 return;
1020 }
1021
1022 string savedState = Path.Combine(Path.GetDirectoryName(assembly),
1023 m_ItemID.ToString() + ".state");
1024 if (File.Exists(savedState))
1025 {
1026 string xml = String.Empty;
1027
1028 try
1029 {
1030 FileInfo fi = new FileInfo(savedState);
1031 int size=(int)fi.Length;
1032 if (size < 512000)
1033 {
1034 using (FileStream fs = File.Open(savedState,
1035 FileMode.Open, FileAccess.Read, FileShare.None))
1036 {
1037 System.Text.ASCIIEncoding enc =
1038 new System.Text.ASCIIEncoding();
1039
1040 Byte[] data = new Byte[size];
1041 fs.Read(data, 0, size);
1042
1043 xml = enc.GetString(data);
1044
1045 ScriptSerializer.Deserialize(xml, this);
1046
1047 m_Engine.m_AsyncCommands.CreateFromData(
1048 m_LocalID, m_ItemID, m_ObjectID,
1049 PluginData);
1050
1051 m_Engine.Log.DebugFormat("[XEngine] Successfully retrieved state for script {0}.{1}", m_PrimName, m_ScriptName);
1052
1053 if (m_RunEvents)
1054 {
1055 m_RunEvents = false;
1056 Start();
1057 if (postOnRez)
1058 PostEvent(new EventParams("on_rez",
1059 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
1060 }
1061
1062 // we get new rez events on sim restart, too
1063 // but if there is state, then we fire the change
1064 // event
1065 if (stateSource == StateSource.NewRez)
1066 {
1067// m_Engine.Log.Debug("[XEngine] Posted changed(CHANGED_REGION_RESTART) to script");
1068 PostEvent(new EventParams("changed",
1069 new Object[] {new LSL_Types.LSLInteger(256)}, new DetectParams[0]));
1070 }
1071 }
1072 }
1073 else
1074 {
1075 m_Engine.Log.Error("[XEngine] Unable to load script state: Memory limit exceeded");
1076 Start();
1077 PostEvent(new EventParams("state_entry",
1078 new Object[0], new DetectParams[0]));
1079 if (postOnRez)
1080 PostEvent(new EventParams("on_rez",
1081 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
1082
1083 }
1084 }
1085 catch (Exception e)
1086 {
1087 m_Engine.Log.ErrorFormat("[XEngine] Unable to load script state from xml: {0}\n"+e.ToString(), xml);
1088 Start();
1089 PostEvent(new EventParams("state_entry",
1090 new Object[0], new DetectParams[0]));
1091 if (postOnRez)
1092 PostEvent(new EventParams("on_rez",
1093 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
1094 }
1095 }
1096 else
1097 {
1098// m_Engine.Log.ErrorFormat("[XEngine] Unable to load script state, file not found");
1099 Start();
1100 PostEvent(new EventParams("state_entry",
1101 new Object[0], new DetectParams[0]));
1102
1103 if (postOnRez)
1104 PostEvent(new EventParams("on_rez",
1105 new Object[] {new LSL_Types.LSLInteger(startParam)}, new DetectParams[0]));
1106 }
1107 }
1108
1109 public void RemoveState()
1110 {
1111 string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly),
1112 m_ItemID.ToString() + ".state");
1113
1114 try
1115 {
1116 File.Delete(savedState);
1117 }
1118 catch(Exception)
1119 {
1120 }
1121 }
1122
1123 public void VarDump(Dictionary<string, object> vars)
1124 {
1125 Console.WriteLine("Variable dump for script {0}", m_ItemID.ToString());
1126 foreach (KeyValuePair<string, object> v in vars)
1127 {
1128 Console.WriteLine("Variable: {0} = '{1}'", v. Key,
1129 v.Value.ToString());
1130 }
1131 }
1132
1133 public void Start()
1134 {
1135 lock (m_EventQueue)
1136 {
1137 if (Running)
1138 return;
1139
1140 m_RunEvents = true;
1141
1142 if (m_EventQueue.Count > 0)
1143 {
1144 if (m_CurrentResult == null)
1145 m_CurrentResult = m_Engine.QueueEventHandler(this);
1146 else
1147 m_Engine.Log.Error("[XEngine] Tried to start a script that was already queued");
1148 }
1149 }
1150 }
1151
1152 public bool Stop(int timeout)
1153 {
1154 IWorkItemResult result;
1155
1156 lock (m_EventQueue)
1157 {
1158 if (!Running)
1159 return true;
1160
1161 if (m_CurrentResult == null)
1162 {
1163 m_RunEvents = false;
1164 return true;
1165 }
1166
1167 if (m_CurrentResult.Cancel())
1168 {
1169 m_CurrentResult = null;
1170 m_RunEvents = false;
1171 return true;
1172 }
1173
1174 result = m_CurrentResult;
1175 m_RunEvents = false;
1176 }
1177
1178 if (SmartThreadPool.WaitAll(new IWorkItemResult[] {result}, new TimeSpan((long)timeout * 100000), false))
1179 {
1180 return true;
1181 }
1182
1183 lock (m_EventQueue)
1184 {
1185 result = m_CurrentResult;
1186 }
1187
1188 if (result == null)
1189 return true;
1190
1191 if (!m_InSelfDelete)
1192 result.Abort();
1193
1194 lock (m_EventQueue)
1195 {
1196 m_CurrentResult = null;
1197 }
1198
1199 return true;
1200 }
1201
1202 public void SetState(string state)
1203 {
1204 PostEvent(new EventParams("state_exit", new Object[0],
1205 new DetectParams[0]));
1206 PostEvent(new EventParams("state", new Object[] { state },
1207 new DetectParams[0]));
1208 PostEvent(new EventParams("state_entry", new Object[0],
1209 new DetectParams[0]));
1210 }
1211
1212 public void PostEvent(EventParams data)
1213 {
1214// m_Engine.Log.DebugFormat("[XEngine] Posted event {2} in state {3} to {0}.{1}",
1215// m_PrimName, m_ScriptName, data.EventName, m_State);
1216
1217 if (!Running)
1218 return;
1219
1220 lock (m_EventQueue)
1221 {
1222 if (m_EventQueue.Count >= m_Engine.MaxScriptQueue)
1223 return;
1224
1225 m_EventQueue.Enqueue(data);
1226 if (data.EventName == "timer")
1227 {
1228 if (m_TimerQueued)
1229 return;
1230 m_TimerQueued = true;
1231 }
1232
1233 if (!m_RunEvents)
1234 return;
1235
1236 if (m_CurrentResult == null)
1237 {
1238 m_CurrentResult = m_Engine.QueueEventHandler(this);
1239 }
1240 }
1241 }
1242
1243 public object EventProcessor()
1244 {
1245 EventParams data = null;
1246
1247 lock (m_EventQueue)
1248 {
1249 data = (EventParams) m_EventQueue.Dequeue();
1250 if (data == null) // Shouldn't happen
1251 {
1252 m_CurrentResult = null;
1253 return 0;
1254 }
1255 if (data.EventName == "timer")
1256 m_TimerQueued = false;
1257 }
1258
1259 m_DetectParams = data.DetectParams;
1260
1261 if (data.EventName == "state") // Hardcoded state change
1262 {
1263// m_Engine.Log.DebugFormat("[XEngine] Script {0}.{1} state set to {2}",
1264// m_PrimName, m_ScriptName, data.Params[0].ToString());
1265 m_State=data.Params[0].ToString();
1266 m_Engine.m_AsyncCommands.RemoveScript(
1267 m_LocalID, m_ItemID);
1268
1269 SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
1270 m_LocalID);
1271 if (part != null)
1272 {
1273 part.SetScriptEvents(m_ItemID,
1274 (int)m_Script.GetStateEventFlags(State));
1275 }
1276 }
1277 else
1278 {
1279 SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
1280 m_LocalID);
1281// m_Engine.Log.DebugFormat("[XEngine] Delivered event {2} in state {3} to {0}.{1}",
1282// m_PrimName, m_ScriptName, data.EventName, m_State);
1283
1284 try
1285 {
1286 m_CurrentEvent = data.EventName;
1287 m_EventStart = DateTime.Now;
1288 m_InEvent = true;
1289
1290 m_Script.ExecuteEvent(State, data.EventName, data.Params);
1291
1292 m_InEvent = false;
1293 m_CurrentEvent = String.Empty;
1294 }
1295 catch (Exception e)
1296 {
1297 m_InEvent = false;
1298 m_CurrentEvent = String.Empty;
1299
1300 if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException))))
1301 {
1302 if (e is System.Threading.ThreadAbortException)
1303 {
1304 lock (m_EventQueue)
1305 {
1306 if ((m_EventQueue.Count > 0) && m_RunEvents)
1307 {
1308 m_CurrentResult=m_Engine.QueueEventHandler(this);
1309 }
1310 else
1311 {
1312 m_CurrentResult = null;
1313 }
1314 }
1315
1316 m_DetectParams = null;
1317
1318 return 0;
1319 }
1320
1321 try
1322 {
1323 // DISPLAY ERROR INWORLD
1324 string text = "Runtime error:\n" + e.ToString();
1325 if (text.Length > 1400)
1326 text = text.Substring(0, 1400);
1327 m_Engine.World.SimChat(Helpers.StringToField(text),
1328 ChatTypeEnum.DebugChannel, 2147483647,
1329 part.AbsolutePosition,
1330 part.Name, part.UUID, false);
1331 }
1332 catch (Exception e2) // LEGIT: User Scripting
1333 {
1334 m_Engine.Log.Error("[XEngine]: "+
1335 "Error displaying error in-world: " +
1336 e2.ToString());
1337 m_Engine.Log.Error("[XEngine]: " +
1338 "Errormessage: Error compiling script:\r\n" +
1339 e.ToString());
1340 }
1341 }
1342 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
1343 {
1344 m_InSelfDelete = true;
1345 if (part != null && part.ParentGroup != null)
1346 m_Engine.World.DeleteSceneObject(part.ParentGroup);
1347 }
1348 }
1349 }
1350
1351 lock (m_EventQueue)
1352 {
1353 if ((m_EventQueue.Count > 0) && m_RunEvents)
1354 {
1355 m_CurrentResult = m_Engine.QueueEventHandler(this);
1356 }
1357 else
1358 {
1359 m_CurrentResult = null;
1360 }
1361 }
1362
1363 m_DetectParams = null;
1364
1365 return 0;
1366 }
1367
1368 public int EventTime()
1369 {
1370 if (!m_InEvent)
1371 return 0;
1372
1373 return (DateTime.Now - m_EventStart).Seconds;
1374 }
1375
1376 public void ResetScript()
1377 {
1378 bool running = Running;
1379
1380 RemoveState();
1381
1382 Stop(0);
1383 SceneObjectPart part=m_Engine.World.GetSceneObjectPart(m_LocalID);
1384 part.GetInventoryItem(m_ItemID).PermsMask = 0;
1385 part.GetInventoryItem(m_ItemID).PermsGranter = LLUUID.Zero;
1386 m_Engine.m_AsyncCommands.RemoveScript(m_LocalID, m_ItemID);
1387 m_EventQueue.Clear();
1388 m_Script.ResetVars();
1389 m_State = "default";
1390 if (running)
1391 Start();
1392 PostEvent(new EventParams("state_entry",
1393 new Object[0], new DetectParams[0]));
1394 }
1395
1396 public void ApiResetScript()
1397 {
1398 // bool running = Running;
1399
1400 RemoveState();
1401
1402 m_Script.ResetVars();
1403 SceneObjectPart part=m_Engine.World.GetSceneObjectPart(m_LocalID);
1404 part.GetInventoryItem(m_ItemID).PermsMask = 0;
1405 part.GetInventoryItem(m_ItemID).PermsGranter = LLUUID.Zero;
1406 m_Engine.m_AsyncCommands.RemoveScript(m_LocalID, m_ItemID);
1407 if (m_CurrentEvent != "state_entry")
1408 {
1409 PostEvent(new EventParams("state_entry",
1410 new Object[0], new DetectParams[0]));
1411 }
1412 }
1413
1414 public Dictionary<string, object> GetVars()
1415 {
1416 return m_Script.GetVars();
1417 }
1418
1419 public void SetVars(Dictionary<string, object> vars)
1420 {
1421 m_Script.SetVars(vars);
1422 }
1423
1424 public DetectParams GetDetectParams(int idx)
1425 {
1426 if (idx < 0 || idx >= m_DetectParams.Length)
1427 return null;
1428
1429 return m_DetectParams[idx];
1430 }
1431
1432 public LLUUID GetDetectID(int idx)
1433 {
1434 if (idx < 0 || idx >= m_DetectParams.Length)
1435 return LLUUID.Zero;
1436
1437 return m_DetectParams[idx].Key;
1438 }
1439
1440 public void SaveState(string assembly)
1441 {
1442 PluginData =
1443 m_Engine.m_AsyncCommands.GetSerializationData(
1444 m_ItemID);
1445
1446 string xml = ScriptSerializer.Serialize(this);
1447
1448 try
1449 {
1450 FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state"));
1451 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1452 Byte[] buf = enc.GetBytes(xml);
1453 fs.Write(buf, 0, buf.Length);
1454 fs.Close();
1455 }
1456 catch(Exception e)
1457 {
1458 Console.WriteLine("Unable to save xml\n"+e.ToString());
1459 }
1460 if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state")))
1461 {
1462 throw new Exception("Completed persistence save, but no file was created");
1463 }
1464 }
1465 }
1466
1467 public class ScriptSerializer
1468 {
1469 public static string Serialize(XScriptInstance instance)
1470 {
1471 bool running = instance.Running;
1472
1473 if (running)
1474 instance.Stop(50);
1475
1476 XmlDocument xmldoc = new XmlDocument();
1477
1478 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
1479 "", "");
1480 xmldoc.AppendChild(xmlnode);
1481
1482 XmlElement rootElement = xmldoc.CreateElement("", "ScriptState",
1483 "");
1484 xmldoc.AppendChild(rootElement);
1485
1486 XmlElement state = xmldoc.CreateElement("", "State", "");
1487 state.AppendChild(xmldoc.CreateTextNode(instance.State));
1488
1489 rootElement.AppendChild(state);
1490
1491 XmlElement run = xmldoc.CreateElement("", "Running", "");
1492 run.AppendChild(xmldoc.CreateTextNode(
1493 running.ToString()));
1494
1495 rootElement.AppendChild(run);
1496
1497 Dictionary<string, Object> vars = instance.GetVars();
1498
1499 XmlElement variables = xmldoc.CreateElement("", "Variables", "");
1500
1501 foreach (KeyValuePair<string, Object> var in vars)
1502 WriteTypedValue(xmldoc, variables, "Variable", var.Key,
1503 var.Value);
1504
1505 rootElement.AppendChild(variables);
1506
1507 XmlElement queue = xmldoc.CreateElement("", "Queue", "");
1508
1509 int count = instance.EventQueue.Count;
1510
1511 while (count > 0)
1512 {
1513 EventParams ep = (EventParams)instance.EventQueue.Dequeue();
1514 instance.EventQueue.Enqueue(ep);
1515 count--;
1516
1517 XmlElement item = xmldoc.CreateElement("", "Item", "");
1518 XmlAttribute itemEvent = xmldoc.CreateAttribute("", "event",
1519 "");
1520 itemEvent.Value = ep.EventName;
1521 item.Attributes.Append(itemEvent);
1522
1523 XmlElement parms = xmldoc.CreateElement("", "Params", "");
1524
1525 foreach (Object o in ep.Params)
1526 WriteTypedValue(xmldoc, parms, "Param", String.Empty, o);
1527
1528 item.AppendChild(parms);
1529
1530 XmlElement detect = xmldoc.CreateElement("", "Detected", "");
1531
1532 foreach (DetectParams det in ep.DetectParams)
1533 {
1534 XmlElement objectElem = xmldoc.CreateElement("", "Object",
1535 "");
1536 XmlAttribute pos = xmldoc.CreateAttribute("", "pos", "");
1537 pos.Value = det.OffsetPos.ToString();
1538 objectElem.Attributes.Append(pos);
1539
1540 XmlAttribute d_linkNum = xmldoc.CreateAttribute("",
1541 "linkNum", "");
1542 d_linkNum.Value = det.LinkNum.ToString();
1543 objectElem.Attributes.Append(d_linkNum);
1544
1545 XmlAttribute d_group = xmldoc.CreateAttribute("",
1546 "group", "");
1547 d_group.Value = det.Group.ToString();
1548 objectElem.Attributes.Append(d_group);
1549
1550 XmlAttribute d_name = xmldoc.CreateAttribute("",
1551 "name", "");
1552 d_name.Value = det.Name.ToString();
1553 objectElem.Attributes.Append(d_name);
1554
1555 XmlAttribute d_owner = xmldoc.CreateAttribute("",
1556 "owner", "");
1557 d_owner.Value = det.Owner.ToString();
1558 objectElem.Attributes.Append(d_owner);
1559
1560 XmlAttribute d_position = xmldoc.CreateAttribute("",
1561 "position", "");
1562 d_position.Value = det.Position.ToString();
1563 objectElem.Attributes.Append(d_position);
1564
1565 XmlAttribute d_rotation = xmldoc.CreateAttribute("",
1566 "rotation", "");
1567 d_rotation.Value = det.Rotation.ToString();
1568 objectElem.Attributes.Append(d_rotation);
1569
1570 XmlAttribute d_type = xmldoc.CreateAttribute("",
1571 "type", "");
1572 d_type.Value = det.Type.ToString();
1573 objectElem.Attributes.Append(d_type);
1574
1575 XmlAttribute d_velocity = xmldoc.CreateAttribute("",
1576 "velocity", "");
1577 d_velocity.Value = det.Velocity.ToString();
1578 objectElem.Attributes.Append(d_velocity);
1579
1580 objectElem.AppendChild(
1581 xmldoc.CreateTextNode(det.Key.ToString()));
1582
1583 detect.AppendChild(objectElem);
1584 }
1585
1586 item.AppendChild(detect);
1587
1588 queue.AppendChild(item);
1589 }
1590
1591 rootElement.AppendChild(queue);
1592
1593 XmlNode plugins = xmldoc.CreateElement("", "Plugins", "");
1594 DumpList(xmldoc, plugins,
1595 new LSL_Types.list(instance.PluginData));
1596
1597 rootElement.AppendChild(plugins);
1598
1599 if (running)
1600 instance.Start();
1601
1602 return xmldoc.InnerXml;
1603 }
1604
1605 public static void Deserialize(string xml, XScriptInstance instance)
1606 {
1607 XmlDocument doc = new XmlDocument();
1608
1609 Dictionary<string, object> vars = instance.GetVars();
1610
1611 instance.PluginData = new Object[0];
1612
1613 doc.LoadXml(xml);
1614
1615 XmlNodeList rootL = doc.GetElementsByTagName("ScriptState");
1616 if (rootL.Count != 1)
1617 {
1618 return;
1619 }
1620 XmlNode rootNode = rootL[0];
1621
1622 if (rootNode != null)
1623 {
1624 object varValue;
1625 XmlNodeList partL = rootNode.ChildNodes;
1626
1627 foreach (XmlNode part in partL)
1628 {
1629 switch (part.Name)
1630 {
1631 case "State":
1632 instance.State=part.InnerText;
1633 break;
1634 case "Running":
1635 instance.Running=bool.Parse(part.InnerText);
1636 break;
1637 case "Variables":
1638 XmlNodeList varL = part.ChildNodes;
1639 foreach (XmlNode var in varL)
1640 {
1641 string varName;
1642 varValue=ReadTypedValue(var, out varName);
1643
1644 if (vars.ContainsKey(varName))
1645 vars[varName] = varValue;
1646 }
1647 instance.SetVars(vars);
1648 break;
1649 case "Queue":
1650 XmlNodeList itemL = part.ChildNodes;
1651 foreach (XmlNode item in itemL)
1652 {
1653 List<Object> parms = new List<Object>();
1654 List<DetectParams> detected =
1655 new List<DetectParams>();
1656
1657 string eventName =
1658 item.Attributes.GetNamedItem("event").Value;
1659 XmlNodeList eventL = item.ChildNodes;
1660 foreach (XmlNode evt in eventL)
1661 {
1662 switch (evt.Name)
1663 {
1664 case "Params":
1665 XmlNodeList prms = evt.ChildNodes;
1666 foreach (XmlNode pm in prms)
1667 parms.Add(ReadTypedValue(pm));
1668
1669 break;
1670 case "Detected":
1671 XmlNodeList detL = evt.ChildNodes;
1672 foreach (XmlNode det in detL)
1673 {
1674 string vect =
1675 det.Attributes.GetNamedItem(
1676 "pos").Value;
1677 LSL_Types.Vector3 v =
1678 new LSL_Types.Vector3(vect);
1679
1680 int d_linkNum=0;
1681 LLUUID d_group = LLUUID.Zero;
1682 string d_name = String.Empty;
1683 LLUUID d_owner = LLUUID.Zero;
1684 LSL_Types.Vector3 d_position =
1685 new LSL_Types.Vector3();
1686 LSL_Types.Quaternion d_rotation =
1687 new LSL_Types.Quaternion();
1688 int d_type = 0;
1689 LSL_Types.Vector3 d_velocity =
1690 new LSL_Types.Vector3();
1691
1692 try
1693 {
1694 string tmp;
1695
1696 tmp = det.Attributes.GetNamedItem(
1697 "linkNum").Value;
1698 int.TryParse(tmp, out d_linkNum);
1699
1700 tmp = det.Attributes.GetNamedItem(
1701 "group").Value;
1702 LLUUID.TryParse(tmp, out d_group);
1703
1704 d_name = det.Attributes.GetNamedItem(
1705 "name").Value;
1706
1707 tmp = det.Attributes.GetNamedItem(
1708 "owner").Value;
1709 LLUUID.TryParse(tmp, out d_owner);
1710
1711 tmp = det.Attributes.GetNamedItem(
1712 "position").Value;
1713 d_position =
1714 new LSL_Types.Vector3(tmp);
1715
1716 tmp = det.Attributes.GetNamedItem(
1717 "rotation").Value;
1718 d_rotation =
1719 new LSL_Types.Quaternion(tmp);
1720
1721 tmp = det.Attributes.GetNamedItem(
1722 "type").Value;
1723 int.TryParse(tmp, out d_type);
1724
1725 tmp = det.Attributes.GetNamedItem(
1726 "velocity").Value;
1727 d_velocity =
1728 new LSL_Types.Vector3(tmp);
1729
1730 }
1731 catch (Exception) // Old version XML
1732 {
1733 }
1734
1735 LLUUID uuid = new LLUUID();
1736 LLUUID.TryParse(det.InnerText,
1737 out uuid);
1738
1739 DetectParams d = new DetectParams();
1740 d.Key = uuid;
1741 d.OffsetPos = v;
1742 d.LinkNum = d_linkNum;
1743 d.Group = d_group;
1744 d.Name = d_name;
1745 d.Owner = d_owner;
1746 d.Position = d_position;
1747 d.Rotation = d_rotation;
1748 d.Type = d_type;
1749 d.Velocity = d_velocity;
1750
1751 detected.Add(d);
1752 }
1753 break;
1754 }
1755 }
1756 EventParams ep = new EventParams(
1757 eventName, parms.ToArray(),
1758 detected.ToArray());
1759 instance.EventQueue.Enqueue(ep);
1760 }
1761 break;
1762 case "Plugins":
1763 instance.PluginData = ReadList(part).Data;
1764 break;
1765 }
1766 }
1767 }
1768 }
1769
1770 private static void DumpList(XmlDocument doc, XmlNode parent,
1771 LSL_Types.list l)
1772 {
1773 foreach (Object o in l.Data)
1774 WriteTypedValue(doc, parent, "ListItem", "", o);
1775 }
1776
1777 private static LSL_Types.list ReadList(XmlNode parent)
1778 {
1779 List<Object> olist = new List<Object>();
1780
1781 XmlNodeList itemL = parent.ChildNodes;
1782 foreach (XmlNode item in itemL)
1783 olist.Add(ReadTypedValue(item));
1784
1785 return new LSL_Types.list(olist.ToArray());
1786 }
1787
1788 private static void WriteTypedValue(XmlDocument doc, XmlNode parent,
1789 string tag, string name, object value)
1790 {
1791 Type t=value.GetType();
1792 XmlAttribute typ = doc.CreateAttribute("", "type", "");
1793 XmlNode n = doc.CreateElement("", tag, "");
1794
1795 if (value is LSL_Types.list)
1796 {
1797 typ.Value = "list";
1798 n.Attributes.Append(typ);
1799
1800 DumpList(doc, n, (LSL_Types.list) value);
1801
1802 if (name != String.Empty)
1803 {
1804 XmlAttribute nam = doc.CreateAttribute("", "name", "");
1805 nam.Value = name;
1806 n.Attributes.Append(nam);
1807 }
1808
1809 parent.AppendChild(n);
1810 return;
1811 }
1812
1813 n.AppendChild(doc.CreateTextNode(value.ToString()));
1814
1815 typ.Value = t.ToString();
1816 n.Attributes.Append(typ);
1817 if (name != String.Empty)
1818 {
1819 XmlAttribute nam = doc.CreateAttribute("", "name", "");
1820 nam.Value = name;
1821 n.Attributes.Append(nam);
1822 }
1823
1824 parent.AppendChild(n);
1825 }
1826
1827 private static object ReadTypedValue(XmlNode tag, out string name)
1828 {
1829 name = tag.Attributes.GetNamedItem("name").Value;
1830
1831 return ReadTypedValue(tag);
1832 }
1833
1834 private static object ReadTypedValue(XmlNode tag)
1835 {
1836 Object varValue;
1837 string assembly;
1838
1839 string itemType = tag.Attributes.GetNamedItem("type").Value;
1840
1841 if (itemType == "list")
1842 return ReadList(tag);
1843
1844 if (itemType == "libsecondlife.LLUUID")
1845 {
1846 LLUUID val = new LLUUID();
1847 LLUUID.TryParse(tag.InnerText, out val);
1848
1849 return val;
1850 }
1851
1852 Type itemT = Type.GetType(itemType);
1853 if (itemT == null)
1854 {
1855 Object[] args =
1856 new Object[] { tag.InnerText };
1857
1858 assembly = itemType+", OpenSim.Region.ScriptEngine.Shared";
1859 itemT = Type.GetType(assembly);
1860 if (itemT == null)
1861 return null;
1862
1863 varValue = Activator.CreateInstance(itemT, args);
1864
1865 if (varValue == null)
1866 return null;
1867 }
1868 else
1869 {
1870 varValue = Convert.ChangeType(tag.InnerText, itemT);
1871 }
1872 return varValue;
1873 }
1874 }
1875} 855}