aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
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/XEngine/XEngine.cs
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 '')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs1076
1 files changed, 28 insertions, 1048 deletions
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}