diff options
Diffstat (limited to '')
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; | |||
32 | using libsecondlife; | 32 | using libsecondlife; |
33 | using Nini.Config; | 33 | using Nini.Config; |
34 | using OpenSim.Region.ScriptEngine.Interfaces; | 34 | using OpenSim.Region.ScriptEngine.Interfaces; |
35 | using Amib.Threading; | ||
35 | 36 | ||
36 | namespace OpenSim.Region.ScriptEngine.Interfaces | 37 | namespace 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 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using libsecondlife; | ||
32 | using log4net; | ||
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Region.ScriptEngine.Shared; | ||
35 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
36 | |||
37 | namespace 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 | |||
28 | using System; | ||
29 | using System.IO; | ||
30 | using System.Threading; | ||
31 | using System.Collections; | ||
32 | using System.Collections.Generic; | ||
33 | using System.Security.Policy; | ||
34 | using System.Reflection; | ||
35 | using System.Globalization; | ||
36 | using System.Xml; | ||
37 | using libsecondlife; | ||
38 | using log4net; | ||
39 | using Nini.Config; | ||
40 | using Amib.Threading; | ||
41 | using OpenSim.Framework; | ||
42 | using OpenSim.Region.Environment; | ||
43 | using OpenSim.Region.Environment.Scenes; | ||
44 | using OpenSim.Region.Environment.Interfaces; | ||
45 | using OpenSim.Region.ScriptEngine.Shared; | ||
46 | using OpenSim.Region.ScriptEngine.Shared.Api; | ||
47 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | ||
48 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; | ||
49 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
50 | |||
51 | namespace 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 | |||
28 | using System; | ||
29 | using System.IO; | ||
30 | using System.Threading; | ||
31 | using System.Collections; | ||
32 | using System.Collections.Generic; | ||
33 | using System.Security.Policy; | ||
34 | using System.Reflection; | ||
35 | using System.Globalization; | ||
36 | using System.Xml; | ||
37 | using libsecondlife; | ||
38 | using log4net; | ||
39 | using Nini.Config; | ||
40 | using Amib.Threading; | ||
41 | using OpenSim.Framework; | ||
42 | using OpenSim.Region.Environment; | ||
43 | using OpenSim.Region.Environment.Scenes; | ||
44 | using OpenSim.Region.Environment.Interfaces; | ||
45 | using OpenSim.Region.ScriptEngine.Shared; | ||
46 | using OpenSim.Region.ScriptEngine.Shared.Api; | ||
47 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | ||
48 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; | ||
49 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
50 | |||
51 | namespace 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; | |||
46 | using OpenSim.Region.ScriptEngine.Shared.Api; | 46 | using OpenSim.Region.ScriptEngine.Shared.Api; |
47 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | 47 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
48 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; | 48 | using OpenSim.Region.ScriptEngine.Shared.CodeTools; |
49 | using OpenSim.Region.ScriptEngine.Shared.Instance; | ||
49 | using OpenSim.Region.ScriptEngine.Interfaces; | 50 | using OpenSim.Region.ScriptEngine.Interfaces; |
50 | 51 | ||
51 | namespace OpenSim.Region.ScriptEngine.XEngine | 52 | namespace 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 | } |